Large bin attack
Large Bin Attack
大小超过
0x400
结构与
unsorted bin
基本相同,多bk_next_size & fd_next_size
指向大小相对大或者小的堆块。
Large Bin 没有固定大小,有固定大小范围。
DEMO来自how2heap
,这是一整个exp
,接下来我会分开做解释
1 | // gcc large_bin_attack.c -o large_bin_attack -g |
Demo解释
1 | unsigned long stack_var1 = 0; |
首先声明了两个目标变量 接下来我们会称其s1,s2
1 | unsigned long *p1 = malloc(0x320); |
这里申请了三个chunk
,分别是p1,p2,p3
,其中,p1
属于small bin
,p2
和 p3
都属于large bin
,每个chunk中间都申请了一个fastbin
,防止三个chunk
在free时被合并。
1 | free(p1); |
free
掉p1,p2
,p1,p2
暂时进入unsorted bin list
,现在,unsorted bin
应该像这样:p1 - p2
1 | void* p4 = malloc(0x90); |
这句话比较重要,在申请p4
的过程中,同时发生三件事 (注意,Unsorted bin 为 FIFO)
- 拿出现在最底部的chunk,计算大小,
p1
放入small bin list
中 - 拿出现在最底部的chunk,计算大小,
p2
放入large bin list
中 - 因为申请了一块
0x90
的内存,且unosorted bin list
为空,从small bin list
中拿出p1
,并中分配一个 chunk 满足请求0x90
,接下来把剩下的0x330 - 0xa0 = 0x290
放回unsorted bin list
,我们称其remainder
1 | free(p3); |
释放掉了p3
,此时unsorted bin list
为remainder <- p3
1 | p2[-1] = 0x3f1; |
我们开始攻击,我们将p2
(已经在large bin list
中)的size
修改为0x3f1
(稍后解释为什么会需要shrink
), bk
修改为s1-0x10
,bk_sz
修改为s2-0x20
,其他可以为0。大概长成这个样子:
1 | prev_size, |
最后
1 | malloc(0x90); |
我们再申请一个长度为0x90
的空间,这个的作用和前面的差不多:
- 拿出现在最底部的chunk,计算大小,
remainder
放入small bin list
中 - 拿出现在最底部的chunk,计算大小,
p4
放入large bin list
中
也就是这一次的放入large bin
触发了篡改。
放入 Large bin 的过程 (Glibc 2.23)
从
unsorted bin
中拿出P3
的时候,首先会判断P3
应该归属的bin
的类型,这里根据size
判断出是large bin
1 | while ((unsigned long) size < chunksize_nomask (fwd)) |
接下来,会对size
和上一个bin
的大小做对比,通过不同的情况给large bin
排序,由于上一个chunk
的size
被我们修改过 =0x3f0
,所以没有进入循环
1 | //other code.... |
接下来,会进入这里,要注意的是,我们进行过篡改的是上一个large bin
,也就是fwd
我们之前把 fwd
的 bk_nextsize
指向了s2
,那么 victim->bk_nextsize->fd_nextsize = fwd->bk_nextsize->->fd_nextsize = *(s2 + 4) = victim
,不过还有。
1 | mark_bin (av, victim_index); |
那么我们可以知道bck -> fd = fwd -> bk -> fd = fwd = victim
总结 large bin attack 的利用方法 ¶
现在我们来总结一下利用的条件:
- 可以修改一个 large bin chunk 的 data
- 从 unsorted bin 中来的 large bin chunk 要紧跟在被构造过的 chunk 的后面
- 通过 large bin attack 可以辅助 Tcache Stash Unlink+ 攻击
- 可以修改 _IO_list_all 便于伪造 _IO_FILE 结构体进行 FSOP。