## ez_re 直接各种调试/Trace。输入长度是 0x38, 输入经过三次变换,第一次为 +0x40(其中存在反调试使用 x64dbg 隐藏PEB即可) ![](https://md.buptmerak.cn/uploads/e4fe69d6-8134-4bc3-9726-84df5b641a64.png) 第二轮 Trace 结果是这样,看起来很复杂,其实就是三个 xor 的定义式,0xE9FCF789 ^ 0xB62DD00 ^ 0xE29E2AF6 = 0x7f,就是xor 0x7f ![](https://md.buptmerak.cn/uploads/df3b077f-0698-4ca2-a587-fa4123db64c4.png) 第三轮是一个XTEA每一步多了个 xor,轮数为 102 轮,密钥是0xEF6FD9DB, 0xD2C273D3, 0x6F97E412, 0x72BFD624,三轮加密之后在最后的cmp那把每一次要对比的值拿到,使用下面的算法解密即可 ```C void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) { unsigned int i; uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds; for (i = 0; i < num_rounds; i++) { v1 -= (((((((v0 << 4) ^ 0x770A8C91) ^ ((v0 >> 5) ^ 0x66527758)) ^ 0x1158FBC9) + v0) ^ 0xBB111015) ^ ((sum + key[(sum >> 11) & 3]) ^ 0x4B1C1A2)) ^ 0xBFA0D1B7; sum -= delta; v0 -= (((((((v1 << 4) ^ 0xB7ECF4CD) ^ ((v1 >> 5) ^ 0x2B530BC8)) ^ 0x9CBFFF05) + v1) ^ 0xE323445C) ^ ((sum + key[sum & 3]) ^ 0x6C6EBD5F)) ^ 0x8F4DF903; } v[0] = v0; v[1] = v1; } int main(void) { uint32_t key[4] = { 0xEF6FD9DB, 0xD2C273D3, 0x6F97E412, 0x72BFD624 }; uint8_t final_data[0x38] = {0xFFFFFFA1, 0xFFFFFFE3, 0x51, 0xFFFFFF98, 0xFFFFFF86, 0x56, 0x76, 0x49, 0x6F, 0x6B, 0x2B, 0xFFFFFF81, 0xFFFFFFCF, 0xFFFFFFCE, 0x12, 0xFFFFFF96, 0xFFFFFFA2, 0x70, 0x35, 0x3C, 0x31, 0x62, 0x5C, 0xFFFFFFF1, 0xFFFFFFFA, 0x77, 0x6B, 0xFFFFFFAA, 0xFFFFFF9E, 0x6D, 0x5, 0xFFFFFFBE, 0xFFFFFFE8, 0x24, 0xFFFFFFA4, 0xFFFFFFF8, 0xFFFFFFDB, 0x23, 0x3A, 0xB, 0x16, 0x20, 0xFFFFFFCC, 0x3, 0xFFFFFFAD, 0xFFFFFFB5, 0x2B, 0xFFFFFFA9, 0x34, 0xFFFFFF9F, 0x78, 0x1D, 0x2E, 0xFFFFFFB9, 0xFFFFFFF9, 0xFFFFFF9E}; for (int i = 0; i < 0x38; ++i) { printf("%02X ", final_data[i]); } printf("\n"); for (int i = 0; i < 0x38; i += 8) { decipher(102, (uint32_t *) (final_data + i), key); for (int j = 0; j < 8; ++j) { final_data[i + j] ^= 0x7f; final_data[i + j] -= 0x40; } } for (int i = 0; i < 0x38; ++i) { printf("%02X ", final_data[i]); } printf("\n"); puts(final_data); return 0; } ``` ## A_game 在 0x1b 对应的逻辑中,存在字符串加密,使用如下脚本解密即可 ```Python from idaapi import * from idautils import * import ida_xref for xref in XrefsTo(0x7FF6D7B2419A, ida_xref.XREF_ALL): if xref.type == 17 and 'rcx' in print_operand(xref.frm - 7, 0): str_addr = get_operand_value(xref.frm - 7, 1) print(hex(str_addr)) while True: t = get_byte(str_addr) if t == 0: break patch_byte(str_addr, (t ^ 0x11) - 34) str_addr += 1 ``` 解密后发现从game.data里解密出来了一个game.ps1使用pwoershell执行 ![](https://md.buptmerak.cn/uploads/bfdfa361-1a0b-4db1-96f7-9fe558c9686e.png) 解密算法一眼丁真 ChaCha20 直接使用如下脚本解密: ```python from Crypto.Cipher import ChaCha20 chacha = ChaCha20.new(key=b'powerpowerpowerpowerpowerpowerpo', nonce=b'powerpowerpo') with open('game.data', 'rb') as f: data = chacha.decrypt(f.read()) with open('game.ps', 'wb') as f1: f1.write(data) ``` PowerShell 脚本有三层 iex 姑且算是混淆吧,改一下脚本执行一下即可得到最终的脚本,分析后解密脚本如下: ```python def de3(e): key = [0x70, 0x30, 0x77, 0x33, 0x72] # Another key 'p0w3r' in hex for k in range(len(e)): e[k] = e[k] // key[k % len(key)] return e def de2(e): key = [0x70, 0x30, 0x77, 0x65, 0x72] # Different key 'p0wer' in hex for k in range(len(e)): e[k] = e[k] - key[k % len(key)] return e def de1(e): print(e) m = bytes(e[:-5]) key = bytes(e[-5:]) # for i in range(len(m)): key = ARC4.new(m).decrypt(key) m = ARC4.new(key).decrypt(m) return m result = [38304, 8928, 43673, 25957 , 67260, 47152, 16656, 62832 , 19480 , 66690, 40432, 15072 , 63427 , 28558 , 54606, 47712 , 18240 , 68187 , 18256, 63954 , 48384, 14784, 60690 , 21724 , 53238 , 64176 , 9888 , 54859 , 23050 , 58368 , 46032 , 15648 , 64260 , 17899 , 52782 , 51968 , 12336 , 69377 , 27844 , 43206 , 63616] flag = de1(de2(de2(de2(de3(de2(de2(result))))))) print(flag) ``` ## baby_re 前面就一标准AES没什么可说的,后面把AES的输出每字节输出为 12 个二进制数,前 8 个是字节的二进制表示,后面的4个是idx,因为后4位已经知道,前八位可以爆破 ```python code = """ 8b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b008945f48b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40048945f08b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40088945ec8b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b400c8945e88b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40108945e48b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40148945e08b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40188945dc8b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b401c8945d88b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40208945d48b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40248945d08b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b40288945cc8b45f84863d04889d04801c04801d048c1e0044889c2488b45104801d08b402c8945c8837dc8000f94c00fb6d08b45f42345f02345ec89c1837de8000f94c00fb6c021c82345e42345e089c1837ddc000f94c00fb6c021c1837dd8000f94c00fb6c021c1837dd4000f94c00fb6c021c1837dd0000f94c00fb6c021c82345cc89c1837df0000f94c00fb6c02345f44189c0837dec000f94c00fb6c04121c0837de8000f94c00fb6c04121c0837de4000f94c00fb6c04421c02345e04189c0837ddc000f94c00fb6c04421c02345d84189c0837dd4000f94c00fb6c04421c02345d04189c0837dcc000f94c00fb6c04421c009c14189c88b45f40b45f00b45ec85c00f94c00fb6c02345e889c1837de4000f94c00fb6c021c1837de0000f94c00fb6c021c1837ddc000f94c00fb6c021c82345d82345d42345d089c1837dcc000f94c00fb6c021c84109c0837df0000f94c00fb6c02345f42345ec2345e889c1837de4000f94c00fb6c021c1837de0000f94c00fb6c021c82345dc89c1837dd8000f94c00fb6c021c1837dd4000f94c00fb6c021c82345d02345cc4409c089d121c18b45f40b45f085c00f94c00fb6c02345ec2345e889c2837de4000f94c00fb6c021d02345e02345dc89c2837dd8000f94c00fb6c021d02345d42345d089c2837dcc000f94c00fb6c021d02345c809c1837df0000f94c00fb6c02345f42345ec2345e82345e489c2837de0000f94c00fb6c021d02345dc89c2837dd8000f94c00fb6c021d02345d489c2837dd0000f94c00fb6c021c2837dcc000f94c00fb6c021d02345c809c1837df4000f94c00fb6c02345f089c2837dec000f94c00fb6c021d02345e82345e489c2837de0000f94c00fb6c021d02345dc2345d82345d489c2837dd0000f94c00fb6c021c2837dcc000f94c00fb6c021c2837dc8000f94c00fb6c021d009c18b45f42345f089c2837dec000f94c00fb6c021c2837de8000f94c00fb6c021d02345e42345e02345dc2345d82345d489c2837dd0000f94c00fb6c021d02345cc2345c809c1837df0000f94c00fb6c02345f489c2837dec000f94c00fb6c021c2837de8000f94c00fb6c021d02345e42345e02345dc2345d889c2837dd4000f94c00fb6c021c2837dd0000f94c00fb6c021c2837dcc000f94c00fb6c021d02345c809c18b45f40b45f00b45ec0b45e80b45e485c00f94c00fb6c02345e089c2837ddc000f94c00fb6c021c2837dd8000f94c00fb6c021c2837dd4000f94c00fb6c021d02345d089c2837dcc000f94c00fb6c021d02345c809c1837df4000f94c00fb6c02345f089c2837dec000f94c00fb6c021c2837de8000f94c00fb6c021d02345e42345e089c2837ddc000f94c00fb6c021c2837dd8000f94c00fb6c021c2837dd4000f94c00fb6c021d02345d02345cc2345c809c18b45f40b45f00b45ec85c00f94c00fb6c02345e889c2837de4000f94c00fb6c021c2837de0000f94c00fb6c021d02345dc89c2837dd8000f94c00fb6c021c2837dd4000f94c00fb6c021c2837dd0000f94c00fb6c021c2837dcc000f94c00fb6c021c2837dc8000f94c00fb6c021d009c18b45f42345f089c2837dec000f94c00fb6c021c2837de8000f94c00fb6c021c2837de4000f94c00fb6c021c2837de0000f94c00fb6c021d02345dc89c2837dd8000f94c00fb6c021c2837dd4000f94c00fb6c021c2837dd0000f94c00fb6c021d02345cc2345c809c1837df4000f94c00fb6c02345f089c2837dec000f94c00fb6c021c2837de8000f94c00fb6c021d02345e489c2837de0000f94c00fb6c021c2837ddc000f94c00fb6c021c2837dd8000f94c00fb6c021d02345d42345d02345cc2345c809c1837df4000f94c00fb6c02345f089c2837dec000f94c00fb6c021c2837de8000f94c00fb6c021d02345e489c2837de0000f94c00fb6c021d02345dc89c2837dd8000f94c00fb6c021d02345d489c2837dd0000f94c00fb6c021d02345cc89c2837dc8000f94c00fb6c021d009c18b45f40b45f00b45ec0b45e885c00f94c00fb6c02345e489c2837de0000f94c00fb6c021d02345dc89c2837dd8000f94c00fb6c021d02345d42345d02345cc89c2837dc8000f94c00fb6c021d009c8 """ code = bytes.fromhex(code) from unicorn import * from unicorn.x86_const import * import struct mu = Uc(UC_ARCH_X86, UC_MODE_64) mu.mem_map(0x100000, 0x2000) mu.mem_map(0x200000, 0x2000) mu.mem_map(0x400000, 0x10000) mu.mem_write(0x402116, code) rbp_val = 0x100100 bool_arr_addr = 0x200000 # mu.reg_write(UC_X86_REG_RIP, 0x402116) mu.reg_write(UC_X86_REG_RBP, rbp_val) # 参数 mu.mem_write(rbp_val + 16, struct.pack("<Q", bool_arr_addr)) # idx mu.mem_write(rbp_val - 8, b'\x00' * 4) # 写入参数值 # mu.mem_write() arr = [0] * 16 for i in range(16): for j in range(256): for k in range(8): mu.mem_write(bool_arr_addr + 4 * k, struct.pack("<I", (j >> (7 - k)) & 1)) for k in range(4): mu.mem_write(bool_arr_addr + 4 * k + 32, struct.pack("<I", (i >> (3 - k)) & 1)) mu.emu_start(0x402116, 0x402116 + len(code)) if 1 == mu.reg_read(UC_X86_REG_EAX): print(i, j) arr[i] = j break print(arr) from Crypto.Cipher import AES flag = AES.new(bytes.fromhex('3577402ECCA44A3F9AB72182F9B01F35'), AES.MODE_ECB).decrypt(bytes(arr)) print('-'.join([f'{i:02x}' for i in flag])) # 4d87ef03-77bb-491a-80f5-4620245807c4 ```