-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.py
149 lines (122 loc) · 4.59 KB
/
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
from binaryninja import BinaryView
from binaryninja.function import Function
def is_hex_str(s):
if s[:2] == "0x":
s = s[2:]
hex_digits = set("0123456789abcdefABCDEF")
for val in s:
if not (val in hex_digits):
return False
return True
def _strip_import_name(func_name: str) -> str:
"""
Clean up a function name to only keep the import name and remove
things like the DLL name and the ordinal.
:param func_name: The name of the function to be cleaned.
:result: The import name without the extra info.
"""
fn1 = func_name.split('.')
if len(fn1) >= 2:
func_name = fn1[1].strip()
fn1 = func_name.split('#')
if len(fn1) >= 2:
func_name = fn1[0].strip()
return func_name
def _define_import_thunk(bv: BinaryView, start: int, thunk_value: int) -> None:
"""
If the binary has the Import Thunk filled, define it as a data chunk
of appropriate size.
:param bv: The current binary view.
:param start: The function start
:param thunk_value: The import thunk value.
:return: None
"""
data = bv.get_data_var_at(start)
if data:
data_value = data.value
if data_value:
if data_value == thunk_value:
bv.define_data_var(start, "void*", None)
def import_funcs_from_file(bv: BinaryView, filename: str, image_base: int) -> tuple:
"""
Read and parse the functions info from a file. The supported formats
are either CSV (default) or TAG (PE-bear, PE-sieve compatibile).
:param bv: The current binary view.
:param filename: The name of the file to save the funcs info.
:return: A tuple containing the number of functions and comments
defined.
"""
funcs_start_list = [f.start for f in bv.functions]
delim = "," # New delimiter (for CSV format)
delim2 = ":" # Old delimiter
rva_index = 0
func_name_index = 1
is_imp_list = False
if ".imports.txt" in filename:
is_imp_list = True
func_name_index = 2
if ".tag" in filename:
delim2 = ";"
functions = 0
comments = 0
with open(filename, "r") as f:
for line in f.readlines():
line = line.strip()
func_entry = line.split(delim)
if len(func_entry) < 2:
# Try the old delimiter
func_entry = line.split(delim2)
if len(func_entry) < 2:
continue
start = 0
addr_chunk = func_entry[rva_index].strip()
if not is_hex_str(addr_chunk):
continue
try:
start = int(addr_chunk, 16)
except ValueError:
# This line doesn't start from an offset, so skip it
continue
func_name = func_entry[func_name_index].strip()
# Check if its an RVA and if so, convert to VA
if start < image_base:
start = image_base + start
if is_imp_list or (start in funcs_start_list):
if is_imp_list:
func_name = _strip_import_name(func_name)
thunk_val = int(func_entry[1].strip(), 16)
_define_import_thunk(bv, start, thunk_val)
# Rename the function
f = bv.get_function_at(start)
if isinstance(f, Function):
f.name = func_name
functions += 1
continue
# If we don't have entries for the function we just add
# a comment
bv.set_comment_at(start, func_name)
comments += 1
return functions, comments
def save_funcs_to_file(bv: BinaryView, filename: str, extension: str) -> None:
"""
Save the function names and RVA into a file. The supported formats
are either CSV (default) or TAG (PE-bear, PE-sieve compatibile).
:param bv: The current binary view.
:param filename: The name of the file to save the funcs info.
:param extension: The extension to use.
:return: None
"""
func_list = []
delim = ","
if ".tag" in extension:
delim = ";"
for f in bv.functions:
va = f.start
image_base = bv.start
rva = va - image_base
func_name = f.symbol.short_name
line = "%lx%c%s" % (rva, delim, func_name)
func_list.append(line)
with open(filename, 'w') as f:
for item in func_list:
f.write("%s\n" % item)