SOC Prime Bias: Medium

08 Mai 2026 18:33

NWHStealer Verbreitung durch Bun JavaScript Runtime

Author Photo
SOC Prime Team linkedin icon Folgen
NWHStealer Verbreitung durch Bun JavaScript Runtime
shield icon

Detection stack

  • AIDR
  • Alert
  • ETL
  • Query

Zusammenfassung

Der Artikel erklärt, wie Bedrohungsakteure die Bun-JavaScript-Laufzeit nutzen, um den Rust-basierten Infostealer NWHStealer zu verbreiten. Bösartige ZIP-Archive enthalten einen Hauptinstaller, der einen Bun-verpackten JavaScript-Loader zusammen mit einem sekundären Loader namens dw.exe startet. Die JavaScript-Komponente führt Anti-Virtualisierungstests durch, greift auf die Kommando-und-Kontroll-Infrastruktur zu, entschlüsselt eine Folge-Payload und missbraucht native Windows-APIs, um den Stealer in den Speicher zu injizieren. Um Verdacht zu reduzieren, versteckt die Kampagne bösartige Dateien hinter legitimen Hosting-Plattformen wie GitHub, MediaFire und SourceForge.

Untersuchung

Forscher fanden heraus, dass Bun verwendet wurde, um bösartigen JavaScript-Code innerhalb des .bun -Abschnitts des Loaders zu verpacken. Zwei Skripte, sysreq.js and memload.js, behandelten Umgebungstests und die Kommunikation mit der Angreifer-Infrastruktur. Der Loader rief Konfigurationsdaten und verschlüsselte Payloads von Domains wie silent-harvester.cc ab, entschlüsselte sie mit AES-256-CBC und injizierte sie durch Win32-API-Aufrufe. Die endgültige Payload war der NWHStealer, der Anmeldeinformationen, Browserdaten und Kryptowährungs-Wallet-Informationen stiehlt und auch zusätzliche Mining-Aktivitäten starten kann.

Abmilderung

Benutzer sollten das Herunterladen von ausführbaren Dateien von nicht vertrauenswürdigen Websites vermeiden und Installationssignaturen vor der Ausführung überprüfen. Sicherheitsteams sollten ungewöhnliche Aktivitäten der Bun-Laufzeit, PowerShell-CIM-Abfragen, die für Virtualisierungstests verwendet werden, und verdächtige API-Aufrufe wie VirtualAlloc and LoadLibraryA überwachen. Organisationen sollten auch die bekannten bösartigen Domains blockieren und Mindestprivileg-Ausführungsrichtlinien durchsetzen, um Missbrauch zu begrenzen.

Reaktion

Wird diese Aktivität entdeckt, sollte der betroffene Endpunkt isoliert, Speicher- und Festplatten-Images gesammelt und nach Installer.exe, dw.exe und verdächtigen .bun Abschnitten gesucht werden. Blockieren Sie die identifizierten Kommando-und-Kontroll-Domains und URLs an der Netzwerkperipherie. Implementieren Sie Endpunkt-Erkennungen für die beobachteten PowerShell-Befehle und Win32-API-Muster. Erneuern Sie exponierte Anmeldeinformationen und überwachen Sie betroffene Systeme auf Anzeichen von unbefugtem Kryptowährungs-Mining.

graph TB %% Klassendefinitionen classDef technique fill:#ffcc99 classDef action fill:#99ccff %% Knoten node_initial_access[„<b>Initialer Zugriff</b><br/><b>T1036.008 Verschleierung: Dateityp</b>: Schädliches ZIP, als harmlose Datei getarnt.<br/><b>T1204.002 Benutzerausführung: Schädliche Datei</b>: Der Benutzer führt die heruntergeladene Datei aus.“] class node_initial_access technique node_obfuscated_loader[„<b>Obfuszierter Loader</b><br/><b>T1027.016 Junk-Code-Einfügung</b>: Einfügen irrelevanten JavaScripts zur Verschleierung der Logik.<br/><b>T1027.008 Entfernung von Payload-Teilen</b>: Entfernen nicht essenzieller Teile zur Analyseumgehung.“] class node_obfuscated_loader technique node_discovery[„<b>Aufklärung</b><br/><b>T1082 Systeminformationen sammeln</b>: Betriebssystem-, Hardware- und Softwaredaten.<br/><b>T1016 Netzwerk-Konfigurationsaufklärung</b>: IP-Adressen, Adapter und Routing-Informationen.“] class node_discovery technique node_credential_access[„<b>Credential Access</b><br/><b>T1555.003 Browser-Zugangsdaten</b>: Extraktion gespeicherter Passwörter und Autofill-Daten.<br/><b>T1550.004 Nutzung alternativer Authentifizierungsdaten</b>: Diebstahl von Session-Cookies.“] class node_credential_access technique node_c2[„<b>Command & Control</b>: Abruf eines AES-Schlüssels und verschlüsselter Payload vom Remote-Server.“] class node_c2 action node_execution[„<b>Ausführung</b><br/><b>T1620 Reflektives Code-Laden</b>: Ausführung im Speicher ohne Festplatten-Schreibzugriff.<br/><b>T1055.009 Prozessinjektion</b>: Einschleusen von Code in laufenden Prozess.“] class node_execution technique node_persistence[„<b>Persistenz</b><br/><b>T1053 Geplante Aufgabe</b>: Erstellung einer geplanten Aufgabe zur wiederholten Ausführung.“] class node_persistence technique %% Verbindungen node_initial_access –>|führt zu| node_obfuscated_loader node_obfuscated_loader –>|führt zu| node_discovery node_discovery –>|führt zu| node_credential_access node_credential_access –>|führt zu| node_c2 node_c2 –>|führt zu| node_execution node_execution –>|führt zu| node_persistence

Angriffsablauf

Simulationsausführung

Voraussetzung: Der Telemetrie- & Baseline-Pre‑flight-Check muss bestanden haben.

Begründung: Dieser Abschnitt beschreibt die genaue Ausführung der gegnerischen Technik (TTP), die darauf abzielt, die Erkennungsregel auszulösen. Die Befehle und das Narrativ MÜSSEN direkt die identifizierten TTPs widerspiegeln und darauf abzielen, die genaue Telemetrie zu erzeugen, die von der Erkennungslogik erwartet wird. Abstrakte oder nicht verwandte Beispiele führen zu Fehldiagnosen.

  • Angriffs-Narrativ & Befehle:

    1. Erster Zugriff: Der Angreifer liefert eine bösartige JavaScript-Datei (loader.js) auf das Opfersystem und führt sie mit der bun Laufzeit (bun loader.js).
    2. Selbsteinjektionsroutine: Der JavaScript-Code ruft native Win32-APIs über einen PowerShell-Helfer auf, der Add‑Type verwendet, um P/Invoke-Signaturen zu definieren für VirtualAlloc, VirtualProtect, und LoadLibraryA.
    3. Speicherallokation: VirtualAlloc reserviert eine RWX-Region in der Größe für den eingebetteten Shellcode.
    4. Shellcode-Injektion: Das PowerShell-Skript kopiert den base64-codierten Shellcode in den zugewiesenen Speicher mit Marshal.Copy.
    5. Berechtigungsänderung: VirtualProtect ändert den Seitenschutz in PAGE_EXECUTE_READ.
    6. Payload-Ausführung: LoadLibraryA wird auf eine bösartige DLL angewendet, die nur im Speicher residiert (der DLL-Header wird in die zugewiesene Region geschrieben, dann wird die Adresse an LoadLibraryA).
    7. Kein neuer Thread: Der Angreifer vermeidet bewusst den Aufruf von CreateThread; DllMain der DLL wird im Kontext des aktuellen Prozesses ausgeführt, was die Ausschlussklausel der Regel erfüllt.
  • Regressionstest-Skript:

    # -------------------------------------------------
    # NWHStealer JavaScript Loader – Selbsteinjektionsdemo
    # -------------------------------------------------
    # Dieses Skript imitiert das Verhalten des echten NWHStealer-Loaders.
    # Es ruft absichtlich VirtualAlloc, VirtualProtect und LoadLibraryA
    # auf, ohne CreateThread zu verwenden.
    
    # 1. Win32-API-Signaturen definieren
    $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. Ausführbaren Speicher zuweisen (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. Beispiel-Shellcode (MessageBox) – base64-codiert zur besseren Lesbarkeit
    $b64 = "AQAAANAAAABAAEAAAABAAAAAgAAAAEAAABWAAAAAQAAAAIAAAD/////AQAAAAAAAAA="
    $shellcode = [Convert]::FromBase64String($b64)
    
    # 4. Shellcode in zugewiesenen Bereich kopieren
    [System.Runtime.InteropServices.Marshal]::Copy($shellcode, 0, $mem, $shellcode.Length)
    
    # 5. Schutz auf EXECUTE_READ ändern
    $oldProtect = 0
    $PAGE_EXECUTE_READ = 0x20
    $ok = [Win32]::VirtualProtect($mem, $size, $PAGE_EXECUTE_READ, [ref]$oldProtect)
    if (-not $ok) { throw "VirtualProtect failed" }
    
    # 6. Die im Speicher befindliche "DLL" laden (hier rufen wir einfach LoadLibraryA auf kernel32 als Platzhalter auf)
    # Im echten Loader wäre dies eine benutzerdefinierte DLL, die in $mem geschrieben wurde.
    $hLib = [Win32]::LoadLibraryA("kernel32.dll")
    if ($hLib -eq [IntPtr]::Zero) { throw "LoadLibraryA failed" }
    
    Write-Host "Selbsteinjektionsschritte abgeschlossen – Der Prozess sollte jetzt von der Erkennungsregel gekennzeichnet werden."
    # -------------------------------------------------
  • Bereinigungskommandos:

    # Beenden Sie die PowerShell-Instanz, die die Injektion durchgeführt hat
    Stop-Process -Id $PID -Force
    
    # (Optional) Wenn eine benutzerdefinierte DLL zum Testen auf die Festplatte geschrieben wurde, entfernen Sie sie
    Remove-Item -Path "$env:TEMPmalicious.dll" -ErrorAction SilentlyContinue

Post-Execution Validierung

  1. Alarmgenerierung bestätigen: Führen Sie die folgende KQL-Abfrage aus, um zu überprüfen, ob die Regel ausgelöst wurde:

     // Erkennungsregel: VirtualAlloc/VirtualProtect/LoadLibraryA ohne CreateThread
     Sysmon
     | where EventID == 1
     | where CallTrace contains "VirtualAlloc" or CallTrace contains "VirtualProtect" or CallTrace contains "LoadLibraryA"
     | where not(CallTrace contains "CreateThread")
     | project TimeGenerated, Process, CallTrace, EventID
  2. Keine False-Positiv bestätigen: Führen Sie den harmlosen Notepad-Befehl erneut aus und stellen Sie sicher, dass die Abfrage null Ergebnisse für diesen Lauf zurückgibt.


Ende des Berichts