堆利用学习之fastbin attack

原理

fastbin attack是一类漏洞的利用方法,是指所有基于 fastbin 机制的漏洞利用方法。主要利用了fast bin的单链表管理机制。

相关源码:
malloc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
If the size qualifies as a fastbin, first check corresponding bin.
This code is safe to execute even if av is not yet initialized, so we
can try it without checking, which saves some time on this fast path.
*/

if ((unsigned long) (nb) <= (unsigned long) (get_max_fast())) {
// 得到对应的fastbin的下标
idx = fastbin_index(nb);
// 得到对应的fastbin的头指针
mfastbinptr *fb = &fastbin(av, idx);
mchunkptr pp = *fb;
// 利用fd遍历对应的bin内是否有空闲的chunk块,
do {
victim = pp;
if (victim == NULL) break;
} while ((pp = catomic_compare_and_exchange_val_acq(fb, victim->fd, victim)) != victim);
...

这里首先根据所需chunk的大小获得该chunk所属fast bin的index,根据该index获得所需fast bin的空闲chunk链表指针,然后将头指针的下一个chunk(victim->fd)作为空闲chunk链表的头部(取出头部的chunk)。这里catomic_compare_and_exchange_val_acq是使用了lock-free的技术实现单向链表删除第一个node的操作,暂时不必关注。
可以注意到,这里是通过fd指针来获取下一个chunk的。所以如果可以控制某个fast bin中chunk的fd指针的值,那么在取出这个chunk后,fd指针指向的内存将会作为下一个将要被取出的内存,再次申请这个大小的内存,也就实现了在任意地方分配chunk的目的。

但是这里需要绕过一个检查:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 存在可以利用的chunk
if (victim != 0) {
// 检查取到的 chunk 大小是否与相应的 fastbin 索引一致。
// 根据取得的 victim ,利用 chunksize 计算其大小。
// 利用fastbin_index 计算 chunk 的索引。
if (__builtin_expect(fastbin_index(chunksize(victim)) != idx, 0)) {
errstr = "malloc(): memory corruption (fast)";
errout:
malloc_printerr(check_action, errstr, chunk2mem(victim), av);
return NULL;
}
...
}

malloc会检查取到的chunk的size是否是符合这个fast bin的,若是不符合则会GG。所以想要在任意地方分配一个chunk,需要先想办法在此处构造合适的size来通过这个检查。
巧妙的是,因为此处没有对内存进行对齐检查,所以可以通过错位的方式来构造出一个假的size出来(详见文末相关题目)

利用前提

  • 存在堆溢出、UAF等可以控制堆块内容(fd指针)的漏洞
  • 漏洞发生于fast chunk
  • 可以在目标位置构造出合适的size来绕过检查

利用过程

  1. 在想要分配的目标内存附近找到或者利用错位构造一个合适的size,用于绕过检查
  2. 释放掉victim(fast chunk)
  3. 通过从上一个chunk溢出或UAf等方式修改victim的fd指针,使fd指针指向构造好size的目标chunk
  4. 通过两次分配,得到目标chunk

题目

文章作者: Hpasserby
文章链接: https://hpasserby.me/post/531412d5.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hpasserby
支付宝赞赏
微信赞赏