堆利用新维度:Large Bin Attack 绕过传统限制的进阶战术
掌握 Large Bin Attack 基础操作后,绝大多数 CTF 选手会默认将其用于修改栈变量以劫持控制流。然而,glibc 内存管理机制中隐藏着更多未被充分探索的攻击面。本文将从实战角度,剖析六种突破传统利用路径的技术思路,帮助读者在 CTF 出题或解题时拓展视野。
1. 从局部到全局:战略重心的迁移
栈变量劫持只是 Large Bin Attack 的起点。真正的价值在于攻击全局性目标,例如 global_max_fast 变量,它控制 ptmalloc 的快速分配阈值。通过将默认值 0x80 修改为 0x7fffffffffffffff,所有内存分配都会转入 fastbin 路径,从而改写后续逻辑:
// 修改前:size > 0x80 的 chunk 进入 small/large bins
malloc(0x90); // 触发 smallbin 分配
// 修改 global_max_fast 后
global_max_fast = 0x7fffffffffffffff;
malloc(0x90); // 现在进入 fastbin 分配
这种技术路线可衍生多种出题变体:
- fastbin dup 增强:扩大 fastbin 范围后,原本只适用于 smallbin 的 UAF 漏洞可转为 fastbin dup。
- 绕过 size 校验:若题目检查分配大小是否在 fastbin 范围内,修改阈值后可突破限制。
- 内存布局异常:强制大块内存走 fastbin 路径,可能导致堆栈混乱,为后续攻击铺路。
注意:glibc 2.35 之后对 global_max_fast 增加了更多完整性检查,利用难度上升。
2. 文件流操纵:精准定位 _IO_list_all
当 FULL RELRO 保护阻挡了传统劫持路径时,文件流利用成为替代方案。Large Bin Attack 可以精确修改 _IO_list_all 指针,为 FSOP(File Stream Oriented Programming)创造机会。关键解决两个难点:
- 如何通过堆布局精准命中
_IO_list_all。 - 如何构造伪造 IO 结构体以实现稳定利用。
典型攻击链如下:
| 步骤 | 操作目标 | 技术实现 |
|---|---|---|
| 1 | 堆布局 | 构建包含目标地址的伪造 chunk |
| 2 | 触发攻击 | 通过 Large Bin Attack 修改 _IO_list_all |
| 3 | 准备结构 | 在可控内存设置伪造 IO_FILE 结构 |
| 4 | 触发 FSOP | 借助 abort 或 fflush 触发链式调用 |
在 CTF 出题中,可设计以下变体:
- 版本适配题:要求选手在不同 glibc 版本下完成利用。
- 结构构造题:仅提供部分内存读写能力,需自行完善 IO_FILE 结构。
- 组合利用题:结合其他漏洞(如 off-by-one)完成完整链。
3. 突破 tcache 封锁:现代 glibc 下的生存术
tcache 机制提高了堆利用门槛,但 Large Bin Attack 仍能通过理解其交互规则找到突破口:
- 优先级利用:当 tcache 链表为空时,分配器会回退到传统 bins。
- 大小阈值控制:tcache 默认缓存
0x400以内 chunk,更大分配走传统路径。 - 数量限制规避:单链表最多 7 个 chunk,超限后回归传统管理。
可设计边界条件:
- 构造大量
0x410大小 chunk,迫使系统使用 large bins。 - 用满 tcache 链表后再触发 Large Bin Attack。
- 利用
realloc特殊行为绕过 tcache 限制。
// 填满 tcache 后回归传统 bins
for (int i = 0; i < 7; i++) {
malloc(0x100); // 填满 tcache[0x100]
}
void *ptr = malloc(0x100); // 现在使用 fast/small bins
free(ptr); // 此释放不进入 tcache
4. 非典型目标:高价值但易忽略的攻击点
除常见全局变量外,以下目标值得关注:
malloc_hook 和 free_hook 的替代目标:在 glibc 2.32 及以上版本中,这些 hook 被移除后,可考虑:
- 修改
mp_.tcache_bins改变 tcache 行为。 - 劫持
pointer_guard影响指针加密。 - 攻击
__malloc_context结构体。
线程本地存储突破点:
- 修改
tcache_perthread_struct中的 counts 数组。 - 操纵
thread_arena分配策略。 - 针对
heap_info结构的关键字段。
动态链接器接口:
_dl_fini中的函数指针数组。link_map结构中的l_addr等字段。_rtld_global中的全局状态。
5. 版本适配:从 glibc 2.27 到 2.35 的攻防演进
不同版本的防护特征对利用影响显著:
| 版本 | 关键变化 | 攻击影响 | 出题建议 |
|---|---|---|---|
| 2.27 | 基础形态 | 无防护 | 适合教学基础原理 |
| 2.29 | 增加 size 检查 | 需要严格对齐 | 可设计绕过检查的题目 |
| 2.32 | 移除 hook | 需要新目标 | 考察替代方案 |
| 2.35 | 增强完整性检查 | 成功率降低 | 适合高难度赛题 |
出题时可利用版本差异:
- 多版本兼容题:提供不同 libc,要求选手自适应。
- 防护绕过题:在严格检查下寻找利用路径。
- 历史漏洞复现:重现特定版本的经典技术。
6. 非常规组合:Large Bin Attack 与其他漏洞的协同
组合利用能放大攻击威力:
与 off-by-one 结合:
- 使用 off-by-one 修改 chunk size。
- 构造 overlapping chunk。
- 通过 Large Bin Attack 扩大攻击效果。
与 UAF 协同:
- 在 UAF 状态触发 Large Bin Attack。
- 使用悬垂指针验证攻击。
- 构建读写原语。
与整数溢出配合:
- 用整数溢出构造异常 size。
- 通过 Large Bin Attack 突破常规限制。
- 实现从任意读到任意写的升级。
在一次获奖竞赛题中,选手将 Large Bin Attack 与 house of apple 结合:先通过堆布局创建特定内存状态,再精确修改 IO 结构体中的 vtable 指针,最终实现无泄漏条件下的 RCE。这种多技术融合的思路,正是未来命制的方向。