Dance In Heap(三):一些堆利用的方法(中)

时间:2022-04-28
本文章向大家介绍Dance In Heap(三):一些堆利用的方法(中),主要内容包括0x01 fastbin attack、0x02 overlapping chunk 1、0x03 overlapping chunk 2、0x04 小结、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

0x00 前面的话

在前一篇堆的利用方法里面,我们简单的提了一下UAF,并主要对从 bin 中释放 chunk 的操作,即 unlink 宏、unsortedbin attack,进行了利用。那么在本篇中,我们主要讨论如何将对一个对一个chunk进行复用来进行某种攻击。

在这里面我们要当心,chunk size的计算是个需要小心的地方,因为这里包括了 prev_size的复用,以及根据不同系统考虑的对齐情况,还有 chunk 的size位表示的是包括chunk header在内的size,而实际可用的size与此不同,它是减去chunk header后的大小。

本篇文章目录

0x01 fastbin attack
0x02 overlapping chunk 1
0x03 overlapping chunk 2
0x04 小结

0x01 fastbin attack

还记不记得我们在第一篇中那个介绍 fastbin 中 dobule free的例子

#include <stdio.h>
#include <stdlib.h>
int main() {
    char *a=malloc(24);
    char *b=malloc(24);
    free(a);
    free(b);
    free(a);
}

这个运行是没有问题的,但是想象一下,这样做之后,现在的 fastbin 中是什么样子

  -------     -------     -------     -------    -------
 | 头结点 |-> |   a   |-> |   b   |-> |   a   |->|  null |
  -------     -------     -------     -------    -------

其中的指向关系由chunk的 fd 指针标识。此时我们再从 fastbin中 malloc 出一个 chunk

c = malloc(24);

此时的 fastbin

  -------     -------     -------     -------
 | 头结点 |-> |   b   |-> |   a   |-> |  null |
  -------     -------     -------     -------

现在我们得到了一个chunk,并且这个 chunk 同时在 fastbin中也存在,那么此时如果我们修改 c 的 fd 指针位置为任意地址,那么 fastbin 中 a 的指向也会发生改变

  -------     -------     -------     -------
 | 头结点 |-> |   b   |-> |   a   |-> |任意地址|
  -------     -------     -------     -------

我们之后连续 malloc 两次

malloc(24);
malloc(24);

现在的 fastbin

  -------     -------
 | 头结点 |-> |任意地址|
  -------     -------

那我们再次 malloc 时,就可以在任意地址创建一个 chunk 了,但是要注意的是,我们在之前提到过,从 fastbin 中取出 chunk 的时候会对 chunk 的size 做检查,也就是这个任意位置的 chunk 的 size 位必须构造。我们可以在栈中构造

int stack = 0x30 // 24 + header = 0x28 ,0x10 对齐后 0x30

这个变量作为size位,我们可以将任意地址填充为 &stack - 8,然后 malloc 之后会返回这个地址的 chunk,在栈中变量无法溢出时,我们可以向 chunk 里面写入数据来造成栈溢出。

d = malloc(24);
d[20] = 0xdeadbeef //控制rip

fastbin attack 中令人兴奋的一点是,它不需要对 chunk 进行溢出就可以进行攻击,这在一些对输入长度检查严格的地方可以得到奇妙的应用。

0x02 overlapping chunk 1

幸运的是,并不是所有的程序都会对输入长度有严格的约束,当我们能够溢出到下一个 chunk 时,我们可以修改它的 size 位来造成 chunk 的覆盖。

首先,我们创建三个chunk,考虑 prev_size 的复用和 0x10字节对齐,我们将 malloc(0x100-8), 系统会给我们(0x100-8)+0x10-0x8,即0x100(0x10对齐)的空间,实际可用的空间正好是0x100-8,并没有多分配,而要是malloc(0x100)的话,你会看到实际可用的空间是0x108(这个不是必须的,只是向大家强调一下 chunk 大小的计算)

a = malloc(0x100-8);
b = malloc(0x100-8);
c = malloc(0x100-8);

然后 free 掉 b,b就会放到 unsortedbin 中 ,这个bin只有一个链表,并不对size进行区分,所以我们可以放入0x100的chunk,修改为size为0x180后就可以拿出0x180的chunk

free(b);

然后我们利用a溢出到b的size位

*(a+0xf8) = 0x181 // 0x01标识a为inuse状态

现在我们malloc一个0x180的 chunk,系统就会将从b开始的0x180大小的空间返还,这其中包括c

d = malloc(0x180-8);

ok,现在我们就可以更改利用d更改c中的内容,如果c中包含某个函数指针,我们也可以去改变它,当然

0x03 overlapping chunk 2

我们在前面先释放再修改size来获得了一个覆盖掉后面chunk 的 chunk,那么如果我们先修改size为一个大值,然后free会怎样呢?

首先我们创建4个chunk

a = malloc(0x100-8);
b = malloc(0x100-8);
c = malloc(0x100-8);
d = malloc(0x100-8);// 第四个为了防止被top chunk 合并,以及应对 free的检查

我们通过a溢出到b的size

*(a+0xf8) = 0x201 // 0x1为inuse标识

我们这里讲b的size扩大到了c,由于free时需要检查下一个chunk的size,所以我们预留了d,并且防止free后直接与top chunk合并,之后我们free掉b,然后再次malloc就又包括了c

free(p);
e = malloc(0x200-8);

然后就可以可以像0x02一样去利用。

0x04 小结

除了这些之外,我们还可以根据不同的条件去构造不同的chunk复用,像是只利用一个字节溢出(off-by-one)来使chunk size减小,以此来构造的poison_null_byte 漏洞等等。了解chunk复用的原理,就是去改变 size 位来使系统对错误的长度进行 malloc、free,这就是我们的目的。