Skip to content

Commit 4395479

Browse files
committed
Config File, and AutoRun Plugins at session load.
1 parent 9effa5b commit 4395479

File tree

9 files changed

+101
-23
lines changed

9 files changed

+101
-23
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,5 @@ vt_key.py
7171
test.py
7272
plugins/overlays/*.zip
7373
plugins/*
74-
!plugins/overlays/__init__.py
74+
!plugins/overlays/__init__.py
75+
volutility.conf

volutility.conf.sample

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[database]
2+
mongo_uri = mongodb://localhost
3+
4+
[virustotal]
5+
api_type = public
6+
api_key =
7+
8+
[autorun]
9+
#
10+
# Volutility will try to run these plugins as soon as the image is loaded.
11+
#
12+
autorun = False
13+
plugins = pslist,psscan

web/checks.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from django.core.checks import Error, Warning, register
22
from django.core.checks import Tags
3-
43
import vol_interface
54

5+
66
##
77
# Django System Checks
88
##
@@ -25,11 +25,6 @@ def compat_check(app_configs=None, **kwargs):
2525
except ImportError:
2626
errors.append(Warning('Unable to import virustotalapi', hint='sudo pip install virustotal'))
2727

28-
try:
29-
from vt_key import API_KEY
30-
except ImportError:
31-
errors.append(Warning('Unable to import virustotal key', hint='create api_key.py as per wiki'))
32-
3328
try:
3429
import yara
3530
except ImportError:
@@ -49,6 +44,16 @@ def compat_check(app_configs=None, **kwargs):
4944
except Exception as error:
5045
errors.append(Error('Unable to find Volatility Version Number', hint='Read the installation wiki'))
5146

47+
# Config
48+
try:
49+
from common import Config
50+
config = Config()
51+
if config.valid:
52+
pass
53+
54+
except:
55+
errors.append(Error('Unable to parse a volutility.conf file', hint='Copy volutiltiy.conf.sample to volutitliy.conf'))
56+
5257

5358
# Database Connection finally
5459
if have_mongo:

web/common.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import contextlib
55
import tempfile
66
import shutil
7+
import ConfigParser
78

89
try:
910
from subprocess import getoutput
@@ -63,3 +64,26 @@ def temp_dumpdir():
6364
temp_dir = tempfile.mkdtemp()
6465
yield temp_dir
6566
shutil.rmtree(temp_dir)
67+
68+
class Config:
69+
def __init__(self):
70+
config = ConfigParser.ConfigParser(allow_no_value=True)
71+
72+
conf_file = 'volutility.conf'
73+
74+
if not os.path.exists('volutility.conf'):
75+
conf_file = 'volutility.conf.sample'
76+
logger.warning('Using default config file. Check your volutility.conf file exists')
77+
78+
79+
valid = config.read(conf_file)
80+
if len(valid) > 0:
81+
self.valid = True
82+
for section in config.sections():
83+
for key, value in config.items(section):
84+
setattr(self, key, value)
85+
else:
86+
self.valid = False
87+
logger.error('Unable to find a valid volutility.conf file.')
88+
89+

web/database.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@
22
import pymongo
33
from bson.objectid import ObjectId
44
from gridfs import GridFS
5+
from common import Config
6+
config = Config()
57

68
class Database():
79
def __init__(self):
810
# Create the connection
11+
if config.valid:
12+
mongo_uri = config.mongo_uri
13+
else:
14+
mongo_uri = 'mongodb://localhost'
915

10-
connection = pymongo.MongoClient('localhost')
16+
connection = pymongo.MongoClient(mongo_uri)
1117

1218
# Version Check
1319
server_version = connection.server_info()['version']

web/static/js/volutility.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ Params:
2424
spinner: Bool = Overlay a loading spinner or not.'
2525
*/
2626

27-
27+
function changeCSS(cssname){
28+
var newcss = '/static/css/bootstrap_' + cssname + '.min.css';
29+
$('#bootswatch').attr('href', newcss);
30+
}
2831

2932

3033
/*
@@ -49,6 +52,7 @@ $(document).ready(function() {
4952
}(jQuery));
5053

5154
});
55+
5256
/*
5357
SpinnerControl opens and closes the loading page
5458
Not many plugins need to use this.

web/templates/base.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<meta charset="UTF-8">
77
<meta name="description" content="Volutility">
88
<meta name="keywords" content="yara,rules">
9-
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
9+
<link id="bootswatch" href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
1010
<link href="{% static 'css/style.css' %}" rel="stylesheet">
1111
<link href="{% static 'css/datatables.min.css' %}" rel="stylesheet">
1212

@@ -56,6 +56,8 @@
5656
<li class="divider"></li>
5757
<li><a href="#" data-toggle="modal" data-target="#aboutModal">About</a></li>
5858
<li><a href="#" onclick="spinnerControl('open', 'Cats Loading Stuffs')">Loading page</a></li>
59+
<li><a href="#" onclick="changeCSS('lumen')">Lumen Css</a></li>
60+
<li><a href="#" onclick="changeCSS('flatly')">Flatly Css</a></li>
5961
</ul>
6062
</li>
6163
</ul>

web/templates/modals/add_session_modal.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ <h5><strong>Extra Plugin Dirs: </strong>{{ plugin_dirs }}</h5>
3737
<textarea class="form-control" rows="3" name="description" placeholder="Description"></textarea>
3838
</div>
3939

40+
<div class="form-group">
41+
<input type="text" class="form-control" name="auto_run" placeholder="optional autorun plugins">
42+
</div>
43+
4044

4145
<button type="submit" class="btn btn-default" name="new" value="New">Submit</button>
4246

web/views.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import hashlib
44
from datetime import datetime
55
from web.common import *
6+
import multiprocessing
7+
from common import Config
8+
config = Config()
69

710
logger = logging.getLogger(__name__)
811

@@ -30,13 +33,6 @@
3033
YARA = False
3134
logger.warning("Unable to import Yara")
3235

33-
try:
34-
from vt_key import API_KEY
35-
VT_KEY = True
36-
except ImportError:
37-
VT_KEY = False
38-
logger.warning("Unable to import VirusTotal API Key from vt_key.py")
39-
4036
##
4137
# Import The volatility Interface and DB Class
4238
##
@@ -141,6 +137,11 @@ def session_page(request, sess_id):
141137
'volatility': vol_interface.vol_version,
142138
'volutility': volutility_version}
143139

140+
# Check if file still exists
141+
142+
if not os.path.exists(session_details['session_path']):
143+
error_line = 'Memory Image can not be found at {0}'.format(session_details['session_path'])
144+
144145

145146
return render(request, 'session.html', {'session_details': session_details,
146147
'plugin_list': plugin_list,
@@ -225,6 +226,22 @@ def create_session(request):
225226
# Store it
226227
session_id = db.create_session(new_session)
227228

229+
# Autorun list from config
230+
if config.autorun:
231+
auto_list = config.plugins.split(',')
232+
else:
233+
auto_list = False
234+
235+
# Merge Autorun from manual post with config
236+
if 'auto_run' in request.POST:
237+
run_list = request.POST['auto_run'].split(',')
238+
if not auto_list:
239+
auto_list = run_list
240+
else:
241+
for run in run_list:
242+
if run not in auto_list:
243+
auto_list.append(run)
244+
228245
# For each plugin create the entry
229246
for plugin in plugin_list:
230247
db_results = {}
@@ -241,7 +258,11 @@ def create_session(request):
241258
db_results['plugin_output'] = None
242259
db_results['status'] = None
243260
# Write to DB
244-
db.create_plugin(db_results)
261+
plugin_id = db.create_plugin(db_results)
262+
263+
if auto_list:
264+
if plugin_name in auto_list:
265+
multiprocessing.Process(target=run_plugin, args=(session_id, plugin_id)).start()
245266

246267
return redirect('/session/{0}'.format(str(session_id)))
247268

@@ -650,30 +671,28 @@ def ajax_handler(request, command):
650671

651672
return render(request, 'hive_details.html', {'hive_details': hive_details})
652673

653-
654674
if command == 'dottree':
655675
session_id = request.POST['session_id']
656676
session = db.get_session(ObjectId(session_id))
657677
vol_int = RunVol(session['session_profile'], session['session_path'])
658678
results = vol_int.run_plugin('pstree', output_style='dot')
659679
return HttpResponse(results)
660680

661-
662681
if command == 'virustotal':
663-
if not VT_KEY or not VT_LIB:
682+
if not config.api_key or not VT_LIB:
683+
logger.error('No Virustotal key provided in volutitliy.conf')
664684
return HttpResponse("Unable to use Virus Total. No Key or Library Missing. Check the Console for details")
665685

666686
if 'file_id' in request.POST:
667687
file_id = request.POST['file_id']
668688

669689
file_object = db.get_filebyid(ObjectId(file_id))
670690
sha256 = file_object.sha256
671-
vt = PublicApi(API_KEY)
691+
vt = PublicApi(config.api_key)
672692
response = vt.get_file_report(sha256)
673693

674694
vt_fields = {}
675695

676-
677696
if response['results']['response_code'] == 1:
678697
vt_fields['permalink'] = response['results']['permalink']
679698
vt_fields['total'] = response['results']['total']

0 commit comments

Comments
 (0)