В ходе постоянного отслеживания угроз ИБ утром 3 октября в одном из Telegram-чатов мы заметили промелькнувший файл со злободневным названием Povestka_26-09-2022.wsf. Беглый осмотр содержимого привлек наше внимание, и мы решили разобрать его подробней. И, как оказалось, не зря.

Разбор вредоносного скрипта

Исходный файл представляет собой обфусцированный JavaScript WSF файл, задачей которого является выполнение нескольких anti-vm/anti-sandbox и запуск основной полезной нагрузки.

Все строки в скрипте зашифрованы простым XOR и представлены в виде шестнадцатеричных последовательностей.  Функция расшифрования строк представлена на рис.1.

Рисунок 1. Алгоритм расшифровки строк в скрипте
Рисунок 1. Алгоритм расшифровки строк в скрипте

При запуске скрипт сначала пытается открыть Internet Explorer для отвлечения внимания пользователя (рис. 2).

Рисунок 2. Открытие Internet Explorer
Рисунок 2. Открытие Internet Explorer

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

Рисунок 3. Проверка имени текущего пользователя
Рисунок 3. Проверка имени текущего пользователя

Затем исследуемый скрипт проверяет установленные на системе AV. Осуществляется это через перечисление всех присутствующих папок в Program Files и Program Files(x86), конкатенацию всех имен файлов в одну строку и поиск подстрок mante (Symantec) orton se (Norton Security) itdefender (Bitdefender) в ней (рис. 4).

Рисунок 4. Проверка установленных AV
Рисунок 4. Проверка установленных AV

Последними проверками являются проверка наличия директорий, специфичных для виртуальных сред, а также проверка имени хоста (рис. 5). Стоит отметить, что в случае VMware проверка является слишком общей и не будет пройдена, если на машине установлены какие-либо продукты компании.

Рисунок 5. Проверка имени хоста и директорий
Рисунок 5. Проверка имени хоста и директорий

Если все проверки были успешно пройдены, то скрипт переходит к восстановлению полезной нагрузки. Алгоритм представлен на рис. 6.

Рисунок 6. Расшифрование нагрузки
Рисунок 6. Расшифрование нагрузки

Восстановленный файл записывается в %APPDATA%\Local\AnalysisManager.bin и затем переименовывается в AnalysisManager.exe. После чего запускается через объект ShellWindows (CLSID: 9BA05972-F6A8-11CF-A442-00A0C90A8F39) (рис. 7).

Рисунок 7. Запуск нагрузки
Рисунок 7. Запуск нагрузки

Анализ ВПО

Все строки и почти все API-вызовы в исследуемом образце обфусцированы. Каждая строка собирается в отдельной функции, после чего она передается в обработчик, ее расшифровывающий. На каждую длину строки может быть один или несколько обработчиков. Пример приведен на рис. 8.

Рисунок 8. Запуск нагрузки
Рисунок 8. Запуск нагрузки

При запуске сэмпл ищет в памяти адрес kernel32.dll по crc32  хэшу (0x6A4ABC5B) и далее, с помощью кастомной реализации GetProcAddress, получает адрес функции LoadLibrary (рис. 9). После чего подгружает прочие требуемые для работы библиотеки.

Рисунок 9. Поиск адреса kernel32 и адреса LoadLibrary
Рисунок 9. Поиск адреса kernel32 и адреса LoadLibrary

Реализация GetProcAddress изображена на рис. 10.

Рисунок 10. Реализация GetProcAddress
Рисунок 10. Реализация GetProcAddress

Затем сэмпл действует аналогично скрипту, собирая информацию о содержимом Program Files и Program Files (x86). Далее идет получение текущего пути запуска через вызов GetModuleFileName(0) и проверяется наличие подстроки ata\Loc в нем (с учетом регистра). Если проверка пройдена, запускается новый поток со следующим этапом anti-vm проверок.

Проверяется наличие директории C:\\Windows\\DataManagerVbox и наличие файлов и pipe, связанных с VirtualBox и VMware. Помимо этого, также проверяется имя хоста на соответствие SSADFU и значение HKLM\HARDWARE\DESCRIPTION\System\BIOS\BiosVendor на наличие подстрок SeaBIOS, VMWare, VirtualBox. Проверки приведены на рис. 11.

Рисунок 11. Anti-vm проверки BiosVendor и файлов
Рисунок 11. Anti-vm проверки BiosVendor и файлов

Также проверяется наличие нескольких специфичных директорий (рис. 12) и текущее имя пользователя (список аналогичен тому, что использовался в скрипте). Дополнительно проверяется наличие подстроки vast (Avast) в ранее собранном списке содержимого Program Files и Program Files(x86).

Особый интерес представляет проверка директории C:\\guest – utils\\, поскольку она служит индикатором для обнаружения старых версий PT Sandbox.

Рисунок 12. Anti-sandbox проверки директорий
Рисунок 12. Anti-sandbox проверки директорий

Если все проверки были успешно пройдены, то сэмпл закрепляется в HKCU\Environment\UserInitLogonScript (рис. 13).

Рисунок 13. Закрепление в реестре
Рисунок 13. Закрепление в реестре

После закрепления создается еще один поток, где идет сбор информации о хосте и начинается взаимодействие с С2.

В процессе образец получает версию ОС, номер билда и разрядность. А также проверяет наличие установленных AV Kasperky и ESET. Проверка приведена на рис. 14.

Рисунок 14. Получении информации об AV
Рисунок 14. Получении информации об AV

Далее собранная информация конкатенируется в одну строку, в формате:

OS;Build;Arch;v25286;DesktopName;UserName;[K1|E1]

Где:

OS — версия ОС

Build — номер билда

Arch — архитектура ос (32/64)

v25286 — константная строка, вероятно версия ВПО.

DesktopName — имя хоста

UserName — имя текущего пользователя

K1|E1 — информация о найденном AV, если Kaspersky — K1, если ESET — E1. Иначе остается пустой.

Затем последняя побайтово XOR’ится с ключом nirgrun895tg9nsvjnwiv12309ASHDbibvenibowrvREXVYBUNIiugycm898y42irwubuv94nabdRDU, кодируется в base64 и преобразуется для HTTP-запроса заменой символов + / = на эквиваленты %2B, %2F, %3D.

Генерация ID агента:

  1. Берется хэш (рис. 15) от строки имени хоста + значения реестра BIOSVendor + v25286.

  2. Берется хэш от строки имени хоста + имя текущего пользователя + строки текущей временной зоны + v25286.

  3. Оба хэша преобразуются в hex-строки по 8 байтов.

  4. К первой строке добавляются первые 4 байта от второй.

Рисунок 15. Алгоритм, используемый при генерации ID агента
Рисунок 15. Алгоритм, используемый при генерации ID агента

Перед обращением к серверу также идет проверка наличия файла конфига. Имя файла собирается из нескольких параметров и в несколько этапов:

  1. Создается директория %APPDATA%\AppInfo\.

  2. Конкатенируются строки v25286 + id агента + hiuhgnywervg9837kjfbhnwuier.

  3. Результат хэшируется функцией на рис. 16, преобразуется в десятичный формат и затем в строку.

  4. К полученной строке конкатенируется строка LKolkijhkUI и расширение .zxtu.

Рисунок 16. Алгоритм хэширования используемый при генерации пути конфига
Рисунок 16. Алгоритм хэширования используемый при генерации пути конфига

Если файл конфигурации был найден, то далее он читается и расшифровывается RC4 с ключом OP789hqedoevrn68f34byicw@#njsunodejwdn023ejcwfedwf3t5hbcuibwegv. Из него сэмпл может получить информацию о новом С2 и используемом протоколе (http/https). Если файл не был найден, то будет использован захардкоженный адрес С2.

Затем ВПО переходит в цикл обращения к контрольному серверу. Между запросами идет случайная задержка (рис. 17).

Рисунок 17. Случайная задержка между обращениями к контрольному серверу
Рисунок 17. Случайная задержка между обращениями к контрольному серверу

Для обращения к серверу ВПО собирает POST-запрос с тремя параметрами:

  • hr&u=3a7319bb710f — 12-байтный ID агента;

  • &sduyviop=5XpOmZ0bT43Q035YY — ID запроса, может иметь длину от 10 до 20 символов;

  • &sfin=X1lcV0lEVwgMA09RDVUFRF9cT19NdXdge20OA2UPKS43TyEjUhccEgBNGXQ%3 — собранная ранее информация о хосте.

Итоговый запрос может выглядеть так:

https[://]my1businessconnection[.]com/hr&u=3a7319bb710f&sduyviop=5XpOmZ0bT43Q035YY&sfin=X1lcV0lEVwgMA09RDVUFRF9cT19NdXdge20OA2UPKS43TyEjUhccEgBNGXQ%3

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

  • watghber — сон 1500мс через комбинацию вызовов CreateEventW + WaitForSingleObject;

  • r4g3rf — аналогично предыдущему, но через CreateSemaphoreW + WaitForSingleObject;

  • 56uhj544getr — увеличить внутренний счетчик на 100 (его значение нигде не используется);

  • gfdfgdfgsfuilkyuj — сделать вызов GetUserNameW, результат также не используется;

  • ccsv — обновить информацию о С2 и используемом протоколе (http/https) и сохранить ее в файл (рис. 18);

Рисунок 18. Обновление конфигурации агента
Рисунок 18. Обновление конфигурации агента
  • plug — создает отдельный поток, где расшифровывает (RC4), размещает в памяти и вызывает полученную библиотеку. Название и функционал намекают, что команда отвечает за установку плагинов;

  • bwtp — похоже на plug, но в отличие от него не создает новый поток, а размещает в памяти и вызывает библиотеку в том же. Результат работы накрывается RC4 и отправляется на С2. После вызова библиотека выгружается из памяти. Пример вызова приведен на рис. 20;

Рисунок 19. Запуск полученной библиотеки
Рисунок 19. Запуск полученной библиотеки
  • rstpg — проходит по адресам загруженных библиотек из команды plug и вызывает второй экспорт для каждой. Скорее всего, команда отвечает за выгрузку всех установленных плагинов (рис. 20);

Рисунок 20. Выгрузка всех плагинов
Рисунок 20. Выгрузка всех плагинов
  • sysinfo — собирает и шлет отдельным POST-запросом расширенную информацию о системе и агенте. Перед отправкой также накрывается RC4.

Помимо описанного ранее (за исключением информации об AV), сюда входит:

  • полный список директорий из Program Files и Program Files(x86);

  • информация о подключенных дисках и их типе;

  • текущий С2;

  • ID агента.

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

Атрибуция

Что говорит в пользу XDSpy:

  1. В рамках проводимых вредоносных кампаний XDSpy всегда была ориентирована на рускоязычные страны. Фишинговые письма составлялись с учетом актуальных событий в России. В частности, вредоносные кампании, проводимые в 2020 г., были ориентированы на COVID-19, волнения в Республике Беларусь. Кроме того, тематика писем также была связана с работой отдельных государственных учреждений (рис. 21).

Рисунок 21. Пример фишингового письма вредоносных кампаний XDSpy за 2020 г.
Рисунок 21. Пример фишингового письма вредоносных кампаний XDSpy за 2020 г.
  1. В качестве вредоносного модуля на первом этапе заражения в данной кампании используется WSF-скрипт. Этот подход также использовался группировкой XDSpy в рамках вредоносных кампаний 2020 г.

При глубоком анализе образцов 2020 и 2022 гг. выявлены следующие схожие функции:

  • реализация обращения к ресурсу-приманке через метод Navigate объекта InternetExplorer.Appplication (рис. 22);

Рисунок 22. Обращение к ресурсу-приманке в образце 2020 г. (слева) и 2022 г. (справа)
Рисунок 22. Обращение к ресурсу-приманке в образце 2020 г. (слева) и 2022 г. (справа)
  • формирование списка всех директорий, содержащихся в папках Program Files и Program Files (x86) одной строкой через разделитель (рис. 23);

Рисунок 23. Формирование списка директорий одной строкой в образце 2020 г. (слева) и 2022 г. (справа)
Рисунок 23. Формирование списка директорий одной строкой в образце 2020 г. (слева) и 2022 г. (справа)
  • проверка перечня защитных решений, установленных на зараженном компьютере с использованием раннее сформированного перечня директорий (рис. 24);

Рисунок 24. Поиск защитных решений в образце 2020 г. (слева) и 2022 г. (справа)
Рисунок 24. Поиск защитных решений в образце 2020 г. (слева) и 2022 г. (справа)
  • проверка работы в виртуальной среде (рис. 25);

Рисунок 25. Проверка работы в виртуальной среде в образце 2020 г. (слева) и 2022 г. (справа)
Рисунок 25. Проверка работы в виртуальной среде в образце 2020 г. (слева) и 2022 г. (справа)
  • запуск полезной нагрузки через объект класса ShellWindows (рис. 26).

Рисунок 26. Запуск полезной нагрузки в образце 2020 г. (слева) и 2022 г. (справа)
Рисунок 26. Запуск полезной нагрузки в образце 2020 г. (слева) и 2022 г. (справа)

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

Однако стоит отметить сходство алгоритма хэширования, используемого для генерации ID агента с тем, что ранее использовался в Trickbot (рис. 27).

Рисунок 27. Алгоритм хэширования строк в Trickbot (слева) и исследуемом образце (справа)
Рисунок 27. Алгоритм хэширования строк в Trickbot (слева) и исследуемом образце (справа)

Вывод

Первый этап заражения похож на ранее описанные подходы XDSpy, однако в основной нагрузке есть некоторые различия. Для закрепления на системе был выбран менее популярный ключ реестра, а также изменился метод шифрования коммуникации с С2. Также интересным моментом является использование одного из алгоритмов хэширования, аналогичному тому, что ранее был замечен в Trickbot. У нас нет достаточных фактов для атрибутирования атаки к активности XDSpy, а обнаруженный фрагмент кода из зловреда Trickbot, не связанного с XDSpy, дает основания полагать, что это может быть примером переиспользования тактик действия с мимикрией под группу, а не только заимствования фрагментов кода. Кроме того, отметим, это был первый известный нам случай попытки уклонения ВПО от обнаружения нашей песочницей.


Александр Тюков

Специалист отдела обнаружения вредоносного ПО экспертного центра безопасности Positive Technologies (PT Expert Security Center)

Комментарии (4)


  1. kolabaister
    11.10.2022 12:59
    +3

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


    1. IDDQDesnik
      11.10.2022 16:20

      Количество признаков и вариантов их проверки стремится к бесконечности, но не проще ли тогда работать в настоящей виртуальной машине?


    1. k1k
      12.10.2022 18:29

      Один из самых лучших таких детектеров тут https://github.com/hfiref0x/VMDE/blob/master/src/vmde/detect.c . Однако, мимикрировать под такие признаки сложнее, чем создавать просто папки в "Program Files".


  1. rivitna
    11.10.2022 13:21

    Все очень хорошо, мне лично только атрибуция и вывод не очень понравились.

    А функция хеширования на рис. 16 - это Chromium SuperFastHash ;-)