how2heap
[TOC]
how2heap
实验环境
操作系统:WSL2 Ubuntu 22.04
glibc 版本:2.31
实验程序:fastbin_dup fastbin_dup_into_stack unsorted_bin_attack tcache_dup tcache_poisoning
实验目标:基础结构理解 + 简单利用
fastbin_dup
源码解析
1 |
|
首先申请 8 个容纳 8 字节的 chunk(大小为 0x20),然后释放了 7 个,刚好填满 0x20 这条 tcache bin。
然后申请 3 个 0x20 的 chunk,在 glibc2.31 版本的
__libc_calloc()
中,不会尝试从 tcache 中分配 chunk。所以还是从 top chunk 中分配。然后进行三次 free,分别是 a,b,a。之所以将两次 free(a)间隔开来,是因为_int_free() 会检查前后两个 chunk 是否相同。此时 fastbin 结构是
fastbinsY[0x20] -> a -> b -> a
fastbin 采用 FIFO 策略。第一次 calloc 分配到是 a,第二次分配到是 b,第三次分配到是 a。所以在程序中 a 和 c 存储的地址是相同的,修改 a 地址的内容,也会影响 c,从而实现利用。
调试过程与原理解析
序号对应上面的分析步骤。
查看 tcache bin
可以看到 tcache 被填了 7 个。
注意链表是通过 fd 区域链接在一起。
查看堆结构。
可以看到 top chunk 地址为
0x555555559390
,可以与下面的地址进行比较。同时可以看到每个 chunk 大小为 0x20 大小。查看 top chunk 地址
可以看到又分配了三个

注意在 tcache 中,prev_inuse 标记位不会被清除和 fastbin 一样。注意
Top chunk 地址从 0x555555559390
增长到了
0x5555555593f0
,刚好增长了 0x60.
fastbin 结构变化
第一次 free(a)之前。
第一次 free(a)之后。由于 tcachebin[0x20]的已经满了,只能放在 fastbin 中。
free(b) 之后。继续存入 fastbin 的栈顶。同时可以发现 fastbin 中的 fd 指向的是下一个 chunk 的 prev_size 的位置。
第二次 free(a)。
可以看到
fastbin[0x20]->a->b->a
重新分配,得到两个相同地址。
执行过程

tcache_house_of_spirit
源码解析
解析在注释中
1 |
|
调试过程与原理解析
填满 tcache
在栈上做一个 fake chunk
设置第一个 chunk 的 size 字段为 0x40,下图红框是 fake_chunks 的存储的位置(设置了 0x10 对齐)。
设置第二个 chunk 的 size 字段。
伪造 chunk。
回收到 fastbin 中。注意要使用
fake_chunks[2]
的地址,因为 free 接收用户数据的地址。然后再使用 calloc 分配。可以在该地址中写入我们的数据,这个地址可以根据攻击位置设置。
执行过程

可以看到 malloc 得到地址被设置成我们想要的。
overlapping_chunks
源码分析
1 | /* |
调试过程
查看三个 chunk 在堆中的分布
第一个 0x80 ,赋值为 0x31;第二个 0x500,赋值为 0x32;第三个为 0x80,赋值为 0x33。
伪造 chunk。
覆盖 size 区域。
free 之前的 top chunk。
先 free,这里不会放到 bin 中,因为它和 top chunk 相邻,会被 top chunk 合并。
通过 malloc 获得与其他块重叠的块。top chunk 变回来,和 free 之前一样。
重叠的块
这里刚好是全覆盖(我将代码中 80 改为了 0x80)。
执行过程

p3 和 p4 结尾地址相同。

可以通过修改 p4 来修改 p3。
总结
通过实践对堆的结构有了更深的了解,学会了利用堆来实现溢出,doublefree 等攻击。