Операция TA505, часть четвертая. Близнецы
Продолжаем рассказывать о деятельности хакерской группировки TA505. Всем известная фраза «новое — это хорошо забытое старое» как нельзя лучше подходит в качестве эпиграфа к очередной главе повествования о группе TA505. Правда, в этот раз «старое» не столько «забыто», сколько переработано и улучшено.
В начале сентября мы обнаружили несколько вредоносных загрузчиков, упакованных специальным PE-пакером группы, о котором мы писали ранее. На первый взгляд они были похожи на хорошо известные стейджеры бэкдора FlawedAmmyy. Но более глубокий анализ показал, что это не так. Не самые передовые техники написания кода вывели нас на кардинально противоположные полезные нагрузки по качеству исполнения.
В этой статье мы подробнее рассмотрим найденные инструменты и проведем параллели с тем, что уже известно.
Загрузчик Twein
Прежде всего любопытно следующее: из всех образцов загрузчиков, которые нам удалось собрать, лишь один имеет цифровую подпись:
Рис. 1. Цифровая подпись загрузчика
Сертификат выдан на имя PEAR SOLUTIONS LTD. К слову, это не первый случай, когда группировка подписывает свои инструменты, выдавая их за легитимное ПО фиктивных организаций. Вот несколько других имен, которые использовали TA505 для других семейств ВПО:
- ET HOMES LTD,
- FIT AND FLEX LIMITED,
- MISHA LONDON LTD,
- SATOJI KAIDA MB,
- VERY TELE LIMITED.
Так как обнаруженные загрузчики между собой не различаются, выберем вышеупомянутый подписанный и остановимся на нем подробнее.
На протяжении работы ВПО практически каждое действие сопровождается записью в файл журнала и отладочным выводом всего происходящего:
Рис. 2. Отладочный вывод и журналирование
Такая трассировка не только упрощает статический разбор файла, но и помогает обнаружить неладное в системах динамического анализа:
Рис. 3. Отладочный вывод в онлайн-анализаторе ANY.RUN
Троян проверяет языковую раскладку клавиатуры — и не работает в России и странах ближнего зарубежья:
Рис. 4. Проверка языковой раскладки клавиатуры
Затем создает мьютекс Global\system32_mutant_service
и проверяет доступность интернета с помощью HTTP GET-запроса к google.com. После этого определяет способ выхода в сеть (выделенный адрес или NAT) путем определения внешнего IP-адреса сервисами myexternalip.com, ipecho.net и ifconfig.me и сравнения полученного значения с указанными в сетевых параметрах системы:
Рис. 5. Сопоставление внутреннего и внешнего IP-адресов
Далее вредонос определяет версию библиотеки %SystemRoot%\system32\crypt32.dll
и, в случае если номер сборки и номер ревизии меньше, чем 7601
и 18741
соответственно, загружает и устанавливает обновление KB3033929
согласно версии операционной системы:
Рис. 6. Загрузка и установка обновления системы
Злоумышленники из TA505 заботятся о жертве и патчат систему по мере необходимости? Вовсе нет. Установка обновления связана с прекращением поддержки сертификатов безопасности кода, подписанных с помощью SHA-1, и отказом от него в пользу алгоритма SHA-2. Вероятнее всего, хакеры уже сталкивались со сложностями запуска подписанных полезных нагрузок на необновленных системах. Интересно, что после установки обновления троян отправляет сформированный журнал действий на управляющий сервер, прекращает свою работу и самоудаляется, подчищая оставленные следы.
Рис. 7. Завершение работы после установки обновления системы
В случае если установка обновления не требуется, загрузчик собирает и отправляет следующую информацию на управляющий сервер:
- информация о системе,
- информация об установленном ПО,
- информация о подписанном ПО в каталогах %ProgramFiles% и %ProgramFiles (x86)% (если есть),
- информация о подписанных драйверах в каталоге %SystemRoot%\drivers.
Отметим, что для получения информации о подписях был использован легитимный код.
Рис. 8. Получение информации о сертификате
После этого загрузчик создает каталог C:\Windows\Logs\diag
и запускает поток, в котором отслеживает изменения в каталоге, отправляя уведомления на управляющий сервер:
Рис. 9. Мониторинг изменений в каталоге
Затем подготавливает уже имеющуюся и недостающую информацию о системе (имя пользователя, версия системы, домен, IP-адрес, информация о видеокарте, подключение к сети — NAT или не NAT) и формирует JSON-файл такого вида:
{
"adm": "0",
"bid": "M3xwwhqLH/AUOhmU2+W55A==",
"bit": "1",
"bnet": "ldr",
"cam": "0",
"cis": "0",
"dmn": "WORKGROUP",
"hash_r": "0",
"lip": "192.168.100.153",
"lvl": "0",
"nat": "1",
"osb": "0",
"osv": "Windows 7 Professional",
"pc": "USER-PC",
"proc_c": "0",
"proc_n": "cpu",
"rep": 0,
"tmt": "0",
"ver": "163",
"video": "Standard VGA Graphics Adapter,"
}
Позже эти данные будут зашифрованы RC4 (ключ шифрования gJypA9RWUlYpnBbzujVqE6fDcEAk0zoz
зашит в теле трояна), закодированы с помощью Base64 и отправлены HTTP POST-запросом на управляющий сервер:
Рис. 10. HTTP POST-запрос на управляющий сервер
Рис. 11. Список управляющих серверов в теле загрузчика
Ответ от сервера расшифровывается RC4 (ключ шифрования тот же, что использовался при отправке данных) и проверяется: первые два байта должны соответствовать строке MZ, что является признаком PE-файла. Мы уже встречали такую последовательность ранее, когда анализировали другой загрузчик группы, который доставлял FlawedAmmyy RAT:
Рис. 12. Схожий код расшифровки и проверки загруженного файла у рассматриваемого загрузчика (слева) и загрузчика FlawedAmmyy RAT (справа)
Загрузка полезной нагрузки происходит не только в главном потоке, но и в отдельно создаваемом. Другими словами, полезных нагрузок — две. В одном случае предварительно проверяется мьютекс Global\system32_host_service, и в случае его отсутствия выполняется загрузка компонента, который именуется в отладочной информации как payload или bot. Интересно то, что после получения ответа от сервера PE-файл никаким образом не запускается. Вместо этого его тело записывается в реестр в раздел HKEY_LOCAL_MACHINE\SYSTEM
в ключ 0x228028
. Затем загрузчик отключает перенаправление файловой системы WoW64 для 32-битных приложений средствами Wow64DisableWow64FsRedirection
и запускает процесс %SystemRoot%\System32\services.exe
с параметром -ww. Использование этого параметра не имеет смысла, но на этом заканчивается цепочка установки полученного пейлоада.
Рис. 13. Установка полезной нагрузки
Про вторую полезную нагрузку мы поговорим позднее.
Twein-плагины
Исследуя рассмотренный выше троян, мы обратили внимание на функцию, которая удаляет два файла из каталога %SystemRoot%
— twein_32.dll
и twein_64.dll
:
Рис. 14. Удаление файлов twein_32.dll и twein_64.dll
Больше эти файлы нигде не встречаются, не фигурируют в логике работы загрузчика. Однако имена библиотек напомнили нам другое ВПО группы, которое мы сейчас рассмотрим.
Двумя месяцами ранее мы обнаружили троян группы TA505, размером около 9 МБ. Файл упакован UPX. Троян устанавливается в систему в качестве сервиса WMDICToss
. В ресурсах содержатся три файла: systemdiron.bat
, twein__32.dll
и twein__64.dll
, которые зашифрованы линейным XOR.
Рис. 15. Расшифровка одного из ресурсов дроппера
Обратим внимание, что имена двух файлов практически совпадают с уже упомянутыми ранее: разница лишь в количестве знаков подчеркивания.
Один из расшифрованных ресурсов с именем systemdiron.bat
ожидаемо представляет собой командный сценарий, который обеспечивает запуск других компонентов в зависимости от разрядности системы:
@echo off
if defined PROCESSOR_ARCHITEW6432 (goto LABEL_X64)
if %PROCESSOR_ARCHITECTURE%==IA64 (goto LABEL_X64)
if %PROCESSOR_ARCHITECTURE%==AMD64 (goto LABEL_X64)
if %PROCESSOR_ARCHITECTURE%==x86 (goto LABEL_X86)
goto LABEL_NON
:LABEL_X64
echo OS type: x64
copy c:\temp\tmp.log c:\i.txt
rundll32.exe C:\Windows\twein__64.dll,Install
copy c:\temp\tmp.log c:\i.txt
rundll32.exe C:\Windows\twein__32.dll,Install
del c:\temp\tmp.log
del c:\i.txt
shutdown.exe -r -t 00
goto LABEL_END
:LABEL_X86
echo OS type: x86
copy c:\temp\tmp.log c:\i.txt
rundll32.exe C:\Windows\twein__32.dll,Install
del c:\temp\tmp.log
del c:\i.txt
shutdown.exe -r -t 00
goto LABEL_END
:LABEL_NON
echo OS type: undefined
goto LABEL_END
:LABEL_END
pause
Обе twein-библиотеки действуют аналогично. Упакованы характерным пакером группы TA505. Оригинальные имена библиотек: av_block.dll
. Анализ существенно усложнен использованием обфускатора, причем доля обфусцированного кода составляет около 80%. Вследствие этого выполнение программы насыщено многочисленными переходами, расшифровками следующих ступеней кода, нелинейными вызовами функций.
Библиотеки содержат внушительный список Base64-подобных строк, которые расшифровываются следующим образом:
1. входная строка разделяется на блоки по 4 байта;
2. каждый блок декодируется с помощью алгоритма замены и сдвига:
import binascii
def block_decode(input_str, len_of_block):
alphabet = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3E\x00\x00\x00\x3F\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x00\x00\x00\x00\x00\x00\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
int_result = 0
for i in range(len_of_block):
alph = ord(alphabet[ord(input_str[i])])
alph <<= 0x6 * i
int_result += alph
str_result = hex(int_result)[2:]
if len(str_result) % 2 != 0:
str_result = '0' + str_result
return binascii.unhexlify(str_result).decode('latin1')[::-1]
3) блоки собираются в единую строку;
4) результат расшифровывается алгоритмом eexec с двухбайтовым ключом, передаваемым в качестве параметра:
Рис. 16. Реализация алгоритма eexec
Бóльшая часть строк — имена и пути до файлов антивирусных продуктов, однако некоторые из них принадлежат вовсе не защитным средствам: MS Exchange Server, MySQL Server, SAP, Apache, PostgreSQL, Elasticsearch и др. Встречались даже такие уникальные пути:
- C:\Users\tislam\Desktop\salik app\Aye_salik_data\Aye_salik_data\bin\Debug\Aye_salik_data.exe
- C:\oem13c\agent13c\agent_13.2.0.0.0\perl\bin\perl.exe
- C:\Users\adadmin\Ubiquiti UniFi\bin\mongod.exe
- C:\Users\sakella\AppData\Local\Microsoft\OneDrive\OneDrive.exe
- D:\Add-ons\IMI_CREDIT_POLICY Test v 02.01\IMI_CREDIT_POLICY.exe
Если в системе обнаружено ПО из списка — файлы и каталоги удаляются.
Для закрепления в системе библиотеки устанавливают себя в качестве интерфейса сервис-провайдера (SPI) Windows Sockets, именуясь Intel и IntelFiltr. Помимо этого, они изменяют очередность обработчиков в цепочке протоколов, чтобы быть первым SPI, который обработает запрос клиента.
В 2015 году наши коллеги из FireEye представили разбор бота LatentBot. Любопытно, что алгоритм шифрования строк в LatentBot и рассмотренных twein-библиотеках полностью совпадает. Кроме этого, LatentBot использует в качестве одного из плагинов security-модуль, который ищет в системе защитные средства по заданным путям и названиям продуктов, правда только проверкой наличия и ограничивается.
Руткит Twein
Вернемся к загрузчику, а именно ко второй полезной нагрузке. По отладочным строкам try to open rootkit… и Driver %S installed несложно догадаться о формате следующего пейлоада. После успешной загрузки драйвер будет записан в каталог %SystemRoot%\System32\drivers
с именем, сформированным псевдопроизвольным образом из имен других легитимных файлов. Затем сервис будет создан и запущен:
Рис. 17. Установка и запуск сервиса
В завершающей стадии своей работы загрузчик сконфигурирует работу драйвера черными списками в ключах реестра: в заданные числовые значения ключей ветки HKEY_LOCAL_MACHINE\SYSTEM
будут занесены имена антивирусных процессов, инструментов анализа и вендоров защитных средств в цифровых подписях файлов:
Рис. 18. Конфигурация драйвера черными списками
В процессе исследования загрузчика нам не удалось получить образец драйвера от управляющего сервера. Однако мы нашли упоминание о рутките, который выкачивался другим аналогичным загрузчиком.
Драйвер подписан цифровой подписью, выданной на имя Lizas Limited
с указанием administrator@lizaslimited.site
в качестве электронной почты:
Рис. 19. Цифровая подпись драйвера
В процессе исследования мы обнаружили много общего с хорошо известным руткитом ботнета Necurs, который активно использовала группа TA505 для рассылки спама и распространения ВПО. Рассмотрим подробнее наиболее интересные особенности его работы.
Драйвер регистрирует обработчики событий на запуск процессов и загрузку PE-образов средствами PsSetCreateProcessNotifyRoutine
и PsSetLoadImageNotifyRoutine
. Другими словами, это позволяет драйверу проконтролировать запуск всех новых процессов и сервисов. Используя черные списки, о которых мы упоминали ранее, руткит завершает нежелательные процессы с помощью ZwTerminateProcess и не дает загрузиться другим, потенциально опасным для него драйверам, перезаписывая значение точки входа на инструкции:
mov eax, 0C0000001
retn 8
Как следствие, сервис будет штатно выгружен с ошибкой STATUS_UNSUCCESSFULL
.
Рис. 20. Завершение процессов
Рис. 21. Перезапись точки входа драйверов
Средствами CmRegisterCallback драйвер перехватывает события доступа к реестру системы. В частности, его дальнейшая работа параметризуется числовыми значениями ключей, к которым происходит обращение в перехваченных событиях.
Рис. 22. Управление руткитом обращениями к ключам реестра
Любопытно, что в некоторых версиях руткита Necurs те же самые числовые значения использовались в качестве кодов ioctl-запросов.
Рис. 23. Управление руткитом Necurs с помощью ioctl-запросов
Этот трюк можно расценивать как шаг в сторону большей скрытности: обращения к реестру вызывают меньше подозрений, чем ioctl-запросы к DeviceObject.
В теле руткита содержится вспомогательная DLL-библиотека, зашифрованная однобайтовым XOR. При создании нового процесса драйвер инжектирует библиотеку вместе с еще одним PE-файлом, который извлекается из реестра и снова расшифровывается однобайтовым XOR.
Рис. 24. Расшифровка и инжект вспомогательной библиотеки в созданный процесс
Вспомогательный компонент представляет собой кастомный рефлективный загрузчик, который корректно разместит в памяти второй PE-файл, выполняющий роль полезной нагрузки, и передаст на него управление. Теперь становится понятно, как именно начинает работать тот пейлоад, который записывался в реестр загрузчиком из первой части статьи.
Рис. 25. Заполнение таблицы импорта вспомогательной библиотекой
Заключение
В статье мы познакомились с особенностями работы множества троянов-близнецов. Почему близнецов? Вредоносный загрузчик, с которого мы начинали наше исследование, по качеству написания кода и нюансам реализации очень похож на хорошо известный загрузчик бэкдора FlawedAmmyy. Библиотеки twein, которые он пытается удалить из системы, — вероятнее всего, те, которые мы рассматриваем дальше. Библиотеки крайне схожи с защитным плагином трояна LatentBot. Один из пейлоадов загрузчика — драйвер, являющийся производной популярного руткита Necurs.
Некоторым семействам ВПО уже более 5 лет, однако злоумышленники продолжают их обновлять и совершенствовать, учитывая при этом развитие операционных систем и средств защиты.
Авторы: Алексей Вишняков и Даниил Колосков, Positive Technologies
a28a54abc30805cc6ea2ce0732989287 — загрузчик Twein
f6b6526b8d494dce14568e3703368432 — дроппер twein-плагинов
983dd279722154a12093410067fe070e — руткит Twein