Diffusione di NWHStealer Attraverso il Runtime JavaScript Bun
Detection stack
- AIDR
- Alert
- ETL
- Query
Sommario
L’articolo spiega come gli attori delle minacce stiano utilizzando il runtime JavaScript Bun per distribuire il ladro di informazioni NWHStealer basato su Rust. Gli archivi ZIP maligni contengono un installer primario che avvia un caricatore JavaScript confezionato con Bun insieme a un caricatore secondario denominato dw.exe. Il componente JavaScript esegue controlli anti-macchina virtuale, comunica con l’infrastruttura di comando e controllo, decripta un payload successivo e sfrutta le API native di Windows per iniettare il ladro in memoria. Per ridurre i sospetti, la campagna nasconde i file maligni dietro a piattaforme di hosting legittime come GitHub, MediaFire e SourceForge.
Indagine
I ricercatori hanno scoperto che Bun è stato utilizzato per confezionare JavaScript maligno nella sezione .bun del caricatore. Due script, sysreq.js and memload.js, gestivano i controlli dell’ambiente e la comunicazione con l’infrastruttura dell’attaccante. Il caricatore recuperava dati di configurazione e payload cifrati da domini come silent-harvester.cc, li decriptava con AES-256-CBC, e li iniettava tramite chiamate API Win32. Il payload finale era NWHStealer, che ruba credenziali, dati del browser e informazioni sui wallet di criptovalute, e può anche avviare attività minerarie aggiuntive.
Mitigazione
Gli utenti dovrebbero evitare di scaricare eseguibili da siti non attendibili e verificare le firme degli installer prima dell’esecuzione. I team di sicurezza dovrebbero monitorare l’attività insolita del runtime Bun, le query CIM di PowerShell utilizzate per i controlli di virtualizzazione, e le chiamate API sospette come VirtualAlloc and LoadLibraryA. Le organizzazioni dovrebbero anche bloccare i domini maligni noti e applicare politiche di esecuzione a privilegi minimi per limitare gli abusi.
Risposta
Se viene rilevata questa attività, isolare il endpoint interessato, raccogliere immagini di memoria e disco, e cercare Installer.exe, dw.exe, e sezioni sospette .bun . Bloccare i domini e gli URL di comando e controllo identificati al perimetro della rete. Distribuire rilevazioni endpoint per i comandi PowerShell osservati e i pattern API Win32. Ruotare le credenziali esposte e monitorare i sistemi interessati per segni di mining non autorizzato di criptovalute.
graph TB %% Definizioni classi classDef technique fill:#ffcc99 classDef action fill:#99ccff %% Nodi node_initial_access[“<b>Accesso iniziale</b><br/><b>T1036.008 Mascheramento: Tipo di file</b>: ZIP malevolo camuffato come file benigno.<br/><b>T1204.002 Esecuzione utente: File malevolo</b>: L’utente esegue il file scaricato.”] class node_initial_access technique node_obfuscated_loader[“<b>Loader offuscato</b><br/><b>T1027.016 Inserimento di codice spazzatura</b>: Inserisce JavaScript irrilevante per nascondere la logica malevola.<br/><b>T1027.008 Rimozione di parti del payload</b>: Rimuove codice non essenziale per ridurre dimensione ed evitare analisi.”] class node_obfuscated_loader technique node_discovery[“<b>Discovery</b><br/><b>T1082 Raccolta informazioni sistema</b>: OS, hardware e software.<br/><b>T1016 Raccolta configurazione rete</b>: Enumerazione di IP, interfacce e routing.”] class node_discovery technique node_credential_access[“<b>Accesso credenziali</b><br/><b>T1555.003 Credenziali browser</b>: Estrazione password salvate e dati di autofill.<br/><b>T1550.004 Uso di materiale di autenticazione alternativo</b>: Furto cookie di sessione.”] class node_credential_access technique node_c2[“<b>Command & Control</b>: Recupera seed AES e payload cifrato da server remoto.”] class node_c2 action node_execution[“<b>Esecuzione</b><br/><b>T1620 Caricamento riflessivo del codice</b>: Esegue payload in memoria senza scrittura su disco.<br/><b>T1055.009 Injection nel processo</b>: Inserisce codice in un processo attivo.”] class node_execution technique node_persistence[“<b>Persistenza</b><br/><b>T1053 Task pianificato</b>: Crea attività pianificata per esecuzione ricorrente.”] class node_persistence technique %% Connessioni node_initial_access –>|porta a| node_obfuscated_loader node_obfuscated_loader –>|porta a| node_discovery node_discovery –>|porta a| node_credential_access node_credential_access –>|porta a| node_c2 node_c2 –>|porta a| node_execution node_execution –>|porta a| node_persistence
Flusso di Attacco
Rilevamenti
Comando e Controllo Sospetto tramite Richiesta DNS di Dominio di Livello Superiore (TLD) Insolito (via dns)
Visualizza
Possibili Controlli di Evasione (via powershell)
Visualizza
Possibile Tentativo di Comunicazione con il Dominio di Lookup IP (via dns)
Visualizza
IOC (HashSha256) da rilevare: Gli attaccanti adottano il runtime JavaScript Bun per diffondere NWHStealer
Visualizza
Rileva Autoiniezione del Caricatore JavaScript NWHStealer [Creazione Processo Windows]
Visualizza
Rilevazione dei Comandi PowerShell Anti-Virtualizzazione di NWHStealer [Windows Powershell]
Visualizza
Esecuzione di Simulazione
Prerequisito: Il Telemetria & Baseline Pre-flight Check deve essere passato.
Razionale: Questa sezione dettaglia l’esecuzione precisa della tecnica avversaria (TTP) progettata per attivare la regola di rilevamento. I comandi e la narrativa DEVONO riflettere direttamente i TTP identificati e mirare a generare la telemetria esatta prevista dalla logica di rilevamento. Esempi astratti o non correlati porteranno a una diagnosi errata.
-
Narrativa dell’Attacco e Comandi:
- Accesso Iniziale: L’attaccante consegna un file JavaScript malevolo (
loader.js) sul sistema della vittima e lo esegue utilizzando il bun runtime (bun loader.js). - Routine di Autoiniezione: Il codice JavaScript chiama le API Win32 native tramite un aiuto PowerShell che usa Add-Type per definire le firme P/Invoke per
VirtualAlloc,VirtualProtect, eLoadLibraryA. - Allocazione di Memoria:
VirtualAllocriserva una regione RWX dimensionata per lo shellcode incorporato. - Iniezione di Shellcode: Lo script PowerShell copia lo shellcode decodificato base64 nella memoria allocata usando
Marshal.Copy. - Cambiamento di Permessi:
VirtualProtectcambia la protezione della pagina a PAGE_EXECUTE_READ. - Esecuzione del Payload:
LoadLibraryAviene invocato su una DLL malevola che risiede solo in memoria (l’intestazione DLL viene scritta nella regione allocata, quindi l’indirizzo viene passato aLoadLibraryA). - Nessun Nuovo Thread: L’attaccante evita deliberatamente di chiamare
CreateThread; il DllMain della DLL viene eseguito nel contesto del processo corrente, soddisfacendo la clausola di esclusione della regola.
- Accesso Iniziale: L’attaccante consegna un file JavaScript malevolo (
-
Script di Test di Regressione:
# ------------------------------------------------- # NWHStealer JavaScript Loader – Demo di Autoiniezione # ------------------------------------------------- # Questo script imita il comportamento del vero loader NWHStealer. # Chiama deliberatamente VirtualAlloc, VirtualProtect e LoadLibraryA # senza invocare CreateThread. # 1. Definizione delle firme API Win32 $sig = @" using System; using System.Runtime.InteropServices; public class Win32 { [DllImport("kernel32.dll", SetLastError=true)] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll", SetLastError=true)] public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect); [DllImport("kernel32.dll", CharSet=CharSet.Ansi, SetLastError=true)] public static extern IntPtr LoadLibraryA(string lpFileName); } "@ Add-Type $sig # 2. Alloca memoria eseguibile (RWX) $size = 0x1000 $MEM_COMMIT = 0x1000 $PAGE_EXECUTE_READWRITE = 0x40 $mem = [Win32]::VirtualAlloc([IntPtr]::Zero, $size, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) if ($mem -eq [IntPtr]::Zero) { throw "VirtualAlloc failed" } # 3. Esempio di shellcode (MessageBox) – codificato in base64 per leggibilità $b64 = "AQAAANAAAABAAEAAAABAAAAAgAAAAEAAABWAAAAAQAAAAIAAAD/////AQAAAAAAAAA=" $shellcode = [Convert]::FromBase64String($b64) # 4. Copia lo shellcode nella regione allocata [System.Runtime.InteropServices.Marshal]::Copy($shellcode, 0, $mem, $shellcode.Length) # 5. Cambia protezione a EXECUTE_READ $oldProtect = 0 $PAGE_EXECUTE_READ = 0x20 $ok = [Win32]::VirtualProtect($mem, $size, $PAGE_EXECUTE_READ, [ref]$oldProtect) if (-not $ok) { throw "VirtualProtect failed" } # 6. Carica la "DLL" in memoria (qui semplicemente chiamiamo LoadLibraryA su kernel32 come segnaposto) # Nel vero loader sarebbe una DLL personalizzata scritta in $mem. $hLib = [Win32]::LoadLibraryA("kernel32.dll") if ($hLib -eq [IntPtr]::Zero) { throw "LoadLibraryA failed" } Write-Host "Passaggi di autoiniezione completati – il processo dovrebbe ora essere segnalato dalla regola di rilevamento." # ------------------------------------------------- -
Comandi di Pulizia:
# Termina l'istanza di PowerShell che ha eseguito l'iniezione Stop-Process -Id $PID -Force # (Opzionale) Se una DLL personalizzata è stata scritta su disco per test, rimuovila Remove-Item -Path "$env:TEMPmalicious.dll" -ErrorAction SilentlyContinue
Validazione Post-Esecuzione
-
Conferma Generazione di Allerta: Esegui la seguente query KQL per verificare che la regola si sia attivata:
// Regola di rilevamento: VirtualAlloc/VirtualProtect/LoadLibraryA senza CreateThread Sysmon | dove EventID == 1 | dove CallTrace contiene "VirtualAlloc" o CallTrace contiene "VirtualProtect" o CallTrace contiene "LoadLibraryA" | dove non(CallTrace contiene "CreateThread") | project TimeGenerated, Process, CallTrace, EventID -
Verifica Nessun Falso Positivo: Riesegui il comando benigno di Notepad e assicurati che la query restituisca zero risultati per quella esecuzione.
Fine del Rapporto