-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
374 lines (310 loc) · 10.8 KB
/
main.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#########################
# File: Main.py
# Author: ChrisRisp
# Contributor: Fdrozenski
# Project: Binview
# Version 0.2
#########################
####
# NOTES
'''
If we flag a group of offsets together with the same label ( When should it flag region )
Offsets within given range occupy certain memory region. How much memory is this relative to the size of file. Signifigance rating
Percentage occupied in memory.
Time is important in forensic investigation this improves the workflow.
Flag region of memory as known type
'''
####
import os
import sys
import binwalk
import math
import datetime
from collections import defaultdict
from subprocess import Popen, PIPE, STDOUT
header = "\
__________.__ .__ \n\
\______ \__| _______ _|__| ______ _ __\n\
| | _/ |/ \ \/ / |/ __ \ \/ \/ /\\\n\
| | \ | | \ /| \ ___/\ /\n\
|______ /__|___| /\_/ |__|\___ >\/\_/ \n\
\/ \/ \/ \n"
colors = {
'blue': '\033[94m',
'pink': '\033[95m',
'green': '\033[92m',
'red' : '\33[31m'
}
# Artifact Count/Offset Dicts
header_count = dict()
header_offsets = defaultdict(list)
header_flagged = defaultdict(list)
#Flag counter
flag_count = 0
# Output text color Func
def colorize(string, color):
if not color in colors: return string
return colors[color] + string + '\033[0m'
#
# Run tools
#
def analyze():
for module in binwalk.scan(sys.argv[1],
signature=True,
quiet=True):
for result in module.results:
key = result.description.split(',')[0]
meta = result.description.split(',')
offset = result.offset
try:
# Increment Occurence count
val = header_count[key]
header_count[key] = val+1
# Save Metadata
if(len(meta) == 5):
header_offsets[key].append([offset, meta[2], meta[3], meta[4]])
if(len(meta) == 4):
header_offsets[key].append([offset, meta[2], meta[3]])
except:
# print ("No such entry yet")
# Increment Occurence count
if (len(meta) == 2):
continue
header_count[key] = 1
# Save Metadata
if (len(meta) >= 5):
meta_fields = [offset]
for el in meta:
meta_fields.append(el)
header_offsets[key].append(meta_fields)
if (len(meta) == 4):
header_offsets[key].append([offset, meta[2], meta[3]])
if (len(meta) == 3):
header_offsets[key].append([offset, meta[2]])
raw_input("Analyzed: Press [Enter] to continue...")
#
# Offsets submenu1: Show Offset results
#
def show_results():
sub = True
while sub:
submenuItems1 = [
{"List Offsets [idx,#]": show_offsets},
{"Flag Filetype [#]": flag_header},
{"Dump All": show_offsets},
{"Exit": exit},
]
os.system('clear')
# Print Table
print(" {0:^10} {1:^10}".format("Count", "Type"))
print("-"*30)
idx = 0
# Get Header occurences
for k, v in header_count.items():
print ("[" + str(idx) + "] {0:^15} {1}".format(v, k))
idx+=1
print '\n'
for item in submenuItems1:
print colorize("[" + str(submenuItems1.index(item)) + "] ", 'blue') + item.keys()[0]
choice = raw_input("(binview)$ ")
selection = choice.split(',')
try:
if int(selection[0]) < 0: raise ValueError
if int(selection[0]) == 3: sub = False
# Call the matching function
if int(selection[0]) == 1:
submenuItems1[int(selection[0])].values()[0](int(selection[1]), str(selection[2]))
else:
submenuItems1[int(selection[0])].values()[0](int(selection[1]))
except (ValueError, IndexError) as e:
print e
#
# Offsets submenu 2
#
def show_offsets(selection):
submenuItems2 = [
{"Inspect [#, bytes]": inspect_offset},
{"Flag Filetype [#]": flag_header},
{"DD Extract [#]": analyze},
{"Extract All": show_offsets},
{"Exit": exit},
]
# Print offsets for selected filetype
idx = 0
for offset in header_offsets[header_offsets.keys()[selection]]:
if (len(offset) > 2):
sys.stdout.write("["+str(idx)+"] " + "Offset: " + hex(offset[0]))
for i in range(1,len(offset)):
sys.stdout.write(str(offset[i]))
sys.stdout.write(' ')
else:
sys.stdout.write("["+str(idx)+"] " + "Offset: " + hex(offset[0]))
for i in range(1, len(offset)):
sys.stdout.write(str(offset[i]))
sys.stdout.write(' ')
idx+=1
print ""
print ""
for item in submenuItems2:
print colorize("[" + str(submenuItems2.index(item)) + "] ", 'blue') + item.keys()[0]
choice = raw_input("(binview)$ ")
off_selection = choice.split(',')
try:
if int(off_selection[0]) < 0: raise ValueError
# Call the matching function
if int(off_selection[0]) == 0:
submenuItems2[int(choice[0])].values()[0](str(hex(header_offsets[header_offsets.keys()[selection]][0][0])),
str(off_selection[2]))
if int(off_selection[0]) == 1:
submenuItems2[int(choice[0])].values()[0](str(off_selection[2]),
header_offsets[header_offsets.keys()[selection]][int(off_selection[1])])
else:
submenuItems2[int(choice)].values()[0]()
except (ValueError, IndexError) as e:
pass
#
# Flag header
#
def flag_header(description, offset):
size = get_size(offset)
header_flagged[description].append([offset[0], size])
print colorize("Header Flagged!", 'red')
#
# Report Builder
#
def build_profile():
# Get Density Report: Print range of memory frequent headers
rp = open(sys.argv[1] + "_report.txt", "w")
# Write heading
rp.write("BinView v0.2 Report\n"
"File: " + sys.argv[1] + "\n")
rp.write(str(datetime.datetime.now()) + "\n\n")
# Write Flagged Headers
rp.write("[Flagged Headers]\n\n")
for key, val in header_flagged.items():
flag_name = key
rp.write("*" + key + "\n")
# Write total identified headers
rp.write("\n\n[Identified Headers]\n\n")
for entry in header_count.keys():
rp.write(entry + "\n")
rp.write("\n\n[Binary Graph]\n\n")
build_graph(rp)
#
# Layout Graphing
#
def build_graph(rp):
scale = 16 # Produce 1:16 scale graph
file_size = os.stat(sys.argv[1]).st_size
tmp = "File Size: " + str(file_size)
print tmp
rp.write("\n" + tmp + "\n")
tmp = "File End: " + str(hex(file_size))
print tmp
rp.write("" + tmp + "\n")
tmp = "Row Count: " + str(file_size/(file_size/scale))
print tmp
rp.write("" + tmp + "\n")
row_count = file_size/(file_size/scale)
row_size = math.ceil(file_size/row_count)
tmp = "Size Per Row: " + str(row_size)
print tmp
rp.write("" + tmp + "\n")
# Flagged Areas to be inserted into graph
# Distance between marked locations for averaging
mem_avgs = []
mem_avg_tmp = []
# Calculate Size Percentage
flag_name = ""
flagged_size_total = 0
# How many offsets associate with flag len(val)
prev_off = -1
for key, val in header_flagged.items():
flag_name = key
# Calculate percentage of binary based on size
for offset in val:
# Should be size
flagged_size_total += int(offset[1])
if prev_off != -1:
mem_avg_tmp.append(math.fabs(int(offset[0])))
prev_off=offset[0]
dist_total = 0
for dist in mem_avg_tmp:
dist_total += dist
dist_total = dist_total / (len(mem_avg_tmp)+1)
mem_avgs.append([flag_name, dist_total])
area = (float(flagged_size_total) / float(file_size))
area_percent = area * 100
tmp = "Memory Occupied: (" + flag_name +"): " + str((area_percent)) + "%"
print tmp
rp.write("" + tmp + "\n")
flagged_size_total=0
# Start building Visual
tmp = colorize("|------------------------|", 'blue')
tmp2 = "|------------------------|"
print tmp
rp.write("\n" + tmp2 + "\n")
for i in range(0,file_size/(file_size/scale)+1): # Or size of file
in_row = False
curr = row_size * i
for addr in mem_avgs:
if(((row_size*i) <= addr[1] <= (row_size*(i+1)))):
tmp = colorize("|########################| <-- Addr: " + str(hex(int(curr))) +
" <-- Flag: " + addr[0] + " Avg: " + str(hex(int(addr[1]))), 'red')
tmp2 = "|########################| <-- Addr: " + str(hex(int(curr))) +\
" <-- Flag: " + addr[0] + " Avg: " + str(hex(int(addr[1])))
print tmp
rp.write("" + tmp2 + "\n")
in_row=True
if(not in_row):
tmp = colorize("|########################| <-- Addr: " + str(hex(int(curr))), 'blue')
tmp2 = "|########################| <-- Addr: " + str(hex(int(curr)))
print tmp
rp.write("" + tmp2 + "\n")
tmp = colorize("|------------------------|", 'blue')
tmp2 = "|------------------------|"
print tmp
rp.write("" + tmp2 + "\n")
#
# get size helper function for binwalk metadata
#
def get_size(meta_data):
size = 0
for el in meta_data:
el = str(el)
if "size" in el:
tmp = el.split(':')
tmp2 = tmp[1].split(' ')
size = tmp2[1]
break
return size
#
# Offsets submenu 2
#
def inspect_offset(offset, bytes):
cmd = 'hexdump -n'+bytes+' -C -s '+offset+' '+sys.argv[1]
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
output = p.stdout.read()
print output
menuItems = [
{"Analyze File": analyze},
{"Show Results": show_results},
{"Build Profile": build_profile},
{"Exit": exit},
]
def main():
while True:
os.system('clear')
print colorize(header, 'blue')
print colorize('version 0.2\n', 'green')
for item in menuItems:
print colorize("[" + str(menuItems.index(item)) + "] ", 'blue') + item.keys()[0]
choice = raw_input("(binview)$ ")
try:
if int(choice) < 0: raise ValueError
# Call the matching function
menuItems[int(choice)].values()[0]()
except (ValueError, IndexError):
pass
if __name__ == "__main__":
main()