
Монитор командных серверов ботнетов
Hale — это монитор/шпион для ботнет-командных серверов (C&C) с модульной архитектурой, упрощающей разработку новых модулей для отслеживания новых протоколов, используемых C&C-серверами. Hale поставляется с IRC- и HTTP-мониторами, разработанными на Twisted для обеспечения масштабируемости при большом количестве соединений. Эти модули имеют настраиваемую грамматику протокола и параметры бота, но также могут быть изменены под ваши нужды. Все перехваченные логи и файлы сохраняются в базу данных, а в случае IRC — также отслеживаются IP-адреса.
Чтобы скрыть местоположение оператора, соединения могут выполняться через SOCKSv5-прокси; это настраивается через веб-интерфейс, где также можно просматривать все логи вместе со статистическими графиками и временными шкалами. Интерфейс разработан с использованием Django и Google Visualization API. Дополнительные возможности веб-интерфейса включают поддержку RESTful API с OAuth и поисковый движок.
Основная идея Hale — помочь охоте на ботнеты и исследованиям, создав сеть сенсоров (мониторов Hale). Для улучшения этой идеи доступен XMPP-бот для подключения к централизованному XMPP-серверу, где в настоящее время используются две разные групповые комнаты: одна для координации между сенсорами и одна для обмена логами и файлами. В комнате координации используются хэши ботнетов, созданные из уникальных ключей в настройках ботнета; таким образом, два ботнета с одинаковым хэшем (идентичностью) не должны отслеживаться одновременно, что повышает эффективность использования. Чтобы помочь сторонним лицам воспользоваться этой сетью, бот может присоединиться к комнате координации и попросить сенсор начать отслеживание ботнета, если он не отслеживается, отправив его конфигурацию. Кроме того, в комнате обмена сторонние боты могут получать логи и файлы, захваченные сенсорами в реальном времени. Для работы с историей логов можно использовать веб-API, поддерживающее GET-запросы.
Hale имеет следующие зависимости:
Python == 2.6
Django == 1.2.1
Twisted == 10.1.0
GeoIP-Python == 1.2.4 (и библиотека GeoIP C)
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 для базы данных, соответствующие используемому серверному движку.
Отредактируйте settings.py в hale/src/webdb/ и настройте следующие параметры: ENGINE, NAME, USER, PASSWORD, HOST и PORT, где параметр engine, например, равен django.db.backends.mysql, если ваш серверный движок — MySQL. Параметр name — это имя вашей базы данных, использованное при её создании.
Если вы не хотите запускать собственный веб-интерфейс, пропустите этот шаг и перейдите к пункту 8). В settings.py измените PATH_TO_APP, указав полный путь к приложению Django, например: '/home/..../Hale/src/webdb'. В каталоге webdb выполните следующую команду: python manage.py syncdb. Если возникнут ошибки, скорее всего, настройки базы данных в settings.py некорректны. Кроме того, во время синхронизации укажите суперпользователя, который будет использоваться при администрировании пользователей.
Для поддержки поиска в веб-интерфейсе выполните python manage.py rebuild_index, чтобы поисковый движок проиндексировал данные в первый раз. Будет создан каталог ; чтобы веб-сервер мог в него записывать, выполните . После этого вместо этой команды запускайте и добавьте её в cron для регулярного обновления индексов с выбранным вами интервалом.
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
и укажите имя пользователя (username) и группу (group), от которых должен работать WSGI-демон. Параметр WSGIScriptAlias должен указывать полный путь к файлу django.wsgi, расположенному в каталоге webdb. Указанный выше Alias необходим для корректного отображения страницы администрирования. Чтобы иметь возможность загружать модули через веб-интерфейс, выполните chmod o+w webdb/modules.
Загрузите модули, которые будут использоваться из hale/src/modules/, или напишите свои собственные (см. раздел «Разработка»). Загрузите нужный модуль в административном интерфейсе, указав, например, имя модуля irc и имя файла ircModule.py. Укажите правила конфигурации для модуля в соответствующем разделе, расположенном в hale/conf/modules.conf, и вставьте их в текстовое поле; также добавьте разделы uniqueKeys для загружаемого модуля.
Перед запуском монитора отредактируйте hale.conf в hale/src/conf/, если вы хотите использовать XMPP-сервер. Чтобы активировать XMPP-бота, установите для параметра use значение True и либо укажите данные существующей учётной записи и сервера, либо запустите собственный XMPP-сервер. Важный шаг при запуске XMPP-сервера — увеличить максимальный размер stanza с значения по умолчанию до примерно 10 МБ. В противном случае передача вредоносного ПО (malware advertisement) будет невозможна. Настройки канала (channel) в hale.conf используются для групповой комнаты обмена, используемой ботом, а настройка coord — для групповой комнаты, где происходит вся координация между сенсорами.
Отредактируйте hale.conf и укажите настройки клиента и сервера.
Чтобы запустить монитор, перейдите в hale/src/ и выполните python server.py. Если он запустится с ошибками, значит файл settings.py Django настроен некорректно или отсутствуют некоторые библиотеки. С помощью клиента можно отправлять команды серверу, но для этого требуется аутентификация пользователя на сервере; доступ предоставляется пользователям, назначенным как 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 задаётся вами для идентификации ботнета.
Веб-интерфейс предоставляет доступ ко всем перехваченным данным в базе данных, доступным с главной страницы. Также есть функция поиска, позволяющая пользователю искать хэши ботнетов и файлов, связанные IP-адреса, идентификаторы ботнетов, используемые модули ботнетов и хосты ботнетов. Если у пользователя есть права на редактирование прокси или модулей, это можно сделать в административном разделе; URL для доступа: http://.../admin. Администратор может устанавливать режимы пользователей, а также добавлять потребителей для веб-API.
Реализуйте модуль, например:
import moduleManager from utils import moduleInterface
@moduleManager.register("irc") def module_setup(config, hash): """ Функция для регистрации модулей. Просто реализуйте её, чтобы передать config и hash объекту модуля и вернуть его обратно. """
return IRC(config, hash)
class IRC(moduleInterface.Module):
def __init__(self, config, hash):
self.config = config
self.hash = hash
# должен быть реализован
def stop(self):
# остановить выполнение
# должен быть реализован
def run(self):
# начать выполнение
# должен быть реализован
def getConfig(self):
return self.config
Добавьте декоратор для функции регистрации (в данном случае module_setup), которая будет вызываться с текущей конфигурацией в качестве аргумента и хэшем конфигурации, созданным из уникальных ключей. Эту функцию можно назвать как угодно. Передайте конфигурации объекту модуля; configHandler перехватывает KeyErrors, поэтому, если в эту функцию отправлены неправильные конфигурации, configHandler уведомит вас об этом.
Также соблюдайте соглашение об именовании nameModule.py и @moduleManager.register("name") и импортируйте moduleManager; в противном случае moduleManager уведомит вас о любых ошибках.
Остальная часть кода модуля опущена, но она должна создавать объект фабрики Twisted и запускать его с реактором в методе run; примеры см. в существующих модулях. Учебные пособия по программированию на Twisted см. здесь. Также есть несколько утилит, которые можно использовать при разработке модулей. Это делается следующим образом:
Socksify:
# импортируем все утилиты
from utils import *
# в конструкторе создаём новый объект прокси
self.prox = proxySelector.ProxySelector()
# в методе run добавьте следующее после создания фабрики.
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)
Обработка ошибок соединения в объекте фабрики:
def clientConnectionFailed(self, connector, reason):
"""
Вызывается при неудачном соединении с сервером
"""
moduleCoordinator.ModuleCoordinator().putError("Error connecting to " + self.config['botnet'], self.module)
def clientConnectionLost(self, connector, reason):
"""
Вызывается при потере соединения с сервером
"""
moduleCoordinator.ModuleCoordinator().putError("Connection lost to " + self.config['botnet'], self.module)
Это отправит ошибки в корзину ошибок (error bucket), доступ к которой осуществляется командой showlog в CLI.
Логирование:
# в фабрике создайте следующий метод для обработки логов (обратите внимание, что hash и config должны быть переданы в фабрику)
# и вызовите его в классе протокола с помощью: self.factory.putLog(data)
def putLog(self, log):
"""
Поместить лог в обработчик событий
"""
moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.LOG_EVENT, log, self.hash, self.config)
# примените регулярное выражение для поиска URL, содержащих возможное вредоносное ПО
# и вызовите его в классе протокола с помощью: self.factory.checkForURL(data)
def checkForURL(self, data):
"""
Проверить URL в обработчике событий
"""
moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.URL_EVENT, data, self.hash)
# если ваш модуль должен обнаруживать IP-адреса других ботов и «пастухов», реализуйте следующий метод в фабрике
def addRelIP(self, data):
"""
Поместить возможный IP, связанный с отслеживаемым ботнетом,
в обработчик событий.
"""
moduleCoordinator.ModuleCoordinator().addEvent(moduleCoordinator.RELIP_EVENT, data, self.hash)
Обработка связанных IP выполняется путём применения регулярного выражения, используемого для протокола, который модуль должен поддерживать. В случае IRC-модуля код выглядит так:
checkHost = data.split(':')[1].split(' ')[0].strip()
match = self.factory.expr.findall(checkHost)
if match:
self.factory.addRelIP(data.split('@')[1].split(' ')[0].strip())
где регулярное выражение следующее:
self.expr = re.compile('!~.*?@')
2) Перетащите файл в каталог modules. moduleManager затем автоматически импортирует его и проверит на ошибки.
В modules.conf отредактируйте конфигурацию.
Загрузите модуль в веб-интерфейс, указав имя модуля, например, irc, имя файла ircModule.py, а затем добавьте пример конфигурации для этого модуля.
При отправке запроса на отслеживание ботнета запрос отправляется следующим образом в групповую комнату координации:
sensorLoadReq
где все сенсоры отвечают своим идентификатором и длиной очереди (количеством отслеживаемых ботнетов):
sensorLoadAck id=353f6650859547ed06597dbfa1dcfd88 queue=0
Затем отправитель (feeder) выбирает один сенсор на основе этой информации, например, с наименьшей длиной очереди; если эти значения равны для нескольких сенсоров, выбирается сенсор с идентификатором, отсортированным по алфавиту с наименьшим значением.
Когда отправитель выбрал сенсор, он отправляет личное чат-сообщение сенсору:
startTrackReq config
где config — строковое представление конфигурации, например:
module=irc botnet=irc.freenode.net и т.д.
Затем сенсор отвечает подтверждением вместе с хэшем конфигурации, который можно использовать для отличия логов этого ботнета от других логов в канале обмена. Пример подтверждения:
startTrackAck hash
если никто другой не отслеживает этот ботнет; в противном случае получается startTrackNack, если ботнет уже отслеживается или на сенсоре не установлен модуль для этого ботнета. Обмен вредоносным ПО осуществляется сенсорами путём отправки сообщения вида:
fileCaptured hash=353f6650... file content
где содержимое кодируется в Base64 и идёт сразу после значения хэша файла.
Для доступа к API вам понадобятся потребительский ключ (consumer key) и секретный ключ (secret key); их может создать администратор, и они используются с OAuth для аутентификации. Следующие URL-адреса доступны для получения данных в формате JSON:
http://.../api/botnet ответит всеми отслеживаемыми ботнетами
http://.../api/botnet/botnethash ответит ботнетом с хэшем, равным botnethash
http://.../api/host/hostname ответит всеми отслеживаемыми ботнетами с хостом, равным hostname
http://.../api/type/module ответит всеми отслеживаемыми ботнетами с указанным модулем
http://.../api/botips/hash ответит всеми IP, захваченными ботнетом со значением hash
http://.../api/bologs/hash ответит всеми логами для ботнета со значением hash
http://.../api/bofiles/hash ответит хэшами файлов, захваченных ботнетом со значением hash
http://.../api/file/hash возвращает информацию о ботнете(ах), захвативших файл с указанным хэшем
http://.../api/ip/addr ответит информацией о ботнете(ах), обнаруживших IP с номером addr
Обратите внимание, что в настоящее время возможны только GET-запросы.
whoosh.index/chmod o+w whoosh.index/python manage.py update_indexВыполните python manage.py runserver и перейдите на http://127.0.0.1:8000, чтобы проверить правильность настройки.
Команда runserver запускает development-сервер, который не рекомендуется для продакшн-использования из-за проблем с производительностью. Вместо этого разверните веб-интерфейс, установив mod_wsgi для Apache. Предполагая, что вы используете Ubuntu, выполните apt-get install libapache2-mod-wsgi. В /etc/apache2/sites-available/default добавьте следующее: