Tcache Stashing Unlink Attack&&House of Lore Attack
0x00 写在最前
由于glibc在2.29中新增了一系列保护措施使得我们对unsortedbin attack的利用举步维艰,那么我们是否可以找到一种替代的方法使得unsortedbin attack的精神延续下去呢?我们知道,unsortedbin attack是通过修改unsortedbin的bk指针为我们想要写大数的地址-0x10即可向该地址写入一个较大的数值,2.29之后,我们可以通过Tcache Stashing Unlink Attack来达到同样的效果,倘若我们可以控制目标地址的fd的话我们甚至可以直接分配堆块到目标地址。
0x01 源码分析
1 | /* |
0x02 Tcache Stashing Unlink Attack
我们首先来看一个smallbin的布置图:
我们不难发现,如果开启tcache的话并没有检测bck->fd == victim,因此,当我们申请一个对应大小的堆块时,我们经过分界线上面的一顿操作后取出了smallbin的第一块chunk,我们执行分界线下面的代码的时候发现并没有对smallbin中的第三块堆块进行合法性检查,这样,倘若tcache中有6个chunk的话,我们申请一个该大小的堆块时,会触发Tcache Stashing Unlink,这时chunk1被取出,chunk2会被放入tcache中,由于tcache的上限为7,因此chunk2会填满chunk而chunk3不会放入tcache中。
因为源码中bck->fd = bin;的存在,chunk3的fd地址会被写入一个bin的地址(bin的地址在main_arena中),所以我们的攻击思路是伪造chunk2的bk,使其指向我们要修改地址的前0x10处,当触发Tcache Stashing Unlink时,程序会误以为第二块的bk中的地址addr-0x10为第三块堆块,然后根据bck->fd = bin;将该堆块的fd指针腹泻为一个main_arena上的bin地址,而我们的fd指针恰好位于addr处,从而完成对该堆块处写入一个大数。
这里有聪明的小伙伴就会问了,当开启tcache时存取堆块都是优先从tcache中进行的,那么我们如何取出smallbin的堆块呢?我们这里的利用条件是题目使用calloc来分配堆块,calloc函数不会从tcache中存取堆块,而是会从其他bin中存取堆块,使得我们可以利用这种攻击方式。
例题:[Black Watch 入群题]PWN2
add只能分配四种大小的堆块:1.0x10 2.0xf0 3.0x300 4.0x400
分配方法是calloc,联想到Tcache Stashing Unlink Attack
delete函数未将指针清零,有uaf漏洞
输入666会判断一个地址的值是否符合条件,这时候我们很自然的想到Tcache Stashing Unlink Attack,我们首先申请9个大小为4的堆块,释放8个,常规方法泄露libc_base,然后也是常规泄露heap_base,将0x100大小的tcache填入6个堆块,接着申请两个0x300的堆块,第一个切割unsortedbin,第二个将unsortedbin的剩余部分放入smallbin中,接下来如法炮制,申请一个最大的堆块释放后申请两个0x300的堆块,这样,我们就得到了两个smallbin中的chunk。
由于smallbin链表是fifo(先进先出),那么我们修改第二个放入smallbin的bk指针为我们需要修改的地址-0x10,这样申请堆块时smallbins就会返回第一块堆块,然后将第二块堆块放入tcache中,接着在addr处写入0x100对应的smallbin在main_arena的地址
写入了main_arena的地址后我们就可以用666来进行栈迁移,迁移到我们预先布置好的orw的堆块上完成解题
exp如下:
1 | from pwn import * |