malloc源码调试(二)
字数 2654 2025-09-01 11:26:17
malloc源码调试与利用技术详解
1. unsorted bin处理机制
1.1 last_remainder处理
当malloc请求无法通过fastbin或small bin满足时,会进入unsorted bin处理流程:
-
首先检查last_remainder chunk:
- 必须满足四个条件:
- 请求大小在small bin范围内
- last_remainder存在且足够大
- last_remainder是unsorted bin中唯一的chunk
- 切割后剩余部分足够形成新的chunk
- 必须满足四个条件:
-
切割过程:
- 计算新的remainder chunk的size和地址
- 更新unsorted bin链首
- 为新remainder chunk设置fd和bk指针
- 更新申请chunk和remainder chunk的size
- 更新高地址相邻chunk的prev_size
利用点:切割后申请到的chunk上会残留main_arena地址,可用于泄漏libc基址(无UAF时常用技巧)
1.2 unsorted bin chunk移出处理
当不满足last_remainder条件时,会遍历unsorted bin中的chunk:
-
检查机制:
- 双向链表完整性检查
- prev_size与prev_inuse位一致性检查
-
利用技术(off_by_one):
- 任意修改size值可导致overlapping
- 示例步骤:
- 构造堆布局,确保unsorted bin中的chunk被last_remainder标记
- 伪造size改大,并设置适当的prev_size和chunksize
- 申请相同size的chunk,造成overlapping
-
移出条件:
- 当chunk size与请求大小完全匹配时:
- 标记为已使用(设置高地址chunk的prev_inuse=1)
- 若tcache未满则放入tcache
- 不匹配时移入small bin或large bin
- 当chunk size与请求大小完全匹配时:
2. small bin与large bin处理
2.1 small bin处理
-
移入过程:
- 从unsorted bin中取出chunk
- 在main_arena中找到对应size的small bin链
- 插入到small bin双向链表尾部
-
检查机制:
- 双向链表完整性检查
2.2 large bin处理与large bin attack
large bin特性:
- 每个large bin链包含一定size范围的chunk
- 使用fd/bk_nextsize维护跳表结构,保证有序性
large bin attack利用(glibc-2.30+):
-
准备条件:
- 在large bin中放置一个大chunk
- 在unsorted bin中放置一个较小chunk(同large bin范围)
-
攻击步骤(第三种情况利用):
- 申请更大size触发unsorted bin chunk移入large bin
- 绕过检查:
- 高版本对第四种情况有跳表检查
- 第三种情况无检查
- 关键赋值:
- victim->bk_nextsize = fwd->fd->bk_nextsize
- fwd->fd->bk_nextsize = victim
- 效果:
- 可在target_addr+0x20处写入堆地址
- 多次利用只需修改large bin中最大chunk的bk_nextsize
3. binmap机制与搜索算法
3.1 binmap结构
- main_arena中bins数组:
- 前2个为unsorted bin
- 随后62×2个small bin
- 最后63×2个large bin
- binmap数组:
- 4个无符号整型(128位)
- 标记125个bin链是否非空
3.2 binmap维护
- 当chunk从unsorted bin移入small/large bin时更新
- 示例:
- 0x20 small bin对应binmap[0]的第3位
- 0xb0 small bin对应binmap[0]的更高位
3.3 bin搜索算法
- 计算起始index
- 获取binmap标记:
- 按bit位从小到大搜索
- 找到第一个满足size≥请求的bin链
- 检查bin链非空
- unlink取出chunk进行切割
4. top chunk处理与利用
4.1 常规top chunk切割
- 当其他bin无法满足时使用top chunk
- 检查机制:
- size ≥ 请求大小 + MINSIZE
- prev_inuse=1
- 地址页对齐
4.2 House of Force(glibc-2.29前)
- 利用条件:
- 可修改top chunk的size
- 无
size > av->system_mem检查
- 攻击步骤:
- 改大top chunk size
- 计算到目标地址的偏移
- 申请特定大小使top延伸至目标地址
- 下次分配即可在目标地址创建chunk
4.3 sysmalloc扩容机制
当top chunk不足时:
4.3.1 mmap分配
- 条件:
- 请求大小 > 0x2000
- mmap计数 < 最大值
- 特点:
- 不与主分配区连续
- 不受main_arena管理
4.3.2 brk扩展(主分配区)
- 计算扩展大小:
- nb + top_pad(128K) + MINSIZE对齐
- 系统调用sbrk分配
- 处理连续性:
- 若地址不连续可能二次扩容
- 设置"栅栏"chunk防止合并
- 释放原top chunk到unsorted bin
- 从新top切割请求chunk
关键点:
- 伪造size可能导致非连续扩展
- 栅栏设置防止free时错误合并
5. 关键检查与绕过总结
-
unsorted bin检查:
- 双向链表完整性(fd/bk)
- prev_size与prev_inuse一致性
-
large bin检查:
- 跳表完整性(2.30+对部分情况)
- 解链时对非跳表首项不检查fd_nextsize
-
top chunk检查:
- size ≤ system_mem(2.29+)
- prev_inuse=1
- 地址页对齐
-
通用绕过策略:
- 精心构造fake size和prev_size
- 利用不检查的代码路径(如large bin第三种情况)
- 控制相邻chunk的元数据
以上内容涵盖了malloc源码调试中的核心处理流程和关键利用技术,包括各种bin的处理机制、安全检查及绕过方法,以及top chunk的特殊处理逻辑。