House of Cat:绕过 glibc 2.24 后 Vtable 检查的 IO_FILE 利用技术详解
字数 2362 2025-08-29 22:41:32

House of Cat: 绕过 glibc 2.24 后 Vtable 检查的 IO_FILE 利用技术详解

概述

House of Cat 是一种针对 glibc 2.24 及以上版本的 IO_FILE 利用技术,主要思路是通过覆盖 vtable 指针并利用 _IO_jump_t 中的函数来绕过 vtable 检查,从而劫持程序控制流。该技术可以通过两种方式触发攻击:FSOP (File Stream Oriented Programming) 或 __malloc_assert

技术背景

自 glibc 2.24 起,引入了对 vtable 的检查机制,防止直接覆盖 vtable 为 system 等危险函数。House of Cat 通过利用 _IO_wfile_jumps 中的函数(特别是 _IO_wfile_seekoff_IO_wfile_overflow)来绕过这些检查。

关键技术点

1. _IO_wfile_jumps 结构利用

_IO_wfile_jumps 是一个重要的虚表结构,其中我们关注两个关键函数:

  1. _IO_wfile_seekoff (偏移 0x48)
  2. _IO_wfile_overflow (偏移 0x18)

_IO_wfile_seekoff 函数关键部分

该函数会调用 _IO_switch_to_wget_mode,需要满足以下条件:

  • fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
  • fp->_mode != 0

_IO_switch_to_wget_mode 函数

该函数在满足条件后会调用 _IO_WOVERFLOW(fp, WEOF),关键点在于:

  • 通过 fp->_wide_data 指向的结构体 _IO_wide_data 中的 _wide_vtable 字段
  • 调用 _wide_vtable 指向的 __overflow 函数(偏移 0x18)
  • 关键优势:_wide_vtable 没有像 vtable 那样的检查机制,可以自由覆盖

2. 伪造 IO_FILE 结构要求

要成功利用,需要精心构造伪造的 IO_FILE 结构:

  1. fp->_mode 字段 (偏移 0xc0) 必须不为 0(通常设置为 -1)
  2. fp->_wide_data 字段 (偏移 0xa0) 指向一个伪造的 _IO_wide_data 结构
  3. 在伪造的 _IO_wide_data 结构中:
    • _IO_write_ptr (偏移 0x18) 设置为 1
    • _IO_write_base (偏移 0x20) 设置为 0
  4. 伪造的 _wide_vtable 可以指向 system 或其他目标函数

3. 触发路径

有两种主要方式触发 _IO_wfile_seekoff 函数:

方法一:FSOP (File Stream Oriented Programming)

调用链:

__GI_exit --> __run_exit_handlers --> _IO_cleanup --> _IO_flush_all_lockp --> _IO_wfile_seekoff --> _IO_switch_to_wget_mode

关键步骤:

  1. 通过 large bin attack 等方法覆盖 _IO_list_all 指针
  2. 伪造的 IO_FILE 结构需要满足 FSOP 链的要求
  3. _IO_flush_all_lockp 中,vtable 被覆盖为 _IO_wfile_jumps + 0x30
  4. 注意 mode 参数的设置(在 glibc 2.31 中会被设为 0)

方法二:__malloc_assert

调用链:

_int_malloc --> sysmalloc --> __malloc_assert --> __fxprintf --> __vfxprintf --> locked_vfxprintf --> __vfprintf_internal --> _IO_file_xsputn

关键要求:

  1. 需要将 _flag 设置为 0x8005(绕过 __vfprintf_internal 中的检查)
  2. 覆盖 stderr 指向伪造的结构
  3. vtable 需要覆盖为 _IO_wfile_jumps + 0x10(这样 +0x38 偏移就能得到 _IO_wfile_seekoff

4. 栈迁移技术

_IO_switch_to_wget_mode 函数中可以利用以下指令序列实现栈迁移:

mov rax, [rdi+0xa0]    ; rdi = FILE*, 获取 _wide_data
mov rdx, [rax+0x20]    ; 获取 _wide_vtable

这可以实现 rdirdx 的转换,进而可以衔接 setcontext + 61 完成栈迁移。

实际利用示例

例题分析:[HGAME 2023 week3]note_context

题目特点:

  1. 存在 UAF 漏洞
  2. 申请大小限制在 0x500 以上
  3. libc 版本为 2.32
  4. 开启了沙箱,需要 ORW 绕过
  5. 保护全开

利用步骤:

  1. 泄漏地址

    • 利用 large bin 的 fd 指针泄漏堆地址
    • 通过 unsorted bin 泄漏 libc 地址
  2. large bin attack

    • 覆盖 _IO_list_all 指针
    • 同时完成堆地址泄漏
  3. 伪造结构

    • 在堆上布置完整的伪造结构:
      • 伪造的 IO_FILE
      • ORW 链
      • _wide_data 结构
      • 寄存器传参设置
  4. 触发利用

    • 通过 exit() 触发 FSOP
    • 完成栈迁移到堆上布置的 ORW
    • 读取 flag

关键伪造结构:

伪造的IO_FILE:
+0xc0: -1                  ; _mode
+0xa0: 指向伪造的_wide_data

伪造的_wide_data:
+0x18: 1                   ; _IO_write_ptr
+0x20: 0                   ; _IO_write_base
+0x20: 指向伪造的_wide_vtable

伪造的_wide_vtable:
+0x18: system或setcontext+61 ; _IO_wfile_overflow

总结

House of Cat 是一种强大的 IO_FILE 利用技术,主要特点包括:

  1. 通过 _IO_wfile_jumps 中的函数绕过 vtable 检查
  2. 利用 _wide_vtable 不受检查的特性
  3. 可通过 FSOP 或 __malloc_assert 两种路径触发
  4. 结合栈迁移技术可以实现更灵活的利用
  5. 适用于 glibc 2.24 及以上版本的保护绕过

在实际利用中,需要注意不同 glibc 版本中函数偏移和检查条件的细微差别,精心构造伪造的结构以满足各种检查条件。

House of Cat: 绕过 glibc 2.24 后 Vtable 检查的 IO_ FILE 利用技术详解 概述 House of Cat 是一种针对 glibc 2.24 及以上版本的 IO_ FILE 利用技术,主要思路是通过覆盖 vtable 指针并利用 _IO_jump_t 中的函数来绕过 vtable 检查,从而劫持程序控制流。该技术可以通过两种方式触发攻击:FSOP (File Stream Oriented Programming) 或 __malloc_assert 。 技术背景 自 glibc 2.24 起,引入了对 vtable 的检查机制,防止直接覆盖 vtable 为 system 等危险函数。House of Cat 通过利用 _IO_wfile_jumps 中的函数(特别是 _IO_wfile_seekoff 和 _IO_wfile_overflow )来绕过这些检查。 关键技术点 1. _IO_wfile_jumps 结构利用 _IO_wfile_jumps 是一个重要的虚表结构,其中我们关注两个关键函数: _IO_wfile_seekoff (偏移 0x48) _IO_wfile_overflow (偏移 0x18) _IO_wfile_seekoff 函数关键部分 该函数会调用 _IO_switch_to_wget_mode ,需要满足以下条件: fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base fp->_mode != 0 _IO_switch_to_wget_mode 函数 该函数在满足条件后会调用 _IO_WOVERFLOW(fp, WEOF) ,关键点在于: 通过 fp->_wide_data 指向的结构体 _IO_wide_data 中的 _wide_vtable 字段 调用 _wide_vtable 指向的 __overflow 函数(偏移 0x18) 关键优势: _wide_vtable 没有像 vtable 那样的检查机制,可以自由覆盖 2. 伪造 IO_ FILE 结构要求 要成功利用,需要精心构造伪造的 IO_ FILE 结构: fp->_mode 字段 (偏移 0xc0) 必须不为 0(通常设置为 -1) fp->_wide_data 字段 (偏移 0xa0) 指向一个伪造的 _IO_wide_data 结构 在伪造的 _IO_wide_data 结构中: _IO_write_ptr (偏移 0x18) 设置为 1 _IO_write_base (偏移 0x20) 设置为 0 伪造的 _wide_vtable 可以指向 system 或其他目标函数 3. 触发路径 有两种主要方式触发 _IO_wfile_seekoff 函数: 方法一:FSOP (File Stream Oriented Programming) 调用链: 关键步骤: 通过 large bin attack 等方法覆盖 _IO_list_all 指针 伪造的 IO_ FILE 结构需要满足 FSOP 链的要求 在 _IO_flush_all_lockp 中,vtable 被覆盖为 _IO_wfile_jumps + 0x30 注意 mode 参数的设置(在 glibc 2.31 中会被设为 0) 方法二: __malloc_assert 调用链: 关键要求: 需要将 _flag 设置为 0x8005(绕过 __vfprintf_internal 中的检查) 覆盖 stderr 指向伪造的结构 vtable 需要覆盖为 _IO_wfile_jumps + 0x10 (这样 +0x38 偏移就能得到 _IO_wfile_seekoff ) 4. 栈迁移技术 在 _IO_switch_to_wget_mode 函数中可以利用以下指令序列实现栈迁移: 这可以实现 rdi 到 rdx 的转换,进而可以衔接 setcontext + 61 完成栈迁移。 实际利用示例 例题分析:[ HGAME 2023 week3]note_ context 题目特点: 存在 UAF 漏洞 申请大小限制在 0x500 以上 libc 版本为 2.32 开启了沙箱,需要 ORW 绕过 保护全开 利用步骤: 泄漏地址 : 利用 large bin 的 fd 指针泄漏堆地址 通过 unsorted bin 泄漏 libc 地址 large bin attack : 覆盖 _IO_list_all 指针 同时完成堆地址泄漏 伪造结构 : 在堆上布置完整的伪造结构: 伪造的 IO_ FILE ORW 链 _wide_data 结构 寄存器传参设置 触发利用 : 通过 exit() 触发 FSOP 完成栈迁移到堆上布置的 ORW 读取 flag 关键伪造结构: 总结 House of Cat 是一种强大的 IO_ FILE 利用技术,主要特点包括: 通过 _IO_wfile_jumps 中的函数绕过 vtable 检查 利用 _wide_vtable 不受检查的特性 可通过 FSOP 或 __malloc_assert 两种路径触发 结合栈迁移技术可以实现更灵活的利用 适用于 glibc 2.24 及以上版本的保护绕过 在实际利用中,需要注意不同 glibc 版本中函数偏移和检查条件的细微差别,精心构造伪造的结构以满足各种检查条件。