Plugin Framework
The Thug Plugin Framework was introduced in version 0.3.0 and totally redesigned in version 0.8.1. If you ever thought about extending Thug with additional features but do not know how to do it you should really keep on reading.
Let’s start by taking a look a the code. Taking a look at thug/thug.py we can read these lines of code
if p:
ThugPlugins(PRE_ANALYSIS_PLUGINS, self)()
p(args[0])
ThugPlugins(POST_ANALYSIS_PLUGINS, self)()
Every operation performed by Thug is started by the line p(args[0]) so you can realize that two hooks exist in order to execute plugins in a pre and post-analysis stage. Please note that you can use the same approach even if developing external tools based on Thug API.
Let’s take a look at how to use the Plugin Framework before diving deep into details of how to write a plugin. During the Thug installation process the (empty) directory /etc/thug/plugins is created automatically. Moreover, take a look at the directory thug/thug/Plugins/plugins in the source tree
~/thug/thug/Plugins/plugins $ ls -lhR
.:
total 0
drwxr-xr-x 2 buffer buffer 41 Oct 12 09:00 POST-TestPlugin-999
drwxr-xr-x 2 buffer buffer 41 Oct 12 09:00 PRE-TestPlugin-999
./POST-TestPlugin-999:
total 4.0K
-rw-r--r-- 1 buffer buffer 885 Oct 12 09:00 Handler.py
-rw-r--r-- 1 buffer buffer 0 Oct 12 09:00 __init__.py
./PRE-TestPlugin-999:
total 4.0K
-rw-r--r-- 1 buffer buffer 885 Oct 12 09:00 Handler.py
-rw-r--r-- 1 buffer buffer 0 Oct 12 09:00 __init__.py
The directories PRE-TestPlugin-999 and POST-TestPlugin-999 contains the plugins we will be using for the next examples.
Before moving on, some details about the plugin directory name convention. The Plugin Framework expects the directory names in the following format for high-priority plugins:
[PHASE]-[PLUGIN NAME]-[PRIORITY]
or the following one for low-priority plugins (more on that later)
[PHASE]-[PLUGIN NAME]
where
PHASE specifies if the plugin has to be executed in a pre or post-analysis stage (possible values: ‘PRE’, ‘POST’)
PLUGIN_NAME specifies the name of the plugin
PRIORITY (optional) defines the plugin priority
If the plugin priority is specified (high-priority plugin), its value should be between 1 and 999. Plugin priority values greater or equal than 1000 are reserved for low-priority plugins and a plugin which does not specify a priority will be automatically assigned a priority value in such range. The plugin priority is useful if you want to enforce a specific order of execution for your plugins. For instance, if plugin B requires plugin A to operate on data before performing its task all you need to do is to define the plugin directory names this way
PRE-PluginA-1
PRE-PluginB-2
and the Plugin Framework guarantees that plugin A will be always executed before plugin B. Note that this applies to post-analysis plugins as well.
Assigning two (or more) high-priority plugins the same priority is possible. Both plugins will be executed but the framework can not guarantee their relative order of execution.
If you respect the convention of the specifically assigned priority value between 1 and 999, not assigning a priority to a plugin will make it a low-priority plugin meaning that it will be executed after all the high-priority plugins. If you define two or more low-priority plugins, there is no guarantee about their relative order of execution but they will executed after the high-priority ones in any case.
The suggested practice is to always assign a priority to each and every plugin in order to effectively control their relative order of execution.
Let’s take a look at how to use the Plugin Framework.
/etc/thug/plugins $ ls -lh
total 0
~/thug/thug $ thug -l ../samples/exploits/22811_Elazar.html
[2016-10-12 09:46:21] ActiveXObject: ierpctl.ierpctl
[2016-10-12 09:46:21] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in Import
[2016-10-12 09:46:21] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in PlayerProperty
Let’s try again after copying one of the test plugin directories provided in the source tree
~/thug/thug $ sudo cp -dpR Plugins/plugins/PRE-TestPlugin-999/ /etc/thug/plugins/
~/thug/thug $ ls -lh /etc/thug/plugins/
total 0
drwxr-xr-x 2 buffer buffer 41 Oct 12 09:00 PRE-TestPlugin-999
~/thug/thug $ thug -l ../samples/exploits/22811_Elazar.html
[2016-10-12 09:48:53] [PLUGIN][TestPlugin] Phase: PRE_ANALYSIS Priority: 999
[2016-10-12 09:48:53] ActiveXObject: ierpctl.ierpctl
[2016-10-12 09:48:53] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in Import
[2016-10-12 09:48:53] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in PlayerProperty
As you can see, TestPlugin is executed in pre-analysis stage (priority 999) as expected.
Let’s try again after copying the other test plugin directory provided in the source tree
~/thug/thug $ sudo cp -dpR Plugins/plugins/POST-TestPlugin-999/ /etc/thug/plugins/
~/thug/thug $ ls -lh /etc/thug/plugins/
total 0
drwxr-xr-x 2 buffer buffer 41 Oct 12 09:00 POST-TestPlugin-999
drwxr-xr-x 2 buffer buffer 78 Oct 12 09:48 PRE-TestPlugin-999
~/thug/thug $ thug -l ../samples/exploits/22811_Elazar.html
[2016-10-12 09:53:16] [PLUGIN][TestPlugin] Phase: PRE_ANALYSIS Priority: 999
[2016-10-12 09:53:17] ActiveXObject: ierpctl.ierpctl
[2016-10-12 09:53:17] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in Import
[2016-10-12 09:53:17] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in PlayerProperty
[2016-10-12 09:53:17] [PLUGIN][TestPlugin] Phase: POST_ANALYSIS Priority: 999
Both plugins are executed now in pre and post-analysis stage with the correct priorities. So all you need is to just drop the directory in the /etc/thug/plugins. But remember that if the directory name does not follow the convention, it will be just ignored!
The last step is to understand the anatomy of a plugin.
The plugin directory must contain a source file named Handler.py and this source file must define the class named Handler (entry point) which should be compliant with the following interface
class IPlugin(zope.interface.Interface):
def run(thug, log):
"""
This method is called when the plugin is invoked
Parameters:
@thug: Thug class main instance
@log: Thug root logger
"""
If the interface is correctly implemented the run method is automatically called passing to it two parameters: the Thug class main instance and the Thug root logger.
Let’s see a really simple example of plugin (TestPlugin)
import zope.interface
from .IPlugin import IPlugin
@implementer(IPlugin)
class Handler:
def run(self, thug, log):
log.debug(thug)
log.debug(log)
This plugin just logs the parameters but you can do whatever you want. Let’s try again the previous example enabling the debug option in order to see the debug messages
~/thug/thug $ thug -l -d ../samples/exploits/22811_Elazar.html
[2016-10-12 10:02:13] [PLUGIN][TestPlugin] Phase: PRE_ANALYSIS Priority: 999
[2016-10-12 10:02:13] <thug.thug.Thug object at 0x7f69b0ca2050>
[2016-10-12 10:02:13] <logging.Logger object at 0x7f69aa85cdd0>
[2016-10-12 10:02:13] Handling DOM Events: load,mousemove
[..]
[2016-10-12 10:02:13] ActiveXObject: ierpctl.ierpctl
[2016-10-12 10:02:13] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in Import
[2016-10-12 10:02:13] [RealMedia RealPlayer Ierpplug.DLL ActiveX] Overflow in PlayerProperty
[2016-10-12 10:02:13] [PLUGIN][TestPlugin] Phase: POST_ANALYSIS Priority: 999
[2016-10-12 10:02:13] <thug.thug.Thug object at 0x7f69b0ca2050>
[2016-10-12 10:02:13] <logging.Logger object at 0x7f69aa85cdd0>
Do you want to pre-check if the URL domain is within a blacklist? Just do it with a pre-analysis plugin. Do you want to extract and/or correlate information from the log files? Just do it with a post-analysis plugin.