ez_re
直接各种调试/Trace。输入长度是 0x38, 输入经过三次变换,第一次为 +0x40(其中存在反调试使用 x64dbg 隐藏PEB即可)
第二轮 Trace 结果是这样,看起来很复杂,其实就是三个 xor 的定义式,0xE9FCF789 ^ 0xB62DD00 ^ 0xE29E2AF6 = 0x7f,就是xor 0x7f
第三轮是一个XTEA每一步多了个 xor,轮数为 102 轮,密钥是0xEF6FD9DB, 0xD2C273D3, 0x6F97E412, 0x72BFD624,三轮加密之后在最后的cmp那把每一次要对比的值拿到,使用下面的算法解密即可
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 对应的逻辑中,存在字符串加密,使用如下脚本解密即可
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执行
解密算法一眼丁真 ChaCha20 直接使用如下脚本解密:
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 姑且算是混淆吧,改一下脚本执行一下即可得到最终的脚本,分析后解密脚本如下:
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位已经知道,前八位可以爆破
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
标签:mu,addr,2024,Writeups,key,print,import,data,强网
From: https://www.cnblogs.com/gaoyucan/p/18487297