- 双击运行可以发现有缺失的 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)
---------------感谢您的阅读---------------