Skip to content

Commit a7ba62e

Browse files
committed
percent
0 parents  commit a7ba62e

37 files changed

+6511
-0
lines changed

.idea/function-parser.iml

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/workspace.xml

+389
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CleanJson.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/python
2+
3+
import r2pipe
4+
import json
5+
from collections import OrderedDict
6+
7+
if __name__ == '__main__':
8+
ecu_files = OrderedDict()
9+
10+
with open('file.json') as file:
11+
json_data = json.load(file, object_pairs_hook=OrderedDict)
12+
13+
for bin in json_data:
14+
split = bin.split('/')
15+
filename = split[len(split) - 1]
16+
17+
print('Parsing {}'.format(filename))
18+
19+
r2 = r2pipe.open('./bins/' + filename)
20+
r2.cmd('e asm.arch=m7700')
21+
r2.cmd('e anal.limits=true')
22+
r2.cmd('e anal.from=0x9000')
23+
r2.cmd('e anal.to=0xffff')
24+
25+
for address, hashes in json_data[bin].items():
26+
r2.cmd('s {}'.format(address))
27+
r2.cmd('af-')
28+
r2.cmd('aaa')
29+
r2.cmd('sf.')
30+
function_addr = r2.cmd('s')
31+
32+
if function_addr in ecu_files.items():
33+
ecu_files[function_addr].append(hashes)
34+
else:
35+
ecu_files[function_addr] = hashes
36+
37+
r2.quit()
38+
print(ecu_files)

Control.xlsx

418 KB
Binary file not shown.

Ground_Truth.xlsx

323 KB
Binary file not shown.

JsonParser.py

+285
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
#!/usr/bin/python
2+
3+
import sys
4+
import json
5+
import xlsxwriter
6+
import r2pipe
7+
from collections import OrderedDict
8+
9+
# Predefined functions containing sensor addresses for comparision's
10+
sensors = {
11+
'batt_voltage': ['0x9a56', '0x9f5b', '0xa166', '0xa307', '-0xae2c', '0xd982', '0xe1cd'],
12+
'vehicle_speed': ['0x9be8', '0x9dce', '0xa59d', '0xa9a7', '0xafc6', '0xb960'],
13+
'engine_speed': ['0xa59d', '0xa5ec', '0xa9a7', '0xafc6', '0xb5bf', '0xb960'],
14+
'water_temp': ['0x9b46', '0xab56'],
15+
'ignition_timing': ['0xdb1a', '0xda0f'],
16+
'airflow': ['0xddcd'],
17+
'throttle_position': ['0xe1cd'],
18+
'knock_correction': ['0xafc6']
19+
}
20+
21+
results = [0, 0]
22+
23+
class EcuFile:
24+
def __init__(self, file_name, functions):
25+
"""
26+
EcuFile constructor
27+
:param file_name: File name of ECU binary
28+
:param functions: JSON of function address & block hashes
29+
"""
30+
self.functions = OrderedDict()
31+
32+
split = file_name.split('/')
33+
self.file_name = split[len(split) - 1]
34+
name = self.file_name.split('-')
35+
self.name = name[0][4:] + '-' + name[1][2:] + '-' + name[4].split('.')[0]
36+
37+
r2 = r2pipe.open('./bins/' + self.file_name)
38+
r2.cmd('e asm.arch=m7700')
39+
r2.cmd('e anal.limits=true')
40+
r2.cmd('e anal.from=0x9000')
41+
r2.cmd('e anal.to=0xffff')
42+
43+
for address, hashes in functions.items():
44+
# Clean up hashes
45+
hashes = hashes[1:-1].split(',')
46+
hashes = [x.replace('\'', '') for x in hashes]
47+
hashes = [x.strip(' ') for x in hashes]
48+
49+
if hashes != [''] and int(address, 16) > 36864:
50+
self.functions[address] = hashes
51+
52+
r2.quit()
53+
print('Created ECU file ' + self.file_name)
54+
55+
56+
class IndexTable:
57+
def __init__(self, ecu_file_1, ecu_file_2):
58+
"""
59+
IndexTable constructor
60+
:param ecu_file_1, ecu_file_2: ECU files used for this table
61+
"""
62+
self.indexes = OrderedDict()
63+
self.tables = OrderedDict()
64+
self.name = ecu_file_1.name + ' ' + ecu_file_2.name
65+
self.test_name = ecu_file_2.file_name
66+
67+
# Custom cell formats
68+
self.header_format = book.add_format({'font_color': 'white', 'bg_color': 'black'})
69+
self.purple_format = book.add_format({'font_color': 'white', 'bg_color': 'purple'})
70+
self.blue_format = book.add_format({'font_color': 'white', 'bg_color': 'blue'})
71+
self.red_format = book.add_format({'font_color': 'white', 'bg_color': 'red'})
72+
73+
print('Created index table ' + self.name)
74+
75+
def push_index(self, function_1, function_2, jaccard_index):
76+
"""
77+
Adds new 'cell' for table
78+
:param function_1, function_2: Header addresses
79+
:param jaccard_index: Jaccard Index calculation
80+
"""
81+
self.indexes[function_1, function_2] = jaccard_index
82+
83+
def _write_format(self, sheet, highest_index, highest_test):
84+
"""
85+
Format cells with result data
86+
:param sheet: Excel sheet to write write results
87+
:param highest_index: Highest jaccad index in row
88+
:param highest_test: Highest gram compare in row
89+
"""
90+
if highest_index[1] == highest_test[1]:
91+
sheet.conditional_format(
92+
highest_index[0], highest_index[1], highest_index[0], highest_index[1],
93+
{'type': 'no_errors', 'format': self.purple_format}
94+
)
95+
results[0] = results[0] + 1
96+
else:
97+
sheet.conditional_format(
98+
highest_index[0], highest_index[1], highest_index[0], highest_index[1],
99+
{'type': 'no_errors', 'format': self.blue_format}
100+
)
101+
sheet.conditional_format(
102+
highest_test[0], highest_test[1], highest_test[0], highest_test[1],
103+
{'type': 'no_errors', 'format': self.red_format}
104+
)
105+
results[1] = results[1] + 1
106+
107+
def write_results(self, book, test_blocks):
108+
"""
109+
Writes all results to Excel sheet
110+
:param book: Excel sheet containing result data
111+
:param test_blocks: Code blocks to test results with
112+
"""
113+
print('Loading sheet ' + table.name)
114+
115+
r2 = r2pipe.open('./bins/' + table.test_name)
116+
r2.cmd('e asm.arch=m7700')
117+
r2.cmd('e anal.limits=true')
118+
r2.cmd('e anal.from=0x9000')
119+
r2.cmd('e anal.to=0xffff')
120+
121+
sheet = book.add_worksheet(table.name)
122+
sheet.freeze_panes(0, 1)
123+
sheet.set_column(0, 0, 23)
124+
125+
row, col = 0, 0
126+
highest_index = [0, 0, 0]
127+
highest_test = [0, 0, 0]
128+
tmp_key = ''
129+
130+
# Write results to cells
131+
for keys, jaccard_index in table.indexes.items():
132+
# Switch to new row
133+
if keys[0] != tmp_key:
134+
tmp_key = keys[0]
135+
row = row + 1
136+
col = 1
137+
138+
# Side header for each row
139+
sheet.write(row, 0, keys[0], self.header_format)
140+
print('\t Added row {}'.format(keys[0]))
141+
142+
if highest_index != [0, 0, 0]:
143+
self._write_format(sheet, highest_index, highest_test)
144+
145+
highest_index = [0, 0, 0]
146+
highest_test = [0, 0, 0]
147+
else:
148+
col = col + 1
149+
150+
# Grab function gram for unknown file
151+
r2.cmd('s {}'.format(keys[1]))
152+
r2.cmd('af-')
153+
r2.cmd('aa')
154+
155+
try:
156+
test_ins = []
157+
for ins in json.loads(r2.cmd('pdfj').decode('utf-8', 'ignore'), strict=False, object_pairs_hook=OrderedDict)['ops']:
158+
test_ins.append(ins['opcode'].split(' ')[0].lower())
159+
except:
160+
col = col - 1
161+
continue
162+
163+
# Calculate Jaccard index for test blocks
164+
for opcodes_list, address in test_blocks.items():
165+
if address == keys[0].split('-')[0]:
166+
test_index = _jaccard_index(opcodes_list, test_ins)
167+
if test_index > highest_test[2]:
168+
highest_test = [row, col, test_index]
169+
170+
# Check if encountered higher Jaccard index
171+
if jaccard_index > highest_index[2]:
172+
highest_index = [row, col, jaccard_index]
173+
174+
sheet.write(0, col, keys[1], self.header_format)
175+
sheet.write(row, col, round(jaccard_index, 2))
176+
177+
r2.quit()
178+
179+
self._write_format(sheet, highest_index, highest_test)
180+
181+
182+
def _jaccard_index(list_1, list_2):
183+
"""
184+
Calculate Jaccard index from two lists (Use shortest list as check)
185+
:param list_1, list_2: Lists to compare
186+
:returns: Jaccard index of list_1 & list_2
187+
"""
188+
if len(list_1) < len(list_2):
189+
intersection = len([x for x in list_1 if x in list_2])
190+
else:
191+
intersection = len([x for x in list_2 if x in list_1])
192+
193+
union = len(list_1) + len(list_2) - intersection
194+
195+
return float(intersection) / union
196+
197+
198+
def _create_tables(control_file, ecu_files):
199+
"""
200+
Creates comparison tables
201+
:param ecu_files: List of EcuFile objects
202+
:returns: List of created tables
203+
"""
204+
tables = []
205+
206+
for ecu_file in ecu_files:
207+
table = IndexTable(control_file, ecu_file)
208+
209+
# Loop through functions in ECU files
210+
for function_1, function_1_hashes in control_file.functions.items():
211+
for function_2, function_2_hashes in ecu_file.functions.items():
212+
for sensor, addresses in sensors.items():
213+
if function_1 in addresses:
214+
table.push_index(
215+
function_1 + '-' + sensor,
216+
function_2,
217+
_jaccard_index(function_1_hashes, function_2_hashes)
218+
)
219+
break
220+
221+
tables.append(table)
222+
223+
return tables
224+
225+
226+
if __name__ == '__main__':
227+
ecu_files = []
228+
control_file = None
229+
230+
if len(sys.argv) != 3:
231+
print('Run \'python JsonParser.py file.json output.xlsx')
232+
exit()
233+
234+
# Open & parse JSON dump
235+
with open(sys.argv[1]) as file:
236+
json_data = json.load(file, object_pairs_hook=OrderedDict)
237+
238+
for file_name in json_data:
239+
ecu_file = EcuFile(file_name, json_data[file_name])
240+
241+
# Pick out control file
242+
if ecu_file.name == '27-93-EG33':
243+
control_file = ecu_file
244+
else:
245+
if 'EG33' in ecu_file.name:
246+
ecu_files.append(ecu_file)
247+
248+
# Open and format block data
249+
test_blocks = OrderedDict()
250+
251+
with open('blocks.txt') as file:
252+
# radare setup
253+
r2 = r2pipe.open('./bins/722527-1993-USDM-SVX-EG33.bin')
254+
r2.cmd('e asm.arch=m7700')
255+
r2.cmd('e anal.limits=true')
256+
r2.cmd('e anal.from=0x9000')
257+
r2.cmd('e anal.to=0xffff')
258+
259+
for address in [x.strip('\n') for x in file]:
260+
opcodes = []
261+
262+
r2.cmd('s {}'.format(address))
263+
r2.cmd('af-')
264+
r2.cmd('aa')
265+
266+
# Grab opcodes from function
267+
for ins in json.loads(r2.cmd('pdfj').decode('utf-8', 'ignore'), strict=False, object_pairs_hook=OrderedDict)['ops']:
268+
opcodes.append(ins['opcode'].split(' ')[0].lower())
269+
270+
test_blocks[tuple(opcodes)] = address
271+
272+
r2.quit()
273+
274+
# Setup Excel sheet
275+
book = xlsxwriter.Workbook(sys.argv[2])
276+
tables = _create_tables(control_file, ecu_files)
277+
278+
# Write all table data to sheets
279+
for table in tables:
280+
table.write_results(book, test_blocks)
281+
282+
book.close()
283+
284+
print('\nWrote values to {}\n'.format(sys.argv[2]))
285+
print('Final results {}%\n'.format(round((float(results[0]) / results[1]) * 100), 2))

0 commit comments

Comments
 (0)