Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 53f98cd

Browse files
committed
merge
1 parent 8d7ad1f commit 53f98cd

File tree

5 files changed

+123
-16
lines changed

5 files changed

+123
-16
lines changed

viper/common/abstracts.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22
# This file is part of Viper - https://github.com/viper-framework/viper
33
# See the file 'LICENSE' for copying permission.
44

5+
import sys
56
import argparse
7+
from distutils.spawn import find_executable
8+
import pkg_resources
9+
10+
import logging
11+
612
import viper.common.out as out
713
from viper.core.config import console_output
814
from viper.common.exceptions import ArgumentErrorCallback
915

16+
log = logging.getLogger('viper')
17+
1018

1119
class ArgumentParser(argparse.ArgumentParser):
1220
def print_usage(self, file=None):
@@ -31,9 +39,64 @@ class Module(object):
3139
authors = []
3240
output = []
3341

42+
min_python_version = (2, 7)
43+
dependency_list_python = []
44+
dependency_list_system = []
45+
3446
def __init__(self):
3547
self.parser = ArgumentParser(prog=self.cmd, description=self.description)
3648

49+
def check(self):
50+
min_python_version = self._check_min_python_version()
51+
dep_python = self._check_dependencies_python()
52+
dep_system = self._check_dependencies_system()
53+
if min_python_version and dep_python and dep_system:
54+
return True
55+
else:
56+
return False
57+
58+
def _check_min_python_version(self):
59+
if sys.version_info >= self.min_python_version:
60+
log.debug("{}: Python Version ok".format(self.__class__.__name__))
61+
return True
62+
else:
63+
log.warning("{}: Python Version NOT ok".format(self.__class__.__name__))
64+
return False
65+
66+
def _check_dependencies_python(self):
67+
if not self.dependency_list_python:
68+
return True
69+
70+
missing = []
71+
72+
for item in self.dependency_list_python:
73+
try:
74+
pkg_resources.require(item)
75+
except pkg_resources.DistributionNotFound as err:
76+
log.debug("{}: Missing Python dependency: {}".format(self.__class__.__name__, err))
77+
missing.append(item)
78+
except pkg_resources.VersionConflict as err:
79+
log.debug("{}: Python dependency wrong version: {}".format(self.__class__.__name__, err))
80+
missing.append(item)
81+
82+
if missing:
83+
log.warning("{}: Missing/Failed Python dependencies: {}".format(self.__class__.__name__, missing))
84+
return False
85+
86+
return True
87+
88+
def _check_dependencies_system(self):
89+
if not self.dependency_list_system:
90+
return True
91+
92+
missing = [item for item in self.dependency_list_system if not find_executable(item)]
93+
94+
if missing:
95+
log.warning("{}: Missing System dependencies: {}".format(self.__class__.__name__, missing))
96+
return False
97+
else:
98+
return True
99+
37100
def set_commandline(self, command):
38101
self.command_line = command
39102

viper/core/plugins.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@
44

55
import pkgutil
66
import inspect
7+
import logging
78
import importlib
89

910
from viper.common.abstracts import Module
1011
from viper.common.abstracts import get_argparse_parser_actions
1112
from viper.common.abstracts import get_argparse_subparser_actions
1213
from viper.common.out import print_warning
1314

15+
log = logging.getLogger('viper')
16+
1417

1518
def load_modules():
1619
# Import modules package.
1720
import viper.modules as modules
1821

19-
plugins = dict()
22+
working_plugins = dict()
23+
failed_plugins = dict()
2024

2125
# Walk recursively through all modules and packages.
2226
for loader, module_name, ispkg in pkgutil.walk_packages(modules.__path__, modules.__name__ + '.'):
@@ -32,16 +36,26 @@ def load_modules():
3236

3337
# Walk through all members of currently imported modules.
3438
for member_name, member_object in inspect.getmembers(module):
35-
# Check if current member is a class.
36-
if inspect.isclass(member_object):
37-
# Yield the class if it's a subclass of Module.
38-
if issubclass(member_object, Module) and member_object is not Module:
39-
plugins[member_object.cmd] = dict(obj=member_object,
40-
description=member_object.description,
41-
parser_args=get_argparse_parser_actions(member_object().parser),
42-
subparser_args=get_argparse_subparser_actions(member_object().parser))
43-
44-
return plugins
45-
46-
47-
__modules__ = load_modules()
39+
if not inspect.isclass(member_object):
40+
continue
41+
# Yield the class if it's a subclass of Module.
42+
if issubclass(member_object, Module) and member_object is not Module:
43+
# run dependency check on each module and only add to working list if successful
44+
if member_object().check():
45+
log.debug("Module: {} - dependency check ok".format(member_name))
46+
working_plugins[member_object.cmd] = dict(obj=member_object,
47+
description=member_object.description,
48+
parser_args=get_argparse_parser_actions(member_object().parser),
49+
subparser_args=get_argparse_subparser_actions(member_object().parser))
50+
else:
51+
log.warning("Module: {} - failed dependency check".format(member_name))
52+
print_warning("Module: {} - failed dependency check".format(member_name))
53+
failed_plugins[member_object.cmd] = dict(obj=member_object,
54+
description=member_object.description,
55+
parser_args=get_argparse_parser_actions(member_object().parser),
56+
subparser_args=get_argparse_subparser_actions(member_object().parser))
57+
58+
return working_plugins, failed_plugins
59+
60+
61+
__modules__, __failed_modules__ = load_modules()

viper/core/ui/commands.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from viper.common.version import __version__
3131
from viper.core.session import __sessions__
3232
from viper.core.project import __project__
33-
from viper.core.plugins import __modules__
33+
from viper.core.plugins import __modules__, __failed_modules__
3434
from viper.core.database import Database
3535
from viper.core.storage import store_sample, get_sample_path
3636
from viper.core.config import Config, console_output
@@ -107,9 +107,13 @@ class About(Command):
107107
cmd = "about"
108108
description = "Show information about this Viper instance"
109109

110+
def __init__(self):
111+
super(About, self).__init__()
112+
self.parser.add_argument('-m', '--modules', action='store_true', help="Show info about modules")
113+
110114
def run(self, *args):
111115
try:
112-
self.parser.parse_args(args)
116+
args = self.parser.parse_args(args)
113117
except:
114118
return
115119

@@ -128,6 +132,27 @@ def run(self, *args):
128132

129133
self.log('table', dict(header=['Configuration', ''], rows=rows))
130134

135+
if args.modules:
136+
rows = list()
137+
for key, value in __modules__.items():
138+
min_python_version_str = ".".join([str(x) for x in value['obj'].min_python_version])
139+
dependency_python = ",".join(value['obj'].dependency_list_python)
140+
dependency_system = ",".join(value['obj'].dependency_list_system)
141+
142+
rows.append([key, dependency_system, min_python_version_str, dependency_python])
143+
144+
self.log('table', dict(header=['Active Modules', 'System dependencies', 'Min Python Version', 'Python requirements'], rows=rows))
145+
146+
rows = list()
147+
for key, value in __failed_modules__.items():
148+
min_python_version_str = ".".join([str(x) for x in value['obj'].min_python_version])
149+
dependency_python = ",".join(value['obj'].dependency_list_python)
150+
dependency_system = ",".join(value['obj'].dependency_list_system)
151+
152+
rows.append([key, dependency_system, min_python_version_str, dependency_python])
153+
154+
self.log('table', dict(header=['Failed Modules', 'System dependencies', 'Min Python Version', 'Python requirements'], rows=rows))
155+
131156

132157
class Analysis(Command):
133158
##

viper/modules/exif.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class Exif(Module):
1818
description = 'Extract Exif MetaData'
1919
authors = ['Kevin Breen']
2020

21+
dependency_list_python = ["exiftool"]
22+
dependency_list_system = ["exif"]
23+
2124
def __init__(self):
2225
super(Exif, self).__init__()
2326

viper/modules/misp.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class MISP(Module):
4848
description = 'Upload and query IOCs to/from a MISP instance'
4949
authors = ['Raphaël Vinot']
5050

51+
dependency_list_python = ["pymisp", "pytaxonomies", "requests"]
52+
5153
def __init__(self):
5254
super(MISP, self).__init__()
5355
self.cur_path = __project__.get_path()

0 commit comments

Comments
 (0)