Skip to content

house of spirit

复制本地路径 | 在线编辑

一个非常古老的攻击方法了。越古老越简单,所以可以一句话总结:伪造一个 chunk,然后 free 到 fastbin 链表中。

没错,就是这样朴实无华。所以很显然,glibc 现在肯定加了不止一个检查。这里以 how2heap 中 2.41 版本的例子说明。

老套路,由于要 free 到 fastbin,所以先塞满 tcache。然后开始准备 fakechunk,这里就直接结合代码说明怎么构造的。

  1. fakechunk->size 需要构造,这个很显然,想要 free 到对应 fastbin 上,那就写上对应的大小呗。对于 size 上的 FLAG 也有需求,低 3 个 flag 位中:PREV_INUSE 位(最低位)可以随便,但 IS_MMAPPED、NON_MAIN_ARENA 必须是 0。
// 假设我们想 free 到 0x40 的 fastbin 上面
fakechunk[1] = 0x40;
  1. fakechunk 下一个块,即 fakechunk+size 之后的块也有要求。需要它的 size 满足 > 2*SIZE_SZ && < av→system_mem,说实话没太明白这里为什么 glibc 要做这样的检查:
// 之所以是 fakechunk[9],因为 fakechunk->size==0x40,所以下一个块的 size 区域就是 fake_chunk + 0x48
fakechunk[9] = 0x1234
// glibc 中的检查

/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr)(((char *)(p)) + (s)))

chunk_at_offset(p, size) <= CHUNK_HDR_SZ, 0; // x64 上是 16
chunk_at_offset(p, size) >= av->system_mem; // 默认是 128Kb

然后我们就可以 free 这个块,即 free(&fakechunk[2]),之所以是 fakechunk[2],是因为 free 的参数是数据区开头,而不是整体的头部。我们的构造块如下:

+++++++++++++ <-- fakechunk
+           +
+   0x40    +
+++++++++++++ <-- fakechunk[2] (fakechunk->data)
+    fd     +
+           +
+           +
+   .....   +
+           +
+           +
+-----------+
+           +
+  0x1234   +
+++++++++++++

最终 fakechunk 会落入 fastbin 中,我们再先多次 malloc 把 tcache 清空,最后再来一次就得到 fakechunk->data 了。

想一想,对于某个我们想控制的地址 target(这里是 fakechunk->data):

  1. 我们需要能写 target 前面 8byte 的内容(对应于上面的 fakechunk[1]
  2. 我们需要能写 target+control_size 的内容(即下一个 chunk 的 size,对应于上面的 0x1234
  3. target 的地址要是 16 的整数倍,这个不多解释了,基本上这个条件都能满足

最难办的还是第一条,我们想要控制某个地址,必须要控制这个地址前面那一块的内容,这个有点苛刻。

Comments