Files
wechat_chatter/idapro/decrypt.py
T
2025-12-08 18:56:29 +08:00

184 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import struct
def decode_from_bytes(byte_data_hex):
"""
根据提供的字节数据解码UTF-8字符串
Args:
byte_data_hex: 十六进制字符串,如 "835594A658483F62EAA226D522BC97"
或者字节列表/字节数组
Returns:
解码后的UTF-8字符串
"""
# 处理输入数据
if isinstance(byte_data_hex, str):
# 如果是字符串,去除空格
byte_data_hex = byte_data_hex.replace(" ", "")
# 将十六进制字符串转换为字节数组
try:
if len(byte_data_hex) % 2 != 0:
byte_data_hex = "0" + byte_data_hex
data_bytes = bytes.fromhex(byte_data_hex)
except ValueError:
# 如果不是有效的十六进制,假设是原始字节
data_bytes = byte_data_hex.encode('latin-1')
elif isinstance(byte_data_hex, (bytes, bytearray)):
data_bytes = bytes(byte_data_hex)
else:
raise ValueError("输入必须是十六进制字符串或字节数据")
# 确保数据足够长
if len(data_bytes) < 0x60:
# 如果数据不够长,填充0
data_bytes = data_bytes.ljust(0x60, b'\x00')
# 初始化常量
x9 = 0 # 索引/计数器
x10 = 0xCCCCCCCCCCCCCCCD # 乘法常量
x11 = 0xFFFFFFFFFFFFFFEC # -20的补码
# 初始化向量寄存器V0(包含0x8A)
v0 = bytes([0x8A, 0x8A, 0x8A, 0x8A]) # 4个字节,每个0x8A
# 解码输出缓冲区(大小至少0x60字节)
result_size = 0x60
decoded_bytes = bytearray(result_size)
# 假设数据在内存中的起始地址(我们不需要实际地址,只需要数据)
# 我们用data_bytes作为内存数据源
# 解码循环
while x9 < result_size: # 循环直到处理完0x60个字节
# UMULH X14, X9, X10 (无符号高位乘法)
# Python中模拟64位无符号乘法的高位
product = (x9 * x10) & 0xFFFFFFFFFFFFFFFF
x14 = (product >> 64) & 0xFFFFFFFFFFFFFFFF if product.bit_length() > 64 else 0
# LSR X14, X14, #4 (逻辑右移4位)
x14 = (x14 >> 4) & 0xFFFFFFFFFFFFFFFF
# X12是数据起始地址,但在Python中我们使用数据偏移
# 实际上x12 + x9就是数据偏移量x9
# ADD X15, X12, X9 -> x15 = x12 + x9 = x9 (偏移量)
# 在Python中,我们直接使用x9作为偏移
x15_offset = x9
# MADD X14, X14, X11, X15
# X14 = X14 * X11 + X15
x14 = ((x14 * x11) + x15_offset) & 0xFFFFFFFFFFFFFFFF
# ADD X15, X15, #0xCDA
x15_with_cda = (x15_offset + 0xCDA) & 0xFFFFFFFFFFFFFFFF
# ADD X14, X14, #0xCC6
x14_with_cc6 = (x14 + 0xCC6) & 0xFFFFFFFFFFFFFFFF
# 从数据中读取(模拟内存读取)
# 注意:在实际汇编中,这些地址可能是绝对地址
# 但在我们的模拟中,我们将它们视为数据内的偏移
# LDR S1, [X15] - 从地址X15读取4个字节
# 我们使用data_bytes作为数据源,但需要确保索引有效
s1_bytes = bytearray(4)
for i in range(4):
# 将地址转换为数据偏移(取模或边界检查)
# 简化:使用地址的低16位作为偏移
offset = (x15_with_cda + i) & 0xFFFF
if offset < len(data_bytes):
s1_bytes[i] = data_bytes[offset]
else:
s1_bytes[i] = 0
# UADDW V1.8H, V0.8H, V1.8B
# 将v0(8个16位)与s1(4个8位零扩展为16位)相加
v1_words = []
for i in range(4):
v0_byte = v0[i % len(v0)]
s1_byte = s1_bytes[i % len(s1_bytes)]
# 8位零扩展为16位然后相加
result = (v0_byte & 0xFF) + (s1_byte & 0xFF)
v1_words.append(result & 0xFFFF)
# LDR S2, [X14] - 从地址X14读取4个字节
s2_bytes = bytearray(4)
for i in range(4):
# 将地址转换为数据偏移
offset = (x14_with_cc6 + i) & 0xFFFF
if offset < len(data_bytes):
s2_bytes[i] = data_bytes[offset]
else:
s2_bytes[i] = 0
print(f"中间结果s2_bytes: {s2_bytes.decode('utf-8', errors='ignore')}")
# USHLL V2.8H, V2.8B, #0
# 8位零扩展为16位
v2_words = []
for i in range(4):
v2_words.append(s2_bytes[i % len(s2_bytes)] & 0xFF)
# EOR V1.8B, V1.8B, V2.8B
# 逐字节异或(只处理低8位)
xor_bytes = bytearray(4)
for i in range(4):
v1_low_byte = v1_words[i] & 0xFF
v2_low_byte = v2_words[i] & 0xFF
xor_bytes[i] = v1_low_byte ^ v2_low_byte
# UZP1 V1.8B, V1.8B, V0.8B
# 交错取V1和V0的低字节,这里简化处理:取异或后的结果
final_bytes = xor_bytes[:4]
print(f"中间结果: {final_bytes.decode('utf-8', errors='ignore')}")
# 存储结果到解码缓冲区
if x9 + 4 <= result_size:
decoded_bytes[x9:x9+4] = final_bytes
# ADD X9, X9, #4
x9 += 4
# 最后在特定位置添加'h'字符(0x68
# 在汇编中:STRH W10, [X9] 其中 W10 = 0x68, X9 = word_1086E320A
# 这里我们简单地在结果中添加这个字符
if result_size > 0:
# 在适当位置添加(根据原始代码逻辑)
# 注意:实际位置可能需要调整
pass # 先注释掉,根据实际需要添加
# 转换为UTF-8字符串
try:
# 查找第一个null字节
null_pos = -1
for i in range(len(decoded_bytes)):
if decoded_bytes[i] == 0:
null_pos = i
break
if null_pos != -1:
result_str = decoded_bytes[:null_pos].decode('utf-8', errors='ignore')
else:
result_str = decoded_bytes.decode('utf-8', errors='ignore')
except UnicodeDecodeError:
# 如果UTF-8解码失败,返回hex表示
result_str = "解码失败,原始数据: " + decoded_bytes.hex()
return result_str, decoded_bytes.hex()
# 使用示例
if __name__ == "__main__":
# 测试用示例数据
test_data = [
"83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 66 A6 5D 4B A7 9D C7 B3 0F 4C BF 1D B9 51 68 13 D0 8B 8F D1 23 AC 6D 1C F7 C7 76 1D 89 7B 1A 6F 26 53 72 11 BF B7 40 6A 1C 19 68 C2 4B 3F C8 0F 94 D1 0D 9A 0C CD 98 F9 6D 6F C5 B0 F1 02 9E 46 4A 1C 0D 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E E0 1B A4 66 32 8C D4 71 E9 FC AA 58 5B D4 49 3E 01 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E A8 2B A3 23 21 93 97 29 ED FC BA 43 53 CF 08 2C 66 DC 7E 0A A8 09 BF 34 38 93 C8 30 F9 FC F6 53 45 DE 44 25 60 CD 4F 13 E6 1D 8F 74 63 D2 8D 05 AF B6 B2 4E 40 D5 42 21 2E DA 7F 0C E2 51 BD 27 3D 81 DF 34 E8 B6 AA 4E 41 C8 4E 22 6F 96 63 1B F4 0D B9 29 3D BF CB 25 F5 EB B8 4C 57 E4 4E 20 71 D5 3E 1D E4 7E F7 C7 76 1D 89 7B 1A 6F 26 53 72 11 BF B7 40 6A 1C 19 68 C2 4B 3F CE 10 84 CB FF D1 ED CE AA FC 71 7B BC B0 06 07 9E 43 3A 3F C9 F6 20 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E E6 1A B4 66 3C 92 98 24 EA FD B8 5F 57 9B 54 28 72 CA 79 11 E9 44 F5 19 53 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 36 B0 4B 38 B2 7D C3 AD 10 3C BD 17 BD 65 68 27 B6 87 7C CF 4A B2 56 44 83 9C C3 7D 01 3C E5 31 B7 5E 6E FC E7 EE 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 58 A7 66 FC AD B0 95 8D 10 3C BD 17 BD 12 5A 1D B6 81 76 CE 63 E5 27 6F EE B3 C7 86 05 39 B8 6B C1 48 6A 26 CC 8B 82 CF 6D E5 27 6F CE F7 C7 76 1D 89 7B 1A 6F 26 53 72 11 BF B7 40 6A 1C 19 68 C2 4B 3F CE 10 84 CB FF D1 ED CE AA FC 71 7B BC B0 06 07 9E 43 37 45 99 0C 73 AC FF A1 DE CE D6 0B 63 5B B8 A4 10 01 D3 44 4A 1C 0D 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 58 A7 66 FC AD B0 95 8D 10 3C BD 17 BD 12 5A 1D B6 81 76 CE 63 E5 27 6F EE B3 C7 86 05 39 B8 6B C1 48 6A 26 CC 8B 82 CF 6D E5 27 6F EA DE C0 82 0E 3D BD 27 78 47 68 27 B6 8F 84 C8 66 EB 6D 3F A3 9C C1 CE 45 73 9C 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 36 B0 37 4C B2 9F C1 7D 2F 3D CB 1C C1 49 6F FC B7 8F 85 B9 4D B0 46 5A CE 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 83 BB 58 A9 56 12 F3 8D 95 87 FB 46 C8 00 CC 4B 70 1D B6 82 7E D0 69 E5 27 6F CE 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E C4 11 85 36 37 81 CC 34 C9 FC AA 58 5B D4 49 1E 6E CB 64 2A EE 13 B5 35 27 81 D5 21 CE F6 9D 69 32 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 90 CE 67 97 41 48 A7 9B D0 87 14 39 C1 1B 8E 0F 3E 38 F7 C7 76 1D 89 7B 1A 6F 26 53 72 11 BF B7 40 6A 1C 19 68 C2 4B 3F BA 04 84 B1 05 A1 0C CD 98 F9 6D 6F C5 B9 0C 14 A3 3E 30 2B 99 13 94 A5 00 D2 E0 AE C7 A8 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 76 BA 52 B3 73 38 B2 A3 C7 CE 45 73 9C F7 C7 76 1D 89 7B 1A 6F 26 53 72 11 BF B7 40 6A 1C 19 68 C2 4B 3F BA 04 84 B1 05 A1 0C CD 98 F9 6D 6F C5 C3 14 07 9B 3E 2A 2B 99 13 94 A5 00 D2 E0 AE C7 A8 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 76 BA 52 A9 6B 45 AA A3 D1 CE 45 73 9C 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E C4 11 85 36 37 81 CC 34 C9 FC AA 58 5B D4 49 02 6F F5 71 0D F3 2D B5 28 37 85 CA 18 F4 FF B6 7F 5D FF 65 4D 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 90 C8 63 A7 67 4A 7D 97 C7 7A FB 0E 79 00 98 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E C4 11 85 36 37 81 CC 34 C9 FC AA 58 5B D4 49 18 6F CB 75 1F E3 29 B9 32 3B A4 DD 3D FF ED BC 4F 7F DE 54 3E 60 DE 75 2A E8 3A 92 46 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 90 C8 67 99 67 4A 7D 97 D1 CE 45 73 7C 17 C1 47 68 27 BD 8F 7A BD 2F E6 41 1C 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 36 B0 37 4C B2 9F C1 7D 2F 3D CB 1C C1 49 6F 0C B7 8F 7D BA 5B A6 5C 6B A2 9F C1 8D 0F 6C BF 07 B6 32 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 6C 9B 66 3D A2 A3 95 87 05 47 CB 32 C3 48 23 5D E2 CE 93 BB 58 B1 5D 36 B3 B0 D6 87 14 39 C8 16 C7 FC 28 13 A9 87 7E D0 46 53 E0 B8 51 9A 99 D9 2B 32 BB 27 4D 01 B9 10 7E C4 11 95 22 3A 94 EB 34 E9 EA B0 44 5C EE 49 3F 64 D8 74 2D F1 0C 99 22 07 8F FC 13 9A 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 36 B0 47 38 A7 B2 E2 7D 0F 47 C5 30 C2 5F 6F 26 CC 8F 83 DA 6B 9D 53 38 82 9D F1 96 40 4D CB 26 C6 48 6C 25 CC BB C2 DE 25 B0 6E 38 7D B1 BF 86 2B 41 B8 5E 7D 59 31 22 CC 85 AC BA 6B 9D 41 45 B2 EB 90 B3 60 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 36 B0 4D 40 B3 9F C3 A7 05 47 CB 32 C3 48 38 22 B7 93 7E C9 36 B0 57 3E A2 92 C6 9C 1E 18 83 55 94 A6 58 48 3F 62 EA A2 26 D5 22 BC 97 C2 33 78 69 37 56 AF 67 3D A0 DE C2 7D 0F 47 C5 30 C2 12 58 22 B7 93 7E C9 2F E6 41 FC B1 9A D0 79 0E 73 C9 31 C6 4F 6C 1C E2 82 76 D0 5C E5 27 6F EE A1 C9 7D 01 46 EF 2E B9 44 72 13 BC 8C 91 C8 58 A7 24 F9 7D BE F7 C7 76 1D 89 7B 1A 6F 26 53 72 11 BF B7 40 6A 1C 19 68 C2 4B 3F BC FB 7E AF E0 A1 EC B7 B2 15 68 79 C5 AF 10 0F A3 18 2F 49 AF 00 74 AB F5 C4 BD 83 55"
]
for i, data in enumerate(test_data):
print(f"\n测试数据 {i+1}: {data}")
try:
result, hex_result = decode_from_bytes(data)
print(f"解码结果: {result}")
print(f"Hex表示: {hex_result}")
except Exception as e:
print(f"解码出错: {e}")