一,版本与限制
libc 2.26开始引入tcache,不过对tcache的doublefree与伪造没有任何限制,可以很轻松拿到信息。libc 2.29开始引入 tcache的doublefree检测,检查 bin->bk 指针是否是tcache_struct,可以通过堆溢出或uaf绕过。
ubuntu16默认用的是libc 2.23,没有tcachebin;ubuntu18是2.27,有tcachebin,但没有任何检测,更加轻松;ubuntu20用的是2.31。
二,小技巧
平时可能要用unsortedbin attack泄露基址,可以相同的堆分配7个,或直接请求一个0x410的堆块,正好超出tcachebin的限制。
三,tcache
如果版本有tcache,可以发现初始heap区域已经有了一个0x250的堆块,这是用来存储tcache_perthread_struct的。
这是ctfwiki上的图片,通过观察与总结。counts有64个元素,分别对应 0x20,0x30,0x30......0x410堆块的数量,注意这个大小是包括头部(pre_size,size),所以请求0x410,大小就是0x420,正好超出了tcachebin的大小范围,每个元素占一字节,总共就是0x40。entries是每个tcachebin链表的头部,地址,所以每个大小是0x8,64个就是0x200。
0x200+0x40+0x10(pre_size,size)=0x250,正好填满堆块。
值得注意的是,由于内存页的存在,heap起始地址的末尾永远是 000 ,有时候可以进行利用。