-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathdependency.py
170 lines (144 loc) · 6.07 KB
/
dependency.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
'''
Code in this file deals with finding data and/or other code that must be
included in the emulation environment for the target code to be able to run
properly.
'''
from .analysis_engine import aengine as ae
# Try to import stuff.
try:
from binaryninja import *
except:
print ("[!!] Not running in Binary Ninja")
try:
import r2pipe
except:
print ("[!!] Not running in Radare2")
class ImportedCall(object):
'''
Convenience class for storing information about imported Calls.
'''
def __init__(self, address, instlen, target, symname):
self.address = address
self.inst_len = instlen
self.target = target
self.symbol = symname
class riprDataRef(object):
'''
Convenience class for storing information on data references we find.
'''
def __init__(self, address, length, _type):
self.address = address
self.length = length
self._type = _type
class riprCodeRef(object):
def __init__(self, address, _type):
self.address = address
self.type = _type
class depScanner(object):
def __init__(self, engine, codeobj):
self.engine = engine
self.codeobj = codeobj
self.impCalls = []
self.dataRefs = []
self.codeRefs = []
self.imports = self.engine.get_imports()
def _mark_imported_call(self, func_addr, address, target):
'''
Create an ImportedCall object for possible later use in "python-hooking"
Note: We /do/ want duplicates (multiple ImportedCall objects for "puts" for example)
as we map expected return addresses to our hooked functions.
'''
self.engine.highlight_instr(func_addr, address, "red")
self.engine.add_comment(func_addr, address, "Imported Call !!")
symname = str(target)
if target in self.imports.keys():
symname = self.imports[target]
icall = ImportedCall(address, self.engine.get_instruction_length(address), target, symname)
self.impCalls.append(icall)
def _mark_additional_branch(self, func_addr, address, destination, _type):
ref = riprCodeRef(destination, _type)
self.engine.highlight_instr(func_addr, address, "blue")
self.codeRefs.append(ref)
def _mark_identified_data(self, func_addr, ref_addr):
self.engine.highlight_instr(func_addr, ref_addr, "yellow")
def branchScan(self, address, isFunc=True):
'''
Function is responsible for mapping calls and jumps
that are outside the current selection's bounds, if possible.
'''
print ("[ripr] Inside branchScan")
def callCallback(dest, instr_addr):
if type(dest) != int:
try:
dest = dest.value
except:
return
if (dest in self.imports):
print ("[ripr] Found imported Call target...")
self._mark_imported_call(address, instr_addr, dest)
elif (self.codeobj.data_saved(dest) == False):
print ("[ripr] Found LLIL CALL instruction")
self._mark_additional_branch(address, instr_addr, dest, "call")
else:
print ("[ripr] Target address already mapped")
def jumpCallback(dest, instr_addr):
print ("[ripr] JUMP TARGET: %s" % (dest))
if isFunc:
self.engine.branches_from_func(address, callCallback, jumpCallback)
else:
ibb = self.engine.find_llil_block_from_addr(address)
if ibb == None:
return self.codeRefs
self.engine.branches_from_block(ibb, callCallback, jumpCallback)
return self.codeRefs
def _find_stringRefs(self, address):
'''
Look for strings that are referenced in the selected code.
'''
ret = []
for stringStart,stringLength in self.engine.get_strings():
for refAddress in self.engine.get_refs_to(stringStart): # Ignored the length
if (self.engine.function_contains_addr(address, refAddress)):
print ("[ripr] Found string reference: 0x%x" % (refAddress))
self._mark_identified_data(address, refAddress)
dref = riprDataRef(stringStart, stringLength, 'str')
self.dataRefs.append(dref)
return ret
def _find_symbolRefs(self, address):
'''
Look for data symbols that are referenced in the selected code.
'''
ret = []
symbols = self.engine.get_data_symbols()
for symStart in symbols:
for refAddress in self.engine.get_refs_to(symStart):
if self.engine.function_contains_addr(address, refAddress):
print ("[ripr] Found Symbol Reference: 0x%x references 0x%x" % (refAddress, symStart))
self._mark_identified_data(address, refAddress)
dref = riprDataRef(symStart, -1, 'sym')
self.dataRefs.append(dref)
ret.append(symStart)
return ret
def _simpleDataScan(self, address):
ret = []
ret += self._find_stringRefs(address)
ret += self._find_symbolRefs(address)
return ret
def dataScan(self, address):
'''
Function is responsible for finding data the target code
needs in order to run correctly.
'''
print ("[ripr] Inside dataScan")
ret = []
# Find the low-hanging fruit
ret += self._simpleDataScan(address)
# Iterate over all instructions for potential pointers
for target, instrAddr in self.engine.scan_potential_pointers(address):
if self.engine.is_plausible_pointer(target):
print ("Found Potential Pointer: %s instaddr %s" % (hex(target), hex(instrAddr)))
self._mark_identified_data(address, instrAddr)
dref = riprDataRef(target, -1, 'ptr')
self.dataRefs.append(dref)
ret.append(target)
return set(ret)