house of rabbit
主要有两种攻击方式
第一种攻击方式是利用malloc_consolidate时缺少对fast bin中chunk的size的检查,通过修改fast bin中的chunk的size造成overlap chunk,然后触发malloc_consolidate 使fast bin清空,从而分配出重叠的堆块。
第二种攻击方式是利用malloc_consolidate将fast bin放入unsorted bin和从进 large bin 以及 large bin 切割 chunk 时对 size 检查不严格从而可以不用严格保证 size 正确的情况下将 fake chunk 申请出来,甚至可以任意地址 malloc 。
首先,要想任意地址 malloc 需要让伪造的 chunk 进入 large bin 的最后一个 bin 那么 size 字段至少为 0x80000 。然而 system_mem 初始默认为 0x21000,因此伪造的 chunk 从 unsorted bin 进入 large bin 时会通不过下面的检查:
| 1 2 3 4 |
if (__builtin_expect (victim->size <= 2 * SIZE_SZ, 0)| __builtin_expect (victim->size > av->system_mem, 0))malloc_printerr (check_action, "malloc(): memory corruption"``,chunk2mem (victim), av); |
因此需要想办法增大 system_mem 。
其中一种办法是通过申请和释放大内存增大 mmap_threshold 然后 sbrk 增大 system_mem 。
当申请一块大内存时如果 ptmalloc 找不到合适的内存会调用 sysmalloc 函数向系统获取内存。
就 main_arena 来说,当调用 sysmalloc 时,ptmalloc 获取内存有直接 mmap 和 brk 扩展 heap 区域两种方式。这两种方式的选择由 mmap_threshold 决定。
| 1 2 3 |
if (av == NULL| ((unsigned long``) (nb) >= (unsigned long``) (mp_.mmap_threshold)&& (mp_.n_mmaps < mp_.n_mmaps_max))) |
只有当所需内存小于 mmap_threshold 时才会调用 brk 扩展内存,system_mem 也才会增加。
| 1 2 3 4 5 |
if (brk != (``char *) (MORECORE_FAILURE)){if (mp_.sbrk_base == 0)mp_.sbrk_base = brk;av->system_mem += size; |
因此需要先想办法增大 mmap_threshold 。
当释放一块 ptmalloc 通过 mmap 得到的内存时会将 mmap_threshold 与 chunk 的 size 取最值,因此可以首先通过申请和释放一块大内存将 mmap_threshold 增大。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
if (chunk_is_mmapped (p)) /* release mmapped memory. */{/* see if the dynamic brk/mmap threshold needs adjusting */if (!mp_.no_dyn_threshold&& p->size > mp_.mmap_threshold&& p->size <= DEFAULT_MMAP_THRESHOLD_MAX){mp_.mmap_threshold = chunksize (p);mp_.trim_threshold = 2 * mp_.mmap_threshold;LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,mp_.mmap_threshold, mp_.trim_threshold);}munmap_chunk (p);return``;} |
之后再次申请一块大内存来增大 system_mem 。
将 fast bin 中的 chunk 的 fd 指向 fake chunk。
将 fake chunk 的 size 置1,是为了避免 malloc_consolidate 时与后面的 chunk 合并时 unlink 出错。因为 size 为 1 时查找的下一个地址相邻的 chunk 是自身。



