В январе 2026 года специалистами группы киберразведки департамента Threat Intelligence экспертного центра безопасности (PT ESC) была обнаружена атака с использованием вредоносного XLL-файла, внутри которого была цепочка обфусцированных JavaScript-файлов, работающих на основе платформы NodeJS. Система жертвы заражалась вредоносным ПО класса RAT (remote access trojan) с большим количеством доступных команд. Среди особенностей вредоносного кода удалось обнаружить SNS-записи (Solana Name Service) для получения альтернативного адреса сервера злоумышленников. Детальное исследование позволило расширить временной диапазон атаки: вредоносная активность зафиксирована с середины октября 2025 года и наблюдается до сих пор.

В этой статье мы подробнее расскажем о том, как работает цепочка атаки с использованием блокчейна Solana.

Вредоносное вложение

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

  • Предложение о сотрудничестве

  • Коммерческое предложение

  • Приказ от командования

Примеры приманок представлены ниже.

Примеры документов-приманок
Примеры документов-приманок

Вредоносный файл во вложении был обнаружен в трех форматах:

  • XLL-файл,

  • LNK-фай,

  • MSI-установщик.

XLL-файл

Алгоритм работы XLL-файла на зараженной системе не отличается высокой сложностью. При открытии файла с Excel-таблицей запускается экспортируемая функция xlAutoOpen, основная цель которой:

  • Декодировать Base64-строку с PowerShell-командой.

  • Выполнить полученную команду.

Сама команда схожа с теми, которые используются далее в других файлах (LNK, MSI):

XLSX-файл, открываемый исполняемым файлом, представляет собой форму для заполнения.

PT Sandbox. Пример Excel-таблицы внутри XLL-файла
PT Sandbox. Пример Excel-таблицы внутри XLL-файла

Во вредоносном файле можно также найти уникальную строку вида ##EMBED_BASE64_START##, которая встречается внутри еще одного файла — тестового XLL-образца, обнаруженного в декабре 2025 года. В то время принцип работы был тот же, меняется лишь сервер злоумышленников с полезной нагрузкой.

Сами индикаторы компрометации будут приложены в конце статьи.

LNK-файл

В ходе исследования мы обнаружили четыре LNK-файла со следующими названиями:

  • Приказ по соединению № 004_Гроза.docx.lnk

  • БОБ, задача фотофіксації для мінування.docx.lnk

  • Гуманитарка_для_подразделения.docx.lnk

  • Волонтерка остатки.docx.lnk

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

Пример вредоносного LNK на портале PT Fusion
Пример вредоносного LNK на портале PT Fusion

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

Пример поиска схожих LNK на портале PT Fusion
Пример поиска схожих LNK на портале PT Fusion

MSI-файл

На основе общего с тестовым XLL-файлом сервера было обнаружено несколько вредоносных установщиков со следующими названиями:

  • kommercheskoe-predlozhenie-xlsx.msi

  • kommercheskoe-predlozhenie-pdf.msi

Внутри установщика были:

  • VBS-файл, который запускает PowerShell-скрипт из той же папки, в которой находится этот файл.

  • PowerShell-скрипт с названием run-script.ps1.

Пример скрипта внутри файла run-script.ps1:

Загрузчик необходимых для атаки компонентов

Выполнение всех команд, показанных выше, приводит к скачиванию полезной нагрузки — PowerShell-скрипта:

Алгоритм работы:

  • Отослать на сервер злоумышленников запрос для фиксации системы жертвы в базе.

  • Проверить наличие Node.js в системе жертвы. Если нет — загрузить легитимный файл.

  • Загрузить следующую полезную нагрузку и запустить через Node.js.

Обфусцированный JavaScript-загрузчик

Скачиваемая полезная нагрузка — обфусцированный вредоносный JavaScript-код размером около 5 МБ. Такой размер обоснован распаковкой базовых модулей Node.js в код самого загрузчика (можно воспринимать как статическую компоновку исполняемых файлов).

Основные компоненты обфускации:

  • переименование переменных;

  • разделение строковых констант;

  • формирование строк из перемешанного массива байтов;

  • распаковка модулей Node.js.

Фрагмент функции main можно видеть ниже.

Фрагмент обфусцированной main-функции загрузчика
Фрагмент обфусцированной main-функции загрузчика

После деобфускации код выглядит следующим образом.

Фрагмент деобфусцированной main-функции загрузчика
Фрагмент деобфусцированной main-функции загрузчика

Алгоритм работы загрузчика:

  • Закрепление в системе:

    • Создание файла %USERPROFILE%\AppData\Local\nodejs\index.vbs со следующим содержимым:

    • Создание LNK-файла CommonApp.lnk в папке автозагрузки для запуска скрипта выше.

    • Создание запланированной задачи с названием ZeroDriveBackupTaskSystem141.1.7272.0 для запуска VBS-скрипта выше. Задача работает каждые 5 минут.

  • Определение сервера злоумышленников:

    • Если установлена переменная окружения SNS_DOMAIN — получить домен через TXT-запись SNS-домена.

    • Если переменной нет — использовать константную API-ссылку https://playerdragonbike[.]com.

  • Формирование прокси-объекта. Сам прокси-объект служит для динамического API-клиента, способного работать на основе нескольких протоколов (HTTP, WebSocket). В контексте вредоносного кода использовался только HTTP-протокол для получения полезной нагрузки.

В процессе анализа JavaScript-кода была обнаружена конфигурация децентрализованного приложения, работающего в блокчейн-сети Solana. Эта конфигурация, равно как и классы, является частью библиотеки @solana/web3.js и необходима только для получения TXT-записи.

Важно уточнить, что последние два шага закрепления загрузчика выполняются через одну PowerShell-команду, которая кодируются в Base64-строку. Команда выглядит следующим образом:

Чтобы получить основной модуль, загрузчик считывает серийный номер диска и считает от этой строки MD5-хеш. Затем отсылается запрос на сервер злоумышленников с GET-параметрами через сформированный прокси-объект vHc:

const v3626 = await vHc.index.$get({
query: {
	cid: "b72f75cb3b22e364", mod: "main", huidMd5: v3625
}
});

Подобный запрос, если возникают какие-то ошибки во время работы кода, бесконечно повторяется каждые 10 секунд.

Основной модуль

Главная полезная нагрузка также является обфусцированным JavaScript-кодом. Способы обфускации не изменились относительного загрузчика. Изучение кода показывает, что полученный модуль является полноценным RAT с большим набором выполняемых команд и собираемых данных.

Установка сетевого соединения

Сетевое взаимодействие с сервером злоумышленников тоже работает на основе прокси-объекта, однако в этот раз он работает в режиме веб-сокета. Для корректной работы в начале функции main выставляется mutex на основе необходимого для сети порта:

const v1656 = await createMutex(40000); // 40000 - WebSocket port

Если порт свободен — в системе жертвы успешно запускается сервер, прослушивающий запросы на порт 40000.

Функция инициализации сетевого соединения
Функция инициализации сетевого соединения

Типы обрабатываемых сообщений. Список команд

После успешной установки сокет-соединения при появлении нового сообщения от сервера проверяется тип этого сообщения:

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

type: 'task' | 'socks5-connect' | 'socks5-data' | 'socks5-close'
additional: {}

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

id: string;
type: 'download-file' | 'dump-outlook' | 'force-delete' | 'get-location' | 'get-meta' | 'install-ssh'| 'list-drives' | 'list-files' | 'powershell' | 'powershell-preconfigured' | 'restart' | 'restart-with-uac-bypass' | 'run-binary' | 'run-ssh-module' | 'screenshot' | 'shutdown' | 'write-file'
args: {}

Для socks5-connect:

connectionId: string;
targetHost: string;
targetPort: number;

Для socks5-data запрос показан ниже. Основная цель SOCKS5-соединения — перенаправление сообщений (данных) на другой сервер:

connectionId: string;
data: string;

Для socks5-close:

connectionId: string;
Всего вредонос способен обработать 17 команд.

Тип команды

Структура аргументов

Описание

Отправляемый ответ

download-file

filePath: string

Загрузить файл из зараженной системы по пути filePath на сервер злоумышленника

success: boolean

fileData: string

fileName: string

fileSize: string

error: string

dump-outlook

Установить модуль для сбора информации из Outlook и запустить его

success: Boolean

data: outlookDumpSchema

error: string

force-delete

Скачать модуль самоуничтоженияпо ссылке

{API_URL}/s/d и запустить его

New-Object System.Device.Location.GeoCoordinateWatcher

get-location

location: string

get-meta

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

type: ‘pc-info’

username:string

hostname: string

osCaption: string

osVersion: string

osBuildNumber: string

cpus: string[]

gpus: string[]

ram: string

domain: string

permissionInfo: permissionsInfoSchema

install-ssh

В коде не реализовано

list-drives

Получение всех логических томов на системе, определение типа тома (сетевой адаптер, CD-ROM и др.), количества свободного места на всех томах

result: driveListSchema

list-files

path: string

Листинг папки по пути path. Каждый файл определяется в результирующем объекте следующими полями: имя файла, путь до файла, тип (файл или папка), размер, дата модификации, атрибуты файла

result: fileListSchema

powershell

commandId: string

Получение команды по ссылке {API_URL}/main/command и ее выполнение

output: string

powershell-preconfigured

commandKey: “cf6180e3501d” | “af4d98a99681” | “f45f0a4a3ccd”

Выполнение PowerShell-команд на основе уже существующих шаблонов с идентификаторами commandKey. Запрос по ссылке {API_URL}/s/{commandKey} и выполнение полученной команды.

cf6180e3501d — команда для выгрузки файла (FileUploadingCommand).

af4d98a99681 — команда для инициализации (InitializationCommand).

f45f0a4a3ccd — команда для сбора информации (StealerCommand)

output: string

restart

Завершение собственного процесса с кодом 0

restart-with-uac-bypass

Завершение собственного процесса с кодом 66

run-binary

binaryUrl: stringbinaryType: “exe” | “msi” | “zip” | “dll”args: {}

Получение исполняемого файла по ссылке binaryUrl и его запуск в зависимости от типа исполняемого файла binaryType. Исполняемый файл с типом exe может быть запущен в дочернем процессе либо внедряться как шеллкод. Все действия происходят в папке %TEMP%

run-ssh-module

Загрузка SSH-модуля по ссылке {API_URL}/?cid=b72f75cb3b22e364&mod=ssh&returnType=zip

screenshot

Формирование снимка экрана

screenshotB64: string

shutdown

В коде не реализована

 

write-file

filePath: stringfileUrl: string

Загрузка файла по ссылке fileUrl и запись его по пути filePath

success: boolean

error: string

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

Помимо основных задач и SOCK5-соединений в коде происходит отдельный запуск двух отдельных модулей — клиппера и кейлоггера. Они также загружаются с сервера злоумышленников.

Сравнение с раннее обнаруженными атаками

Похожие атаки уже были обнаружены другими исследователями. Так, специалисты BlueVoyant описывали аналогичные обфусцированные JavaScript-файлы с подобными способами закрепления и сетевым взаимодействием. Однако в их исследовании указано использование техники ClickFix, что отличается от тех цепочек атак, которые были обнаружены нами.

Сконцентрируемся на особенностях кода, которые были замечены во время деобфускации:

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

    Получаем TXT-запись для домена
    # Проверяем через группу локальных администраторов
  • Использование чат-ботов для написания кода. Это можно понять на основе нескольких факторов:

    • Расхождение в общей логике кода. Например, если в загрузчике определяется API_URL на основе переменной окружения SNS_DOMAIN, то в основном модуле снова используется константная ссылка.

    • Комментарии с использованием эмодзи:

      🔍 Using API URL:
      ❌ Ошибка при получении TXT-записи:
      ⚠️ Records V2 не найдены, проверяем V1.

Поскольку наши коллеги никак не назвали этот кластер активности, мы решили назвать группу хакеров, стоящих за этими атаками, HeartlessSoul.

Другая, не менее важная составляющая — расположенные на серверах злоумышленников страницы. Например, на IP-адресе 185.208.158[.]188 одновременно находилось несколько доменов, один из которых — домен, обнаруженный в атаке, другой — ozonwork.org.

Несколько доменов на одном IP-адресе
Несколько доменов на одном IP-адресе

Из имени домена ясно, что злоумышленники мимикрируют под известный маркетплейс, дополнительно собирая пользовательские данные. Из любопытных деталей можно заметить комментарии в разметке страницы (см. ниже).

Комментарий в HTML-разметке
Комментарий в HTML-разметке

Однако не стоит делать выводы только на основе языка HTML-комментария. Стоит также учитывать географию атак: мы наблюдаем их на территории России и других стран, например Молдовы, Украины, Мексики, Германии, США. 


Наша команда киберразведки продолжит наблюдать за активностью злоумышленников из HeartlessSoul.

Индикаторы компрометации

Индикаторы, связанные с атакой

(DOMAINS)

newfolder[.]click
landownerdozenguard[.]com
playerdragonbike[.]com
ozonjob[.]org
ozonwork[.]org

(LNK)
e59b01f23bea63893707542ef15b3e092928b52254a7134924e5a5cb6407e6e2
d8498dafcd22923116bba133be9969c467953acbf3c04b365c4b725bfa590061
ff690b11f7b2fbcf1f3abd217476b9fa6830cc380cb5607af2d0ec4e5a345208
8f50ad1027bbe999313bd6b9cf690f5dcafdd926a3e7ebdf7b82c80cec95c511

(MSI)
b9cb3dba8a536eb41c9fee7d243640dc0ec3cd5a7e80eb4855467d0acbf7af5e
ae4fd0d67b40c5b680a6c481a1d2486893c16b067680bb3d604ac8272f16570c
c0ddf84e29374cd53ff4a44ff50e88e1b663fae404bc1a5200bbac38c8d1df36

(ZIP)
da51169b370f6cc1cc10ce54fd4756276e53b57b2687f23176e793f6f6ef66c4

(XLL)
3d3fd2af8e5efdcc3ab8d8b50200c89e6a31bf42e19a3d1bac5f9fb51dabac46
6ac78281275c1770245b28de04542383a51b0702d7f0cb380dfd043806b975d3

Сетевые индикаторы после расширения кластера

Здесь хочется упомянуть индикаторы компрометации, которые связаны с обнаруженными по следующим параметрам:

  • Схожий формат ссылок (/c/add)

  • Общие IP-адреса

  • Похожая структура домена и (или) поддомена (повторяющиеся биграммы, идентичная доменная зона и др.)

*.kyun[.]li
codeinecrazy[.]xyz
wsconnection[.]xyz
w2socks[.]xyz
w2li[.]xyz
w2link[.]xyz
weaplink[.]com
wv3link[.]com
wv3pub[.]com
sharecodepro[.]com

Климентий Галкин

Специалист группы киберразведки TI-департамента экспертного центра безопасности Positive Technologies 

Максим Суслов

Старший специалист группы анализа уязвимостей экспертного центра безопасности Positive Technologies