关于house of apple
0x00
在复现LitCTF2024的heap-2.39时候遇到了house of apple,既然碰到了,那么就学习一下吧!(其实在上学期校赛的时候就碰到了)
0x01 house of apple 原理
先贴上roderick01师傅的原创文章镇帖(
[原创] House of apple 一种新的glibc中IO攻击方法 (1)-Pwn-看雪-安全社区|安全招聘|kanxue.com
[原创] House of apple 一种新的glibc中IO攻击方法 (2)-Pwn-看雪-安全社区|安全招聘|kanxue.com
[原创]House of apple 一种新的glibc中IO攻击方法 (3)-Pwn-看雪-安全社区|安全招聘|kanxue.com
我们调试demo (姑且先看apple2)
_IO_wfile_overflow
1 | _IO_wfile_overflow |
demo如下(glibc2.35)
1 |
|
直接运行到最后一步前,看stderr的相关状态
1 | pwndbg> p *stderr |
总结一下条件fp->_flags设置为0xfffff7f5或者0xfbadf7f5(满足~(2 | 0x8 | 0x800)),后续四字节根据情况设置为;sh\x00fp->vtable设置为_IO_wfile_jumps (/_IO_wfile_jumps_mmap/_IO_wfile_jumps_maybe_mmap)fp->_IO_write_ptr > fp->_IO_write_basefp->_wide_data写入可控地址fp->_wide_data->_wide_vtable->doallocate(位于fp->_wide_data->_wide_vtable+0x68)设置为后门函数fp->_wide_data->_IO_write_base == fp->_wide_data->_IO_buf_base == 0
至于这些条件为什么这么设置,看glibc源码便知
我们看最终效果
1 | r3t2@LAPTOP-6JKPOVPE:~/CTF/pwn_demos/apple$ ./demo3 |
成功getshell
_IO_wdefault_xsgetn
这条链执行的条件是调用到_IO_wdefault_xsgetn时rdx寄存器,也就是第三个参数不为0
1 | _IO_wdefault_xsgetn |
demo如下(glibc2.35)
1 |
|
总结一下条件fp->_flags设置为0x800,如果需要getshell则设置为0xfbad0802或者0xffff0802,然后后续加上;sh\x00即可fp->vtable设置为_IO_wstrn_jumps (/_IO_wmem_jumps/_IO_wstr_jumps),这里测试发现_IO_wstrn_jumps - 0x20可行 fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_basefp->_wide_data->_IO_read_end == fp->_wide_data->_IO_read_ptr == 0fp->_wide_data写入可控地址fp->_wide_data->_wide_vtable->overflow(位于fp->_wide_data->_wide_vtable+0x68)设置为后门函数fp->_wide_data->_IO_write_base == fp->_wide_data->_IO_buf_base == 0
效果如下
1 | r3t2@LAPTOP-6JKPOVPE:~/CTF/pwn_demos/apple$ ./demo2 |
然后这里我们在step2加上
1 | sprintf(&stderr2[4], "%s", ";sh\x00"); |
step7改成
1 | *(size_t *)(p2 + 0x18) = (size_t)(&system); |
这时候gdb执行到最后发现
1 | pwndbg> r |
发现这里确实启动了/usr/bin/dash但是直接退出了,这里怀疑是system的参数问题,然后意识到覆盖的_wide_vtable->_overflow的参数是stderr,我们这里仅仅在其_flags域(为0x800)后加上;sh\x00,会被0x800的\x00截断导致system的参数异常
如何解决呢?把截断想办法去掉就好了
1 | *(size_t *)stderr2 = 0xfbad0802; //0xffff0802 |
这样修改后执行
1 | r3t2@LAPTOP-6JKPOVPE:~/CTF/pwn_demos/apple$ ./demo2 |
成功getshell
_IO_wfile_underflow_mmap
#todo
0x02 例题 LitCTF2024 heap-2.39
题目源码如下
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
建堆函数
1 | __int64 create() |
限定了size在largebin范围。记录了size大小
free函数
1 | void delete() |
未清指针,可以uaf
打印函数
1 | int show() |
直接输出,注意printf的截断
edit函数
1 | ssize_t edit() |
根据建堆时记录的size限制输入大小,无法溢出,但是可以利用presize的复用
退出函数
1 | void __noreturn Exit() |
可以主动触发exit();
例行公事,checksec一下
1 | r3t2@LAPTOP-6JKPOVPE:~/2.39$ checksec heap |
此题可以申请16个chunk进行操作。限制很少,总体思路是利用unsortedbin leak泄露libc地址,heap_base也可以直接打印largebin中的chunk的fd_nextsize来泄露,然后largebin attack来向_IO_list_all写入堆地址,接着利用可控的chunk来伪造一个fake_io_file,打house of apple2。本题io链如下
1 | _IO_OVERFLOW(fp, ch) |
exp
1 | from pwn import* |


