TL; DR
Екипът за изследвания в областта на сигурността на Xygeni идентифицира сложна npm кампания за кражба на информация, предоставяна чрез два злонамерени пакета: конзола намлява selfbot-lofy.
Най-новата версия (consolelofy@1.3.0) вгражда 216KB AES-криптиран полезен товар, който се декриптира по време на изпълнение и се изпълнява чрез vm.runInNewContext()Тъй като злонамерената логика е напълно криптирана, статичните скенери, разчитащи на проверка на низове, не могат да наблюдават поведението ѝ до момента на изпълнение.
След декриптиране, полезният товар, вътрешно брандиран Крадецът на Никс, цели:
- Токени за удостоверяване в Discord
- 50+ хранилища за идентификационни данни за браузъра
- 90+ разширения за портфейли с криптовалута
- Сесии в Roblox, Instagram, Spotify, Steam, Telegram и TikTok
- Устойчивост на Discord десктоп клиента
И двата пакета, всичките 20 версии, бяха докладвани и потвърдени като злонамерени.
Технически преглед на този npm Infostealer
За разлика от традиционния зловреден софтуер, инсталиран по време на инсталиране, тази кампания разчита на по време на работа модел на декриптиране.
Има:
- Без злонамереност
preinstallorpostinstallhooks - Няма очевидни мрежови повиквания по време на инсталиране
- Няма логика за събиране на идентификационни данни в открит текст
Полезният товар се активира, когато модулът бъде импортиран. Цялото злонамерено тяло е криптирано и се материализира в паметта само по време на изпълнение.
Този дизайн специално избягва откриването по време на инсталирането на пакета.
Как всъщност се изпълнява този npm Infostealer
Преди да анализираме какво краде Nyx Stealer, трябва да разберем как се изпълнява.
Злонамерената логика в този npm инфостейлър следва последователен модел:
Малък зареждащ механизъм декриптира голям криптиран полезен товар и го изпълнява динамично в контекст на виртуална машина Node.js.
Този дизайн е умишлен. Нападателят не крие функционалност само зад обфускация, той... пълно премахване на злонамерен код от статичната видимост.
Модел на изпълнение на високо ниво
На високо ниво, обвивката прави четири неща:
- Извлича AES ключ от твърдо кодирана парола, използвайки SHA-256
- Декриптира голям шестнадесетично кодиран шифрован текст, използвайки AES-256-CBC
- Изпълнява декриптирания JavaScript, използвайки
vm.runInNewContext() - Предоставя пясъчник, който все още предоставя мощни примитиви по време на изпълнение
Обобщение на основната техника
| Компонент | Конфигурация / Стойност |
|---|---|
| алгоритъм | AES-256-CBC |
| Извличане на ключ | SHA-256 (парола) |
| Вектор за инициализация (IV) | 16 байта от 0x00 |
| Изпълнение | vm.runInNewContext(декриптирано, пясъчник) |
Важно е да се отбележи, че пясъчникът преминава през:
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 стартира паралелни вълни за събиране на данни.
Вълна 1: Извличане на идентификационни данни от браузъра
Зловредният софтуер:
- Изтегля Python runtime от NuGet CDN
- Инсталира криптографски библиотеки
- Извлича хранилища за идентификационни данни, базирани на 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
- Влива се в административни инструменти
Това е декриптиране на идентификационни данни на ниво операционна система, а не извличане на данни от данните.
Вълна 2: Декриптиране на 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 токени blobs
- Валидиране на токени спрямо Discord API
- Обогатете с Nitro, значки, информация за фактуриране
Това не е генерично изтриване на идентификационни данни. Това е отвличане на сесия, съобразено с протокола.
Вълна 3: Таргетиране на портфейли с криптовалути
npm infostealer изброява:
- 90+ разширения за портфейли в браузъра
- 27 настолни портфейла
- Пътища за студени портфейли
- Seed файлове на 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 Desktop
След събиране на идентификационни данни, Nyx Stealer се опитва да осигури персистентност, като променя локалните раздор клиент.
Цел:
%LOCALAPPDATA%\Discord*\app-*\modules\discord_desktop_core\index.js Оперативна последователност
Инфокрадецът изпълнява следните стъпки:
- Прекратява изпълняваните процеси на Discord
- Намира инсталирани варианти на Discord (Stable, Canary, PTB)
- Презаписва
discord_desktop_core/index.js - Вмъква контролирана от атакуващия логика на уеб кукичката
- Рестартира Discord
Това гарантира, че бъдещите сесии на Discord автоматично ще изпускат нови токени за удостоверяване.
Важно е да се отбележи, че тази постоянство не зависи от планирани задачи или промени в системния регистър. Тя използва модификация на кода на ниво приложение, което е по-скрит подход.
Дори ако злонамереният npm пакет бъде премахнат по-късно, Discord клиентът остава компрометиран.
Техническо сравнение: Легитимен Selfbot срещу npm Infostealer
| Компонент | Легитимна библиотека | Nyx npm Инфостейлер |
|---|---|---|
| Encryption | None | Пълно AES-криптирано полезно натоварване |
| Виртуална машина по време на изпълнение | Не се изисква | vm.runInNewContext изпълнение |
| Достъп с идентификационни данни | Само Discord API | Браузър, портфейли, DPAPI |
| Външни изтегляния | Не | Python среда за изпълнение чрез NuGet |
| Постоянство | Не | Инжектиране на Discord клиент |
| Осигуряването | Автоматизация на ботове | Препродажба на удостоверения |
Само слоят за криптиране вече отделя тази кампания от типичния форк с отворен код.
Легитимен Discord selfbot няма причина да криптира цялата си кодова база, да стартира PowerShell за достъп до DPAPI, да изтегля външни среди за изпълнение или да променя вътрешните компоненти на десктоп приложенията. Когато тези възможности се появят в зависимост, която твърди, че автоматизира взаимодействията в Discord, архитектурното несъответствие става невъзможно да се игнорира.
От гледна точка на разследването, този npm инфостейлър оставя следи на множество слоеве. Най-надеждните индикатори обаче не са твърдо кодираните URL адреси или специфични файлови пътища, тъй като те могат да се променят между версиите. Вместо това, трайните сигнали са структурни.
На ниво пакет, най-силният червен флаг е комбинацията от голям криптиран полезен товар и обвивка за декриптиране по време на изпълнение, която се изпълнява незабавно чрез vm.runInNewContext()Въпреки че самото криптиране не е по своята същност злонамерено, използването на AES декриптиране, последвано от динамично изпълнение на виртуална машина в рамките на пакет с помощни програми на Discord, е силно аномално.
На ниво хост, подозрителните модели включват неочаквана активност по декриптиране на DPAPI, стартиране на процеси от контекст на зависимост на Node.js и модификация на локални файлове на приложения, които никога не трябва да се променят от библиотеки на трети страни. По подобен начин, на мрежово ниво, изходящата комуникация в стил webhook, инициирана от зависимост за разработка, представлява друга значима аномалия.
С други думи, повърхността за откриване не е единичен индикатор за компрометиране. Заплахата е разкрита чрез корелация между криптиране, изпълнение по време на изпълнение, достъп до идентификационни данни и поведение при постоянство.
Откриване и смекчаване с Xygeni
Този npm крадец на информация беше идентифициран от Ранно предупреждение за зловреден софтуер (MEW) на Xygeni чрез многопластова поведенческа корелация, а не чрез просто съпоставяне на сигнатури.
Вместо да търси известни злонамерени низове, MEW оценява структурни аномалии в цялото дърво на изходния код. В този случай откриването е резултат от конвергенцията на няколко сигнала: вградена AES декриптираща рутина във входната точка на модула, незабавно изпълнение в контекста на виртуална машина и ясно несъответствие между възможностите и намеренията.
Важно е да се отбележи, че нито един от тези сигнали сам по себе си не доказва злонамерено намерение. Въпреки това, когато се анализират заедно, те разкриват опит за прикриване на поведение по време на изпълнение. Този многопластов подход значително намалява фалшивите положителни резултати, като същевременно идентифицира заплахи за веригата за доставки с висока степен на доверие.
Освен това, този случай илюстрира защо само проверката по време на инсталиране е недостатъчна. Злонамерената логика не се намира в скриптовете на жизнения цикъл. Тя се активира само след зареждане на модула и става видима едва след декриптиране в паметта. Следователно, ефективната защита изисква анализ, съобразен с криптирането, разпознаване на поведенчески модели и непрекъснато наблюдение на зависимостите след инсталирането.
Премахването на системния регистър е реактивно. Анализът по време на изпълнение е превантивен.
Защо този npm крадец на информация е важен
Nyx Stealer представлява структурна еволюция в зловредния софтуер, базиран на npm.
В миналото много злонамерени пакети са разчитали на видими скриптове по време на инсталиране или очевидни крайни точки за извличане на идентификационни данни. За разлика от това, тази кампания криптира полезния си товар, отлага изпълнението до средата на изпълнение, използва легитимни API-та на операционната система и установява постоянство в надеждни приложения.
Следователно, атакуващият не е необходимо да използва самата npm инфраструктура. Вместо това, атаката е успешна, защото инсталирането на зависимости предполага доверие. Разработчиците приемат, че импортирането на библиотека е безопасна операция, особено когато тя се представя като правдоподобен fork (разклонение) на популярен инструмент.
С нарастването на екосистемите и разпространението на форковете, тази имплицитна граница на доверие се превръща във все по-привлекателна повърхност за атака. Следователно, защитата срещу съвременните крадци на информация от npm изисква разпознаване на архитектурни модели, а не търсене на статични низове.
В крайна сметка, тази кампания затвърждава един важен урок в software supply chain securityНай-опасните заплахи не са тези, които изглеждат злонамерени на пръв поглед, а тези, които изглеждат структурно легитимни, докато по време на изпълнение не се разкрие истинското им поведение.




