Содержание статьи
Руткит из семейства Festi заинтересовал нас по многим причинам, но главные из них две. Во-первых, по сей день это один из самых активных спам-ботов, а во-вторых — именно этот ботнет осуществлял DDoS-атаку на платежную систему ASSIST (в результате расследования этой атаки был арестован небезызвестный Павел Врублевский).

Семейство руткитов Festi известно с 2009 года и в первую очередь прославилось массовыми рассылками спама и целенаправленными DDoS-атаками (рис. 1). В начале текущего года прошло серьезное обновление ботнета и миграция на новые командные серверы (рис. 2). Именно это обновление и привлекло наше внимание — слишком многое поменялось. Во-первых, изменился протокол взаимодействия с командным центром: если раньше это был HTTP с зашифрованным POST-ответом, то сейчас это специально разработанный протокол с возможностью обхода различных защитных средств, анализирующих сетевой трафик. Во-вторых, все задания для ботов загружаются только в память зараженной машины, и что наиболее интересно — загружаются они в адресное пространство на уровне ядра операционной системы.
Warning!
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.

Warning!
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
Архитектура Festi
Дроппер необходим только для установки основного функционала в виде драйвера, который осуществляет всю основную активность. На рис. 3 представлен граф вызова функций после выполнения точки входа этого драйвера.

Основной задачей этого модуля является взаимодействие с командным центром и установка дополнительных модулей.
Нами было замечено два основных дополнительных модуля — для рассылки спама и для осуществления DDoS-атак соответственно. Свою работу бот начинает с обращения на командный центр и получения актуального задания, после чего скачивается соответствующий плагин. Все расширения активируются непосредственно из памяти и не сохраняются на диске, что существенно затрудняет процесс криминалистической экспертизы, так как после выключения компьютера восстановить цели и задачи конкретного бота практически невозможно.
Еще одной интересной особенностью этого бота является то, что он написан на C++ с использованием ООП. Подобные вещи нечасто можно встретить при разработке модулей режима ядра. Основные его компоненты (классы):
- менеджер памяти;
- собственная реализация сокетов;
- парсер протокола взаимодействия с C&C;
- менеджер плагинов.
Схема взаимодействия между ними изображена на рис. 4. За счет разработанного уровня абстракции основное ядро Festi может быть легко портировано под другие операционные системы, в том числе отличные от MS Windows.

Система плагинов
Наибольший интерес представляют сами плагины, так как именно при помощи них выполняются задания, полученные от командного центра. Система плагинов реализована по принципу массива указателей на специально определенные структуры.

Структура описывает плагин и протокол обмена данными с ним. Восстановленный в процессе обратного анализа вариант структуры выглядит следующим образом:
struct PLUGIN_INTERFACE
{
// Initialize plugin
PVOID Initialize;
// Release plugin, perform cleanup operations
PVOID Release;
// Get plugin version information
PVOID GetVersionInfo_1;
// Get plugin version information
PVOID GetVersionInfo_2;
// Write plugin specific information into tcp stream
PVOID WriteIntoTcpStream;
// Read plugin specific information from tcp strteam and parse data
PVOID ReadFromTcpStream;
// Reserved fields
PVOID Reserved_1;
PVOID Reserved_2;
};

Когда бот передает данные на командный центр, выполняется обработка плагинов и активируется функция WriteIntoTcpStream() для каждого зарегистрированного плагина. При получении данных с сервера выполняется другая функция — ReadFromTcpStream(). Структура данных, передаваемых по сети, представлена на рис. 7.

Взаимодействие с плагинами обеспечивает менеджер плагинов, который загружает соответствующий плагин и отвечает за его корректное выполнение. Каждый плагин содержит две экспортируемые функции:
- PLUGIN_INTERFACE *CreateModule(PVOID DriverInterfaces)
- VOID DeleteModule().
Полный цикл загрузки плагина можно увидеть на рис. 8.

Сетевой протокол
В Festi реализован собственный защищенный от перехвата протокол. Ботнет использует клиент-серверную топологию с несколькими командными центрами. Например, один отвечает за раздачу заданий на рассылку спама, а другой только за проведение DDoS-атак.
Сетевой протокол работает в нескольких фазах:
- инициализация — получение IP-адресов активных командных центров;
- активация — получение текущего задания из командного центра.
В первой фазе осуществляется запрос на заранее указанные DNS-серверы с целью получения IP-адресов для указанных доменов, которые хранятся в качестве констант в теле самого бота. В фазе активации происходит взаимодействие по протоколу TCP, получается текущее задание и плагин.
Протокол для второй фазы состоит из заголовка сообщения и непосредственно буфера с самим плагином. В буфере содержатся данные с тег-ориентированным протоколом (чем-то похож на XML), раздел данных, содержащий непосредственно плагин, зашифрован следующим алгоритмом:
key = (0x17, 0xFB, 0x71,0x5C)
def decr_data(data):
for ix in xrange(len(data)):
data[ix] ^= key[ix % 4]
Обход HIPS и межсетевых экранов
Одна из интересных особенностей Festi — обход защитных средств, установленных на зараженном компьютере. Festi встраивается уровнем ниже, чем это реализуется в стандартных драйверах NDIS, которые работают на канальном уровне. Для отправки или приема сетевых пакетов открываются непосредственно устройства \Device\Tcp или \Device\Udp в зависимости от типа протокола. В большинстве персональных межсетевых экранов или HIPS реализовано наблюдение через перехват запросов IRP_MJ_CREATE_FILE, которые направляются транспортному драйверу отрытого устройства. Этот способ позволяет также установить процесс, от которого было инициировано сетевое взаимодействие. Подобный мониторинг можно реализовать двумя способами:
- установить хук на ZwCreateFile для мониторинга всех попыток открытия устройства;
- непосредственно аттач на \Device\Tcp или \Device\Udp для перехвата всех IRP-запросов.
Festi для обхода подобного мониторинга собственными силами реализует функцию ZwCreateFile(), практически дублируя ее (схему реализации функции ZwCreateFile() см. на рис. 9).

Из представленной схемы видно, что Festi создает объект связи с устройством и напрямую посылает запросы IRP_MJ_CREATE транспортному драйверу. Таким образом, все защитное ПО, отслеживающее устройства \Device\Tcp или \Device\Udp, пропустит запросы от бота. Для прямого взаимодействия с устройствами \Device\Tcp или \Device\Udp вредоносной программе нужны указатели к соответствующим объектам устройств (device objects). Для получения указателя на Tcpip.sys на объект драйвера можно использовать:
NTSTATUS
ObReferenceObjectByName (
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN PACCESS_STATE AccessState OPTIONAL,
IN ACCESS_MASK DesiredAccess OPTIONAL,
IN POBJECT_TYPE ObjectType,
IN KPROCESSOR_MODE AccessMode,
IN OUT PVOID ParseContext OPTIONAL,
OUT PVOID *Object
);

Это недокументированная системная функция, получающая в качестве одного из параметров юникод-строку с именем устройства. Festi осуществляет итерацию по всему списку устройств, чтобы найти нужное соответствие. Восстановленный код этой процедуры представлен на рис. 11.

Проблемы анализа ООП-кода
Анализ несколько затруднило присутствие ООП-кода, так как современные инструменты обратного анализа и даже IDA не умеют эффективно его восстанавливать. К примеру, восстановление графа потока управления в С++ усложняется полиморфизмом на уровне виртуальных функций, что показано на рис. 12.

Сложность заключается в точном получении адреса процедуры, которая будет вызвана. Статический анализ не дает информации о том, куда будет указывать регистр EAX. Для того чтобы получить адрес, нужно выяснить, где создается объект указанного типа, а это происходит непосредственно в процессе выполнения, и именно тогда инициализируется указатель на таблицу виртуальных методов.
На рис. 13 приведен пример конструктора класса CSocket, реализованного в Festi. Видно, что происходит непрозрачный вызов и инициализация указателя CSocket::vTable на таблицу виртуальных методов.

В качестве заключения
Руткит Festi довольно нетипичный экземпляр вредоносного ПО, авторы которого подошли очень серьезно к процессу его разработки. Они предусмотрели множество нюансов, которые обеспечивают незаметное присутствие этого бота в системе длительное время и затрудняют обратный анализ. К примеру, на момент извлечения экземпляров вредоносных плагинов из памяти зараженной системы ни один антивирусный продукт их не обнаруживал.
Проблемы с полным анализом сложного вредоносного ПО возникают довольно часто, но лишь полный анализ может собрать весь пазл целиком и найти эффективные способы противодействия таким угрозам…