Tl; DR
Ang Pangkat ng Pananaliksik sa Seguridad ng Xygeni natukoy ang isang sopistikadong kampanya ng npm infostealer na inihatid sa pamamagitan ng dalawang malisyosong pakete: consolelofy at selfbot-lofy.
Ang pinakabagong bersyon (consolelofy@1.3.0) nag-eembed ng 216KB na AES-encrypted payload na nagde-decrypt sa runtime at isinasagawa sa pamamagitan ng vm.runInNewContext()Dahil ang malisyosong lohika ay ganap na naka-encrypt, ang mga static scanner na umaasa sa string inspection ay hindi maaaring obserbahan ang kilos nito hanggang sa oras ng pagpapatupad.
Kapag na-decrypt na, ang payload, na may internal na tatak Magnanakaw ng Nyx, target:
- Mga token ng pagpapatotoo ng Discord
- 50+ na tindahan ng kredensyal ng browser
- 90+ na extension ng cryptocurrency wallet
- Mga sesyon ng Roblox, Instagram, Spotify, Steam, Telegram, at TikTok
- Pagtitiyaga ng kliyente ng desktop ng Discord
Ang lahat ng 20 bersyon sa parehong pakete ay naiulat at nakumpirmang malisyoso.
Teknikal na Pangkalahatang-ideya ng npm Infostealer na Ito
Hindi tulad ng tradisyonal na malware sa oras ng pag-install, ang kampanyang ito ay umaasa sa isang runtime modelo ng decryption.
Mayroong:
- Walang malisya
preinstallorpostinstallhooks - Walang halatang mga tawag sa network sa oras ng pag-install
- Walang lohika sa pagkuha ng kredensyal ng plaintext
Maga-activate ang payload kapag na-import ang module. Ang buong malisyosong katawan ay naka-encrypt at lumilitaw lamang sa memorya sa oras ng pagpapatakbo.
Partikular na iniiwasan ng disenyong ito ang pagtuklas habang ini-install ang pakete.
Paano Talaga Naisasagawa ang npm Infostealer na Ito
Bago natin suriin kung ano ang ninanakaw ng Nyx Stealer, kailangan muna nating maunawaan... kung paano ito isinasagawa.
Ang malisyosong lohika sa loob ng npm infostealer na ito ay sumusunod sa isang pare-parehong padron:
Ang isang maliit na loader ay nagde-decrypt ng isang malaking naka-encrypt na payload at dynamic na isinasagawa ito sa loob ng konteksto ng Node.js VM.
Sinadya ang disenyong ito. Hindi lamang itinatago ng umaatake ang mga functionality sa likod ng obfuscation, sila ay ganap na pag-aalis ng malisyosong code mula sa static visibility.
Modelo ng Pagpapatupad na Mataas ang Antas
Sa mataas na antas, ang pambalot ay gumagawa ng apat na bagay:
- Kumukuha ng AES key mula sa isang hardcoded passphrase gamit ang SHA-256
- Nagde-decrypt ng malaking hex-encoded ciphertext gamit ang AES-256-CBC
- Isinasagawa ang na-decrypt na JavaScript gamit ang
vm.runInNewContext() - Nagbibigay ng sandbox na naglalantad pa rin ng malalakas na runtime primitives
Buod ng Pangunahing Teknik
| bahagi | Konpigurasyon / Halaga |
|---|---|
| Algorithm | AES-256-CBC |
| Key Derivation | SHA-256 (passphrase) |
| Vector ng Pagsisimula (IV) | 16 na byte ng 0x00 |
| Pagpapatupad | vm.runInNewContext(na-decrypt, sandbox) |
Kritikal, ang sandbox ay dumadaan sa:
requireprocessBuffer- timers
- mga pag-export ng modyul
Nangangahulugan ito na ang na-decrypt na payload ay nananatili ang buong kakayahan upang:
- Mga proseso ng pag-spawn
- Magbasa at magsulat ng mga file
- Gumawa ng mga tawag sa network
- Baguhin ang mga lokal na aplikasyon
Hindi ito isang restricted VM. Ito ay isang VM na ginagamit bilang isang execution trampoline.
Pattern ng Pag-encrypt ng Runtime (Pangunahing Mekanismo ng Pagpapatupad)
Maliit lang ang kargador.
Ang malisyosong katawan ay hindi.
Nasa ibaba ang pattern ng pagpapatupad na matatagpuan sa loob ng pakete:
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); } Bakit Ito bagay na ito
Ang na-decrypt na payload:
- Ba hindi umiiral sa plaintext sa loob ng npm package
- Hindi nakikita ng simpleng
grepo pag-scan ng static string - Lumilitaw lamang sa memorya sa oras ng pagpapatakbo
- Nagpapatupad nang may kumpletong kakayahan sa runtime ng Node
Ang kombinasyong ito ng pagpapatupad ng AES + VM ay isang malakas na tagapagpahiwatig ng pag-uugali ng isang Sinusubukan ng npm infostealer na umiwas sa static na inspeksyon.
Sa ibang salita:
Kung i-scan mo ang package source tree, wala kang makikitang magnanakaw.
May makikita kang decryptor.
Ano ang Mangyayari Pagkatapos ng Decryption
Kapag naisakatuparan na, inilulunsad ng Nyx Stealer ang mga parallel data collection wave.
Wave 1: Pagkuha ng Kredensyal sa Browser
Ang malware:
- Nagda-download ng Python runtime mula sa NuGet CDN
- Nag-i-install ng mga cryptographic library
- Kinukuha ang mga imbakan ng kredensyal na nakabatay sa Chromium
- Nagde-decrypt ng mga sikretong protektado ng DPAPI
Sa halip na i-compile ang mga native binding, ginagamit nito ang PowerShell upang direktang tawagin ang 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'); } Ang diskarteng ito:
- Iniiwasan ang mga artifact ng compilation
- Gumagamit ng mga katutubong Windows crypto API
- Pinagsasama sa mga kagamitang administratibo
Ito ay decryption ng kredensyal sa antas ng OS, hindi scraping.
Wave 2: Pag-decrypt ng Token ng Discord
Alam ng magnanakaw ang protocol. Nauunawaan nito ang naka-encrypt na format ng token ng 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'); } Daloy ng Operasyon:
- I-extract ang master key mula sa Discord's
Local State - I-decrypt ang master key gamit ang DPAPI
- I-decrypt ang mga token blob ng AES-GCM
- I-validate ang mga token laban sa Discord API
- Pagyamanin gamit ang Nitro, mga badge, impormasyon sa pagsingil
Hindi ito pangkaraniwang paglalaglag ng kredensyal. Ito ay isang protocol-aware session hijacking.
Wave 3: Pag-target sa Cryptocurrency Wallet
Inililista ng npm infostealer ang mga sumusunod:
- 90+ na extension ng browser wallet
- 27 desktop wallet
- Mga landas ng cold wallet
- Mga file ng binhi ng Exodo
Halimbawang pagtatangka sa pag-decrypt ng seed:
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'); } Kung magtagumpay, ang pagkakompromiso sa pitaka ay agarang at hindi na mababawi.
Kinakatawan nito ang pinakamataas na halaga ng vector ng monetization ng kampanya.
Pagtitiyaga sa pamamagitan ng Discord Desktop Injection
Matapos makuha ang mga kredensyal, sinubukan ni Nyx Stealer na magtiyaga sa pamamagitan ng pagbabago ng lokal Hindi magkasundo client.
Target:
%LOCALAPPDATA%\Discord*\app-*\modules\discord_desktop_core\index.js Operational Sequence
Isinasagawa ng infostealer ang mga sumusunod na hakbang:
- Tinatapos ang mga proseso ng Discord na tumatakbo
- Hinahanap ang mga naka-install na variant ng Discord (Stable, Canary, PTB)
- Nag-o-overwrite
discord_desktop_core/index.js - Naglalagay ng lohika ng webhook na kontrolado ng attacker
- Ire-restart ang Discord
Tinitiyak nito na awtomatikong maglalabas ng mga bagong authentication token ang mga susunod na sesyon ng Discord.
Mahalaga, ang pagtitiyaga na ito ay hindi umaasa sa mga naka-iskedyul na gawain o mga pagbabago sa registry. Ginagamit nito ang pagbabago ng code sa antas ng application, isang mas palihim na pamamaraan.
Kahit na maalis ang malisyosong npm package sa kalaunan, mananatiling nakompromiso ang Discord client.
Teknikal na Paghahambing: Lehitimong Selfbot vs npm Infostealer
| bahagi | Lehitimong Aklatan | Magnanakaw ng Impormasyon ng Nyx npm |
|---|---|---|
| Encryption | Wala | Buong payload na naka-encrypt ng AES |
| Runtime VM | Hindi kinakailangan | vm.runInNewContext pagpapatupad |
| Pag-access sa Kredensyal | Discord API lamang | Browser, mga wallet, DPAPI |
| Mga Panlabas na Pag-download | Hindi | Oras ng pagpapatakbo ng Python sa pamamagitan ng NuGet |
| Pagtitiyaga | Hindi | Iniksyon ng kliyente ng Discord |
| monetization | Awtomasyon ng bot | Muling pagbebenta ng kredensyal |
Ang encryption layer pa lamang ay nakapaghihiwalay na sa kampanyang ito mula sa isang tipikal na open-source fork.
Walang dahilan ang isang lehitimong Discord selfbot para i-encrypt ang buong codebase nito, gamitin ang PowerShell para ma-access ang DPAPI, mag-download ng mga external runtime, o baguhin ang mga internal na desktop application. Kapag lumitaw ang mga kakayahang iyon sa loob ng isang dependency na nagsasabing awtomatiko ang mga interaksyon sa Discord, nagiging imposibleng balewalain ang architectural mismatch.
Mula sa pananaw ng imbestigasyon, ang npm infostealer na ito ay nag-iiwan ng mga bakas sa maraming layer. Gayunpaman, ang mga pinaka-maaasahang indicator ay hindi ang mga hardcoded na URL o mga partikular na file path, dahil maaaring magbago ang mga iyon sa pagitan ng mga bersyon. Sa halip, ang mga matibay na signal ay istruktural.
Sa antas ng pakete, ang pinakamatinding pulang bandila ay ang kombinasyon ng isang malaking naka-encrypt na payload at isang runtime decryption wrapper na agad na isinasagawa sa pamamagitan ng vm.runInNewContext()Bagama't ang pag-encrypt lamang ay hindi likas na nakakapinsala, ang paggamit ng AES decryption na sinusundan ng dynamic VM execution sa loob ng isang Discord utility package ay lubhang anomalya.
Sa antas ng host, kabilang sa mga kahina-hinalang pattern ang hindi inaasahang aktibidad ng pag-decrypt ng DPAPI, paglitaw ng proseso mula sa konteksto ng dependency ng Node.js, at pagbabago ng mga lokal na file ng aplikasyon na hindi dapat baguhin ng mga third-party library. Gayundin, sa network layer, ang outbound webhook-style na komunikasyon na sinimulan ng isang development dependency ay kumakatawan sa isa pang makabuluhang anomalya.
Sa madaling salita, ang detection surface ay hindi isang iisang indikasyon ng kompromiso. Ito ay ang ugnayan ng encryption, runtime execution, credential access, at persistence behavior na nagpapakita ng banta.
Pagtuklas at Pagpapagaan gamit ang Xygeni
Ang npm infostealer na ito ay kinilala ni Maagang Babala sa Malware ng Xygeni (MEW) sa pamamagitan ng layered behavioral correlation sa halip na simpleng signature matching.
Sa halip na maghanap ng mga kilalang malisyosong string, sinusuri ng MEW ang mga anomalya sa istruktura sa buong source tree. Sa kasong ito, lumitaw ang pagtuklas mula sa pagtatagpo ng ilang signal: isang naka-embed na AES decryption routine sa module entry point, agarang pagpapatupad sa loob ng konteksto ng VM, at isang malinaw na hindi pagkakatugma ng kakayahan sa layunin.
Mahalaga, wala sa mga senyales na ito lamang ang nagpapatunay ng malisyosong intensyon. Gayunpaman, kapag pinag-aralan nang magkasama, inilalantad nila ang isang pagtatangka na itago ang pag-uugali ng runtime. Ang layered na pamamaraang ito ay makabuluhang binabawasan ang mga maling positibo habang tinutukoy ang mga banta sa supply chain na may mataas na kumpiyansa.
Bukod pa rito, inilalarawan ng kasong ito kung bakit hindi sapat ang inspeksyon sa oras ng pag-install lamang. Ang malisyosong lohika ay hindi matatagpuan sa mga script ng lifecycle. Ito ay nag-a-activate lamang pagkatapos mag-load ang module at makikita lamang kapag na-decrypt na sa memorya. Samakatuwid, ang epektibong depensa ay nangangailangan ng pagsusuri na may kamalayan sa encryption, pagkilala sa mga pattern ng pag-uugali, at patuloy na pagsubaybay sa dependency na lampas sa mga kaganapan sa pag-install.
Ang pagtanggal ng registry ay reaktibo. Ang pagsusuring may kamalayan sa runtime ay pang-iwas.
Bakit Mahalaga ang npm Infostealer na Ito
Ang Nyx Stealer ay kumakatawan sa isang estruktural na ebolusyon sa npm-based na malware.
Sa kasaysayan, maraming malisyosong pakete ang umaasa sa mga nakikitang script sa oras ng pag-install o mga halatang endpoint ng exfiltration ng kredensyal. Sa kabaligtaran, ine-encrypt ng kampanyang ito ang payload nito, ipinagpapaliban ang pagpapatupad sa runtime, ginagamit ang mga lehitimong API ng operating system, at nagtatatag ng persistence sa loob ng mga pinagkakatiwalaang application.
Dahil dito, hindi kailangang gamitin mismo ng attacker ang npm infrastructure. Sa halip, magtatagumpay ang pag-atake dahil ang pag-install ng dependency ay nagpapahiwatig ng tiwala. Ipinapalagay ng mga developer na ang pag-import ng library ay isang ligtas na operasyon, lalo na kapag ipinapakita nito ang sarili bilang isang kapani-paniwalang fork ng isang sikat na tool.
Habang patuloy na lumalaki ang mga ecosystem at dumarami ang mga fork, ang implicit trust boundary na iyon ay nagiging isang lalong kaakit-akit na attack surface. Samakatuwid, ang pagtatanggol laban sa mga modernong npm infostealer ay nangangailangan ng pagkilala sa mga architectural pattern sa halip na paghahanap ng mga static string.
Sa huli, pinatitibay ng kampanyang ito ang isang kritikal na aral sa software supply chain securityAng mga pinaka-mapanganib na banta ay hindi iyong mga mukhang malisyoso sa unang tingin, kundi iyong mga tila lehitimo sa istruktura hanggang sa ipakita ng runtime ang kanilang tunay na pag-uugali.




