unsortedbin leak及unsortedbin attack利用分析
Heap基础知识
[toc]
unsortedbin attack
广义上的unsorted bin attack
其实分为unsorted bin leak
和unsorted bin attack
,前者可以根据unsorted bin
的特性来泄露出libc
的地址,后者的作用是对一个指定地址写入一个非常大的值(其实是写入main_arena
的地址的一个偏移)。
unsortedbin特性
首先是unsorted bin
的来源,这里抄一下wiki
1 |
|
然后是使用情况,抄一下wiki
1 |
|
用一下gzy
的图
unsortedbin leak
从上图也可以看到,与unsorted bin
直接相连的一个bin
是最后插入到unsorted bin
里面来的。它的bk
指针指向unsorted bin
。换句话说,它的bk
指针指向main_arena
的一个固定偏移,而main_arena
和libc_base
也有一个固定偏移,那么只要泄露出来了它的bk
指针,也就不愁计算出libc
的地址了。这里用先插入到unsorted bin
的fd
指针也是同理的。
unsortedbin attack
作用是向指定地址写入一个非常大的值,即main_arena
的一个固定偏移。
unsotred bin attack
的攻击过程发生在这种情况:
调用malloc
时,反向遍历unsorted bin
,若unsorted bin
里面恰好有与请求的chunk size
相等的chunk
大小,那么将对应的chunk
取出来,该chunk
也就被叫做victim
。若不是恰好相等,那么这个chunk
就会被放到对应的small bin
或者large bin
中去。
来看这一小段glibc2.23
的源代码:(第一行和第二行之间省略了一部分不影响的)
1 |
|
正常情况下,这一小段代码会将victim
取出,而unsorted bin
继续保持双向链表。注意,victim
始终是unsorted bin
里面的最后一个chunk
,因为是反向遍历的unsorted bin
,且遍历到的chunk
要么会返回给用户,要么就会被移动到small bin
或者large bin
里面去。
而攻击情况下,我们将控制victim
的bk
指针为希望进行地址修改的地方减去0x10
的地方。
我们通过画图的方式来解释一下正常情况和攻击的情况。
首先是正常情况:
如图所示,我们假设最后一个chunk
刚好是malloc
需要的大小,因此被标记为victim
。
此时运行到第一行代码 bck = victim->bk;
很简单,我们将victim
的bk
指针指向的chunk
标记为bck
。如图所示:
然后是第二行代码unsorted_chunks (av)->bk = bck;
很简单,本来unsorted bin
的bk
指针是指向victim
的,而victim
将要被malloc
,因此先将unsorted bin
的bk
指针指向bck
。
第三行代码bck->fd = unsorted_chunks (av);
也很简单,和上面同理,我们要将bck
的fd
指针指向unsorted bin
,以此将victim
脱链。这两步如图所示:
此时实际上victim
的两个指针还指向它们,但unsorted bin
和bck
指针都不再指向它,因此相当于victim
已经被取出了。
现在我们考虑对其进行攻击的情况。
若我们能够控制victim
的bk
指针,并将其指向一个fake_chunk
(该fake_chunk
的fd
指针是我们希望修改的值。也就是&fake_chunk + 0x10
,那么在代码的第一行bck = victim->bk;
,将会出现如图所示的情况:
那么第二行代码unsorted_chunks (av)->bk = bck;
,将会将unsorted bin
的bk
指针也指向该fake_chunk
。
第三行代码bck->fd = unsorted_chunks (av);
则是攻击的真正实施:它将bck
处的fd
指针修改为了unsorted bin
的地址。也就是实现了这一步:*(&fake_chunk + 0x10) = unsorted_bin
。
此时如图所示:
至此,已经实现了攻击。