IO利用之House of kiwi & House of emma
字数 2087 2025-08-23 18:31:08

House of Kiwi & House of Emma 高级堆利用技术详解

1. House of Kiwi

1.1 背景与简介

在glibc 2.29之后开启了sandbox的堆题中,传统利用方法受限:

  • 劫持free_hook利用特定gadget进行栈迁移
  • 劫持malloc_hook为setcontext+61并劫持IO_list_all链表调用exit

glibc 2.34后取消了关键hook,使得上述方法难以实施,House of Kiwi应运而生。

1.2 利用原理

触发IO流的三种方式中,House of Kiwi利用malloc_assert刷新IO流:

static void __malloc_assert(const char *assertion, const char *file, unsigned int line, const char *function) {
    (void) __fxprintf(NULL, "%s%s%s:%u: %s%sAssertion `%s' failed.\n",
                      __progname, __progname[0] ? ": " : "",
                      file, line,
                      function ? function : "", function ? ": " : "",
                      assertion);
    fflush(stderr);
    abort();
}

关键点:

  • 调用fflush(stderr)后会调用_IO_file_jumps中的sync指针
  • _int_malloc中的assert(chunk_main_arena(bck->bk))可触发
  • 当top_chunk大小不足时,进入sysmalloc中的assert判断

1.3 利用条件

  1. 能够触发__malloc_assert
  2. 能够进行任意地址写

1.4 利用步骤

  1. 通过largebin attack等任意地址写方法:

    • _IO_file_jumps + 0x60_IO_file_sync指针改为setcontext+61的gadget
    • 修改IO_helper_jumps + 0xA0为ROP位置
    • 修改IO_helper_jumps + 0xA8为ret指令gadget位置
  2. 触发assert:

    • 修改top_chunk的size|flags使其不满足assert条件
    • 触发malloc分配失败进入assert流程

1.5 示例代码分析

// 设置关键指针
*((size_t *)IO_helper + 0xA0/8) = ROP;  // 设置rsp
*((size_t *)IO_helper + 0xA8/8) = ret;  // 设置rcx
*((size_t *)SYNC) = magic_gadget;  // 设置fflush(stderr)中调用的指令地址

// 触发assert
size_t *top_size = (size_t *)((char *)malloc(0x10) + 0x18);
*top_size = (*top_size) & 0xFFE;  // top_chunk size改小并将inuse写0
malloc(0x1000);  // 触发assert

2. House of Emma

2.1 背景与简介

glibc 2.34彻底删除了常用hook函数,House of Emma利用_IO_cookie_jumps作为替代调用链。

2.2 利用原理

利用_IO_cookie_file结构体中的函数指针:

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

关键点:

  • 函数指针使用pointer_guard加密(循环右移0x11再异或)
  • 通过控制IO内容控制函数调用

2.3 利用条件

  1. 能够进行任意地址写
  2. 能够控制IO_FILE结构内容
  3. 能够触发IO流操作

2.4 利用步骤

  1. 使用largeBin Attack:

    • stderr指针处写入可控地址
    • __pointer_chk_guard处写入已知地址
  2. 构造加密的函数指针与合理的IO_FILE结构

  3. 利用Unsorted Bin与Top Chunk合并机制修改Top Chunk Size,触发malloc_assert

  4. 进入调用链,利用gadget转移rdi到rdx,为Setcontext提供内容

  5. 执行ROP链进行ORW

2.5 示例分析

# 构造fake 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 = 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(ROL(gadget_addr ^ (heap_base + 0x22a0), 0x11))

# 构造SROP链
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

3. 关键区别与选择

特性 House of Kiwi House of Emma
适用版本 glibc 2.29+ glibc 2.34+
利用点 _IO_file_jumps sync指针 _IO_cookie_jumps函数指针
加密机制 pointer_guard加密
触发方式 malloc_assert malloc_assert
需要控制 IO_helper_jumps _IO_cookie_file结构
复杂度 相对简单 更复杂

4. 防御与缓解

  1. 更新glibc版本
  2. 启用Pointer Guard保护
  3. 加强堆内存管理
  4. 限制IO操作权限
  5. 使用现代防护技术如ASLR、DEP等

5. 总结

House of Kiwi和House of Emma是针对高版本glibc的高级堆利用技术:

  • 都利用malloc_assert触发IO流操作
  • 都需要精确控制内存布局和函数指针
  • 在hook被移除后仍能发挥作用
  • 需要结合ROP等技术完成最终利用

掌握这些技术需要深入理解glibc的IO实现和内存管理机制,是二进制安全研究中的重要课题。

House of Kiwi & House of Emma 高级堆利用技术详解 1. House of Kiwi 1.1 背景与简介 在glibc 2.29之后开启了sandbox的堆题中,传统利用方法受限: 劫持free_ hook利用特定gadget进行栈迁移 劫持malloc_ hook为setcontext+61并劫持IO_ list_ all链表调用exit glibc 2.34后取消了关键hook,使得上述方法难以实施,House of Kiwi应运而生。 1.2 利用原理 触发IO流的三种方式中,House of Kiwi利用 malloc_assert 刷新IO流: 关键点: 调用 fflush(stderr) 后会调用 _IO_file_jumps 中的sync指针 _int_malloc 中的 assert(chunk_main_arena(bck->bk)) 可触发 当top_ chunk大小不足时,进入 sysmalloc 中的assert判断 1.3 利用条件 能够触发 __malloc_assert 能够进行任意地址写 1.4 利用步骤 通过largebin attack等任意地址写方法: 将 _IO_file_jumps + 0x60 的 _IO_file_sync 指针改为 setcontext+61 的gadget 修改 IO_helper_jumps + 0xA0 为ROP位置 修改 IO_helper_jumps + 0xA8 为ret指令gadget位置 触发assert: 修改top_ chunk的size|flags使其不满足assert条件 触发malloc分配失败进入assert流程 1.5 示例代码分析 2. House of Emma 2.1 背景与简介 glibc 2.34彻底删除了常用hook函数,House of Emma利用 _IO_cookie_jumps 作为替代调用链。 2.2 利用原理 利用 _IO_cookie_file 结构体中的函数指针: 关键点: 函数指针使用 pointer_guard 加密(循环右移0x11再异或) 通过控制IO内容控制函数调用 2.3 利用条件 能够进行任意地址写 能够控制IO_ FILE结构内容 能够触发IO流操作 2.4 利用步骤 使用largeBin Attack: 在 stderr 指针处写入可控地址 在 __pointer_chk_guard 处写入已知地址 构造加密的函数指针与合理的IO_ FILE结构 利用Unsorted Bin与Top Chunk合并机制修改Top Chunk Size,触发malloc_ assert 进入调用链,利用gadget转移rdi到rdx,为Setcontext提供内容 执行ROP链进行ORW 2.5 示例分析 3. 关键区别与选择 | 特性 | House of Kiwi | House of Emma | |---------------------|----------------------------|----------------------------| | 适用版本 | glibc 2.29+ | glibc 2.34+ | | 利用点 | _ IO_ file_ jumps sync指针 | _ IO_ cookie_ jumps函数指针 | | 加密机制 | 无 | pointer_ guard加密 | | 触发方式 | malloc_ assert | malloc_ assert | | 需要控制 | IO_ helper_ jumps | _ IO_ cookie_ file结构 | | 复杂度 | 相对简单 | 更复杂 | 4. 防御与缓解 更新glibc版本 启用Pointer Guard保护 加强堆内存管理 限制IO操作权限 使用现代防护技术如ASLR、DEP等 5. 总结 House of Kiwi和House of Emma是针对高版本glibc的高级堆利用技术: 都利用malloc_ assert触发IO流操作 都需要精确控制内存布局和函数指针 在hook被移除后仍能发挥作用 需要结合ROP等技术完成最终利用 掌握这些技术需要深入理解glibc的IO实现和内存管理机制,是二进制安全研究中的重要课题。