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}