简单介绍
在高版本中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利用