Installation and setup
First off, there are a couple of dependencies that must be installed
> sudo apt-get install python-configobj
> sudo apt-get install python-gevent
assuming you are using Ubuntu. Further, the following packages are required
Validictory - https://github.com/sunlightlabs/validictory
Socksipy-branch - http://code.google.com/p/socksipy-branch/
hpfeeds - https://github.com/rep/hpfeeds
Next step is to clone the project from out Github repository and run it.
> git clone https://github.com/buttinsky/buttinsky.git
> python buttinsky.py
In the buttinsky/settings directory you can find two setting files for HTTP and IRC specific configurations. The filenames are used to load the configurations when spawning new botnet monitors as shown in the Figure 1. Based on these commands, Buttinsky will spawn a new botnet monitor and join the C&C channel on the IRC server specified in the configuration file irc_test.set.
Figure 1. Spawning a new monitor using the CLI
In the configuration file, in this case irc_test.set as shown below, it is possible to specify what plugins should be used at each layer and network configurations such as host, port, reconnection attempts and any proxies that should be used when connecting to the botnet. You can also specify plugins to be used for logging, protocol and behavior. This enables you to customize the decoding of protocol data, how your botnet monitor should behave and how you want to log collected data.
Another way of spawning new botnet monitors is based on hpfeeds, which is a lightweight authenticated publish-subscribe protocol. This enables you to receive botnet credentials from example a sandbox system or any other systems publishing this kind of information. There is also a hpfeeds logging component that can published collected data from a monitor. Setting up hpfeed-related stuff is performed in buttinsky/conf/buttinsky.cfg. Using hpfeeds it is now also possible to share information published using hpfriends.
Implementation and design
Buttinsky is supposed to be a framework where botnet analysts can implement their own plugins to support new botnet C&C protocols or customized ones.
Therefore, the design is such that each layer can be customized and the layer stack is visualized in Figure 2. Each layer can be fully customized and perform a certain task on the data before passed on to the above layer (or passed down to underlying layer). So far, IRC and HTTP communication layers have been added added to the stack and these can be used as a guidance on how to implement different plugins at each layer.
Figure 2. Layer
The behavioral layer will allow fine grained definition of the protocol details to support customized versions. As a proof-of-concept we added one behavior plugin that mimics a fictional IRC bot and its behavior. This is based on manual modeling of a botnet protocol in Netzob and exporting it so that Buttinsky can parse the model and botnet monitors can respond according to the model. More specifically, this is accomplished in Netzob by describing the protocol message formats and machine states of the protocol. For the interested reader, we refer to the Netzob documentation.
However, in order to construct a model of an unknown protocol, we need to infer the message format and state machine using machine learning. This is something we are working towards for the next and final release in this program.
Listing below shows the skeleton of a plugin. If there are any settings required for the plugin, it can be passed via the settings function. Two functions are required, receive that receives messages from the layer under and transmit that receives the data from the layer above. Messages are passed to layers above or under by returning a Message object. All these functions are mandatory to implement, if there is no need for initializing settings, it can simply be implemented as the example shows. For the Message object, you can access its class variables data and left. The former contains complete data received while the latter can be used for buffering data until everything is received. This can normally be handled at the protocol layer that decodes received data according to the protocol specification. If the receive function is called in your plugin and it is located at the last layer of the stack you can simply return the Message object as usual and the transmit function of that plugin will be called.
Finally, specify a unique name for you plugin and modify spawner.py around line 162 (https://github.com/buttinsky/buttinsky/blob/dev/spawner.py#L162) in order to set the layer plugin to be active. You may also need to import your plugin in spawner.py.
from stack import LayerPlugin, Message
def settings(self, settings):
def receive(self, msg):
return Message(msg.data, msg.left)
def transmit(self, msg):
return Message(msg,data, msg.left)
Customized logging can be implemented by following the implementation as in our example print_logger (https://github.com/buttinsky/buttinsky/blob/dev/modules/reporting/print_logger.p y).
This post should serve as an introduction to the design philosophy in Buttinsky in order for you to start experimenting with your own customizations and plugin implementations. If you get stuck or have any questions, contact us via our project webpage.