题目分析
这个题目给了相当多的check:
- 沙箱ban了open,openat和execve,glibc 2.35, 释放有UAF, chunk只能分配0x500-0x5FF大小,其余大小都会变成0x500,最多5个,只有一次edit一次show。
- 程序开始会把IO_wfile_jumps向后的page全写0
- 同时允许一个经过check的地址写16字节,check不允许写stdin到stdin向后0x1b000,以及stdin-1C67F700往前(非libc段不让写)
- 另外提供了一个接口,允许查询USER环境变量或者将其修改为“flag?",只能用一次。
- Largebin attack会用完5个块,同时也会用掉唯一一次UAF edit。后续没有办法再次控制chunk内容
- 而且题目提供的任意地址写无法写glibc前面(也就是堆)地址,同时也没法直接写已经打开的IO(0-2和IOlistall都不行)
1 | unsigned __int64 change_user_env() |
1 | void *check_addr() |
这种情况下我们该怎么攻击?下面介绍几种通过这个题其他队伍解出来的wp获得的思路,感觉下面这些再不通就没什么太多别的思路了。
思路?
_IO_wfile_jumps_mmap与House of apple
在house_of_apple v2中,劫持控制流依靠的是IO_wfile_overflow
函数,利用了对这部分vtable没有检查的特性。但其实这个函数存在于三个虚表中,包括IO_wfile_jumps
,io_wfile_jumps_mmap
以及io_wfile_jumps_maybe_mmap
。这道题其实没有控制IO_wfile_jumps_maybe_mmap
,因此其实我们还是能用house of apple。
在pwndbg中确定io_wfile_overflow
的地址后利用search pointer可以看到:
1 | pwndbg> search -t pointer 0x7ffff7de1390 |
尽管io_wile_jumps被写0了,我们还是有2个虚表存了这个函数。在IDA中看了下,这两个表libc都没有给符号,但是都在io_wfile_jumps上面一点点所以利用应该也是比较简单。我们把本来写IO_wfile_jumps
的地方写成IO_wfile_Jumps-0xc0
就行了。
5个块够发起一次largebin attack了,所以下面附上笔者自己复现的思路,同时顺手总结一下通解板子希望下次能快点。有空抽出来单发一篇blog
拆解步骤-House of apple v2解决沙箱堆
上次ciscn的那道题复现细节太多了,没有很好地整体把握,有点机械的对着exp解释代码,这次勤来看这篇应该不会有太大问题了。
-
确定漏洞点,我们是否能有一次largebin attack的机会?是不是能UAF控制largebin的内容?如果是,那这题只需要绕过题目的限制就结束了
-
我们都知道House of apple的链条,下面具体说一下
House of Apple-v2是一系列利用高版本libc下不对IO_file_complete中处理宽字符流的_wide_data的vtable做检查的特性实现的攻击手段。具体思想是伪造io_file,然后有两步的跳转:
-
伪造wide_data指向一个可控地址,wide_data也是类似于一个IO_file的结构体
-
控制wide_data的vtable字段,让vtable指向可控地址
-
vtable+0x68写为我们要跳转的地方(exit的时候调用的io_wfile_overflow)
-
没有沙箱这里就可以使用one_gadget等手段了,有沙箱就涉及到栈迁移+ROP或ret2sc的思想
我们利用setcontext+61(glibc 2.29前是setcontext+53并且能用rdi控制)这个gadget,在rdx+0xa0写入fakestack的地址,在rdx+0xa8写入第一条ROP指令起点(写个ret就行)注意要观察跳入setcontext的时候rdx或者rdi寄存器的内容。比如如果低于2.34的版本可以打free_hook然后rdi会是我们的fakeio地址。这道题是直接通过exit退出,调试发现跳入setcontext的时候rdx就是wide_data的地址
后面就可以执行我们的ROP链了。
exp(板子和思路重要)
对于涉及来回偏移,overlap复用空间等等操作来说,pwntools的FileStructure()
就不那么好用了,可以参考自己写的下面这个带有偏移的板子来构造,单一chunk包含所有信息:
1 | from pwn import * |
tls_dtor_lists
利用程序ld段进行攻击。