Hale 是一款僵尸网络命令与控制(C&C)监控/侦察工具,采用模块化设计,可轻松开发新模块来监控 C&C 服务器使用的新协议。Hale 自带基于 Twisted 开发的 IRC 和 HTTP 监控模块,可处理大量连接带来的扩展性问题。这些模块具有可配置的协议语法和机器人设置,也可根据您的需求进行修改。所有捕获的日志和文件都会保存到数据库中,对于 IRC 模式,还会记录被跟踪的 IP 地址。
为了隐藏操作者的位置,可以通过 SOCKSv5 代理建立连接,这可通过 Web 界面进行配置,所有日志以及统计图表和时间线也都可以在界面上浏览。该界面使用 Django 和 Google Visualization API 开发。Web 界面的一些附加功能包括支持 OAuth 的 RESTful API 以及搜索引擎。
Hale 的主要理念是通过创建传感器网络(Hale 监控器)来帮助僵尸网络追踪和研究协作。为改进这一理念,Hale 提供了一个 XMPP 机器人,可连接到集中式 XMPP 服务器,目前使用两个不同的群组房间:一个用于传感器之间的协调,另一个用于共享日志和文件。协调房间使用由僵尸网络设置中的唯一键生成的僵尸网络哈希,这样,具有相同哈希(身份)的两个僵尸网络就不必同时被监控,从而提高了利用率。为帮助第三方利用此网络,机器人可以加入协调房间,通过发送配置信息请求传感器开始跟踪尚未被跟踪的僵尸网络。此外,在共享房间中,第三方机器人可以实时获取传感器捕获的日志和文件。为便于查看日志历史,可以使用支持 GET 请求的 Web API。
Hale 具有以下依赖项:
Python == 2.6
Django == 1.2.1
Twisted == 10.1.0
GeoIP-Python == 1.2.4 (and GeoIP C lib)
Whoosh == 0.3.18
django-haystack == 1.0.1-final
django-piston == 0.2.3rc1
pefile == 1.2.10-63
sleekxmpp == 0.9Rrc1
wsgiref == 0.1.2
zope.interface == 3.6.1
oauth2 == 1.2.0
httplib2 == 0.6.0
此外,监控器需要与 django 所使用的数据库相对应的数据库后端驱动程序。安装完这些库后,请从此处下载源代码并解压到任意位置。
首先创建 Hale 将使用的数据库,数据库引擎可任选其一。如果您使用现有数据库,则可跳过此步骤。
下一步是安装与服务器引擎所使用的数据库相对应的 Python 数据库后端驱动程序。
编辑 hale/src/webdb/ 中的 settings.py,修改以下配置项:ENGINE、NAME、USER、PASSWORD、HOST 和 PORT。其中,如果您的服务器引擎是 MySQL,则 engine 设置项例如为 django.db.backends.mysql。name 设置项是您创建数据库时使用的数据库名称。
如果您不想启动自己的 Web 界面,请跳过此步骤,直接转到第 8) 步。在 settings.py 中,将 PATH_TO_APP 改为指向 Django 应用程序的完整路径,例如:'/home/..../Hale/src/webdb'。在 webdb 目录下运行以下命令:python manage.py syncdb。如果此处出现任何错误,很可能是 settings.py 中的数据库设置不正确。此外,在同步过程中,请设置用于管理用户的超级用户。
为支持 Web 界面中的搜索功能,请运行 python manage.py rebuild_index 让搜索引擎进行首次索引。这将创建一个名为 whoosh.index/ 的目录,为让 Web 服务器能够在此写入,请执行 chmod o+w whoosh.index/。此后,您只需运行 python manage.py update_index,并应将其设置为 cron 任务,以便按您选择的固定时间间隔更新索引。
运行 python manage.py runserver,然后访问 http://127.0.0.1:8000 检查设置是否正确完成。
runserver 命令部署的是开发服务器,由于性能问题,不建议在生产环境中使用。请改为安装 Apache 的 mod_wsgi 来部署 Web 界面。假设您运行的是 Ubuntu,请执行 apt-get install libapache2-mod-wsgi。在 /etc/apache2/sites-available/default 中添加以下内容:
Alias /media /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/
<Location /media>
Order allow,deny
Allow from all
</Location>
WSGIDaemonProcess username processes=2 maximum-requests=500 threads=10
WSGIProcessGroup group
WSGIScriptAlias / /home/..../webdb/django.wsgi
并编辑 WSGI 守护进程运行所使用的 username 和 group。WSGIScriptAlias 应设置为位于 webdb 目录中的 django.wsgi 文件的完整路径。上面指定的 Alias 用于确保管理页面能够正确渲染。为了能够通过 Web 界面上传模块,请执行 chmod o+w webdb/modules。
上传将要从 hale/src/modules/ 使用的模块,或编写您自己的模块(参见开发章节)。在管理界面上传所需模块,例如将模块名称修改为 irc,文件名修改为 ircModule.py。在位于 hale/conf/modules.conf 的相应部分中为模块指定配置规则,并将其放入文本框中,同时为所上传的模块添加 uniqueKeys 部分。
运行监控器之前,如果您希望使用 XMPP 服务器,请编辑 hale/src/conf/ 中的 hale.conf。要激活 XMPP 机器人,请将 use 设置改为 True,并将登录信息编辑为现有账号和服务器,或自行启动 XMPP 服务器。启动 XMPP 服务器时,一个重要步骤是将最大 stanza 大小从默认值增加到约 10Mb,否则将无法进行恶意软件通告。hale.conf 中的 channel 设置用于机器人使用的共享群组房间,coord 设置用于传感器之间进行所有协调的群组房间。
编辑 hale.conf 并设置客户端和服务器参数。
要启动监控器,请进入 hale/src/ 目录并执行 python server.py。如果启动时出现错误,则说明 django 的 settings.py 文件设置不正确,或缺少某些库。使用客户端可以向服务器发出命令,但用户需要先向服务器进行身份验证,只有通过 Web 界面设置为 staff 成员的用户才能获得访问权限。客户端运行时,输入 help 或 ? 可查看可用命令。输入 help 命令名可查看特定命令的更多信息。启动监控机器人时,首先编辑 hale/src/conf/modules.conf 文件,例如使用如下 IRC 配置:
[uniqueKeys]
irc = botnet, *grammar
[ircConf]
module = irc
botnet = irc.freenode.net
port = 6667
password = None
nick = nickname
username = agent007
realname = Spying
channel = #channelname
channel_pass = somepass
pass_grammar = PASS
nick_grammar = NICK
user_grammar = USER
join_grammar = JOIN
version_grammar = VERSION
time_grammar = TIME
privmsg_grammar = PRIVMSG
topic_grammar = TOPIC
currenttopic_grammar = 332
ping_grammar = PING
pong_grammar = PONG
通过指定一个具有唯一名称的新部分([ircConf] 部分)来编辑或创建新配置。配置文件顶部有一个名为 uniqueKeys 的部分,其中指定了模块的所有唯一字段,并用于生成僵尸网络哈希。为保持正确的僵尸网络跟踪,通常不应更改此部分。完成后,运行 useconf section 加载配置,然后使用 exec modulename id 启动机器人,其中 id 由您自行设置以标识僵尸网络。
Web 界面提供对数据库中所有已捕获数据的访问,可从首页进入。此外还有一个搜索功能,使用户能够搜索僵尸网络和文件哈希、相关 IP 地址、僵尸网络 ID、所使用的僵尸网络模块以及僵尸网络主机。如果用户拥有编辑代理或模块的权限,则可以在管理部分进行操作,其网址为 http://.../admin。管理员可以设置用户模式,也可以为 Web API 添加使用者(consumer)。
实现模块,例如:
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)
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
为 register 函数(在此例中为 module_setup)添加装饰器,该函数将以当前配置和由唯一键生成的配置哈希作为参数被调用。此函数可以任意命名。将配置传递给模块对象,configHandler 会捕获 KeyError,因此如果向此函数发送了错误的配置,configHandler 会通知您。
同时请遵循命名约定 nameModule.py 和 @moduleManager.register("name"),并导入 moduleManager,否则 moduleManager 会通知您任何错误。
模块的其余代码此处省略,但应创建一个 twisted factory 对象,并在 run 方法中使用 reactor 启动它,可参考现有模块的示例。有关 Twisted 编程的教程,请参见此处。开发模块时还可以使用一些工具函数,使用方法如下:
Socksify:
# import all utils
from utils import *
# 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)
在 factory 对象中处理连接错误:
def clientConnectionFailed(self, connector, reason):
"""
Called on failed connection to server
"""
moduleCoordinator.ModuleCoordinator().putError("Error connecting to " + self.config['botnet'], self.module)
def clientConnectionLost(self, connector, reason):
"""
Called on lost connection to server
"""
moduleCoordinator.ModuleCoordinator().putError("Connection lost to " + self.config['botnet'], self.module)
这会将错误发送到错误桶(error bucket),可通过在 CLI 中执行 showlog 来查看。
日志记录: