Skip to content

Commit 37bc67e

Browse files
authored
Merge pull request #17 from sportshead/ghidra-getkey
feat: port getkey to ghidra Jython
2 parents 9bd40a4 + 8e57d7f commit 37bc67e

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

ghidra/ghidra_getkey.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# @author
2+
# @category Analysis
3+
# @keybinding
4+
# @menupath
5+
# @toolbar
6+
7+
"""Ghidra Jython implementation of "get_key_via_md5" for statically obtaining key."""
8+
9+
import hashlib
10+
import struct
11+
from ghidra.program.model.address import Address
12+
from ghidra.program.model.mem import MemoryAccessException
13+
14+
# This string is a unique license ID of the person who obfuscated the script, in the free version it would always be 000000 and in paid versions its unique per person
15+
PYARMOR_STRING = b"pyarmor-vax-000000\x00\x00"
16+
17+
# References to these are in the "get_key_via_md5" function
18+
"""
19+
md5_process(auStack_1c8,s_pyarmor-vax-000000_003bc98c,0x14);
20+
md5_process(auStack_1c8,&DAT_003bc9c0 + DAT_003bc9b0,(long)DAT_003bc9b4);
21+
"""
22+
INFO_BLOB_ADDR = 0x003BC9C0
23+
24+
# First xmmword that is xored:
25+
# puVar1 = (ulong *)&DAT_003bc860;
26+
27+
# md5_process(auStack_1c8,&DAT_003bc860,0x10e);
28+
# ^ addr ^ size
29+
RSA_KEY2_ADDR = 0x003BC860
30+
RSA_KEY2_SIZE = 0x10E
31+
32+
# Byte value that RSA_KEY2 is xored with
33+
RSA_XOR_KEY = 0xF1
34+
35+
36+
# https://gist.github.com/c3rb3ru5d3d53c/de02e869f64a551bfcd78fb318668292
37+
def get_address(addr):
38+
return currentProgram.getAddressFactory().getAddress(str(hex(addr)))
39+
40+
41+
def get_bytes(addr, size):
42+
address = get_address(addr)
43+
return bytearray(map(lambda b: b & 0xFF, getBytes(address, size)))
44+
45+
46+
def read_dword(addr):
47+
b = get_bytes(addr, 4)
48+
return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]
49+
50+
51+
md = hashlib.md5()
52+
md.update(PYARMOR_STRING)
53+
54+
rsakey_size = read_dword(INFO_BLOB_ADDR - 0xC)
55+
print("RSA Key size: 0x%x" % rsakey_size)
56+
57+
rsakey = get_bytes(INFO_BLOB_ADDR + 0x20, rsakey_size)
58+
59+
sig_offset = read_dword(INFO_BLOB_ADDR - 0x8)
60+
print("Signature offset: 0x%x" % sig_offset)
61+
62+
hashed_area_size = read_dword(INFO_BLOB_ADDR + sig_offset + 4)
63+
print("Hashed area size: 0x%x" % hashed_area_size)
64+
65+
hashed_area = get_bytes(INFO_BLOB_ADDR + sig_offset + 0x20, hashed_area_size)
66+
67+
rsakey2_raw = get_bytes(RSA_KEY2_ADDR, RSA_KEY2_SIZE)
68+
rsakey2 = bytearray([b ^ RSA_XOR_KEY for b in rsakey2_raw])
69+
70+
md.update(str(rsakey))
71+
md.update(str(hashed_area))
72+
md.update(str(rsakey2))
73+
74+
print("MD5 Hash: " + md.hexdigest())

0 commit comments

Comments
 (0)