House of apple2

文章发布时间:

最后更新时间:

文章总字数:
612

预计阅读时间:
2 分钟

前言

虽然是名为house of apple2 但是和apple1的利用没有太大的关系 当成一条全新的链就行了

只需要一次largebin就可以实现的链 适用于2.35这样的高版本 触发条件为exit或者abort 需要调用到io结构体的vtable的overflow函数

链路分析

触发的方式和apple1是一样的 可以通过显示调用的exit 或者是从main函数返回的隐式exit 或者是malloc_assert输出报错信息

下面是通过exit触发的链

exit -> fcloseall -> _IO_cleanup -> _IO_flush_all_lockp -> _IO_OVERFLOW

主要的思想就是劫持IO_list_all为堆地址 从而我们可以伪造io结构体

这里主要注意的就是两个成员 一个是_wide_data 一个是vtable

我们先说vtable 这里的思路是将其伪造为_IO_wfile_jumps

这样触发io时会调用到_IO_wfile_overflow 来看一下这个函数主要的内容

image-20230716161414471

其内部调用了wdoallocbuf函数 这个函数存在一个任意函数调用的点

image-20230716161503609

其索引是通过rax寄存器来的

而此时的rax值 就是fakeio的0xa0偏移处的wide_data成员

image-20230716161559230

其wide_data处要求是一个结构体指针 wdoallocbuf函数会调用该指针的vtable的overflow函数

如果我们将其控制为setcontext 就可以实现一段rop 哪怕是开启了沙盒 也是适用的

伪造分析

关键的伪造点就那几个

1.先要把_IO_list_all利用largebin attack先覆盖成可控地址 用来伪造结构体 下面称fakeio1

2.控制fakeio1的vtable为_IO_wfile_jumps 从而调用到 _IO_wfile_overflow

3.控制fakeio1的_wide_date为fakeio2

4.控制fakeio2的vtable为fakeio3

5.控制fakeio3的偏移0x68处为setcontext

需要注意的就是最后的rop链存放的位置不能影响到fakeio的其他成员 导致程序执行流无法顺利执行

还有就是之所以 不直接更改_wide_data->vtable->0x68为system函数 然后设置fakeio首地址处为/bin/sh 这样破坏了flag成员 无法让程序执行流按预期的执行

剩下的就参考下面的模板吧

1
2
3
4
5
6
7
8
9
fakeio1


IO_wfile_jumps = libc_addr + 0x2160c0
fake_file = b''
fake_file = fake_file.ljust(0x20,b'\x00')+p64(0)+p64(1)
fake_file = fake_file.ljust(0xa0,b'\x00')+p64(chunk5_addr)
fake_file = fake_file.ljust(0xd8,b'\x00')+p64(IO_wfile_jumps)
payload = cyclic(0x10)+fake_file
1
2
3
4
5
6
7
fakeio2


payload = b''
payload = payload.ljust(0x58,b'\x00')+p64(setcontext)
payload = payload.ljust(0x90,b'\x00')+p64(chunk5_addr+0xf0)+p64(ret_addr)
payload = payload.ljust(0xd0,b'\x00')+p64(chunk5_addr)+p64(0)+p64(rdi_addr)+p64(binsh_addr)+p64(system_addr)