0%

IO_FILE 常用调用链(持续更新)

house of cat

1
__malloc_assert -> __fxprintf -> __vfxprintf -> locked_vfxprintf -> __vfprintf_internal -> [_IO_wfile_seekoff] (IO_wfile_jumps)

触发条件:

  • 伪造 vtable = IO_wfile_jumps+0x10
  • 修改 top chunk -> P = 0,使 top chunk 不够分配

house of emma

1
__malloc_assert -> __fxprintf -> __vfxprintf -> locked_vfxprintf -> __vfprintf_internal -> [_IO_cookie_write](IO_wfile_jumps)
1
2
3
4
5
0x7fc235f79a20 <_IO_cookie_write+48>    call   rax                           <getkeyserv_handle+528>
rdi: 0x562b7f47baf0 ◂— 0x0 /* __cookie:可控heap */
rsi: 0x7fc2360bb360 ◂— "%s%s%s:%u: %s%sAssertion `%s' failed.\n"
rdx: 0x0
rcx: 0x0

触发条件:

  • 伪造 vtable = IO_wfile_jumps+0x40
  • 修改 top chunk -> P = 0,使 top chunk 不够分配

house of kiwi

1
__malloc_assert -> fflush -> sync(_IO_file_jumps)
1
2
3
4
5
0x7ffff7e78523 <fflush+131>    call   qword ptr [rbp + 0x60]        <setcontext+61>
rdi: 0x7ffff7fc35e0 (_IO_2_1_stderr_) ◂— 0xfbad2887
rsi: 0xc00
rdx: 0x7ffff7fc38c0 (_IO_helper_jumps) ◂— 0x0
rcx: 0x7ffff7ef2417 (write+23) ◂— cmp rax, -0x1000 /* 'H=' */

触发条件:

  • 修改 top chunk -> P = 0,使 top chunk 不够分配

IO_flush_all

1
_IO_flush_all -> _IO_flush_all_lockp -> [_IO_wdefault_xsgetn](IO_wstrn_jumps) -> _IO_switch_to_wget_mode

触发条件:

  • 伪造 vtable = IO_wstrn_jumps+0x28
  • 手动调用 _IO_flush_all

_IO_str_jumps -> _IO_str_overflow

1
2
malloc_printerr -> __libc_message -> __GI_abort -> _IO_flush_all_lockp -> _IO_str_overflow
__run_exit_handlers -> _IO_cleanup -> _IO_flush_all_lockp -> _IO_str_overflow
  • libc-2.27.so 及之前,程序在 _IO_str_overflow 里可以通过 call qword ptr [rbx + 0xe0] 来执行指定的函数
  • libc-2.29.so 及之后,程序在 __GI__IO_str_overflow 里不再使用上面的指令,而是调用 call malloc@plt ,所以要在 &_IO_list_all.vtable+8 处写入将要执行的函数

伪造条件:

1
2
3
4
5
6
7
fp->_flags = 0
fp->_IO_write_base = 0
fp->_IO_write_ptr = addr_rdx
fp->_IO_buf_base = 0
fp->_IO_buf_end = (addr_rdi - 100) / 2
fp->_mode = 0
vtable = addr_IO_str_jumps

触发条件:

  • 破坏 unsortedbin
  • 执行 exit

_IO_str_jumps -> _IO_str_finish

1
2
malloc_printerr -> __libc_message -> __GI_abort -> _IO_flush_all_lockp -> [_IO_str_finish]
__run_exit_handlers -> _IO_cleanup -> _IO_flush_all_lockp -> [_IO_str_finish]
  • libc-2.27.so 及之前,程序在 _IO_str_finish 里可以通过 call qword ptr [rbx + 0xe8] 来执行指定的函数
  • libc-2.29.so 及之后,程序在 _IO_str_finish 里不再使用上面的指令,而是调用 call free@plt ,所以要在 &_IO_list_all.vtable+0x10 处写入将要执行的函数

伪造条件:

1
2
3
4
5
6
7
8
fp->_flags = 0
fp->_IO_write_ptr = 0xffffffff
fp->_IO_write_base = 0
fp->_wide_data->_IO_buf_base = addr_rdi // 也就是 fp->_IO_write_end
fp->_flags2 = 0
fp->_mode = 0
vtable = addr_IO_str_jumps - 8

触发条件:

  • 破坏 unsortedbin
  • 执行 exit