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 结构体,可以控制:
- 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")调用
- 通过 exit 或 flush 触发
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 结构体
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 内存布局要求
_IO_write_ptr > _IO_write_base:确保进入_IO_str_overflow的利用路径_IO_buf_end - _IO_buf_base:控制 malloc 的大小_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. 防御绕过技巧
-
检查绕过:
- largebin attack 需要绕过完整性检查
- tcache stashing 需要确保目标地址可写
-
限制绕过:
- 当存在写入限制时,利用不同角色的部分写入能力组合完成利用
- 使用 SROP 技术绕过系统调用限制
-
稳定性提升:
- 在修改关键指针后修复相关结构
- 确保各 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. 调试技巧
-
关键断点:
_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 子系统实现细节。