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

Commit 9816e04

Browse files
committed
Added documentation for creating new modules
1 parent 2bfccb2 commit 9816e04

File tree

1 file changed

+183
-1
lines changed

1 file changed

+183
-1
lines changed

docs/source/customize/index.rst

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,184 @@
1-
Create new plugins
1+
Create new modules
22
==================
3+
4+
Viper in itself is simply a framework, modules are what give it analytical capabilities. We receive and include new modules all the time from contributors, but there are always new features to add. If you have an idea, you should implement a module for it and contribute it back to the community.
5+
6+
The following paragraphs introduce you to the first steps to create a new module.
7+
8+
9+
First steps
10+
-----------
11+
12+
First thing first, you need to create your *.py* script under the ``modules/`` directory: all modules are dynamically loaded by Viper from that folder exclusively. You can create subfolders and place your modules anywhere, Viper will be able to find them.
13+
14+
Any module needs to have some basic attributes that will make it recognizable. It needs to be a Python class inheriting ``Module``, it needs to have a ``cmd`` and ``description`` attribute and it needs to have a ``run()`` function. For example the following would be a valid, although not very useful, Viper module:
15+
16+
.. code-block:: python
17+
:linenos:
18+
19+
from viper.common.abstracts import Module
20+
21+
class MyModule(Module):
22+
cmd = 'mycmd'
23+
description = 'This module does this and that'
24+
25+
def run(self):
26+
print("Do something.")
27+
28+
29+
Arguments
30+
---------
31+
32+
When a module is invoked from the Viper shell it can be provided with a number of arguments. These are made accessible to the module through the ``self.args`` attribute, which is simply a Python list.
33+
34+
You will need to take care of parsing and interpreting the arguments, for example using Python's ``getopt`` module:
35+
36+
37+
.. code-block:: python
38+
:linenos:
39+
40+
import getopt
41+
42+
from viper.common.abstracts import Module
43+
44+
class MyModule(Module):
45+
cmd = 'mycmd'
46+
description = 'This module does this and that'
47+
48+
def run(self):
49+
try:
50+
opts, argv = getopt.getopt(self.args[0:], 'hs', ['help', 'something'])
51+
except getopt.GetoptError as e:
52+
print(e)
53+
return
54+
55+
for opt, value in opts:
56+
if opt in ('-h', '--help'):
57+
help()
58+
elif opt in ('-s', '--something'):
59+
print("Do something.")
60+
61+
62+
Accessing the session
63+
---------------------
64+
65+
In most cases, you will probably want to execute some analysis function on the currently opened file and in order to do so you'll need to access the session. Sessions are internally made available through a global object called ``__sessions__``, which has the following attributes:
66+
67+
* ``__sessions__.current``: a ``Session`` object for the currently opened file.
68+
* ``__sessions__.sessions``: the list of all ``Session`` objects opened during the current Viper execution.
69+
* ``__sessions__.find``: a list contains all the results from the last executed ``find`` command.
70+
71+
A ``Session`` object has the following attributes:
72+
73+
* ``Session.id``: an incremental ID for the session.
74+
* ``Session.created_at``: the date and time when the session was opened.
75+
* ``Session.file``: a ``File`` object containing common attributes of the currently opened file (generally speaking, the same information returned by the ``info`` command).
76+
77+
Following are the information available on the opened file:
78+
79+
* ``__sessions__.current.file.path``
80+
* ``__sessions__.current.file.name``
81+
* ``__sessions__.current.file.size``
82+
* ``__sessions__.current.file.type``
83+
* ``__sessions__.current.file.mime``
84+
* ``__sessions__.current.file.md5``
85+
* ``__sessions__.current.file.sha1``
86+
* ``__sessions__.current.file.sha256``
87+
* ``__sessions__.current.file.sha512``
88+
* ``__sessions__.current.file.crc32``
89+
* ``__sessions__.current.file.ssdeep``
90+
* ``__sessions__.current.file.tags``
91+
92+
Here is an example:
93+
94+
.. code-block:: python
95+
:linenos:
96+
97+
from viper.common.abstracts import Module
98+
from viper.core.session import __sessions__
99+
100+
class MyModule(Module):
101+
cmd = 'mycmd'
102+
description = 'This module does this and that'
103+
104+
def run(self):
105+
# Check if there is an open session.
106+
if not __sessions__.is_set():
107+
# No session opened.
108+
return
109+
110+
# Print attributes of the opened file.
111+
print("MD5: " + __sessions__.current.file.md5)
112+
113+
# Do something to the file.
114+
do_something(__sessions__.current.file.path)
115+
116+
117+
Accessing the database
118+
----------------------
119+
120+
In case you're interested in automatically retreiving all files stored in the local repository or just a subset, you'll need to access the local database. Viper provides an interface called ``Database()`` to be imported from ``viper.core.database``.
121+
122+
You can then use the ``find()`` function, specify a key and an optional value and you will obtain a list of objects you can loop through. For example:
123+
124+
.. code-block:: python
125+
:linenos:
126+
127+
from viper.common.abstracts import Module
128+
from viper.core.database import Database
129+
130+
class MyModule(Module):
131+
cmd = 'mycmd'
132+
description = 'This module does this and that'
133+
134+
def run(self):
135+
db = Database()
136+
# Obtain the list of all stored samples.
137+
samples = db.find(key='all')
138+
139+
# Obtain the list of all samples matching a tag.
140+
samples = db.find(key='tag', value='apt')
141+
142+
# Obtain the list of all samples with notes matching a pattern.
143+
samples = db.find(key='note', value='maliciousdomain.tld')
144+
145+
# Loop through results.
146+
for sample in samples:
147+
print("Sample " + sample.md5)
148+
149+
150+
Printing results
151+
----------------
152+
153+
Viper provides few functions to facilitate and standardize the output of your modules. Following are the functions available from ``viper.common.out``:
154+
155+
* ``print_info()``: prints the message with a ``[*]`` prefix.
156+
* ``print_warning()``: prints the message with a yellow ``[!]`` prefix.
157+
* ``print_error()``: prints the message with a red ``[!]`` prefix.
158+
* ``print_success()``: prints the message with a green ``[+]`` prefix.
159+
* ``print_item()``: prints an item from a list.
160+
161+
You can also easily print tables, such as in the following example:
162+
163+
.. code-block:: python
164+
:linenos:
165+
166+
from viper.common.abstracts import Module
167+
from viper.common.out import *
168+
169+
class MyModule(Module):
170+
cmd = 'mycmd'
171+
description = 'This module does this and that'
172+
173+
def run(self):
174+
print_info("Do something.")
175+
176+
# This is the header of the table.
177+
header = ['Column 1', 'Column 2']
178+
# These are the rows.
179+
rows = [
180+
['Row 1', 'Row 1'],
181+
['Row 2', 'Row 2']
182+
]
183+
184+
print(table(header=header, rows=rows))

0 commit comments

Comments
 (0)