В апреле 2022 года мы, специалисты PT Expert Security Center, выявили атаку на ряд российских организаций сферы медиа и ТЭК. В атаках использовался вредоносный документ с именем «список.docx», извлекающий из себя вредоносную нагрузку, упакованную VMProtect. Мы проанализировали пакет сетевой коммуникации и выяснили, что он идентичен тому, который мы рассматривали в отчете по исследованию инструментов группировки APT31 (c ее профайлом можно ознакомиться здесь). Это позволило предположить, что и эти инструменты могут принадлежать этой же группировке. Экземпляры изучаемого вредоносного ПО датируются периодом с ноября 2021 года по июнь 2022-го.

Анализ распакованного ВПО подтвердил наши предположения, так как содержащаяся под протектором вредоносная нагрузка оказалась идентичной рассмотренной нами ранее. Дальнейший мониторинг позволил нам найти еще ряд документов, использованных в атаках на те же организации, имеющих схожее по используемым техникам содержимое, однако отличающееся от того, что мы видели ранее как по сетевой части, так и по коду.

Что интересно: детальный анализ инструментов позволил выявить использование сервиса Яндекс.Диск в качестве контрольного сервера. И это нам показалось достаточно любопытным, так как в этом случае потенциально зарубежная группировка использовала российский сервис, в частности для того, чтобы сетевая нагрузка была внешне похожа на легитимную. Техника не новая: ее использовала группировка TaskMasters в своем ВПО Webdav-O. Смысл использования этой техники — обход сетевых средств защиты, так как происходит соединение с легитимным сервисом. Использование ранее группировкой APT31 облачного сервиса Dropbox, а также пересечения с теми инструментами, которые мы уже видели, дают основание предположить, что и в этом случае нами были найдены инструменты группировки APT31.

Что такое KasperskyOneDrive: разбор вредоносных документов

Исходный документ, с которого мы начали наше исследование (рис. 1), используя технику Template Injection, скачивает шаблон с макросом, загружающим вредоносные компоненты (легитимный файл, компонент Java и вредоносную библиотеку msvcr100.dll, упакованную с помощью VMProtect) с удаленного сервера.

Рисунок 1. Внешний вид вредоносного документа

Что интересно: макрос шаблона, фрагмент которого изображен на рис. 2, создает файлы по пути C:\ProgramData\KasperskyOneDrive. Основная задача легитимного файла­ — передача управления вредоносной библиотеке с помощью техники DLL Side-Loading и формирование инициализирующего пакета, который отправляется на контрольный сервер.

Рисунок 2. Код загруженного макроса

В ходе дальнейшего поиска схожих угроз был найден ряд документов, с полем «Автор», равным pc1q213 (рис. 3), содержащих идентичный код декодирования Base64.

Рисунок 3. Свойства найденного документа

Анализ найденных документов наглядно продемонстрировал их внешнее сходство (рис. 4). Кроме того, код содержащихся в них макросов идентичен вплоть до имен функций и переменных (рис. 5 и 6).

Рисунок 4. Внешний вид найденного документа

Характерные особенности всех документов — сохранение компонентов, эксплуатирующих DLL Side-Loading для запуска вредоносной нагрузки, которая находится в них, внешнее сходство встроенных в документы макросов, а также кодирование содержащейся внутри документов нагрузки Base64.

Рисунок 5. Код макроса из найденного документа
Рисунок 6. Код макроса из схожего документа

Извлекаемая нагрузка также имеет ряд сходств:

  • большинство бинарных файлов упакованы VMProtect;

  • все выявленные легитимные исполняемые файлы являются какими-либо компонентами Яндекс.Браузера и подписаны действительной цифровой подписью;

  • в качестве вредоносных библиотек использовались winhttp.dll, wtsapi.dll, замаскированные под легитимные (в частности, наличием, количеством и именами экспортов).

Разбираем вредоносное ПО: как использовались Яндекс.Диск и Яндекс.Браузер

В ходе анализа вредоносного ПО мы выявили две новых разновидности ВПО, которые мы назвали YaRAT (потому что оно обладает функциональностью RAT и в качестве контрольного сервера использует Яндекс.Диск) и Stealer0x3401 (по константе, используемой при обфускации ключа шифрования). При этом YaRAT мы встречали в двух модификациях — с шифрованием токена внутри кода программы и без него.

YaRAT

В качестве легитимного файла, уязвимого для DLL Side-Loading, использовался инсталлятор Яндекс.Браузера, подписанный действительной цифровой подписью «Яндекса», либо его portable-версия. Файл загружает и вызывает одну из функций вредоносной winhttp.dll.

Рисунок 7. Сведения о цифровой подписи легитимного исполняемого файла

А вот пример вызовов функций внутри легитимного бинарного файла.

Рисунок 8. Вызов функции вредоносной библиотеки

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

На первом этапе также происходит распаковка LZMA, после чего дважды происходит расшифровка распакованных данных (отдельно расшифровываются секции кода и прочие секции — импорты, данные и т. д.).

Расшифровка данных производится алгоритмом RC4, оба ключа шифрования вшиты в код. Отличительной особенностью обоих блоков расшифровки данных является характерный тип обфускации кода (Control Flow Flattening), затрудняющий статический анализ. Наряду с этой техникой внутри тела функции вставлен лишний байт 0xB9, который сбивает дизассемблер с толку и не дает сгенерировать декомпилированный вид функции.

Пример кода, отвечающего за расшифровку данных после этапа PRNG, приведен на рис. 9.

Рисунок 9. Фрагмент обфусцированного блока, отвечающего за расшифровку кода и данных

Последующий код, отвечающий за восстановление импортов, их адресов (разрешение адресов функций и библиотек), а также за изменение атрибутов на блоки виртуальной памяти (вызовы VirtualProtect), идентичны обычному UPX (на рис. 10 — фрагмент кода упаковщика, на рис. 11 — обычный UPX). Также стоит отметить отличительные и характерные для UPX вызовы push и pop соответственно в начале и конце функции распаковки. После распаковки управление передается на полезную нагрузку.

Рисунки 10 и 11. Фрагменты кода рассматриваемого упаковщика (слева) и обычного UPX (справа)

Разбор полезной нагрузки

На первом этапе создается мьютекс с именем YandexDisk, а вредонос прописывает себя в автозагрузку через ключ реестра.

Рисунок 12. Создание мьютекса и обеспечение закрепления в системе

Далее ВПО формирует строковые запросы к Яндекс.Диску с параметром Authorization: OAuth, к которому конкатенируется токен для этого аккаунта. Сам токен вшит в код. Мы обнаружили несколько ключей, принадлежащих трем аккаунтам — jethroweston, Poslova.Marian, upy4ndexdate.

Рисунок 13. Формирование запроса к Яндекс.Диску

После этого формируются две строки по паттерну: pcname + /a.psd и pcname + /b.psd, например: DESKTOP-IM5NM8R/a.psd, DESKTOP-IM5NM8R/b.psd.

Первый запрос, который ВПО отправляет на контрольный сервер, это PUT на https://cloud-api.yandex.net:443/v1/disk/resources?path= (пример формирования показан на рис. 14). Его можно рассматривать как инициализирующий запрос, на основе которого будет создан каталог на Яндекс.Диске (рабочий удаленный каталог).

Рисунок 14. Формирование PUT-запроса и его передача на сервер

В случае успешного соединения вредонос скачивает файл (рис. 15) с именем, состоящим из следующих строк: имени, сгенерированного на предыдущем этапе, и строкового модификатора «a.psd», который завершает (конкатенируется в конец) строку-имя. К примеру, https://cloud-api.yandex.net/v1/disk/resources/download?path=DESKTOP-IM5NM8R%2Fa.psd.

Рисунок 15. Содержимое загруженного с C2 файла

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

Команды исполняются в стандартном шелле Windows (cmd.exe), ВПО конкатенирует их результаты, а также формирует их как ответ и отправляет на Яндекс.Диск как файл b.psd. Стоит отметить, что результат исполнения каждой команды отделен от других строкой ==============\r\n (на рис. 16 отчетливо видны результаты исполнения, разделенные этой строкой).

Рисунок 16. Содержимое файла с собранными данными

Далее ВПО переходит в режим исполнения команд. Команды, исполняемые ВПО:

  • DIR — получение списка файлов каталога;

  • EXEC — исполнение команды (по факту, вызов функции WinExec библиотеки kernel32.dll);

  • SLEEP — вызов функции Sleep с параметром (0x3E8 умножить на переданную константу);

  • UPLOAD — скачать файл с Яндекс.Диска;

  • DOWNLOAD — загрузить файл на Яндекс.Диск.

Вся сетевая коммуникация осуществляется при помощи curl. В свою очередь, передача данных осуществляется в формате JSON, для работы с ним используется библиотека nlohmann/json. Обе библиотеки статически скомпилированы с проектом.

Широкий модельный ряд: вторая модификация YaRAT

Был также найден ряд образцов, «накрытых» VMProtect и неупакованных описанным выше пакером. Отличительной особенностью всех образцов является то, что «накрыта» протектором лишь DllEntryPoint, в то время как экспорты, в которых находится основная функциональность, виртуализации не подверглись (кроме некоторых WinAPI-вызовов).

Также отличительной чертой подобных экземпляров ВПО является шифрование токена шифром Blowfish со встроенным в код ключом.

Рисунок 17. Ключ расшифровки внутри ВПО

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

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

Смотрим внимательно на Stealer0x3401

Механизм заражения в этом случае идентичен рассмотренному в нашем отчете: легитимный бинарный файл dot1xtray.exe подгружает вредоносную msvcr110.dll. В этом случае вредоносным был экспорт __crtGetShowWindowMode.

Что интересно: на первом этапе ВПО проверяет имя запущенного процесса: оно не должно быть qip.exe, aim.exe, icq.exe. В противном случае управление не будет передано на основную функциональность.

Далее расшифровывается адрес контрольного сервера (рис. 18). Очевидна идентичность этого алгоритма рассмотренному в предыдущем отчете. Неизменным остались как ключ шифрования, так и формат его расположения.

Рисунок 18. Алгоритм расшифровки адреса контрольного сервера

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

Рисунок 19. Пример команды, содержащейся в ВПО
Рисунок 20. Собираемая информация о системе

Все собранные данные перед отправкой шифруются RC4 и кодируются Base64. В отличие от того, что мы видели ранее, ключ шифрования генерируется для каждого нового запуска, алгоритм формирования ключа следующий (рис. 21): на основе текущего времени генерируется 16 псевдослучайных чисел типа qword (цикл заполняет 64-разрядными числами до конкретного адреса, разность между ними 128 байт, соответственно по типу данных получится 16 qword-значений), к которым после будет применена стандартная для RC4 процедура расширения ключа. После этого расширенным ключом происходит шифрование собранных данных.

Рисунок 21. Формирование ключа шифрования

Что интересно: при передаче шифрованных данных ключ шифрования передается не в явном виде, для его обфускации применяется ранее не встречавшаяся процедура вычисления так называемой контрольной суммы (рис. 22) для каждого qword-значения, использованного в процедуре расширения ключа.

Сама процедура состоит из двух этапов: формирование таблицы расчета хеша и непосредственный подсчет результата. На первом этапе циклически рассчитываются остатки от деления инициализирующей константы (в этом случае 0x3401) по модулю 2 (пока она не станет нулем), то есть число раундов на каждом этапе подсчета контрольной суммы будет идентичным.

На втором этапе производится модификация исходного значения (на рис. 22 _inputVal) в соответствии с двумя переменными, изначально равными 0 и 1 (на рис. 22 temValDword_1 и tempvalDword2), из которых на каждом этапе формируется значение типа __int64 по модулю 0x90c9bff (на рис. 22 result_x64Val). Сами константы также модифицируются на каждом раунде.

Как видно, исходное значение модифицируется на конкретном раунде в соответствии с таблицей остатков, сформированной на первом этапе. Eсли остаток равен 1, то происходит модификация как хеша, так и самих переменных, участвующих в подсчете промежуточных значений и итогового значения. Таким образом, за указанные 14 раундов (заранее известных в плане модификации исходного значения, так как таблица для всех раундов одна и та же) формируется итоговое значение.

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

Рисунок 22. Процедура обфускации ключа шифрования

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

Сформированные данные кодируются Base64, после чего предваряются строкой data= и в таком виде передаются на сервер (рис. 23).

Рисунок 23. Отправляемые данные

Сформированные данные ВПО отсылает на контрольный сервер ramblercloud[.]com, который маскируется под легитимный облачный диск Rambler, однако таковым не является.

Атрибуция

В ходе исследования документа, использующего Template Injection, в результате запуска которого происходило заражение системы, мы выявили трафик, описанный нами в предыдущем отчете (рис. 24).

Рисунок 24. Фрагмент выявленного трафика (характерна схожесть формата передачи с рассмотренным ранее ВПО)

После заражения системы ВПО производит обмен данными с С2, затем происходит выполнение команд с сервера управления.

В ходе анализа распакованного образца были выявлены сходства с образцами, выявленными нами ранее. В частности, идентичными оказались имена RTTI-объектов (в том числе и имена таблиц vtbl, используемых для имплементации коммуникации с сервером управления), а также функциональность обоих приложений. Каких-либо изменений архитектуры, исполняемых команд или способов формирования пакетов не выявлено, не изменился и ключ шифрования трафика, вшитый в код программы. Единственным отличием образцов ВПО является частичная виртуализация API-вызовов внутри защищенного приложения (что характерно для любой программы, накрытой VMProtect). Фрагмент функции, выполняющей обработку команд с сервера, приведен на рис. 25.

Рисунок 25. Функция, отвечающая за исполнение команд

Не претерпели изменений служебные строки, форматные строки, используемые для формирования пакетов и структур данных внутри приложения, имена используемых API, порядок их вызова.

В ходе анализа различных вредоносных компонентов был выявлен характерный признак, предположительно указывающий на единую кодовую базу. Во всех случаях ВПО собирали информацию о сетевых адаптерах, причем код функций, последовательность вызовов во всех случаях идентичны: вызов GetAdaptersInfo и затем получение значения ключей NetCfgInstanceId и Characteristics ветки реестра SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}.

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

Также идентичен код, генерируемый компилятором, фрагменты которого (пример на рис. 26) мы нашли во всех распакованных вредоносных компонентах, использованных в рамках кампании.

Рисунок 26. Фрагмент кода, присутствующий во всем найденном ВПО

Таким образом, можно подтвердить наше предположение, что это ВПО относится к группировке APT31.

Все найденные нами вредоносные компоненты можно разделить на несколько групп:

  • документы с одинаковой заглушкой;

  • исходные документы имеют идентичное поле «Автор»;

  • вредоносные компоненты имеют уникальные (в рамках нашего покрытия) фрагменты кода, ранее нам нигде не встречавшиеся;

  • ВПО использует облачный сервис в качестве контрольного сервера.

Первое, на что стоит обратить внимание, — внешнее сходство заглушки в документах, которые мы чуть выше отнесли к группировке APT31, и заглушки в документе, который извлекал вредоносные компоненты, взаимодействующие с Яндекс.Диском. Второе — это идентичный код, получающий информацию о сетевых адаптерах, который мы встретили как в атрибутированных инструментах, так и в инструментах, описанных в этом отчете.

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

Таким образом, это ВПО является связующим элементом для всех рассмотренных выше вредоносных компонентов.

Проанализировав рассмотренные выше инструменты, мы можем с большой долей уверенности отнести исследованные нами образцы ВПО к одной группировке. А с учетом использования облачных сервисов в качестве серверов управления (в этом случае Яндекс.Диска), которые уже были в арсенале этой группировки (ранее она использовала Dropbox), можно сделать предположение о единой кодовой базе, используемой для написания вредоносных компонентов.

Схожие техники заражения, закрепления, многочисленные пересечения в коде, артефакты используемых средств компиляции позволяют сделать вывод, что исследованная нами группировка может продолжить свои атаки на организации в России.

Ознакомиться с полной версией нашего исследования и получить индикаторы компрометации (файловые и сетевые индикаторы, а также MITRE TTPs) можно по ссылке. Еще больше отчетов PT Expert Security Center об актуальных киберугрозах, новых образцах ВПО, активности APT-группировок, хакерских техниках и инструментах вы найдете в нашем блоге

 

Авторы:

Даниил Колосков

Старший специалист отдела исследования угроз PT Expert Security Center

Денис Кувшинов

Руководитель отдела исследования угроз ИБ PT Expert Security Center


Читайте также в нашем хаброблоге: