关于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\x00
fp->vtable
设置为_IO_wfile_jumps
(/_IO_wfile_jumps_mmap/_IO_wfile_jumps_maybe_mmap
)fp->_IO_write_ptr
> fp->_IO_write_base
fp->_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_base
fp->_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* |