Skip to content

fastbin dup consolidate

复制本地路径 | 在线编辑

利用了 malloc_consolidate 的机制。

要求:可以 Double Free
结果:Double Reference(两个指针指向同一片内存),可用于后续如 tcache poisoning 等攻击操作

原理说明

使用 how2heap 的例子,首先老套路,申请多个块,然后释放 7 次塞满 tcache,然后释放 1 次落入到了 fastbin 中。

for(int i = 0; i < 7; i++)
    ptr[i] = malloc(0x40);
void* p1 = malloc(0x40);

for(int i = 0; i < 7; i++)
    free(ptr[i]);
free(p1);
tcache <- ptr6 <- ... <- ptr0
fastbin -> p1

然后申请一个大块(>=400),此时会触发 malloc_consolidate,这个机制把 fastbin 和邻居合并,并且尽可能和 Top chunk 合并,下面这条语句:

  • fastbin 只有 p1,而它就在 top chunk 旁,所以会融合进 top chunk
  • malloc 会从 top chunk 中分割出 0x400 的块给 p2

void* p2 = malloc(0x400);
// p1 == p2

第三步,也是程序漏洞的所在,即有一个可以 Double free 的指针 p1,我们继续 free(p1),最终这个蓝色块会落入 tcache 中(0x400 在 tcache 范围内)。

free(p1);

第四步,此时我们再申请这个大小的块,很显然,从 tcache 中得到了这个蓝色块。此时 p3==p2

p3 = malloc(0x400);

现在我们就有两个指针指向了同一片 tcache 大小的内存。后续的攻击就是用其他的手段,比如:

free(p3);
p2[0] = want_addr; // 修改 next 指针

malloc(0x400);
victim = malloc(0x400); // 从 tcache 中拿到控制块

这里举例是修改 next 指针,但由于 safe-linking 的存在(即存储的不是 next,而是 next 和块地址异或的值),所以我们需要知道 heap 地址才行。总之我们是有了 Double Refrence,至于攻击,还需要其他辅助。

Double Free --> fastbin dup consolidate --> Double Refrence 

思路一:Double Refrence + 泄露 heap 地址 --> tcache poisoning 成功修改 next 指针
思路二:...

其他说明

malloc_consolidate 的触发条件如下,上面的原理利用了第一条。

As of glibc version 2.35 it is called only in the following five places:

  1. _int_malloc: A large sized chunk is being allocated (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3965)
  2. _int_malloc: No bins were found for a chunk and top is too small (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L4394)
  3. _int_free: If the chunk size is >= FASTBIN_CONSOLIDATION_THRESHOLD (65536) (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L4674)
  4. mtrim: Always (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L5041)
  5. __libc_mallopt: Always (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L5463)

Comments