Positive Technologies
PT Expert Security Center

PaaS, или Как хакеры ускользают от антивирусов

PaaS, или Как хакеры ускользают от антивирусов

Одним из главных инструментов любой хакерской группировки является вредоносное ПО. В зависимости от уровня квалификации хакеров и особенностей операции, они могут использовать как массовые, зачастую публично доступные инструменты (типичным примером может быть фреймворк Cobalt Strike), так и собственные разработки.

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

Чтобы бороться с этой проблемой, хакеры используют техники упаковки, шифрования и мутации кода. Такие техники часто реализуют отдельные инструменты — «крипторы» (crypters), иногда называемые просто «пакерами». В этой статье на примере банковского трояна RTM мы рассмотрим, какие пакеры могут использовать злоумышленники, как эти пакеры осложняют обнаружение конкретного ВПО и какие еще вредоносы ими упаковываются.

Packer-as-a-service

Хакерская группа, стоящая за распространением RTM, до конца 2020 года регулярно проводила массовые фишинговые рассылки с вредоносными вложениями. Этот процесс, по всей видимости, происходил автоматически.

Фишинговое письмо RTM, декабрь 2020
Рис. 1. Фишинговое письмо RTM, декабрь 2020

Каждое такое вложение содержало существенно отличающиеся друг от друга файлы, при этом итоговая полезная нагрузка практически не менялась.

Пример архива RTM
Рис. 2. Пример архива RTM

Подобная особенность — естественное следствие применения крипторов. Первоначально группа, стоящая за RTM, использовала свой собственный уникальный криптор, однако в течение 2020 года дважды его сменила.

При исследовании по-новому упакованных образцов нам удалось обнаружить множество другого ВПО, которое было защищено аналогичным образом. Пересечения с другими вредоносами с учетом автоматизации процесса упаковки, на наш взгляд, позволяют говорить об использовании злоумышленниками модели packer-as-a-service. В этой модели упаковка вредоносных файлов делегируется специальному сервису, которым управляет третья сторона.

Сайт одного из крипт-сервисов
Рис. 3. Сайт одного из крипт-сервисов

Доступ к таким сервисам часто продается на хакерских форумах.

Пример объявления о продаже услуг по упаковке файлов
Рис. 4. Пример объявления о продаже услуг по упаковке файлов

Далее мы рассмотрим конкретные примеры крипторов, которые были применены группой RTM.

Rex3Packer

Первое использование этого пакера группой RTM, которое нам удалось обнаружить, относится к ноябрю 2019 года. Активное же его применение, по нашим данным, приходится на период апрель—май 2020 года. Единичные случаи использования этого пакера для распространения старых версий трояна RTM мы также наблюдали в конце января 2021 года.

Фишинговое письмо RTM, январь 2021
Рис. 5. Фишинговое письмо RTM, январь 2021

Нам не удалось связать этот упаковщик с каким-либо из ранее описанных публично, поэтому мы дали ему свое название по трем особенностям его устройства: наличию рекурсии (recursion), реверса битов (reverse), и рефлективной загрузки PE-файлов (reflection) — Rex3Packer.

Алгоритм распаковки

Общий алгоритм извлечения полезной нагрузки выглядит так:

  1. С помощью VirtualAlloc выделяется заранее определенное количество памяти с правами на чтение, запись и исполнение.
  2. В выделенный буфер копируется содержимое образа текущего процесса в памяти (в частности, секция .text).
  3. Управление передается на функцию внутри буфера.
  4. Вычисляется разница между положением одних и тех же данных в буфере и в образе PE-файла (разность между адресами в буфере и виртуальными адресами в образе). Эта разность заносится в регистр ebx. Все обращения к виртуальным адресам в коде проиндексированы содержимым этого регистра. За счет этого, везде, где это необходимо, к адресам из PE-образа добавляется поправка, которая позволяет получить соответствующий адрес в буфере.
    Обращения к функциям и переменным с учетом поправки в регистре ebx
    Рис. 6. Обращения к функциям и переменным с учетом поправки в регистре ebx
  5. Выделяется еще один буфер под упакованные данные.
  6. Через вызов VirtualProtect устанавливаются права RWX на весь регион памяти с образом PE-файла.
  7. Упакованные данные копируются в свой буфер.
  8. Происходит декодирование упакованных данных.
  9. Регион памяти с образом PE заполняется нулевыми байтами.
  10. Декодированные данные представляют собой исполняемый файл — PE-нагрузку. Эта полезная нагрузка рефлективно загружается на место исходного PE-образа, и управление передается на ее точку входа.

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

Непосредственно упакованным данным предшествует заголовок размером 16 байт, который содержит 4 поля по 4 байта:

  • размер самого заголовка,
  • размер исходных данных (PE-нагрузки),
  • позиция в исходных данных (*), по которой происходит их разделение (об этом ниже),
  • режим кодирования (1, 2, либо 4).

Декодирование выполняется следующим образом:

  1. Внутри каждого байта выполняется реверс порядка битов (к примеру, 10011000 становится 00011001).
  2. В зависимости от режима кодирования (1, 2, 4) данные разбиваются на блоки размером N = 9, 5, либо 3 байта соответственно. Результат декодирования блока — это (N – 1) байт (то есть 8, 4, или 2).
  3. В первых N-1 байтах блока отсутствует часть битов: их значения всегда равны нулю. Чтобы восстановить оригинальные байты, с помощью масок вида 00000001, 00010001 или 01010101 из последнего байта блока извлекаются недостающие биты. При этом для каждого следующего байта маска сдвигается. То есть последний байт блока фактически составлен из объединенных логической операцией OR битов, которые извлечены из предыдущих байтов.

    Например, в режиме 4 последний байт состоит из четных битов первого байта блока и нечетных битов второго байта блока. В результате возврата этих битов в первый и второй байты, получается оригинальная последовательность из двух байт.

    Схема получения исходных байтов в режиме 4
    Рис. 7. Схема получения исходных байтов в режиме 4
  4. После операции по восстановлению битов во всех блоках полученные данные представляют собой исходный PE-файл, который был разделен по позиции (*) на две части. Эти части, в свою очередь, были переставлены между собой. Обратная перестановка с учетом значения (*) позволяет получить оригинальный файл.

Обфускация

Чтобы усложнить анализ, в пакере применяются несколько техник добавления «мусорного» кода :

  • В промежутках между исполнением полезных команд делаются вызовы различных функций WinAPI. Их результаты сохраняются, но не используются, а сами функции выбираются так, чтобы не влиять на работу программы.

    Примеры вызова функций WinAPI
    Рис. 8. Примеры вызова функций WinAPI
  • Характерная особенность данного пакера — наличие циклов (не выполняющих полезных операций), которые реализуются через рекурсивную функцию.

    Функция с рекурсивным вызовом (вариант без обфускации)
    Рис. 9. Функция с рекурсивным вызовом (вариант без обфускации)
  • Для дополнительного запутывания в исполняемый файл добавляется несколько десятков случайно сгенерированных функций. Они могут ссылаться друг на друга, но в процессе работы ни одна из них не получает управления.

    Пример сгенерированной функции
    Рис. 10. Пример сгенерированной функции

Использование

Кроме экземпляров RTM, мы обнаружили использование Rex3Packer для упаковки различного ВПО, в основном имеющего происхождение из стран СНГ. Ниже расположен список некоторых примеров таких вредоносов.

Семейство ВПО SHA256
Phobos Ransomware 6e9c9b72d1bdb993184c7aa05d961e706a57b3becf151ca4f883a80a07fdd955
Zeppelin Ransomware 8d44fdbedd0ec9ae59fad78bdb12d15d6903470eb1046b45c227193b233adda6
Raсcoon Stealer 3be91458baa365febafb6b33283b9e1d7e53291de9fec9d3050cd32d98b7a039
KPOT Stealer 9b6af2502547bbf9a64ccfb8889ee25566322da38e9e0ccb86b0e6131a67df1e
Predator The Thief d1060835793f01d1e137ad92e4e38ef2596f20b26da3d12abcc8372158764a8f
QakBot 18cc92453936d1267e790c489c419802403bb9544275b4a18f3472d2fe6f5dea

Также мы отметили использование пакера для упаковки экземпляров ВПО из семейств Nemty, Pony, Amadey. Безусловно, приведенные нами примеры — это далеко не все случаи использования Rex3Packer.

HellowinPacker

В мае 2020 группа RTM переключилась на использование нового упаковщика, который продолжала активно использовать до начала 2021 года. Мы назвали его HellowinPacker из-за встречающихся в некоторых экземплярах строк с именем файла hellowin.wav.

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

Сравнение кода в двух экземплярах разной структуры
Рис. 11. Сравнение кода в двух экземплярах разной структуры

На примере выше можно увидеть сравнение образцов 5b5f30f7cbd6343efd409f727e656a7039bff007be73a04827cce2277d873aa0 (слева) и 1f9a8b3c060c2940a81442c9d9c9e36c31ad37aaa7cd61e1d7aec2d86fe1c585 (справа).

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

Сравнение кода в двух экземплярах одной структуры
Рис. 12. Сравнение кода в двух экземплярах одной структуры

Так же, как и в случае с Rex3Packer, мы имеем дело с массовым использованием HellowinPacker для упаковки различного ВПО. При этом вредоносное ПО из одного семейства, как правило, имеет в упакованном виде одну и ту же структуру. Это можно пронаблюдать, по крайней мере, на протяжении некоторого времени — затем структура может измениться.

Все эти особенности хорошо согласуются с описанием одного из сервисов упаковки, доступ к которому продается на хакерских форумах:

[Уникальность]Для клиента дается уникальный криптор, который не зависит от других клиентов. Если ваши файлы спалились, то только от ваших же прогрузов. Мы не набираем >10000 клиентов, только аккуратная Premium-поддержка, клиенты единичные. We make only unique stubs for a customer.

По всей видимости, в каждый такой уникальный криптор закладывается собственная структура генерируемого кода. При этом сам криптор также умеет изменять код, но уже на более низком уровне, не меняя структуру программы в целом. В любом случае содержание «полезного» исполняемого кода остается одинаковым.

Алгоритм распаковки

Одни из первых действий, которые встречаются во всех упакованных файлах — это попытки открыть ключ реестра HKEY_CLASSES_ROOT\Interface\{b196b287-bab4-101a-b69c-00aa00341d07} (регистр символов в конкретном случае может отличаться) и запросить в нем значение по умолчанию (Default). От успешности этих операций в некоторых модификациях генерируемого кода зависит корректное продолжение работы программы.

GUID интерфейса в разных случаях также может отличаться. Вот некоторые из возможных вариантов:

  • {3050f1dd-98b5-11cf-bb82-00aa00bdce0b}
  • {aa5b6a80-b834-11d0-932f-00a0c90dcaa9}
  • {683130a6-2e50-11d2-98a5-00c04f8ee1c4}
  • {c7c3f5a1-88a3-11d0-abcb-00a0c90fffc0}
  • {b8da6310-e19b-11d0-933c-00a0c90dcaa9}

Дальнейший код некоторым образом получает адрес, по которому располагается блок зашифрованных данных.

Этот блок начинается с четырехбайтного числа, которое хранит размер исходных данных (тех, которые будут получены после декодирования). Вызовом VirtualAlloc под расшифрованные данные выделяется блок памяти нужного размера с правами RWX. В выделенную память блоками по X байт копируются зашифрованные данные. При этом в оригинальном файле между этими блоками располагаются пропуски длиной Y байт.

Схема копирования данных в HellowinPacker
Рис. 13. Схема копирования данных в HellowinPacker

Затем происходит процесс дешифровки блоками по 4 байта:

  • очередной блок интерпретируется как целое число (DWORD),
  • к его значению прибавляется индекс первого байта в блоке,
  • выполняется операция XOR между полученным значением и суммой индекса и фиксированного ключа, числа Z.

Пример реализации алгоритма на Python:

def decrypt(data, Z): index = 0 while index < len(data): dword = struct.unpack("<I", data[index:index + 4])[0] dword = (dword + index) & (2 ** 32 - 1) dword = dword ^ (index + Z) data[index:index + 4] = struct.pack("<I", dword) index += 4

Значения X, Y и Z варьируются в зависимости от конкретного упакованного экземпляра.

Внутри дешифрованных данных располагается следующая стадия извлечения полезной нагрузки — шеллкод. Он получает управление после окончания расшифровки.

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

Таблица импорта в дешифрованных данных
Рис. 14. Таблица импорта в дешифрованных данных

Для большей вариативности строки в таблице импорта могут частично заполняться посторонними символами. Так, в примере выше, первое имя функции — GetProcAddress — полностью заменено на строку aaa45678901234; кроме того, повреждены имена VirtualAlloc и VirtualProtect. Непосредственно перед обработкой таблицы шеллкод восстанавливает корректные значения для всех символов.

Код восстановления испорченных имен функций
Рис. 15. Код восстановления испорченных имен функций

Полезная нагрузка (на этот раз, это PE-файл) извлекается шеллкодом из оставшейся части дешифрованных данных. Она вновь зашифрована, причем тем же алгоритмом, который описан выше. В качестве ключа Z всегда используется число 1001.

После окончательной расшифровки шеллкод производит рефлективную загрузку PE-файла, используя для этого импортированные на первом этапе функции.

Обфускация

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

Точка входа в одной из упакованных библиотек
Рис. 16. Точка входа в одной из упакованных библиотек

Дополнительным эффектом от такого использования WinAPI становится невозможность детектирования по списку импортируемых функций и imphash.

При работе с различными числовыми значениями часто встречается некоторая арифметическая обфускация: необходимые константы представляются в виде суммы или разности других констант (в определенных случаях равной нулю). При этом для получения констант могут быть использованы и вызовы функций WinAPI, дающие предсказуемый результат (например, 0 в случае неудачи).

Пример такой обфускации приведен на рис. 17: единственная задача данной функции — присвоить глобальной переменной, на которую указывает target, значение аргумента source. В данном случае результат вызова GetStockObject(789644) всегда будет равняться нулю, поскольку функции передан заведомо некорректный аргумент.

Арифметическая обфускация в коде HellowinPacker
Рис. 17. Арифметическая обфускация в коде HellowinPacker

Разного рода мутации встречаются и на ассемблерном уровне: вставка «мусорных» команд, непрозрачные предикаты (opaque predicates), передача неиспользуемых аргументов в функции и повторные вызовы функций, изменение инструкций на эквивалентные.

Пример обфускации на уровне ассемблерного кода
Рис. 18. Пример обфускации на уровне ассемблерного кода

Использование

HellowinPacker существует по крайней мере с 2014 года. За это время он был использован в различном массовом вредоносном ПО. Вот лишь несколько примеров:

Семейство ВПО SHA256
Cerber Ransomware 1e8b814a4bd850fc21690a66159a742bfcec212ccab3c3153a2c54c88c83ed9d
ZLoader 44ede6e1b9be1c013f13d82645f7a9cff7d92b267778f19b46aa5c1f7fa3c10b
Dridex f5dfbb67b582a58e86db314cc99924502d52ccc306a646da25f5f2529b7bff16
Bunitu 54ff90a4b9d4f6bb2808476983c1a902d7d20fc0348a61c79ee2a9e123054cce
QakBot c2482679c665dbec35164aba7554000817139035dc12efc9e936790ca49e7854

Пакер неоднократно упоминался в отчетах других исследователей. Самое раннее упоминание, которое нам удалось найти, относится к 2015 году. В своей статье о крипторах специалисты Malwarebytes в качестве примера исследуют образцы с HellowinPacker. Другие исследователи позже напишут о нем, как об упаковщике Emotet: (1, 2). Уже в 2020 году наши коллеги из NCC Group дадут ему название CryptOne и опишут его применение для упаковки вымогателя WastedLocker. По данным NCC Group, он также использовался в таких семействах ВПО, как Netwalker, Gozi ISFB v3, ZLoader, Smokeloader.

Заключение

Пример с использованием крипторов позволяет проиллюстрировать разделение обязанностей в хакерской среде, в особенности среди массового ВПО. Разработка вредоносной нагрузки, ее защита от антивирусов (крипт) и доставка конечному пользователю может выполняться совершенно не связанными между собой хакерами, при этом каждый элемент в этой цепочке может предоставляться как сервис. Такой подход снижает порог входа для технически не подготовленных киберпреступников: для проведения массовой атаки достаточно обладать лишь необходимой суммой денег на оплату всех сервисов.

Описанные нами упаковщики, конечно же, далеко не единственные из существующих на рынке. При этом они хорошо демонстрируют общие свойства подобного рода инструментов: в результате их работы получается исполняемый файл с обфусцированным полиморфным кодом распаковщика и шифрованной тем или иным образом полезной нагрузкой. Мутации в коде и переиспользование одних и тех же крипторов делают практически невозможным статическое детектирование полезной нагрузки. Однако поскольку эта нагрузка так или иначе расшифровывается в память и начинает свою вредоносную деятельность, поведенческий анализ с использованием песочниц (таких, как PT Sandbox) позволяет обнаруживать ВПО и давать точные вердикты даже для упакованных файлов. Помимо этого, нужно отметить, что упаковщики никак не влияют на взаимодействие вредоносов с управляющими серверами. Это даёт возможность определять присутствие ВПО в сети, используя инструменты анализа трафика – такие, как PT Network Attack Discovery.

Вердикты наших продуктов

PT Sandbox

  • Trojan.Win32.RTM.a

  • Trojan.Win32.RTM.b

  • Trojan-Banker.Win32.RTM.a

  • Trojan-Banker.Win32.RTM.b

  • Trojan-Banker.Win32.RTM.c

  • Trojan-Banker.Win32.RTM.d

  • Trojan-Banker.Win32.RTM.e

  • Trojan-Banker.Win32.RTM.f

PT Network Attack Discovery

  • REMOTE [PTsecurity] TeamBot/RTM
    sid: 10004412;

  • BACKDOOR [PTsecurity] TeamBot/RTM
    sid: 10004415;

  • MALWARE [PTsecurity] RTM Banker CnC POST
    sid: 10000765;

  • MALWARE [PTsecurity] RTM.N (Redaman)
    sid: 10005556; 10005557;

  • MALWARE [PTsecurity] Spy.RTM.AF
    sid: 10005468;

  • MALWARE [PTsecurity] Trojan[Banker]/RTM
    sid: 10004855; 10004875;

  • MALWARE [PTsecurity] Win32/Spy.RTM.N (Redaman)
    sid: 10003414; 10004754; 10005555;

  • PAYLOAD [PTsecurity] RTM.Payload.xor
    sid: 10005585;

IOCs (RTM)

Дата обнаружения Криптор SHA256 SHA1 MD5
19.04.2020 RTM a4229a54f76815ac30a2a878eadf275e199c82da657dbc5f3fc05fe95603c320 ad22ceb309dd30dc769f63174292657fe07f0ced 80b116708f75de212b49ff994ad8b43e
22.04.2020 Rex3Packer 9b88e8143e4452229dac7fdcc3d9281d21390f286c086f09aec410f120dc4325 f881729f6a5ca6fe80f385a2b0f8583b19214466 3965b819eb945a9c0defc746bbc8ed7a
13.05.2020 HellowinPacker 43e8ebacfa319ff7d871eef3cc35266cfa7c6f44dd787f27a48311e39727e10f 8a28b75285409c55d5bbeca62e3819c83c8e663f afd18be08d135f7bf07007c1c9041126
28.01.2021 Rex3Packer (2 слоя) fbf5974daee93bf5a2ed1816a4edbb108ceccb264d3e3f72d0aed268dd45e315 2e3352c6341ce57a03aaf2c4fbf484f3a0a4bfe3 6e0c8510443586cdc8f84330e447aae5