第一次接触house of orange + unsorted bin attack + IO_FILE的堆题,大佬们秒的题我硬是做了两三天才搞出来,结果远程打通了反而本地没打通,本地的问题就先放一放以后再解决了。
题目描述
保护全开,题目给了四个功能:
1 | 1. Create |
其中Create功能中malloc了3个chunk,第二个chunk的大小是可控的,但不超过0x900,第三个chunk的前8个字节是可控的,为两个signed int型的整数,第一个chunk中存了另外两个chunk的地址,以及第一个堆块的地址存在全局变量中(这两个没什么作用)。该功能限制使用4次。
1 | (chunk_1)+----+----+ |
Edit功能可以修改chunk_2中的数据,由于size可以重新给定,这里存在一个堆溢出可以利用。该功能限制使用1次。
Show功能用来输出chunk_2中的数据。该功能限制使用2次。
Exit就是调用exit(0)(用不上)
利用思路
- 题目没有提供free函数,需要利用house of orange得到一个unsorted bin
- 由于题目提供的输入函数没有在字符串末尾补0,可以利用这一点leak出libc的基址(unsorted bin->bk)
- 需要使用_IO_FILE结构攻击,低版本下(glibc<=2.23)是通过伪造vtable进行的。但是题目提供的glibc==2.24,添加了新的检查机制(vtable必须要满足在
__stop___IO_vtables
和__start___libc_IO_vtables
之间),这里需要利用_IO_str_jumps
结构体进行绕过,因为它不在检查范围之内。这里需要用到malloc_printerr调用链,最终执行的会是_IO_str_overflow
。但最终需要的是调用1
malloc_printerr-> __libc_message—>abort->flush->_IO_flush_all_lock->_IO_OVERFLOW
_IO_str_finish
,利用(((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base)
完成system("/bin/sh")
。1
2
3
4
5
6
7
8_IO_str_finish (_IO_FILE *fp, int dummy)
{
if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
(((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base); //[fp+0xe8]
fp->_IO_buf_base = NULL;
_IO_default_finish (fp, 0);
} - 通过unsorted bin attack,将
_IO_list_all
改为main_arena+0x58
即main_arena中unsorted bin的位置,此时_IO_list_all->_chain
将指向main_arena+0x58+0x68
main_arena中size=0x60的small bin,这个small bin以及其中的内容可以通过Edit中的堆溢出利用得到。当unsorted bin因为unsorted bin attack被破坏时,再次遍历会出错,会调用malloc_printerr。 - 伪造的IO_FILE结构体即
_IO_list_all->_chain
指向的结构体需要满足:fp->_mode
= 0fp->_IO_write_ptr
<fp->_IO_write_base
fp->_IO_read_ptr
= 0x61 , smallbin4 + 8 (smallbin size)fp->_IO_read_base
=_IO_list_all
-0x10 , smallbin->bk, unsorted bin attack (以上为绕过_IO_flush_all_lockp
的条件)- vtable =
_IO_str_jumps
- 8 ,这样调用_IO_overflow
时会调用到_IO_str_finish
fp->_flags
= 0fp->_IO_buf_base
=binsh_addr
fp+0xe8
= system_addr
exp
1 | def create(size, content, _217, _108): |
小结
- 在触发malloc_printerr之后,size=0x60的unsorted bin是怎么进入到small bin的机制还不是很清楚
- 除了利用
_IO_str_finish
之外,还可以利用_IO_str_overflow
,不过好像稍微复杂一点,没有尝试 - glibc==2.24的情况下利用IO_FILE结构体攻击的方法不限于此种,还有其他利用方法没有尝试
相关链接
学习了其他大佬们的文章以及CTF wiki