free源码调试分析
字数 2672 2025-08-29 22:41:02
Glibc堆管理机制深入分析与利用技术
1. main_arena结构概述
main_arena是glibc堆管理中的核心数据结构,负责管理所有非mmap分配的内存块。它包含了多个bin链表头,用于管理不同大小的空闲内存块。
2. free_hook机制分析
2.1 free_hook基本功能
- 在glibc-2.34之前,free函数会首先检查
__free_hook是否存在指针 - 如果存在,则直接跳转到该指针指向的函数执行,并将释放的chunk地址作为第一个参数(rdi)
2.2 利用技术
- 直接getshell:覆盖free_hook为system函数地址,释放包含"/bin/sh"的chunk
- ORW利用:覆盖free_hook为gadget链地址,构造ROP链实现ORW(read/open/write)
2.3 版本差异
- glibc-2.34移除了free_hook机制,直接调用内部free实现
3. tcache机制深入解析
3.1 数据结构
- mp_结构体:存储tcache全局配置信息
- tcache_perthread_struct:
counts:记录每个大小类别的chunk数量entries:每个大小类别的chunk链表头指针tcache_count:单个tcache能容纳的最大chunk数量tcache_bins:tcache支持的最大chunk大小对应的索引
3.2 安全机制演进
- key字段检查(glibc-2.29+):
- 用于检测double free
- 释放时会检查chunk的key字段是否匹配tcache_key
- next指针加密(glibc-2.32+):
- 加密算法:
PROTECT_PTR(pos, ptr) = ((pos) >> 12) ^ (ptr) - 解密算法:
REVEAL_PTR(pos, ptr) = ((pos) >> 12) ^ (ptr) - 第一个chunk的next字段值为
(chunk_addr >> 12)
- 加密算法:
3.3 利用技术
- size字段篡改:
- 修改较小chunk的size字段使其释放时进入较大的tcache链
- 再次申请时可造成堆块重叠(overlapping)
- next指针控制:
- 泄漏tcache_key后可以伪造next指针
- tcache取出时不检查size,可实现任意地址分配
- tcache位置劫持:
- tcache指针存储在TLS段
- 修改该指针可改变tcache位置
- 可实现
tcache_perthread_struct劫持
4. fastbin机制分析
4.1 基本特性
- 当tcache满时,小chunk(通常≤0x80)会进入fastbin
- 采用LIFO策略,新释放的chunk插入链表头部
4.2 安全机制
- double free检查:
- 仅检查链首chunk,可通过
A→B→A顺序释放绕过
- 仅检查链首chunk,可通过
- fd指针加密(glibc-2.32+):
- 加密方式与tcache相同
- 需要泄漏堆地址才能伪造fd指针
4.3 利用技术
- global_max_fast扩展:
- 修改
global_max_fast可扩大fastbin处理范围 - 例:设为0x100可使0xa0大小chunk进入fastbin
- 修改
- 任意地址分配:
- 泄漏堆基址后计算加密密钥
- 伪造加密后的fd指针实现任意地址分配
5. unlink与合并机制
5.1 合并条件
- tcache和fastbin中的chunk不会被合并
- 只有释放的chunk相邻空闲chunk时才会触发合并
5.2 安全检查演进
- glibc-2.28及之前:
- 仅检查待合并chunk的size与prev_size是否一致
- glibc-2.29+:
- 增加对相邻chunk的prev_size检查
- 必须满足:
chunk_size == next_chunk->prev_size
5.3 利用技术
- 向前合并利用:
- 伪造prev_inuse和prev_size字段
- 构造假chunk通过unlink检查
- 可实现堆块重叠
- prev_size天然填充:
- 先释放chunk使其size填入相邻chunk的prev_size
- 再申请回来保留prev_size值
- 适用于无法直接控制prev_size但能控制prev_inuse的情况
6. top chunk处理
- 当释放的chunk与top chunk相邻时,直接合并到top chunk
- 计算新top chunk大小并更新main_arena中的top指针
7. 实际利用案例
7.1 例题分析
[NSSRound#4 SWPU]做道堆题休息一下吧
利用链:
- 通过unlink合并制造overlapping
- 申请chunk到IO_2_1_stderr结构体
- 修改IO结构体实现堆迁移
- 覆盖top chunk的size触发IO链
7.2 关键点
- 需要精确控制堆布局
- 利用IO_FILE结构体进行利用
- 结合多种技术完成完整利用链
8. 版本差异总结
| 特性 | glibc-2.28- | glibc-2.29 | glibc-2.32+ |
|---|---|---|---|
| tcache double free检查 | 无 | 增加key字段检查 | 保持 |
| next指针加密 | 无 | 无 | 增加加密 |
| fastbin fd加密 | 无 | 无 | 增加加密 |
| unlink检查 | 宽松 | 严格size检查 | 保持严格检查 |
9. 防御绕过策略
- 加密指针绕过:
- 泄漏堆地址计算加密密钥
- 构造正确的加密指针
- 检查绕过:
- 精确伪造chunk元数据
- 利用天然填充的prev_size
- 版本适配:
- 针对不同glibc版本采用不同利用技术
- 检测版本特性动态调整利用方式
10. 高级利用技巧
- 多技术组合:
- 结合tcache/fastbin/unlink等多种技术
- 分阶段完成复杂利用
- IO_FILE利用:
- 通过堆重叠修改IO结构体
- 触发IO流实现控制流劫持
- 堆风水:
- 精确控制堆布局
- 利用分配/释放顺序制造有利条件
通过深入理解glibc堆管理机制的内部实现和版本差异,可以针对不同环境构造有效的利用方案。关键在于掌握各数据结构的组织方式和安全检查机制,从而找到绕过防御的突破口。