DASCTF2024年10月赛

ezelf #

Drink the tea and go to find the fish!!

ollvm 平坦化过的控制流

使用 deflat 去平坦化

首先要过一个魔改过的 xxtea,这里的明文是密钥 DASCTF{dr1nk_te@_4nd_cont1nu3..}

然后过一个魔改过得 blowfish,粗略看了下用的似乎是 rc4 的 sbox,但无所谓,sbox 和 pbox 都调试 dump 出来

算法也魔改过,照着抄一个解密

from pwn import u32, p32
from Crypto.Cipher import Blowfish

xxtea_ct=b'\xb4\xb5ZB\xa6y\x0b\xac\x0e#x\xde\xe1-\xc6\x1d\xbb)\x8c\xe2\x94\xfe\x14\xd9\xaa\x03\xe3\x8a\x14\x92\x1cd'
#xxtea_key=[1234,2341,3412,4123]
xxtea_key=[11,45,14,777]

def shift(z, y, x, k, p, e):
    return ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((x ^ y) + (k[(p & 3) ^ e] ^ z)))

def decrypt(v, k):
    delta = 0x11451400
    n = len(v)
    rounds = 16
    x = (rounds * delta) & 0xFFFFFFFF
    y = v[0]
    for i in range(rounds):
        e = (x >> 2) & 3
        for p in range(n - 1, 0, -1):
            z = v[p - 1]
            v[p] = (v[p] - shift(z, y, x, k, p, e)) & 0xFFFFFFFF
            y = v[p]
        p -= 1
        z = v[n - 1]
        v[0] = (v[0] - shift(z, y, x, k, p, e)) & 0xFFFFFFFF
        y = v[0]
        x = (x - delta) & 0xFFFFFFFF
    return v

#xxtea_vec = [u32(xxtea_ct[i:i+4]) for i in range(0,32,4)]
#decrypt(xxtea_vec, xxtea_key)
#blowfish_key = b''.join(p32(xxtea_vec[i]) for i in range(8))

blowfish_key = b'DASCTF{dr1nk_te@_4nd_cont1nu3..}'
blowfish_ct = b'p\xb7\xf0\x8d\x8e\xb2\x1eK\x1c\\\xc6s\xfdH\xdeS4\xdf.\x98#\x91"\xd8\x82\x11\'\x90\xe7qB\x1f'

pbox = [
0x00000125,0x243f6a8b,0x243f6b5f,0x000000e0,
0x000001a4,0x243f6b08,0x243f6b6f,0x000001c9,
0x00000044,0x243f6b78,0x243f6b15,0x000000af,
0x000000be,0x243f6a3b,0x243f6ba7,0x00000026,
0x0000009a,0x243f6ba8
]

sbox=[
[],
[],
[],
[],
]

with open("ezelf.dump", "rb") as fp:
    buf = fp.read()

for i in range(256):
    sbox[0].append(u32(buf[i*4:i*4+4]))
    sbox[1].append(u32(buf[(i+256)*4:(i+256)*4+4]))
    sbox[2].append(u32(buf[(i+512)*4:(i+512)*4+4]))
    sbox[3].append(u32(buf[(i+768)*4:(i+768)*4+4]))

def swap(x,y):
    return y, x

def fes(v):
    a = (v>>24)&0xff
    b = (v>>16)&0xff
    c = (v>>8)&0xff
    d = v&0xff
    sa = sbox[0][a]
    sb = sbox[1][b]
    sc = sbox[2][c]
    sd = sbox[3][d]
    m = (sa+sb)&0xffff_ffff
    n = (sc+sd) &0xffff_ffff
    return m ^ n

def bfdec(L, R):
    L = L^(pbox[17])
    for i in range(17, 1, -1):
        R = R ^ fes(L)
        L, R = swap(L, R)
    
    L, R = swap(L, R)

    L = L ^ pbox[0]

    return L, R

flag = b''

for i in range(0,4):
    L = u32(blowfish_ct[i*8:i*8+4])
    R = u32(blowfish_ct[i*8+4:i*8+8])
    L, R = bfdec(L, R)
    flag += p32(L)
    flag += p32(R)
print(flag)
# DASCTF{Y0u_fin@l1y_f1nd_@nswer!}

EZRE #

Themida 保护的 exe

网上找一个 脱壳器

脱壳之后发现有花,检查之后只有一种 jz,jnz 花,直接模式匹配全换成 0x90

算法是魔改的 rc4 和 tea,从头到尾所有参数都魔改了,很考验视力。。

def dejunk():
    from ida_bytes import get_bytes,patch_bytes
    import re
    text_start = 0x811000
    text_size=0x2000
    text=get_bytes(text_start,text_size)
    jzjnz =bytes.fromhex("33 C0 85 C0 74 03 75 00 E8")
    for it in re.finditer(jzjnz, text):
        patch_bytes(it.start()+text_start,b'\x90'*jzjnz)

#dejunk()

from pwn import p32,u32

v4=[0]*44
v4[0] = 80
v4[1] = -44
v4[2] = -56
v4[3] = -60
v4[4] = -113
v4[5] = -124
v4[6] = 64
v4[7] = -21
v4[8] = 50
v4[9] = -127
v4[10] = -113
v4[11] = -123
v4[12] = 108
v4[13] = -78
v4[14] = 43
v4[15] = 6
v4[16] = -65
v4[17] = 5
v4[18] = 53
v4[19] = 93
v4[20] = 46
v4[21] = -29
v4[22] = 125
v4[23] = 70
v4[24] = -115
v4[25] = 53
v4[26] = 1
v4[27] = 112
v4[28] = 58
v4[29] = 0x80
v4[30] = -127
v4[31] = -59
v4[32] = -26
v4[33] = 113
v4[34] = -45
v4[35] = -42
v4[36] = 80
v4[37] = 105
v4[38] = 111
v4[39] = -30
v4[40] = 110
v4[41] = 120
v4[42] = 20
v4[43] = -40

for i in range(len(v4)):
    v4[i]&=0xff

flag=bytearray(v4)

assert(len(flag)==44)

rc4_key=b'th0s_i0_ke9'

def ksa(key):
    j, sbox = 0, list(range(256))
    for i in range(256):
        j = (j + key[i % len(key)] + sbox[i]) & 255
        sbox[i], sbox[j] = sbox[j], sbox[i]
    return sbox

def prga(sbox):
    i, j = 0, 0
    while True:
        i = (i + 1) & 255
        j = (j + sbox[i]) & 255
        sbox[i], sbox[j] = sbox[j], sbox[i]
        s = sbox[(sbox[i] + sbox[j]) & 255] ^ 51
        yield s

rc4=prga(ksa(rc4_key))

tea_key=[0]*4
tea_key[0] = 0x6E982837
tea_key[1] = 0x44332211
tea_key[2] = 0x11223344
tea_key[3] = 0x3728986E

delta = 0x9e3779b8
sbase = 0x66778899
uint32 = lambda x: x & 0xffff_ffff

def dec(v, k, r=32):
    s = uint32(sbase + uint32(delta * r))
    v0, v1 = v[0], v[1]
    for i in range(r):
        v1 = uint32(v1 - (uint32(uint32((v0 << 4) ^ (v0 >> 5)) + v0) ^ uint32(s + k[(s >> 11) & 3])))
        s = uint32(s - delta)
        v0 = uint32(v0 - (uint32(uint32((v1 << 5) ^ (v1 >> 6)) + v1) ^ uint32(s + k[s & 3])))
    return v0, v1

for i in range(36, -1, -1):
    v0 = u32(flag[i:i+4])
    v1 = u32(flag[i+4:i+8])
    v0, v1 = dec((v0, v1), tea_key, 33)
    flag[i:i+4]=p32(v0)
    flag[i+4:i+8]=p32(v1)

for i in range(len(flag)):
    flag[i] = (flag[i]-next(rc4))&0xff
print(flag)
# DASCTF{Th1l_t8e1a_rc4_l8s_s8o_int9r3es4t1ng}

ezAndroid #

提交时将 flag 换成 DASCTF

魔改的 lua 加载器,需要解密 lua 字节码

用 ida 打开 lib/xxx/libluajava.so 找到 loadbufferx 函数可知加密公式

解密,然后 unluac.jar 反编译,得到源代码,是魔改的 xxtea

delta 调换了顺序,没仔细看,导致比赛时间没有调试出来,麻了。

import sys
from pwn import u32,p32

def decrypt():

        with open(sys.argv[1],"rb") as fp:
                raw=fp.read()

        bytecount=len(raw)
        s=0

        dump=[0x1b]
        for i in range(1,bytecount):
                s+=bytecount
                b=raw[i]^(s%255)
                dump.append(b)

        dump=bytes(dump)
        with open(sys.argv[1]+".lua","wb") as fp:
                fp.write(dump)

#decrypt()

key = [
        114 * 51 + 4 - 1 + 145 + 14,
        114 * 51 * 4 + (1145 * 14 + (1 * -(1 - 4) * 514 - 11 + 45 - 1 - 4)),
        (114514 + 114514) * (11451 + 4 + (1 + 14 * 51 * 4 + (1 * 14 * (5 + 1) + 4))) +(114514 + (114 * 514 + (11 * 4514 + (-1145 * (1 - 4) + 1 * 14 + 5 * 14)))),
        (114514 + 114514) * (114 * (51 + 4) + (1 + 1 + 4 * 5 * 14 + (11 / (45 - 1) * 4))) +(114514 + ((1 + 1) * 4514 + 114 * 5 * 1 * 4 + 1 * 14 - 5 + 14))
]

for i in range(4):
        key[i] = int(key[i])


delta = int((114514+114514)*((1+1)*4514+((1+1)*4*51-4+11-4*5+14))+(114514+(114*514+(114*51*4+((1+1)*4*514+(11*(45-1)/4))))))
round = int(-11 + 45 * 1 + 4)

uint32 = lambda x: x & 0xffff_ffff

ct=[
(114514 + 114514) * ((1 + 1) * 451 * 4 + 114 + 51 - 4 + 11 * -4 + 51 - 4) + (114 * 51 * 4 + ((1 + 1) * 45 * 14 - 11 + 45 * 1 + 4)),
(114514 + 114514) * (1 * -(1 - 4) * 514 + 114 - 51 - 4) + (114514 + (114 * 51 * 4 + (1 + 14514 + ((1 + 1) * 45 * 14 + 11 - 4 + 5 * 14)))),
(114514 + 114514) * (11451 + 4 + (11 * (4 + 5) * 14 + 1 + 14 - 5 + 1 + 4)) + (114514 + (114 * 514 + (11451 * 4 + ((1 + 1) * 4 * 51 * 4 + 1 - 14 + 5 + 14)))),
(114514 + 114514) * (1145 * (1 + 4) - 11 + 4 + 5 + 14) + (114514 + (1 + 14514 + (11 * -45 * (1 - 4) + 11 - 4 + 5 / 1 - 4))),
(114514 + 114514) * ((1 + 1) * 4514 + 1 + 145 * 14 + 11 - 4 * 5 + 14) + 114 * 514 + 1 + 14514 + 1145 - 14,
(114514 + 114514) * (114 * (51 - 4) + (1 + 1 * 4 * 5 * (1 + 4))) + (11 * (451 - 4) + 1 - 14 + 51 - 4),
(114514 + 114514) * (1 + 14514 + (1 - 14 * -(5 + 1) * 4 + 11 * -4 + 51 - 4)) + 114 * 514 + 114 * 5 * 14 - 11 + 45 * 14 + 11 - 4 + 5 / 1 - 4,
(114514 + 114514) * (114 * 51 + 4 + 114 + 5 + 1 + 4) + (114514 + (114 * 51 * 4 + (1145 * 14 + (114 * -5 * (1 - 4) + 11 * 4 + 5 + 1 - 4)))),
(114514 + 114514) * (11451 + 4 + (11 * (45 + 1) * 4 + 11 * -4 + 51 - 4)) + (114514 + (114 * 51 * 4 + (11451 + 4 + (114 * (5 + 1) * 4 + 11 + 4 * 5 / 1 - 4)))),
(114514 + 114514) * (11451 + 4 + (11 * 4 * (51 - 4) + 114 - 5 * 14)) + 11451 * 4 + 11 * 4 * 5 * 14 + 11 * 4 + 5 * 14,
]

for i in range(len(ct)):
        ct[i] = int(ct[i])

def dec(v, k, r=32):

        s = uint32(delta * r)
        v0, v1 = v[0]^14, v[1]^17 # 这里xor了
        for i in range(r):
                v1 = uint32(v1 - (uint32(uint32((v0 << 4) ^ (v0 >> 5)) + v0) ^ uint32(s + k[(s >> 11) & 3])))
                v0 = uint32(v0 - (uint32(uint32((v1 << 4) ^ (v1 >> 5)) + v1) ^ uint32(s + k[s & 3])))
                s = uint32(s - delta) # 这里调换了顺序
        return v0, v1

flag=b''
for i in range(0,len(ct),2):
        v0,v1=dec(ct[i:i+2],key,round)
        flag+=p32(v0,endianness="big")+ p32(v1,endianness="big")

print(flag)
# DASCTF{7a5e-55e45-1671e-df3b7-cd7a1-6f1e-27fc}