Skip to content

Commit

Permalink
Reformatting files and variable names + fontawesome
Browse files Browse the repository at this point in the history
  • Loading branch information
k1nd0ne committed Oct 3, 2022
1 parent 1d9379c commit 495084d
Show file tree
Hide file tree
Showing 65 changed files with 954 additions and 810 deletions.
1 change: 1 addition & 0 deletions VolWeb/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
'django.contrib.staticfiles',
'crispy_forms',
'cookiebanner',
'fontawesomefree',
]

MIDDLEWARE = [
Expand Down
91 changes: 50 additions & 41 deletions VolWeb/voltools.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@
from volatility3.framework.renderers import format_hints
from .keyconfig import Secrets


class GraphException(Exception):
"""Class to allow filtering of the graph generation errors"""


def file_handler(output_dir):
class CLIFileHandler(interfaces.plugins.FileHandlerInterface):
"""The FileHandler from Volatility3 CLI"""

def _get_final_filename(self):
"""Gets the final filename"""
if output_dir is None:
raise TypeError("Output directory is not a string")
os.makedirs(output_dir, exist_ok = True)
os.makedirs(output_dir, exist_ok=True)

pref_name_array = self.preferred_filename.split('.')
filename, extension = os.path.join(output_dir, '.'.join(pref_name_array[:-1])), pref_name_array[-1]
Expand All @@ -31,9 +34,10 @@ def _get_final_filename(self):

class CLIDirectFileHandler(CLIFileHandler):
"""We want to save our files directly to disk"""

def __init__(self, filename: str):
fd, self._name = tempfile.mkstemp(suffix = '.vol3', prefix = 'tmp_', dir = output_dir)
self._file = io.open(fd, mode = 'w+b')
fd, self._name = tempfile.mkstemp(suffix='.vol3', prefix='tmp_', dir=output_dir)
self._file = io.open(fd, mode='w+b')
CLIFileHandler.__init__(self, filename)
for item in dir(self._file):
if not item.startswith('_') and not item in ['closed', 'close', 'mode', 'name']:
Expand Down Expand Up @@ -66,7 +70,8 @@ def close(self):

return CLIDirectFileHandler

#Inspired by the JsonRenderer class.

# Inspired by the JsonRenderer class.
class DictRendererPsTree(text_renderer.CLIRenderer):
"""Directly inspired by the JsonRenderer rendered
Return : Dict of the plugin result.
Expand All @@ -91,7 +96,7 @@ def render(self, grid: interfaces.renderers.TreeGrid):
{}, [])

def visitor(
node: interfaces.renderers.TreeNode, accumulator: Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]
node: interfaces.renderers.TreeNode, accumulator: Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]
) -> Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]:
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
acc_map, final_tree = accumulator
Expand All @@ -116,13 +121,12 @@ def visitor(
if not grid.populated:
grid.populate(visitor, final_output)
else:
grid.visit(node = None, function = visitor, initial_accumulator = final_output)
grid.visit(node=None, function=visitor, initial_accumulator=final_output)

return final_output[1]



#Inspired by the JsonRenderer class.
# Inspired by the JsonRenderer class.
class DictRenderer(text_renderer.CLIRenderer):
_type_renderers = {
format_hints.HexBytes: text_renderer.quoted_optional(text_renderer.hex_bytes_as_text),
Expand All @@ -144,7 +148,7 @@ def render(self, grid: interfaces.renderers.TreeGrid):
{}, [])

def visitor(
node: interfaces.renderers.TreeNode, accumulator: Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]
node: interfaces.renderers.TreeNode, accumulator: Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]
) -> Tuple[Dict[str, Dict[str, Any]], List[Dict[str, Any]]]:
# Nodes always have a path value, giving them a path_depth of at least 1, we use max just in case
acc_map, final_tree = accumulator
Expand All @@ -162,15 +166,16 @@ def visitor(
final_tree.append(node_dict)
acc_map[node.path] = node_dict

return (acc_map, final_tree)
return acc_map, final_tree

if not grid.populated:
grid.populate(visitor, final_output)
else:
grid.visit(node = None, function = visitor, initial_accumulator = final_output)
grid.visit(node=None, function=visitor, initial_accumulator=final_output)

return final_output[1]


def memory_image_hash(dump_path):
"""Compute memory image signature.
Args:
Expand All @@ -179,21 +184,22 @@ def memory_image_hash(dump_path):
Returns:
A dict of different types of hash computed
"""
BLOCKSIZE = 65536 # Read the file in 64kb chunks.
blocksize = 65536 # Read the file in 64kb chunks.
md5 = hashlib.md5()
sha1 = hashlib.sha1()
sha256 = hashlib.sha256()
try:
with open(dump_path, 'rb') as afile:
buf = afile.read(BLOCKSIZE)
buf = afile.read(blocksize)
while len(buf) > 0:
md5.update(buf)
sha1.update(buf)
sha256.update(buf)
buf = afile.read(BLOCKSIZE)
signatures = {'md5':format(md5.hexdigest()), 'sha1': format(sha1.hexdigest()), 'sha256': format(sha256.hexdigest())}
buf = afile.read(blocksize)
signatures = {'md5': format(md5.hexdigest()), 'sha1': format(sha1.hexdigest()),
'sha256': format(sha256.hexdigest())}
except:
signatures = {'md5':'Error', 'sha1': 'Error', 'sha256': 'Error'}
signatures = {'md5': 'Error', 'sha1': 'Error', 'sha256': 'Error'}
return signatures


Expand All @@ -204,25 +210,27 @@ def file_sha256(path):
Returns:
sh256 of the file
"""
BLOCKSIZE = 65536 # Read the file in 64kb chunks.
blocksize = 65536 # Read the file in 64kb chunks.
sha256 = hashlib.sha256()
try:
with open(path, 'rb') as afile:
buf = afile.read(BLOCKSIZE)
buf = afile.read(blocksize)
while len(buf) > 0:
sha256.update(buf)
buf = afile.read(BLOCKSIZE)
buf = afile.read(blocksize)
return format(sha256.hexdigest())
except:
return 'error'


def generate_network_graph(data):
graph_data = {'nodes':[], 'edges':[]}
for entrie in data:
node_data_1 = {'id':entrie['LocalAddr'], 'Involved_PIDs': [entrie['PID']], 'Owner(s)': [entrie['Owner']], 'Local_Ports':[entrie['LocalPort']], 'State':entrie['State']}
node_data_2 = {'id':entrie['ForeignAddr'], 'Involved_PIDs': [entrie['PID']], 'Owner(s)': [entrie['Owner']], 'Local_Ports':[entrie['ForeignPort']], 'State':entrie['State']}
edge_data = {'from': entrie['LocalAddr'], 'to': entrie['ForeignAddr']}
graph_data = {'nodes': [], 'edges': []}
for entry in data:
node_data_1 = {'id': entry['LocalAddr'], 'Involved_PIDs': [entry['PID']], 'Owner(s)': [entry['Owner']],
'Local_Ports': [entry['LocalPort']], 'State': entry['State']}
node_data_2 = {'id': entry['ForeignAddr'], 'Involved_PIDs': [entry['PID']], 'Owner(s)': [entry['Owner']],
'Local_Ports': [entry['ForeignPort']], 'State': entry['State']}
edge_data = {'from': entry['LocalAddr'], 'to': entry['ForeignAddr']}
if not graph_data['nodes']:
graph_data['nodes'].append(node_data_1)

Expand All @@ -234,12 +242,12 @@ def generate_network_graph(data):
if not is_present:
graph_data['nodes'].append(node_data_1)
else:
if entrie['PID'] not in item['Involved_PIDs']:
item['Involved_PIDs'].append(entrie['PID'])
if entrie['LocalPort'] not in item['Local_Ports']:
item['Local_Ports'].append(entrie['LocalPort'])
if entrie['Owner'] not in item['Owner(s)']:
item['Owner(s)'].append(entrie['Owner'])
if entry['PID'] not in item['Involved_PIDs']:
item['Involved_PIDs'].append(entry['PID'])
if entry['LocalPort'] not in item['Local_Ports']:
item['Local_Ports'].append(entry['LocalPort'])
if entry['Owner'] not in item['Owner(s)']:
item['Owner(s)'].append(entry['Owner'])

is_present = False
for item in graph_data['nodes']:
Expand All @@ -250,22 +258,23 @@ def generate_network_graph(data):
if not is_present:
graph_data['nodes'].append(node_data_2)
else:
if entrie['PID'] not in item['Involved_PIDs']:
item['Involved_PIDs'].append(entrie['PID'])
if entrie['ForeignPort'] not in item['Local_Ports']:
item['Local_Ports'].append(entrie['ForeignPort'])
if entrie['Owner'] not in item['Owner(s)']:
item['Owner(s)'].append(entrie['Owner'])
if entry['PID'] not in item['Involved_PIDs']:
item['Involved_PIDs'].append(entry['PID'])
if entry['ForeignPort'] not in item['Local_Ports']:
item['Local_Ports'].append(entry['ForeignPort'])
if entry['Owner'] not in item['Owner(s)']:
item['Owner(s)'].append(entry['Owner'])

if edge_data not in graph_data['edges']:
graph_data['edges'].append(edge_data)

return graph_data


def vt_check_file_hash(hash):
client = vt.Client(Secrets.VT_API_KEY)
try:
file = client.get_object("/files/"+hash)
file = client.get_object("/files/" + hash)
client.close()
result = file.last_analysis_stats
result.update({'SHA256': file.sha256})
Expand All @@ -274,11 +283,11 @@ def vt_check_file_hash(hash):
except:
pass
try:
result.update({'crowdsourced_yara_results': file.crowdsourced_yara_results} )
result.update({'crowdsourced_yara_results': file.crowdsourced_yara_results})
except:
pass
try:
result.update({'sandbox_verdicts' : file.sandbox_verdicts})
result.update({'sandbox_verdicts': file.sandbox_verdicts})
except:
pass
return result, "success"
Expand All @@ -302,11 +311,11 @@ def build_timeline(data):
try:
actual_date = str(i["Created Date"])
if actual_date != saved_date:
timeline.append([saved_date,nb_event])
timeline.append([saved_date, nb_event])
saved_date = actual_date
nb_event = 1
else:
nb_event+=1
nb_event += 1
except:
raise GraphException('Could not generate timeline graph')
return timeline
6 changes: 4 additions & 2 deletions dashboard/static/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
opacity: 1;
}



.dismiss {
font-size: 26px;
width: 35px;
Expand Down Expand Up @@ -197,8 +199,8 @@ thead, tbody {
.spinner-review {
z-index: 2;
position: absolute;
top: 30%;
left: 60%;
top: 10%;
left: 55%;
margin: -25px 0 0 -25px;
}

Expand Down
8 changes: 4 additions & 4 deletions dashboard/static/js/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class FileUpload {
investDesc.innerHTML += "</br> Investigators : " + investigators.value;
var end;
var self = this;
var existingPath = model_id;
var existing_path = model_id;
var formData = new FormData();
var nextChunk = start + this.max_length + 1;
var currentChunk = this.file.slice(start, nextChunk);
Expand All @@ -108,7 +108,7 @@ class FileUpload {
$('.filename').text(this.file.name)
$('.textbox').text("Uploading file")
formData.append('eof', end)
formData.append('existingPath', existingPath);
formData.append('existing_path', existing_path);
formData.append('nextSlice', nextChunk);
formData.append('title', title.value);
formData.append('description', description.value);
Expand Down Expand Up @@ -152,8 +152,8 @@ class FileUpload {
if (nextChunk < self.file.size) {
console.log(res)
// upload file in chunks
existingPath = res.existingPath
self.upload_file(nextChunk, existingPath);
existing_path = res.existing_path
self.upload_file(nextChunk, existing_path);
} else {
alertBox.innerHTML = "<p class='text-white'>Upload completed you can now start the analysis from <a href=\"../\">here</a></p>";
}
Expand Down
4 changes: 3 additions & 1 deletion dashboard/templates/dashboard/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
<link rel="stylesheet" href="{% static '/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link href="{% static 'fontawesomefree/css/fontawesome.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'fontawesomefree/css/brands.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'fontawesomefree/css/solid.css' %}" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="{% static '/css/fontawesome5-overrides.min.css' %}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<link rel="stylesheet" href="{% static '/css/styles.css' %}">
Expand Down
3 changes: 2 additions & 1 deletion dashboard/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.urls import path
from . import views

urlpatterns = [
path('',views.dashboard, name='dashboard')
path('', views.dashboard, name='dashboard')
]
21 changes: 11 additions & 10 deletions dashboard/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from django.contrib.auth import get_user_model
from django.core import serializers

#Dashboard view : Return the dashboard with the latest IOCs and Investigations

# Dashboard view : Return the dashboard with the latest IOCs and Investigations
@login_required
def dashboard(request):
"""Load the dashboard
Expand All @@ -18,12 +19,12 @@ def dashboard(request):
Display the dashboard and pass the users/activities/analysis/iocs
"""
User = get_user_model()
activity = serializers.serialize("json", Activity.objects.all(), fields = ("date", "count"))
return render(request,'dashboard/dashboard.html',
{
'Activity': activity, 'Users':User.objects.filter(is_superuser = False),
'investigations':UploadInvestigation.objects.all().count(),
'iocs':IOC.objects.all().count(),
'symbols':Symbols.objects.all().count(),
'team':User.objects.all().count()
})
activity = serializers.serialize("json", Activity.objects.all(), fields=("date", "count"))
return render(request, 'dashboard/dashboard.html',
{
'Activity': activity, 'Users': User.objects.filter(is_superuser=False),
'investigations': UploadInvestigation.objects.all().count(),
'iocs': IOC.objects.all().count(),
'symbols': Symbols.objects.all().count(),
'team': User.objects.all().count()
})
1 change: 1 addition & 0 deletions investigations/apps.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.apps import AppConfig


class InvestigationsConfig(AppConfig):
name = 'investigations'
Loading

0 comments on commit 495084d

Please sign in to comment.