四月安恒月赛
prese
平坦化混淆
经过输入测试和代码分析可发现,核心加密是这一句的逻辑,这一句会根据输入的长度生成temp数组
尝试得到输入与输出的映射关系后解:
cipher = [0x86, 0x83, 0x91, 0x81, 0x96, 0x84, 0xB9, 0xA5, 0xAD, 0xAD, 0xA6, 0x9D, 0xB6, 0xAA, 0xA7,0x9D, 0xB0, 0xA7, 0x9D, 0xAB, 0xB1, 0x9D, 0xA7, 0xA3, 0xB1, 0xBB, 0xAA, 0xAA, 0xAA, 0xAA, 0xBF, 0]
a = [chr(i) for i in range(96, 96+32)]
print("".join(a))
src = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}"
for i in range(64+31, 64+31+31):print(chr(i), end="")
# exit()
table = [0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF] + \[0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE] + \[0xBF, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E,0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D]
# for i in range(len(table)):
# table[i] ^= 0x22
print(len(src), len(table))
flag = ""
table = bytes(table)
for i in range(32):cipher[i] ^= 0x22index = table.find(cipher[i])flag += src[index]# print(index)
print(flag)
for i in cipher:print(hex(i), end=" ")
DASCTF{good_the_re_is_easyhhhh}
ezVM
ezvm的check dll是一个fake逻辑
ezvm exe会生成新的check dll去调用
调用这个函数的前提是key输入对,总之尝试解一下key。
首先key是16位数字
然后是一个vm
vm exp:
cipher = b"QTFVASnst~pST^PsT~pSt~psytr}}}}}}}}}}}}}}}}h"
cipher = [0x0D, 0x08, 0x1A, 0x0A, 0x1D, 0x0F, 0x32, 0x78, 0x2A, 0x7B, 0x2A, 0x7B, 0x7C, 0x7D, 0x71, 0x64, 0x7A, 0x2C, 0x7B, 0x7D, 0x64,0x28, 0x7D, 0x71, 0x2C, 0x64, 0x78, 0x78, 0x7D, 0x7A, 0x64, 0x28, 0x7A, 0x7D, 0x70, 0x7F, 0x28, 0x7A, 0x2B, 0x7E, 0x7D, 0x79, 0x79, 0x34]
for i in range(44):cipher[i] ^= 0x49
print(bytes(cipher))
vm = [0x000000A2, 0x00000000, 0x00000084, 0x000000A3, 0x00000008, 0x00000000, 0x000000A3, 0x00000008, 0x00000001, 0x000000B0, 0x00000008, 0x0000013C, 0x000000B2, 0x000000A3, 0x00000009, 0x00000001, 0x000000A3, 0x00000009, 0x00000002, 0x000000A3, 0x00000009, 0x00000003, 0x000000B0, 0x00000009, 0x0000009E, 0x000000B2, 0x000000A6, 0x00000004, 0x00000016, 0x000000A3, 0x00000000, 0x00000004, 0x000000B0, 0x00000000, 0x00000379, 0x000000B2, 0x000000A4, 0x00000005, 0x0000000B, 0x000000A1, 0x00000008, 0x00000005, 0x000000A3, 0x00000008, 0x00000006, 0x000000B0,0x00000008, 0x00000026, 0x000000B2, 0x000000A3, 0x00000007, 0x00000006, 0x000000B0, 0x00000007, 0x00000060, 0x000000B2, 0x000000A1, 0x00000009, 0x00000001, 0x000000A3, 0x00000009, 0x00000002, 0x000000A5, 0x00000009, 0x00000005, 0x000000B0, 0x00000009, 0x0000006F, 0x000000B2, 0x000000A6, 0x00000005, 0x00000007, 0x000000A1, 0x00000008, 0x00000000, 0x000000A5, 0x00000008, 0x00000006, 0x000000A3, 0x00000008, 0x00000005, 0x000000B0, 0x00000008, 0x0000035B, 0x000000B2, 0x000000A3, 0x00000003, 0x00000004, 0x000000B0, 0x00000003, 0x000002C2, 0x000000B2, 0x000000C0]
i = 0
while vm[i] != 192:op = vm[i]if op < 178:arg1 = vm[i+1]arg2 = vm[i+2]if op == 160:print("mov key[" + str(arg1) + "] ," + str(arg2))if op == 161:print("mov key[" + str(arg1) + "] ,key[" + str(arg2)+"]")if op == 162:print("add key[" + str(arg1) + "] ," + str(arg2))if op == 163:print("add key[" + str(arg1) + "] ,key[" + str(arg2)+"]")if op == 164:print("sub key[" + str(arg1) + "] ," + str(arg2))if op == 165:print("sub key[" + str(arg1) + "] ,key[" + str(arg2)+"]")if op == 166:print("mul key[" + str(arg1) + "] ," + str(arg2))if op == 167:print("mul key[" + str(arg1) + "] ,key[" + str(arg2)+"]")if op == 176:print("cmp key[" + str(arg1) + "] ," + str(arg2))if op == 177:print("cmp key[" + str(arg1) + "] , key[" + str(arg2)+"]")if op == 178:print("jz out")i += 1continuei += 3
add key[0] ,132
add key[8] ,key[0]
add key[8] ,key[1]
cmp key[8] ,316
jz out
add key[9] ,key[1]
add key[9] ,key[2]
add key[9] ,key[3]
cmp key[9] ,158
jz out
mul key[4] ,22
add key[0] ,key[4]
cmp key[0] ,889
jz out
sub key[5] ,11
mov key[8] ,key[5]
add key[8] ,key[6]
cmp key[8] ,38
jz out
add key[7] ,key[6]
cmp key[7] ,96
jz out
mov key[9] ,key[1]
add key[9] ,key[2]
sub key[9] ,key[5]
cmp key[9] ,111
jz out
mul key[5] ,7
mov key[8] ,key[0]
sub key[8] ,key[6]
add key[8] ,key[5]
cmp key[8] ,859
jz out
add key[3] ,key[4]
cmp key[3] ,706
jz out
多项表达式,可以用z3解。
import dis
from z3 import *def solve():s = Solver()d = [BitVec('v'+str(x), 8) for x in range(8)]print(d[0])values = []s.add(d[0] + 132 + d[1] == 316) # d[0] += 132s.add(d[1] + d[2] + d[3] == 158)# d[4] *= 22 d[0] = d[0] + 132 + d[4] * 22s.add(d[4] * 22 + d[0] + 132 == 889)s.add(d[5] - 11 + d[6] == 38) # d[5] -= 11s.add(d[7] + d[6] == 96) # d[7] += d[6]s.add(d[1] + d[2] - d[5] + 11 == 111)s.add((d[5]-11) * 7 + d[0] + 132 + d[4] * 22 - d[6] == 859) # (d[5]-11)*7s.add(d[3] + d[4] * 22 == 706)for i in range(8):s.add(d[i] < 100)if s.check() == sat:result = [0] * len(d)keyword = 'v'offset = 0m = s.model()print(m)for l in range(len(result)):for i in m:# print(i.name,type(i))# 取定义的nums与i名比对if keyword + str(l + offset) == str(i):value = m[i]values.append(value)# for i in values:# print(i)print("values: ", values)key = ""for i in values:key += str(i)print(key, len(key))solve()
输入正确后可动调进入真实dll。其简单做了一个异或加密
cipher = [0x0D, 0x08, 0x1A, 0x0A, 0x1D, 0x0F, 0x32, 0x78, 0x2A, 0x7B, 0x2A, 0x7B, 0x7C, 0x7D, 0x71, 0x64, 0x7A, 0x2C, 0x7B, 0x7D, 0x64,0x28, 0x7D, 0x71, 0x2C, 0x64, 0x78, 0x78, 0x7D, 0x7A, 0x64, 0x28, 0x7A, 0x7D, 0x70, 0x7F, 0x28, 0x7A, 0x2B, 0x7E, 0x7D, 0x79, 0x79, 0x34]
for i in range(44):cipher[i] ^= 0x49
print(bytes(cipher))
DASCTF{1c2c2548-3e24-a48e-1143-a3496a3b7400}
unwind
此题先有一个简单的xxtea
而后实际上,在这个去除符号的程序里,这个strcmp是唯一保留的符号,是自定义的strcmp。:
这个程序会在程序开头略微修改指令:
修改后该strcmp会触发异常,进而触发异常处理程序。
不断动调可发现,此题除了main里的xxtea,还做了连续两次的xtea
exp:
from ctypes import *def MX(z, y, total, key, p, e):temp1 = (z.value >> 5 ^ y.value << 2) + (y.value >> 3 ^ z.value << 4)temp2 = (total.value ^ y.value) + (key[(p & 3) ^ e.value] ^ z.value)return c_uint32(temp1 ^ temp2)def xxdecrypt(n, v, key):delta = 0x9e3779b9rounds = 6 + 52//ntotal = c_uint32(rounds * delta)y = c_uint32(v[0])e = c_uint32(0)while rounds > 0:e.value = (total.value >> 2) & 3for p in range(n-1, 0, -1):z = c_uint32(v[p-1])v[p] = c_uint32((v[p] - MX(z, y, total, key, p, e).value)).valuey.value = v[p]z = c_uint32(v[n-1])v[0] = c_uint32(v[0] - MX(z, y, total, key, 0, e).value).valuey.value = v[0]total.value -= deltarounds -= 1return vdef decrypt(v, key):v0, v1 = c_uint32(v[0]), c_uint32(v[1])delta = 0x9E3779B9rounds = 36total = c_uint32(delta * rounds)for i in range(rounds):v1.value -= (((v0.value << 4) ^ (v0.value >> 5)) +v0.value) ^ (total.value + key[(total.value >> 11) & 3])total.value -= deltav0.value -= (((v1.value << 4) ^ (v1.value >> 5)) +v1.value) ^ (total.value + key[total.value & 3])return v0.value, v1.value# 标准xtea
if __name__ == "__main__":cipher = [0xC1, 0xA7, 0xAA, 0x87, 0xB6, 0x21, 0x73, 0x85, 0x8C, 0xD2, 0x71, 0x0E, 0xF2, 0x39, 0xDF,0xCA, 0x14, 0xCA, 0xEF, 0x58, 0xD8, 0xD9, 0xE7, 0xD7, 0x5D, 0x5C, 0x9F, 0xF2, 0x5E, 0xD4, 0x5E, 0x5F]value = [0] * (len(cipher)//4)print("cypher len:", len(cipher))print(hex(0x86 ^ 0xeb), hex(0x10 ^ 0xeb))for i in range(0, len(cipher), 4):if 'bytes' in str(type(cipher)):value[i//4] = int.from_bytes(cipher[i:i+4], 'little')elif 'list' in str(type(cipher)):try:value[i//4] = (ord(cipher[i]) | (ord(cipher[i+1]) << 8)| (ord(cipher[i+2]) << 16) | (ord(cipher[i+3]) << 24))except:value[i//4] = ((cipher[i]) | ((cipher[i+1]) << 8)| ((cipher[i+2]) << 16) | ((cipher[i+3]) << 24))key = b"D\x00\x00\x00A\x00\x00\x00S\x00\x00\x00!"k = [int.from_bytes(key[i:i+4], 'little')for i in range(0, len(key), 4)]flag = b""for i in range(0, len(value), 2):res = decrypt(value[i:i+2], k)flag += res[0].to_bytes(4, 'little') + res[1].to_bytes(4, 'little')print(flag)cipher = flagfor i in range(0, len(cipher), 4):if 'bytes' in str(type(cipher)):value[i//4] = int.from_bytes(cipher[i:i+4], 'little')elif 'list' in str(type(cipher)):try:value[i//4] = (ord(cipher[i]) | (ord(cipher[i+1]) << 8)| (ord(cipher[i+2]) << 16) | (ord(cipher[i+3]) << 24))except:value[i//4] = ((cipher[i]) | ((cipher[i+1]) << 8)| ((cipher[i+2]) << 16) | ((cipher[i+3]) << 24))flag = b""for i in range(0, len(value), 2):res = decrypt(value[i:i+2], k)flag += res[0].to_bytes(4, 'little') + res[1].to_bytes(4, 'little')print(flag)cipher = flag# paddingcipher = bytes(cipher)padlen = 0if len(cipher) % 4 != 0:padlen = 4 - len(cipher)cipher = cipher.ljust(len(cipher)+padlen, b'\x00')key = key.ljust(16, b'\x00')print(cipher)print(key)# bytes convert to 32bit intv = [int.from_bytes(cipher[i:i+4], 'little')for i in range(0, len(cipher), 4)]k = [int.from_bytes(key[i:i+4], 'little')for i in range(0, len(key), 4)]print(v)print(k)n = len(v)res = xxdecrypt(n, v, k)flag = b''for i in res:flag += i.to_bytes(4, 'little')print(flag)
"""
Data is : 0x12345678 0x78563412
Encrypted data is : 0xae685ec7 0x59af4238
Decrypted data is : 0x12345678 0x78563412
"""
DASCTF{Gr3@t!Y0u_have_50lv3d_1T}