Skip to content

Commit

Permalink
formatted readme
Browse files Browse the repository at this point in the history
  • Loading branch information
pjlantz committed Aug 12, 2010
1 parent 8b7f4d8 commit 0231426
Showing 1 changed file with 105 additions and 106 deletions.
211 changes: 105 additions & 106 deletions README.md
Expand Up @@ -55,7 +55,7 @@ Usage
------------

To start the monitor head to hale/src/ and execute python main.py. If it fires up with errors then the django settings.py file is not correctly set or some libraries are missing. When the monitor is running type 'help' or '?' to get the available commands. Type help command to get more info about the specific command. Starting up a monitor bot is done by first editing the hale/src/conf/modules.conf file, for example using a irc configuration as follow:
**`

[ircConf]
module = irc
botnet = irc.freenode.net
Expand All @@ -77,7 +77,6 @@ To start the monitor head to hale/src/ and execute python main.py. If it fires u
currenttopic_grammar = 332
ping_grammar = PING
pong_grammar = PONG
`**

Edit or create a new config by specifying a new uniquely named section ([ircConf] part). At the top of the config file there is a section called uniqueKeys where all unique fields for a module are specified and used to generate the botnet hash, this should usually not be changed to preserve correct botnet tracking. When this is done run useconf section to load the configuration and then fire up the bot with exec modulename id where id is set by you to identify the botnet.

Expand All @@ -90,129 +89,129 @@ How to add modules, the current module API work as follow:

1) Implement module, for example:

import moduleManager
from utils import moduleInterface

@moduleManager.register("irc")
def module_setup(config, hash):
"""
Function to register modules, simply
implement this to pass along the config
and hash to the module object and return
the it back.
"""

return IRC(config, hash)

# must inherit from Module class
class IRC(moduleInterface.Module):

def __init__(self, config, hash):
self.config = config
self.hash = hash

# must be implemented
def stop(self):
# stop execution

# must be implemented
def run(self):
# start execution

# must be implemented
def getConfig(self):
return self.config
import moduleManager
from utils import moduleInterface
@moduleManager.register("irc")
def module_setup(config, hash):
"""
Function to register modules, simply
implement this to pass along the config
and hash to the module object and return
the it back.
"""
return IRC(config, hash)
# must inherit from Module class
class IRC(moduleInterface.Module):
def __init__(self, config, hash):
self.config = config
self.hash = hash
# must be implemented
def stop(self):
# stop execution
# must be implemented
def run(self):
# start execution
# must be implemented
def getConfig(self):
return self.config

Add decorator for the register function (in this case module_setup) which will be called with the current configuration as argument and the config hash made of the unique keys. This function can be named anything. Pass along the configurations to the module object, the configHandler catches KeyErrors so if wrong configurations are sent to this function configHandler will notify you about it.

Also follow the naming convention nameModule.py and @moduleManager.register("name") and import the moduleManager, if not the moduleManager will notify you about any errors.

The rest of the module code is omitted but should create a twisted factory object and start this with the reactor in the run method, see the existing modules for an example. For tutorials on programming with Twisted, please see http://twistedmatrix.com/trac/wiki/Documentation. There are also some utils to make use of when developing modules, this is done as following:

# import all utils
from utils import *

Socksify:

# in the constructor create a new proxy object
self.prox = proxySelector.ProxySelector()

# in the run method add the following after having created the factory method.
proxyInfo = self.prox.getRandomProxy()
if proxyInfo == None:
self.connector = reactor.connectTCP(host, port, factory)
else:
proxyHost = proxyInfo['HOST']
proxyPort = proxyInfo['PORT']
proxyUser = proxyInfo['USER']
proxyPass = proxyInfo['PASS']
socksify = socks5.ProxyClientCreator(reactor, factory)
if len(proxyUser) == 0:
self.connector = socksify.connectSocks5Proxy(host, port, proxyHost, proxyPort, "HALE")
else:
self.connector = socksify.connectSocks5Proxy(host, port, proxyHost, proxyPort, "HALE", proxyUser, proxyPass)
# import all utils
from utils import *
Socksify:
# in the constructor create a new proxy object
self.prox = proxySelector.ProxySelector()
# in the run method add the following after having created the factory method.
proxyInfo = self.prox.getRandomProxy()
if proxyInfo == None:
self.connector = reactor.connectTCP(host, port, factory)
else:
proxyHost = proxyInfo['HOST']
proxyPort = proxyInfo['PORT']
proxyUser = proxyInfo['USER']
proxyPass = proxyInfo['PASS']
socksify = socks5.ProxyClientCreator(reactor, factory)
if len(proxyUser) == 0:
self.connector = socksify.connectSocks5Proxy(host, port, proxyHost, proxyPort, "HALE")
else:
self.connector = socksify.connectSocks5Proxy(host, port, proxyHost, proxyPort, "HALE", proxyUser, proxyPass)
Logging:

# in the factory create the following method to handle logs (note that the hash and config must be sent to the factory)
# and call it in the protocol class with: self.factory.putLog(data)
def putLog(self, log):
"""
Put log to the event handler
"""

moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.LOG_EVENT, log, self.hash, self.config)

# apply reg expression to look for URLs containing possible malware
# and call it in the protocol class with: self.factory.checkForURL(data)
def checkForURL(self, data):
"""
Check for URL in the event handler
"""
# in the factory create the following method to handle logs (note that the hash and config must be sent to the factory)
# and call it in the protocol class with: self.factory.putLog(data)
def putLog(self, log):
"""
Put log to the event handler
"""
moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.LOG_EVENT, log, self.hash, self.config)

moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.URL_EVENT, data, self.hash)
# apply reg expression to look for URLs containing possible malware
# and call it in the protocol class with: self.factory.checkForURL(data)
def checkForURL(self, data):
"""
Check for URL in the event handler
"""
moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.URL_EVENT, data, self.hash)

# if you module should detect IP numbers of other bots and herders implement the following method in the factory
def addRelIP(self, data):
"""
Put possible ip related to the botnet being monitored
in the event handler.
"""

moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.RELIP_EVENT, data, self.hash)
# if you module should detect IP numbers of other bots and herders implement the following method in the factory
def addRelIP(self, data):
"""
Put possible ip related to the botnet being monitored
in the event handler.
"""
moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.RELIP_EVENT, data, self.hash)

handling related IPs is done by applying a regular expression to be used for the protocol that the module is going to support, in case of irc module, the code looks like this:

checkHost = data.split(':')[1].split(' ')[0].strip()
match = self.factory.expr.findall(checkHost)
if match:
self.factory.addRelIP(data.split('@')[1].split(' ')[0].strip())
checkHost = data.split(':')[1].split(' ')[0].strip()
match = self.factory.expr.findall(checkHost)
if match:
self.factory.addRelIP(data.split('@')[1].split(' ')[0].strip())

where the regular expression is as follow:

self.expr = re.compile('!~.*?@')
self.expr = re.compile('!~.*?@')


2) Drag the file to the modules directory. The moduleManager will then automatically import it and check for errors.

3) In modules.conf edit the configuration, in this case:

# specify unique configs for module
# a * means that all configs contaning the strings equal to the one
# after the * will be treated as unique.
# in this example all pass_grammar, mode_grammar etc should be
# treated as unique keys
[uniqueKeys]
irc = botnet, *grammar, ... etc
# name a section, can be anything as long as its unique
# and add module regname (in this case irc) as module option
[myIrcConf]
module = irc
nick = SpyBot
channel = #irc
...
etc.
# specify unique configs for module
# a * means that all configs contaning the strings equal to the one
# after the * will be treated as unique.
# in this example all pass_grammar, mode_grammar etc should be
# treated as unique keys
[uniqueKeys]
irc = botnet, *grammar, ... etc
# name a section, can be anything as long as its unique
# and add module regname (in this case irc) as module option
[myIrcConf]
module = irc
nick = SpyBot
channel = #irc
...
etc.

4) Upload the module to the web ui by setting the module name to for example irc, filename ircModule.py and then add a config example for this module.

Expand All @@ -221,35 +220,35 @@ Feeder bot HOWTO:
When sending a request for a botnet to track the request is made as follow
to the groupchat coordination room

sensorLoadReq
sensorLoadReq

where all sensors reply with their id and queue length (number of monitored botnets)

sensorLoadAck id=353f6650859547ed06597dbfa1dcfd88 queue=0
sensorLoadAck id=353f6650859547ed06597dbfa1dcfd88 queue=0

The feeder then choose one sensor based on this info like lowest queue length
and if these are equal for several sensors, then the sensor id sorted alphabetically
with lowest value is chosen.

When the feeder has chosen a sensor it sends a private chat message to the sensor

startTrackReq config
startTrackReq config

where config is a string representation of the configuration, for example

module=irc botnet=irc.freenode.net etc..
module=irc botnet=irc.freenode.net etc..

The sensor then replies with with an acknowledgement together with the config hash
which can be used to distringuish the botnet logs from the other logs in the share channel
Example of acknowledgment:

startTrackAck hash
startTrackAck hash

if no one else is monitoring this botnet, otherwise a startTrackNack is received if the
botnet is already monitored or the sensor does not have the module installed for this botnet.
Malware share is done by sensors sending a message like:

FileCaptured hash=353f6650... file content
FileCaptured hash=353f6650... file content

where the content is Base64 encoded and comes directly after the file hash value.

Expand Down

0 comments on commit 0231426

Please sign in to comment.