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 利用技术

  1. 直接getshell:覆盖free_hook为system函数地址,释放包含"/bin/sh"的chunk
  2. ORW利用:覆盖free_hook为gadget链地址,构造ROP链实现ORW(read/open/write)

2.3 版本差异

  • glibc-2.34移除了free_hook机制,直接调用内部free实现

3. tcache机制深入解析

3.1 数据结构

  1. mp_结构体:存储tcache全局配置信息
  2. tcache_perthread_struct
    • counts:记录每个大小类别的chunk数量
    • entries:每个大小类别的chunk链表头指针
    • tcache_count:单个tcache能容纳的最大chunk数量
    • tcache_bins:tcache支持的最大chunk大小对应的索引

3.2 安全机制演进

  1. key字段检查(glibc-2.29+):
    • 用于检测double free
    • 释放时会检查chunk的key字段是否匹配tcache_key
  2. 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 利用技术

  1. size字段篡改
    • 修改较小chunk的size字段使其释放时进入较大的tcache链
    • 再次申请时可造成堆块重叠(overlapping)
  2. next指针控制
    • 泄漏tcache_key后可以伪造next指针
    • tcache取出时不检查size,可实现任意地址分配
  3. tcache位置劫持
    • tcache指针存储在TLS段
    • 修改该指针可改变tcache位置
    • 可实现tcache_perthread_struct劫持

4. fastbin机制分析

4.1 基本特性

  • 当tcache满时,小chunk(通常≤0x80)会进入fastbin
  • 采用LIFO策略,新释放的chunk插入链表头部

4.2 安全机制

  1. double free检查
    • 仅检查链首chunk,可通过A→B→A顺序释放绕过
  2. fd指针加密(glibc-2.32+):
    • 加密方式与tcache相同
    • 需要泄漏堆地址才能伪造fd指针

4.3 利用技术

  1. global_max_fast扩展
    • 修改global_max_fast可扩大fastbin处理范围
    • 例:设为0x100可使0xa0大小chunk进入fastbin
  2. 任意地址分配
    • 泄漏堆基址后计算加密密钥
    • 伪造加密后的fd指针实现任意地址分配

5. unlink与合并机制

5.1 合并条件

  • tcache和fastbin中的chunk不会被合并
  • 只有释放的chunk相邻空闲chunk时才会触发合并

5.2 安全检查演进

  1. glibc-2.28及之前
    • 仅检查待合并chunk的size与prev_size是否一致
  2. glibc-2.29+
    • 增加对相邻chunk的prev_size检查
    • 必须满足:chunk_size == next_chunk->prev_size

5.3 利用技术

  1. 向前合并利用
    • 伪造prev_inuse和prev_size字段
    • 构造假chunk通过unlink检查
    • 可实现堆块重叠
  2. 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]做道堆题休息一下吧

利用链

  1. 通过unlink合并制造overlapping
  2. 申请chunk到IO_2_1_stderr结构体
  3. 修改IO结构体实现堆迁移
  4. 覆盖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. 防御绕过策略

  1. 加密指针绕过
    • 泄漏堆地址计算加密密钥
    • 构造正确的加密指针
  2. 检查绕过
    • 精确伪造chunk元数据
    • 利用天然填充的prev_size
  3. 版本适配
    • 针对不同glibc版本采用不同利用技术
    • 检测版本特性动态调整利用方式

10. 高级利用技巧

  1. 多技术组合
    • 结合tcache/fastbin/unlink等多种技术
    • 分阶段完成复杂利用
  2. IO_FILE利用
    • 通过堆重叠修改IO结构体
    • 触发IO流实现控制流劫持
  3. 堆风水
    • 精确控制堆布局
    • 利用分配/释放顺序制造有利条件

通过深入理解glibc堆管理机制的内部实现和版本差异,可以针对不同环境构造有效的利用方案。关键在于掌握各数据结构的组织方式和安全检查机制,从而找到绕过防御的突破口。

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 顺序释放绕过 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堆管理机制的内部实现和版本差异,可以针对不同环境构造有效的利用方案。关键在于掌握各数据结构的组织方式和安全检查机制,从而找到绕过防御的突破口。