house of pig与house of pig orw
字数 2674 2025-08-20 18:17:53

House of Pig 与 House of Pig ORW 利用技术详解

1. 技术概述

House of Pig 是一种结合了多种堆利用技术的攻击方法,主要利用 _IO_str_overflow 函数中的 malloc、memcpy 和 free 操作链,通过伪造 FILE 结构体实现任意代码执行。当系统调用被限制时,可以演变为 House of Pig ORW 技术实现绕过。

2. 核心利用点

2.1 _IO_str_overflow 利用

_IO_str_overflow 函数中存在以下关键操作序列:

old_blen = _IO_blen(fp);
new_size = 2 * old_blen + 0x64;
new_buf = malloc(new_size);
memcpy(new_buf, old_buf, old_blen);
free(old_buf);

通过精心构造的 FILE 结构体,可以控制:

  1. malloc 的大小和返回地址
  2. memcpy 的源地址和目标地址
  3. free 的参数

2.2 _IO_str_jumps 表

_IO_str_jumps 是 GLIBC 中定义的一个跳转表,包含 _IO_str_overflow 等函数的指针。通过将 FILE 结构体的 vtable 指向 _IO_str_jumps,可以劫持程序执行流。

3. 利用条件

  1. 能够泄露堆和 libc 地址
  2. 能够进行 largebin attack
  3. 能够伪造 FILE 结构体
  4. 能够触发 exit 或 flush 操作

4. 完整利用流程

4.1 House of Pig 标准流程

  1. 准备阶段

    • 布置 tcache 和 smallbin 中的 chunk
    • 使用 largebin attack 泄露 libc 和堆地址
  2. largebin attack

    • 第一次攻击:向 __free_hook-0x8 写入堆地址
    • 第二次攻击:向 _IO_list_all 写入堆地址
  3. tcache stashing unlink attack

    • __free_hook-0x10 链入 tcache
    • 通过修改 smallbin 的 bk 指针实现
  4. 伪造 FILE 结构体

    • 设置 _IO_write_ptr > _IO_write_base
    • 设置 _IO_buf_base_IO_buf_end 控制 malloc 大小
    • vtable 指向 _IO_str_jumps
  5. 触发利用

    • 通过 exit 或 flush 触发 _IO_str_overflow
    • 最终实现 system("/bin/sh") 调用

4.2 House of Pig ORW 流程

当 system 被禁用时,利用 _IO_str_overflow 的特殊指令实现 ORW:

  1. 利用指令

    • mov rdx,QWORD PTR [rdi+0x28]:rdi 指向伪造的 FILE 结构体
  2. 具体步骤

    • 劫持 stderr->_chain 为堆地址 ck0
    • 劫持 global_max_fast 或 tcache 管理结构为堆地址 ck1
    • 设置 tcache 使得 malloc 返回 __malloc_hook
    • 构造 FILE 结构体使 rdi+0x28 指向伪造的 SROP frame
    • 通过 exit 触发两次 _IO_str_overflow
      • 第一次设置 __malloc_hook 为 setcontext+61
      • 第二次触发 SROP 执行 ORW

5. 关键数据结构构造

5.1 伪造的 FILE 结构体

fake_IO_FILE = 2 * p64(0)  # _flags and _IO_read_ptr
fake_IO_FILE += p64(1)      # _IO_write_base = 1
fake_IO_FILE += p64(0x1000) # _IO_write_ptr = 0x1000
fake_IO_FILE += p64(0)      # _IO_write_end = 0
fake_IO_FILE += p64(heap_base + 0x148a0) # _IO_buf_base
fake_IO_FILE += p64(heap_base + 0x148b8) # _IO_buf_end
fake_IO_FILE = fake_IO_FILE.ljust(0xb0, b'\x00')
fake_IO_FILE += p64(0)      # _mode = 0
fake_IO_FILE = fake_IO_FILE.ljust(0xc8, b'\x00')
fake_IO_FILE += p64(IO_str_vtable) # vtable

5.2 内存布局要求

  1. _IO_write_ptr > _IO_write_base:确保进入 _IO_str_overflow 的利用路径
  2. _IO_buf_end - _IO_buf_base:控制 malloc 的大小
  3. _IO_buf_base:通常设置为包含 "/bin/sh" 的地址

6. 相关地址获取

6.1 关键符号地址

# libc 符号
libc_base = leak_address - 0x1ebfe0
IO_list_all = libc_base + libc.sym['_IO_list_all']
IO_str_vtable = libc_base + 0x1ED560
system_addr = libc_base + libc.sym['system']
free_hook = libc_base + libc.sym['__free_hook']

# 堆地址
heap_base = leak_address - 0x13940

6.2 偏移说明

  • _IO_str_jumps 通常位于 libc 的 data 段,偏移固定
  • _IO_list_all 是全局变量,指向链表头
  • __free_hook 是最后 free 时调用的函数指针

7. 防御绕过技巧

  1. 检查绕过

    • largebin attack 需要绕过完整性检查
    • tcache stashing 需要确保目标地址可写
  2. 限制绕过

    • 当存在写入限制时,利用不同角色的部分写入能力组合完成利用
    • 使用 SROP 技术绕过系统调用限制
  3. 稳定性提升

    • 在修改关键指针后修复相关结构
    • 确保各 bin 状态符合预期

8. 实际应用示例

8.1 例题分析

题目特点:

  • C++ 实现,堆管理结构存储在栈上
  • 不同角色有不同写入权限:
    • A:控制 fd/bk
    • B:控制 fd_nextsize/bk_nextsize
    • C:控制其他部分
  • 通过 change role 时的拷贝不完全漏洞实现 UAF

8.2 利用脚本关键部分

# largebin attack 修改 __free_hook-8
Edit(8, p64(0) + p64(free_hook-0x28) + b'\n')

# tcache stashing unlink attack
payload = b'A'*0x50 + p64(heap_base+0x12280) + p64(free_hook-0x20)
Edit(8, payload + b'\n')

# 伪造 FILE 结构体
fake_IO_FILE = 2*p64(0)
fake_IO_FILE += p64(1)  # _IO_write_base
fake_IO_FILE += p64(0x1000)  # _IO_write_ptr
[...]

9. 调试技巧

  1. 关键断点:

    • _IO_str_overflow 函数入口
    • malloc/memcpy/free 调用处
    • exit 函数调用处
  2. 内存检查:

    • 验证 FILE 结构体伪造是否正确
    • 检查各 bin 状态是否符合预期
    • 确认 hook 是否被正确覆盖
  3. 错误处理:

    • 修复被破坏的堆结构
    • 调整偏移计算
    • 验证指针有效性

10. 扩展技术

10.1 其他 IO 函数利用

除了 _IO_str_overflow,还可以研究:

  • _IO_file_overflow
  • _IO_wstr_overflow
  • _IO_switch_to_get_mode

10.2 结合其他攻击技术

  1. 与 FSOP 结合

    • 利用更广泛的 FILE 操作函数
    • 通过多个 FILE 结构体形成利用链
  2. 与堆风水结合

    • 精确控制堆布局
    • 提高利用稳定性
  3. 与 SROP 结合

    • 实现更复杂的利用链
    • 绕过更多保护机制

11. 防护措施

  1. 检测措施

    • 监控 _IO_list_all 等关键全局变量
    • 检查 FILE 结构体的 vtable 指针
  2. 缓解措施

    • 启用 vtable 验证
    • 随机化关键数据结构地址
    • 加强堆完整性检查
  3. 开发建议

    • 避免使用不安全的 IO 操作
    • 及时更新 libc 版本
    • 实施严格的输入验证

12. 总结

House of Pig 及其变种是高级堆利用技术的代表,结合了多种利用方法,展示了现代漏洞利用的复杂性。理解这些技术不仅有助于漏洞挖掘和利用开发,也能帮助设计更好的防护机制。掌握这些技术需要深入理解 glibc 的堆管理和 IO 子系统实现细节。

House of Pig 与 House of Pig ORW 利用技术详解 1. 技术概述 House of Pig 是一种结合了多种堆利用技术的攻击方法,主要利用 _IO_str_overflow 函数中的 malloc、memcpy 和 free 操作链,通过伪造 FILE 结构体实现任意代码执行。当系统调用被限制时,可以演变为 House of Pig ORW 技术实现绕过。 2. 核心利用点 2.1 _ IO_ str_ overflow 利用 _IO_str_overflow 函数中存在以下关键操作序列: 通过精心构造的 FILE 结构体,可以控制: malloc 的大小和返回地址 memcpy 的源地址和目标地址 free 的参数 2.2 _ IO_ str_ jumps 表 _IO_str_jumps 是 GLIBC 中定义的一个跳转表,包含 _IO_str_overflow 等函数的指针。通过将 FILE 结构体的 vtable 指向 _IO_str_jumps ,可以劫持程序执行流。 3. 利用条件 能够泄露堆和 libc 地址 能够进行 largebin attack 能够伪造 FILE 结构体 能够触发 exit 或 flush 操作 4. 完整利用流程 4.1 House of Pig 标准流程 准备阶段 : 布置 tcache 和 smallbin 中的 chunk 使用 largebin attack 泄露 libc 和堆地址 largebin attack : 第一次攻击:向 __free_hook-0x8 写入堆地址 第二次攻击:向 _IO_list_all 写入堆地址 tcache stashing unlink attack : 将 __free_hook-0x10 链入 tcache 通过修改 smallbin 的 bk 指针实现 伪造 FILE 结构体 : 设置 _IO_write_ptr > _IO_write_base 设置 _IO_buf_base 和 _IO_buf_end 控制 malloc 大小 vtable 指向 _IO_str_jumps 触发利用 : 通过 exit 或 flush 触发 _IO_str_overflow 最终实现 system("/bin/sh") 调用 4.2 House of Pig ORW 流程 当 system 被禁用时,利用 _IO_str_overflow 的特殊指令实现 ORW: 利用指令 : mov rdx,QWORD PTR [rdi+0x28] :rdi 指向伪造的 FILE 结构体 具体步骤 : 劫持 stderr->_chain 为堆地址 ck0 劫持 global_max_fast 或 tcache 管理结构为堆地址 ck1 设置 tcache 使得 malloc 返回 __malloc_hook 构造 FILE 结构体使 rdi+0x28 指向伪造的 SROP frame 通过 exit 触发两次 _IO_str_overflow : 第一次设置 __malloc_hook 为 setcontext+61 第二次触发 SROP 执行 ORW 5. 关键数据结构构造 5.1 伪造的 FILE 结构体 5.2 内存布局要求 _IO_write_ptr > _IO_write_base :确保进入 _IO_str_overflow 的利用路径 _IO_buf_end - _IO_buf_base :控制 malloc 的大小 _IO_buf_base :通常设置为包含 "/bin/sh" 的地址 6. 相关地址获取 6.1 关键符号地址 6.2 偏移说明 _IO_str_jumps 通常位于 libc 的 data 段,偏移固定 _IO_list_all 是全局变量,指向链表头 __free_hook 是最后 free 时调用的函数指针 7. 防御绕过技巧 检查绕过 : largebin attack 需要绕过完整性检查 tcache stashing 需要确保目标地址可写 限制绕过 : 当存在写入限制时,利用不同角色的部分写入能力组合完成利用 使用 SROP 技术绕过系统调用限制 稳定性提升 : 在修改关键指针后修复相关结构 确保各 bin 状态符合预期 8. 实际应用示例 8.1 例题分析 题目特点: C++ 实现,堆管理结构存储在栈上 不同角色有不同写入权限: A:控制 fd/bk B:控制 fd_ nextsize/bk_ nextsize C:控制其他部分 通过 change role 时的拷贝不完全漏洞实现 UAF 8.2 利用脚本关键部分 9. 调试技巧 关键断点: _IO_str_overflow 函数入口 malloc/memcpy/free 调用处 exit 函数调用处 内存检查: 验证 FILE 结构体伪造是否正确 检查各 bin 状态是否符合预期 确认 hook 是否被正确覆盖 错误处理: 修复被破坏的堆结构 调整偏移计算 验证指针有效性 10. 扩展技术 10.1 其他 IO 函数利用 除了 _IO_str_overflow ,还可以研究: _IO_file_overflow _IO_wstr_overflow _IO_switch_to_get_mode 10.2 结合其他攻击技术 与 FSOP 结合 : 利用更广泛的 FILE 操作函数 通过多个 FILE 结构体形成利用链 与堆风水结合 : 精确控制堆布局 提高利用稳定性 与 SROP 结合 : 实现更复杂的利用链 绕过更多保护机制 11. 防护措施 检测措施 : 监控 _IO_list_all 等关键全局变量 检查 FILE 结构体的 vtable 指针 缓解措施 : 启用 vtable 验证 随机化关键数据结构地址 加强堆完整性检查 开发建议 : 避免使用不安全的 IO 操作 及时更新 libc 版本 实施严格的输入验证 12. 总结 House of Pig 及其变种是高级堆利用技术的代表,结合了多种利用方法,展示了现代漏洞利用的复杂性。理解这些技术不仅有助于漏洞挖掘和利用开发,也能帮助设计更好的防护机制。掌握这些技术需要深入理解 glibc 的堆管理和 IO 子系统实现细节。