В предыдущей статье мы рассказали о необычном способе раздачи вредоносного ПО — под видом обновления истекшего сертификата безопасности. После ее выхода мы провели более детальный анализ образцов и получили интересные данные. Все зловреды, изученные нами в рамках данной вредоносной кампании, были упакованы одним пакером, который получил название Trojan-Dropper.NSIS.Loncom. Зловред использует легитимное ПО NSIS для упаковки и запуска шелл-кода, а также Microsoft Crypto API для расшифровки финальной полезной нагрузки. И тут тоже не обошлось без сюрпризов: в одном из запакованных образцов мы обнаружили ПО, используемое APT-группировками.
Первичный анализ
Loncom использует NSIS, чтобы запустить шелл-код, который находится в файле с именем, состоящим из цифр. В нашем примере это файл 485101134:
После распаковки шелл-кода на жесткий диск и его загрузки в память NSIS-скрипт вычисляет, с какой позиции необходимо начать выполнение, и переходит к следующей стадии.
Работа шелл-кода
Прежде чем перейти к расшифровке полезной нагрузки, шелл-код начинает расшифровывать себя по частям, используя следующий алгоритм действий:
- Найти позицию следующего dword 0xDEADBEEF.
- Прочитать dword — размер данных для расшифровки.
- Прочитать dword — первую часть ключа.
- Прочитать dword — вторую часть ключа.
- Подобрать подходящий ключ: перебор чисел от 0 до тех пор, пока xor(i , вторая часть ключа) != первая часть ключа. Данный перебор необходим для задержки и предотвращения детектирования. Если упростить алгоритм, ключ = i = xor(первая часть, вторая часть).
- Расшифровать следующую часть шелл-кода (xor) и перейти к ней.
Код, исполняющий вышеописанный алгоритм:
После нескольких итераций одинаковой расшифровки блоков шелл-код переходит к активным действиям — загружает библиотеки и получает адреса необходимых функций с помощью техники ApiHashing. Она позволяет не указывать названия необходимых функций напрямую, а указать лишь их хэши. При поиске функции по ее хэшу для каждого элемента из таблицы экспорта библиотеки хэш будет вычисляться до тех пор, пока не совпадет с искомым.
Далее Loncom расшифровывает полезную нагрузку, которая находится в том же файле с шелл-кодом, и переходит к ее выполнению. Полезная нагрузка зашифрована с помощью блочного шифра AES-256. Ключ для расшифровки прописан в коде, а смещение до полезной нагрузки и ее размер передаются из NSIS-скрипта.
Снимаем упаковку
Для автоматизированной распаковки Loncom нам нужно понять, каким образом хранятся данные в упакованных NSIS-установщиках, получить смещение и размер полезной нагрузки из NSIS-скрипта, а затем вытащить ключ из шелл-кода.
Распаковка NSIS
После небольшого анализа нам удалось выяснить, что NSIS-установщики имеют следующую структуру:
- MZPE NSIS-интерпретатор, в оверлее которого лежат данные для обработки: флаг, сигнатуры, размер распакованного «заголовка» и общий размер данных, затем и сами сжатые данные — контейнеры.
- Контейнеры вида «dword (размер данных):zlib_deflate(данные)». В нулевом контейнере находится «заголовок», в первом — наш файл с шелл-кодом и полезной нагрузкой, во втором — DLL с NSIS-плагином. В заголовке находится таблица операционных кодов для интерпретатора NSIS, таблица строк, таблица языковой информации.
Так как мы получили зашифрованный файл, остается лишь найти смещение и размер полезной нагрузки, а затем перейти к расшифровке ее и шелл-кода.
Так как все аргументы в операционных кодах NSIS при работе с плагинами передаются как строки, нам необходимо извлечь из таблицы строк заголовка все строки, которые похожи на числа в логичных пределах (от 0 до размера файла за вычетом размера шелл-кода).
Код распаковки NSIS:
Чтобы избежать сложностей с определением смещения и размера полезной нагрузки, мы можем вспомнить структуру файла с шелл-кодом: расшифровка зашифрованных блоков идет от меньшего адреса к большему, сверху вниз, и полезная нагрузка находится «над» шелл-кодом. Следовательно, мы можем определить позицию байта 0xDEADBEEF и считать ее концом зашифрованных данных (при необходимости выполняя выравнивание, так как AES — блочный шифр).
Расшифровка шелл-кода
Для того чтобы расшифровать полезную нагрузку, нам необходимо:
- расшифровать блоки шелл-кода;
- определить, где находится ключ для AES;
- извлечь ключ;
- попробовать расшифровать полезную нагрузку для смещений, полученных от NSIS;
- остановиться, получив первые два байта = ‘MZ’.
Первый пункт можно выполнить, слегка изменив код, исполняющий алгоритм расшифровки в IDA Pro. Определить ключ можно с помощью простого регулярного выражения: ‘\xC7\x45.(….)\xC7\x45.(….)\xC7\x45.(….)\xC7\x45.(….)\xE8’ – 4 mov dword ptr, call за ними (Pseudocode в главной части шелл-кода).
Остальные пункты не требуют детального разбора, и мы можем перейти к вредоносному ПО, которое было упаковано Loncom.
Что внутри?
Кроме упомянутых в прошлой статье Mokes и Buerak, мы заметили упакованных представителей семейств Backdoor.Win32.DarkVNC и Trojan-Ransom.Win32.Sodin (также известного как REvil и Sodinokibi). Первое — бэкдоры, используемые для управления зараженной машиной при помощи протокола VNC. Второе — шифровальщики, шантажирующие жертву публикацией зашифрованной информации.
Но самой интересной находкой стала утилита Cobalt Strike, используемая как легальными пентестерами, так и различными APT-группировками. Командный центр содержащего Cobalt Strike образца также ранее был замечен в раздаче CactusTorch (утилиты для запуска шелл-кода, которая присутствует в модулях Cobalt Strike) и того же Cobalt Strike, но упакованного другим пакером.
Мы продолжаем следить за Trojan-Dropper.NSIS.Loncom и надеемся вскоре поделиться новыми находками.
Индикаторы заражения
BB00BA9726F922E07CF243D3CCFC2B6E (Backdoor.Win32.DarkVNC)
EBE191BF77044961684DF51B88CA8D05 (Backdoor.Win32.DarkVNC)
4B4C98AC8F04680F7C529956CFE8519B (Trojan-Ransom.Win32.Sodin)
AEF8FBB5C64734093E78EB13E6FA7849 (CobaltStrike)
Пакер Loncom — от бэкдоров к Cobalt Strike