-
Notifications
You must be signed in to change notification settings - Fork 29
/
extract_ghidra_decomp.py
80 lines (67 loc) · 2.27 KB
/
extract_ghidra_decomp.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
76
77
78
79
80
#!/usr/bin/env python
import ghidra_bridge
# Bring in all the Ghidra classes
bridge = ghidra_bridge.GhidraBridge(namespace=globals(), hook_import=True)
import os, json
from tqdm import tqdm
from collections import defaultdict
# Sketchy Ghidra remote imports
from ghidra.app.decompiler import DecompInterface, DecompileOptions
currentProgram = getCurrentProgram()
# Create output directory
progName = currentProgram.getName()
os.makedirs(progName, exist_ok=True)
# Map function names to their objects
funcNames = {}
# Build the call graph
callGraph = defaultdict(list)
fm = currentProgram.getFunctionManager()
functions = list(fm.getFunctions(True))
for func in tqdm(functions, desc="Building call graph"):
# Get the function name
name = func.getName()
funcNames[name] = func
for calledFunc in func.getCalledFunctions(getMonitor()):
if calledFunc.isThunk(): continue
calledName = calledFunc.getName()
if calledName == name: continue
callGraph[name].append(calledName)
callGraph = dict(callGraph)
for func in functions:
name = func.getName()
if name not in callGraph and not func.isThunk():
callGraph[name] = []
# Decompile all the functions
decompiler = DecompInterface()
# Pull decompiler options from the current program
opt = DecompileOptions()
opt.grabFromProgram(currentProgram)
decompiler.setOptions(opt)
missing = []
decompiler.openProgram(currentProgram)
decomps = {}
for func in tqdm(functions, desc="Decompiling functions"):
name = func.getName()
decompResult = decompiler.decompileFunction(func, 0, getMonitor())
decompFunc = decompResult.getDecompiledFunction()
if not decompFunc:
missing.append(name)
continue
decomps[name] = decompFunc.getC()
decompiler.closeProgram()
# Save the decompilations
with open(os.path.join(progName,"decompilations.json"), "w") as f:
json.dump(decomps, f)
f.write("\n")
# Remove missing functions from the call graph
for func in missing:
del callGraph[func]
for called in callGraph:
if func in callGraph[called]:
callGraph[called].remove(func)
print(f"Missing {len(missing)} functions:")
print(missing)
# Save the call graph
with open(os.path.join(progName,"call_graph.json"), "w") as f:
json.dump(callGraph, f)
f.write("\n")