-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathmake_hash_db.py
75 lines (57 loc) · 2.43 KB
/
make_hash_db.py
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
import glob
import json
import os
from collections import defaultdict
from functools import partial
import pefile
API_XOR_KEY = 0x5a80eae
LIB_XOR_KEY = 0x1fc325da
INTERESTING_DLLS = [
'kernel32.dll', 'comctl32.dll', 'advapi32.dll', 'comdlg32.dll',
'gdi32.dll', 'msvcrt.dll', 'netapi32.dll', 'ntdll.dll',
'ntoskrnl.exe', 'oleaut32.dll', 'psapi.dll', 'shell32.dll',
'shlwapi.dll', 'srsvc.dll', 'urlmon.dll', 'user32.dll',
'winhttp.dll', 'wininet.dll', 'ws2_32.dll', 'wship6.dll',
'advpack.dll', 'crypt32.dll', 'userenv.dll', 'wtsapi32.dll'
]
def calc_hash(name, key):
value = 0
for c in name:
value = (ord(c) + value * 0x1003f) & 0xffffffff
return value ^ key
def get_export_api(dllpath):
pe = pefile.PE(dllpath)
if ((not hasattr(pe, "DIRECTORY_ENTRY_EXPORT")) or (pe.DIRECTORY_ENTRY_EXPORT is None)):
raise RuntimeError(f'{dllpath} doesn\'t have export table')
for sym in pe.DIRECTORY_ENTRY_EXPORT.symbols:
if sym.name is not None:
yield sym.name.decode('utf-8')
def main():
import argparse
p = argparse.ArgumentParser()
p.add_argument('--lib-key', dest='lib_key', default=LIB_XOR_KEY, type=lambda x: int(x, 0), help='XOR key for lib name hashing')
p.add_argument('--api-key', dest='api_key', default=API_XOR_KEY, type=lambda x: int(x, 0), help='XOR key for API hashing')
args = p.parse_args()
# partially apply calc_hash function with XOR key
emotet_xor_for_lib = partial(calc_hash, key=args.lib_key)
emotet_xor_for_api = partial(calc_hash, key=args.api_key)
results = defaultdict(dict)
# enumerate all .dll files in %windir%\system32
target_path = os.path.join(os.environ.get('windir'), 'system32')
for dll_filepath in glob.glob(os.path.join(target_path, '*.dll')):
dllname = os.path.basename(dll_filepath)
# filter uninteresting dlls for easy use
if dllname.lower() not in INTERESTING_DLLS:
continue
# calc hash of dll name
hashed_dllname = emotet_xor_for_lib(dllname.lower())
results[hex(hashed_dllname)] = dllname
# calc hash of each API name in DLL
for api in get_export_api(dll_filepath):
hashed_api = emotet_xor_for_api(api)
results[hex(hashed_api)] = api
# dump tp json file
with open('db.json', 'w') as f:
json.dump(results, f, indent=4)
if __name__ == '__main__':
main()