-
Notifications
You must be signed in to change notification settings - Fork 2
/
ghidra_utils.py
127 lines (101 loc) · 3.73 KB
/
ghidra_utils.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# Gross, but seems to be the way to get the ghidra apis/values from an external module
from __main__ import currentProgram, monitor
from array import array
from ghidra.program.model.symbol import SourceType
from ghidra.program.flatapi import FlatProgramAPI
from ghidra.app.decompiler import DecompInterface
flatProgramAPI = FlatProgramAPI(currentProgram)
toAddr = flatProgramAPI.toAddr
getFunctionContaining = flatProgramAPI.getFunctionContaining
getNamespace = flatProgramAPI.getNamespace
memory = currentProgram.getMemory()
symbolTable = currentProgram.getSymbolTable()
namespaceManager = currentProgram.getNamespaceManager()
globalNamespace = namespaceManager.getGlobalNamespace()
decomp = DecompInterface()
decomp.openProgram(currentProgram)
def bytesToByteStr(bytes):
encoded_bytes = map(lambda byte : chr(byte), bytes)
return ''.join(encoded_bytes)
def bytesToByteArr(bytes):
return array('b', bytesToByteStr(bytes))
def findByteArray(bytes, mask = None):
result = []
addr = toAddr(0)
byte_arr = bytesToByteArr(bytes)
mask_arr = None
if mask is not None:
mask_arr = bytesToByteArr(mask)
while True:
addr = memory.findBytes(addr.add(len(bytes)), byte_arr, mask_arr, True, monitor)
if addr is not None:
result.append(addr)
else:
return result
def findFirstByteArray(bytes, mask = None):
byte_arr = bytesToByteArr(bytes)
mask_arr = None
if mask is not None:
mask_arr = bytesToByteArr(mask)
return memory.findBytes(toAddr(0), byte_arr, mask_arr, True, monitor)
def readBytes(addr, len):
byteArray = bytesToByteArr([0 for i in range(len)])
memory.getBytes(addr, byteArray)
return byteArray
def forceSetVariableName(variable, name):
while True:
try:
variable.setName(name, SourceType.USER_DEFINED)
break
except:
name = '_' + name
return name
def decompileContainingFunction(addr):
func = getFunctionContaining(addr)
return decomp.decompileFunction(func, 60, monitor), func
def getOrCreateNamespace(namespace_name, parent_namespace = globalNamespace):
namespace = getNamespace(parent_namespace, namespace_name)
if namespace is not None:
return namespace
return symbolTable.createNameSpace(parent_namespace, namespace_name, SourceType.USER_DEFINED)
def getOrCreateNestedNamespace(str, parent_namespace):
namespaces = str.split('::')
current_parent = parent_namespace
for namespace in namespaces:
if len(namespace) > 0:
current_parent = getOrCreateNamespace(namespace, current_parent)
return current_parent
def nameCtrFunc(func, name):
split_name = name.split('::')
base_name = split_name[-1]
namespace = '::'.join(split_name[:-1])
ctr_namespace = getOrCreateNamespace('ctr')
func_namespace = getOrCreateNestedNamespace(namespace, ctr_namespace)
func.setName(base_name, SourceType.USER_DEFINED)
func.setParentNamespace(func_namespace)
print('Named {} to {}'.format(func.getEntryPoint(), base_name))
def getCallArgs(caller_func, callee_addr):
decompiled_func = decomp.decompileFunction(caller_func, 60, monitor)
high_func = decompiled_func.getHighFunction()
if not high_func:
return []
opiter = high_func.getPcodeOps()
while opiter.hasNext():
op = opiter.next()
mnemonic = str(op.getMnemonic())
if mnemonic == 'CALL':
inputs = op.getInputs()
addr = inputs[0].getAddress()
if addr == callee_addr:
return inputs[1:]
return []
def getCallArgsFromRef(call_ref):
from_addr = call_ref.getFromAddress()
to_addr = call_ref.getToAddress()
func = getFunctionContaining(from_addr)
return getCallArgs(func, to_addr)
def getValueFromConstantVarnode(varnode):
addr = varnode.getAddress()
if addr.isConstantAddress():
return addr.getOffset()
return None