简单介绍
在高版本中large bin attack算是为数不多的可以任意地址写堆地址的方法。
这一利用方式是相较于其他house of 系列来说存在一定差异,它不是直接通过IO_FILE getshell是通过扩大现存的写堆地址漏洞的方式,从而辅佐其他house of 系列。
利用条件
- 程序从
main
函数返回或能调用exit
函数 - 能泄露出
heap
地址和libc
地址 - 能使用一次
largebin attack
利用原理
调用链和house of pig一致:
exit
=>fcloseall
=>_IO_cleanup
=>_IO_flush_all_lockp
=>_IO_OVERFLOW
首先在vtbale中存在这样一个函数:
1 | static wint_t |
首先是将fp转化为_IO_wstrnfile结构体
1 | typedef struct |
根据上面,如果通过fp->_wide_data->_IO_buf_base != snf->overflow_buf
判断则会对fp->_wide_data
的_IO_write_base
、_IO_read_base
、_IO_read_ptr
和_IO_read_end
赋值为snf->overflow_buf
或者与该地址一定范围内偏移的值,最后对fp->_wide_data
的_IO_write_ptr
和_IO_write_end
赋值。
只要控制了fp->_wide_data
,就可以控制从fp->_wide_data
开始一定范围内的内存的值,也就等同于任意地址写已知地址
不过可以看到在赋值之前会路过这一函数:
1 | void |
所以一般来说需要绕过free函数,所以我们可以控制_flags2=8
即可
随后就是_IO_wstrnfile
结构体涉及到其他结构体:
1 | struct _IO_str_fields |
因为其中存在着其他结构体,最后可以看出来overflow_buf的偏移量位0xf0,那就是在vtable后面
而struct _IO_wide_data
结构体如下:
1 | struct _IO_wide_data |
最后呢,也就是在调用vtable之前需要绕过的一点是:
1 | int |
构造方式
这里我看原创文章的构造描述和他写的demo的构造方式存在一定差异,所以我这里根据下面的demo来描述构造方式:
- 首先修改vtable的值为:_IO_wstrn_jumps
- 绕过free,修改_flags2的值为8
- 修改_IO_write_ptr的值为-1
- 最后修改_wide_data的地址为我们的目标地址
利用思路
这里修改mp_
结构体和global_max_fast
就不再赘述,这两者的攻击方式类似,这里重点提一下如何配合house of pig
与house of pig的联用
在我之前的FSOP这篇文章的关于vtable的检验实际上并不完善,其中只提到了检验内部vtable,关于外部vtable的检验没怎么提。
1 | _IO_vtable_check (void) |
可以看到这里如果我们的flag值等于_IO_vtable_check
的值,函数就会立即返回
通过汇编代码可知这里是将IO_accept_foreign_vtables
经过PTR_DEMANGLE
这样一个函数的变化最后进行比较,而在house of emma中这个函数的本质就是上面汇编中显示的循环右移0x11然后与fs:0x30也就是pointer_guard
进行异或。所以,如果pointer_guard
和IO_accept_foreign_vtables
是我们已知的值,我们即可绕过这一判断。最后任意伪造vtable劫持程序执行流即可。
与house of emma联用
相较于上面的需要进行两次任意地址写的情况,这一利用方式算是比较简单,只需要通过house of apple修改pointer_guard
的值,随后进行house of emma即可。
例题演示
例题使用的方式为house of apple & house of emma
因为原创已经分析过了,这里就不再分析了,这里主要提一下堆风水即可。
首先题目申请chunk的size只能申请三种,分别是:key+0x10,key+0x20,2*key+0x10
并且题目的输入只能输入一次,所以我们需要在修改掉已经在large bin中的chunk的bk_nextsize的指针的同时修改掉即将进入large bin的chunk的内容为我们伪造的IO_FILE结构体。
所以我们的目标是,有一个指针指向我们已经在large bin中的chunk,并且在这个chunk的内部还存在一个我们即将进入large bin的chunk,并且我们还希望,在修改bk_nextsize之后紧接着就可以修改掉后一个chunk的内容,让我们可控的内容尽可能的多一点。(其实仔细思考一下发现我们完全可以构造成ptr,ptr+0x30效果也是差不多,构造起来还较为简单一点)
exp
1 | from pwn import * |
总结
house of apple与以往的house of系列存在一定区别,他的效果只是任意地址写堆地址,将_IO_FILE地址+0xf0的地址写到_IO_wide_data
所指向的地址(当然结合源码看的话可以看出来是进行一定范围的写操作)
其实house of apple只是单纯的利用fcloseall函数会循环调用_IO_FILE
的_chain,也就是利用一次任意地址写的机会进行多次_IO_FILE
利用