Adding draw_boot to herrewebpy
This commit is contained in:
parent
5d9cadc0ff
commit
dd28bd80d4
207
herrewebpy/firmware_forensics/memory_drawer.py
Normal file
207
herrewebpy/firmware_forensics/memory_drawer.py
Normal file
@ -0,0 +1,207 @@
|
||||
# Using plotly
|
||||
import plotly.graph_objects as go
|
||||
import random, argparse
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
def read_data(df):
|
||||
data = pd.read_csv('stack_and_functions.csv')
|
||||
|
||||
def convert_to_int(value):
|
||||
try:
|
||||
if isinstance(value, str) and value.startswith('0x'):
|
||||
return int(value, 16)
|
||||
else:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
return value
|
||||
|
||||
data['start'] = data['start'].apply(convert_to_int)
|
||||
data['end'] = data['end'].apply(convert_to_int)
|
||||
data['size'] = data['end'] - data['start']
|
||||
|
||||
data.sort_values(by=['size'], inplace=True, ascending=False)
|
||||
data.sort_values(by=['start'], inplace=True)
|
||||
|
||||
# Inverse the order of the data
|
||||
data.reset_index(drop=True, inplace=True)
|
||||
|
||||
data['overlap'] = False
|
||||
|
||||
for i, row in data.iterrows():
|
||||
for j, row2 in data.iterrows():
|
||||
if i == j:
|
||||
continue
|
||||
if row['start'] <= row2['end'] and row['end'] > row2['start']:
|
||||
if row['end'] - row['start'] >= row2['end'] - row2['start']:
|
||||
continue
|
||||
data.at[i, 'overlap'] = True
|
||||
data.at[j, 'overlap'] = True
|
||||
data.at[i, 'overlap_with'] = j
|
||||
|
||||
data['overlap_with'] = data['overlap_with'].fillna(data.index.to_series())
|
||||
data['overlap_with'] = data['overlap_with'].astype(float)
|
||||
|
||||
# Send warnings if sizes are negative
|
||||
if (data['size'] < 0).any():
|
||||
print(f'Warning: Negative sizes detected at indices {data[data["size"] < 0].index}')
|
||||
|
||||
|
||||
def draw_diagram(data):
|
||||
tickpointers = []
|
||||
vertical_len = len(data['overlap_with'].unique())
|
||||
vertical_gap_percentage = 0.08
|
||||
horizontal_gap = 0.1
|
||||
labels = pd.DataFrame()
|
||||
|
||||
def random_color():
|
||||
return f'#{random.randint(0, 0xFFFFFF):06x}'
|
||||
|
||||
fig = go.Figure()
|
||||
|
||||
for i, d in data.iterrows():
|
||||
fillcolor = random_color()
|
||||
data.at[i, 'fillcolor'] = fillcolor
|
||||
|
||||
x0=1
|
||||
x1=4
|
||||
|
||||
if d['overlap'] == False:
|
||||
y0=d['overlap_with']
|
||||
y1=d['overlap_with']+1
|
||||
elif d['overlap'] == True:
|
||||
overlaps = data.loc[data['overlap_with'] == d['overlap_with']].shape[0]
|
||||
|
||||
# Calculate relative size of the overlap
|
||||
overlap_sizes = data.loc[data['overlap_with'] == d['overlap_with']].iloc[1:]['size'].sum()
|
||||
|
||||
if d['overlap_with'] == i:
|
||||
y0=i
|
||||
y1=overlaps+i
|
||||
if i != data.shape[0]+1:
|
||||
if d['end'] > data.iloc[i+1].start and d['end'] < data.iloc[i+1].end:
|
||||
y1=overlaps+i-0.5
|
||||
x0=x0-horizontal_gap
|
||||
x1=x1+horizontal_gap
|
||||
else:
|
||||
y0=0.02+i
|
||||
y1=0.87+i
|
||||
else:
|
||||
print(f'Something went wrong with {d}. Skipping')
|
||||
continue
|
||||
|
||||
fig.add_shape(
|
||||
type="rect",
|
||||
x0=x0,
|
||||
x1=x1,
|
||||
y0=y0+vertical_gap_percentage,
|
||||
y1=y1-vertical_gap_percentage,
|
||||
line=dict(width=2),
|
||||
fillcolor=fillcolor,
|
||||
opacity=0.5,
|
||||
layer="below",
|
||||
)
|
||||
|
||||
# Add middle text
|
||||
fig.add_trace(go.Scatter
|
||||
(
|
||||
x=[(x0+x1)/2],
|
||||
y=[y0+0.5],
|
||||
text=d['name'],
|
||||
mode="text",
|
||||
textposition="middle center",
|
||||
name=d['name'],
|
||||
marker=dict(
|
||||
color=fillcolor,
|
||||
),
|
||||
))
|
||||
|
||||
# Add top-left text with d['end']
|
||||
fig.add_trace(go.Scatter
|
||||
(
|
||||
x=[(x0+0.14+horizontal_gap)],
|
||||
y=[y1-0.16],
|
||||
text=hex(d['end']),
|
||||
mode="text",
|
||||
textposition="middle center",
|
||||
marker=dict(
|
||||
color=fillcolor,
|
||||
),
|
||||
showlegend=False,
|
||||
))
|
||||
|
||||
# Add bottom-left text with d['end']
|
||||
fig.add_trace(go.Scatter
|
||||
(
|
||||
x=[(x0+0.14+horizontal_gap)],
|
||||
y=[y0+0.14],
|
||||
text=hex(d['start']),
|
||||
mode="text",
|
||||
textposition="middle center",
|
||||
marker=dict(
|
||||
color=fillcolor,
|
||||
),
|
||||
showlegend=False,
|
||||
))
|
||||
|
||||
fig.update_xaxes(
|
||||
range=[0, 5],
|
||||
tickvals=[0, 1, 2, 3, 4, 5],
|
||||
)
|
||||
|
||||
start_values = data['start'].sort_values()
|
||||
end_values = data['end'].sort_values()
|
||||
|
||||
labels = []
|
||||
|
||||
for i, d in data.iterrows():
|
||||
if i == 0:
|
||||
labels.append(f'{hex(start_values.iloc[i])}')
|
||||
elif i == len(data)-1:
|
||||
labels.append(f'{hex(end_values.iloc[i])}')
|
||||
else:
|
||||
labels.append(f'{hex(start_values.iloc[i])}<br>{hex(end_values.iloc[i-1])}')
|
||||
|
||||
tickpointers = [i for i in range(len(data))]
|
||||
|
||||
fig.update_yaxes(
|
||||
# tickvals=[i for i in range(len(data)+1)],
|
||||
tickvals = tickpointers,
|
||||
# ticktext= labels,
|
||||
griddash="longdashdot",
|
||||
gridwidth=0,
|
||||
gridcolor="black",
|
||||
showgrid=False,
|
||||
showticklabels=True,
|
||||
autorange='reversed',
|
||||
)
|
||||
|
||||
fig.update_xaxes(
|
||||
showgrid=False,
|
||||
showticklabels=False,
|
||||
)
|
||||
|
||||
fig.update_layout(
|
||||
width=1200,
|
||||
height=1200,
|
||||
autosize=True,
|
||||
margin=dict(l=200, r=20, t=20, b=20),
|
||||
font=dict(
|
||||
size=18,
|
||||
),
|
||||
# Legend being the name of the function
|
||||
legend_title_text="Function/Locations",
|
||||
)
|
||||
|
||||
def write_output(fig):
|
||||
fig.write_html("../_static/stack_and_functions.html")
|
||||
|
||||
if __name__ == '__main__':
|
||||
argparser = argparse.ArgumentParser()
|
||||
argparser.add_argument('input', help='Input CSV file path', required=True)
|
||||
argparser.add_argument('output', help='Output HTML filename', required=False)
|
||||
args = argparser.parse_args()
|
||||
|
||||
data = read_data('stack_and_functions.csv')
|
||||
fig = draw_diagram(data)
|
||||
write_output(fig)
|
@ -59490,7 +59490,7 @@
|
||||
59488,2023-11-20T08:55:01.628662,FATAL,ServiceA,Data Corruption,1584,User47,192.168.1.81,67ms
|
||||
59489,2023-11-20T08:55:01.641823,WARNING,ServiceB,Input Validation Warnings,6622,User85,192.168.1.57,29ms
|
||||
59490,2023-11-20T08:55:01.650487,FATAL,ServiceB,Data Corruption,6001,User92,192.168.1.229,22ms
|
||||
59491,2023-11-20T08:55:01.666493,DEBUG,ServiceC,Algorithm Steps,4124,User9,192.168.1.217,25ms
|
||||
59491,2023-11-20T08:55:01.666493,DEBUG,ServiceC,Algorithm Steps,4124,User9,192.168.1.217,25ms
|
||||
59492,2023-11-20T08:55:01.690573,ERROR,ServiceB,Critical Errors,7688,User54,192.168.1.170,94ms
|
||||
59493,2023-11-20T08:55:01.706807,INFO,ServiceC,Status Updates,1180,User6,192.168.1.79,28ms
|
||||
59494,2023-11-20T08:55:01.722570,WARNING,ServiceC,Input Validation Warnings,4491,User85,192.168.1.175,77ms
|
Can't render this file because it is too large.
|
Loading…
Reference in New Issue
Block a user