- 双击运行可以发现有缺失的 DLL。打开 IDA 大概看一下,程序流图比较大,有一堆的 throw 和 catch,F5 无法正常反编译,纯静态不好看
- Findcrypt 看一眼有 AES 的 S 盒和逆 S 盒
- 字符串可以看到编译信息,也可以用 DIE 之类的工具看一眼,
GCC: (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
。于是安装环境,边调边看汇编逆(保留了符号信息,还算比较好看) - 结合 IDA 的程序流图,在 catch 的地方下断,防止跑飞
- 第一步可以看出是一个 TEA 加密。首先取输入的前 16 个字节,组成 4 个 DWORD,两两同时进行加密。碰到函数可以直接步过看效果。魔改了两个地方,首先是改了 delta,另外是多异或了一个
sum + i
- TEA 加密结束后,4 个 DWORD 的最低字节与
"SCTF"
的一个字母异或 - 然后进入 AES 加密
- 通过 S 盒和密钥扩展常量可以识别密钥扩展部分
- 第一次轮密钥加之后还与 0x66 进行了一次异或
- 通过使用逆 S 盒可以判断是在做逆 S 盒变换
- 逆行移位给了函数名
- 剩下就是列混淆了,不用步进,步过看效果验证猜想
- 至此整个逻辑就比较清晰了:程序分两次对输入进行加密,每次取 16 个字节,经过魔改 TEA、异或、魔改 AES 得到密文。最后与程序开头的正确密文进行比较
- 另外学习 Windows SEH 可以参考《加密与解密》第八章
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106import ctypes
from pwn import p32, u32
from aeskeyschedule import key_schedule
from phoenixAES import MC, InvMC, InvSBox, SBox, InvShiftRow, ShiftRow, AddKey
def tea_encrypt(plain, key):
y, z = [ctypes.c_uint32(x) for x in plain]
sum_val = ctypes.c_uint32(0)
delta = 0x73637466
for i in range(32):
sum_val.value += delta
y.value += ((z.value << 4) + key[0]) ^ (z.value + sum_val.value) ^ ((z.value >> 5) + key[1]) ^ (sum_val.value + i)
z.value += ((y.value << 4) + key[2]) ^ (y.value + sum_val.value) ^ ((y.value >> 5) + key[3]) ^ (sum_val.value + i)
return [y.value, z.value]
def tea_decrypt(cipher, key):
y, z = [ctypes.c_uint32(x) for x in cipher]
sum_val = ctypes.c_uint32(0x6C6E8CC0)
delta = 0x73637466
for i in range(31, -1, -1):
z.value -= ((y.value << 4) + key[2]) ^ (y.value + sum_val.value) ^ ((y.value >> 5) + key[3]) ^ (sum_val.value + i)
y.value -= ((z.value << 4) + key[0]) ^ (z.value + sum_val.value) ^ ((z.value >> 5) + key[1]) ^ (sum_val.value + i)
sum_val.value -= delta
return [y.value, z.value]
def AES_encrypt(plain, round_keys):
cipher = plain
cipher = AddKey(cipher, round_keys[0])
for i in range(16):
cipher[i] ^= 0x66
for j in range(1, 10):
cipher = InvSBox(cipher)
cipher = InvShiftRow(cipher)
cipher = MC(cipher)
cipher = AddKey(cipher, round_keys[j])
cipher = SBox(cipher)
cipher = ShiftRow(cipher)
cipher = AddKey(cipher, round_keys[10])
return cipher
def AES_decrypt(cipher, round_keys):
plain = cipher
plain = AddKey(plain, round_keys[10])
plain = InvShiftRow(plain)
plain = InvSBox(plain)
for j in range(9, 0, -1):
plain = AddKey(plain, round_keys[j])
plain = InvMC(plain)
plain = ShiftRow(plain)
plain = SBox(plain)
for i in range(16):
plain[i] ^= 0x66
plain = AddKey(plain, round_keys[0])
return plain
TEA_key = [0] * 4
TEA_key[1] = 0x21667463
TEA_key[0] = 0x735F6F74
TEA_key[3] = 0x5F656D6F
TEA_key[2] = 0x636C6557
cipher = b"\xBE\x1C\xB3\xF3\xA1\xF4\xE4\x63\x11\xE1\x1C\x6B\x54\x0A\xDF\x74\xF2\x93\x55\xDA\x48\xFC\xA2\x3C\x89\x63\x2E\x7F\x8D\xA4\x6D\x4E"
delta = [0x66, 0x74, 0x63, 0x73][::-1]
AES_key = b'Welcome_to_sctf!'
round_keys = key_schedule(AES_key)
assert AES_key == round_keys[0]
# 0: 57656c636f6d655f746f5f7363746621
# 1: c4569198ab3bf4c7df54abb4bc20cd95
# 2: 71ebbbfddad04f3a0584e48eb9a4291b
# 3: 3c4e14abe69e5b91e31abf1f5abe9604
# 4: 9adee6157c40bd849f5a029bc5e4949f
# 5: e3fc3db39fbc803700e682acc5021633
# 6: b4bbfe152b077e222be1fc8eeee3eabd
# 7: e53c843dce3bfa1fe5da06910b39ec2c
# 8: 77f2f516b9c90f095c130998572ae5b4
# 9: 892b784d30e277446cf17edc3bdb9b68
# 10: 063f3daf36dd4aeb5a2c343761f7af5f
flag = b''
for i in range(2):
AES_cipher = cipher[i * 16: i * 16 + 16]
AES_plain = AES_decrypt(AES_cipher, round_keys)
for i in range(4):
AES_plain[i * 4] ^= delta[i]
TEA_cipher = AES_plain
TEA_plain = []
TEA_plain += tea_decrypt([u32(TEA_cipher[0:4]), u32(TEA_cipher[4:8])], TEA_key)
TEA_plain += tea_decrypt([u32(TEA_cipher[8:12]), u32(TEA_cipher[12:16])], TEA_key)
for num in TEA_plain:
flag += p32(num)
print(flag)
---------------感谢您的阅读---------------