VM-Abwehr - Telemetrie & Reaktionen
Melden Sie Erkennungen der VM-Abwehr mit vmDefenseHook an Ihr Backend und steuern Sie mit vmDefenseReaction, wie jede Erkennungskategorie reagiert - von einem völlig unterbrechungsfreien, rein telemetrischen Build bis zum harten Abbruch bei einem gestohlenen Bundle.
Das Problem
Die VM-Abwehrmechanismen – vmSelfDefending, vmDebugProtection und vmDomainLock – wirken lokal: Wird ein Debugger, ein Automatisierungswerkzeug, eine manipulierte Umgebung oder eine nicht autorisierte Domain erkannt, bricht der geschützte Code ab oder vergiftet stillschweigend seine eigenen Ergebnisse. Das stoppt den Angreifer, aber standardmäßig erfahren Sie nie davon. Sie können nicht erkennen, wie oft Ihr Bundle sondiert wird, welcher Detektor ausgelöst hat oder ob eine Abwehrmaßnahme einem legitimen Nutzer im Weg steht.
Seit v7.1.0 schließen zwei Optionen diese Lücke. Keine von beiden aktiviert eine Abwehrmaßnahme – sie beobachten und steuern lediglich die Mechanismen, die Sie bereits eingeschaltet haben:
vmDefenseHook– ein globaler Callback, der bei jeder Erkennung ein Signalobjekt erhält. Nutzen Sie ihn, um Telemetriedaten an Ihr Backend zu senden.vmDefenseReaction– eine Zuordnung pro Kategorie, die festlegt, wie eine aktivierte Abwehrmaßnahme reagiert: abbrechen, vergiften oder lokal nichts tun.
Rezept 1 – Erkennungen an Ihr Backend melden
Schritt 1 – eine globale Hook-Funktion registrieren, bevor das obfuskierte Bundle geladen wird
Die VM-Laufzeit und ihre Abwehrmechanismen laufen vor Ihrem geschützten Programm, sodass viele Erkennungen bereits beim Start auslösen. Definieren Sie den Hook als einfache globale Funktion in der Host-Seite, noch vor dem Skript-Tag des obfuskierten Codes:
<script>
// In your page, BEFORE the obfuscated script:
window.__vmDetection = function (signal) {
navigator.sendBeacon('/api/vm-defense', JSON.stringify(signal));
};
</script>
<script src="/app.obfuscated.js"></script>
Schritt 2 – vmDefenseHook darauf verweisen lassen
Die Option ist ein Objekt, dessen name die aufzurufende globale Funktion angibt (aliases ist optional – siehe unten):
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
// the hook alone enables nothing - a defense must be on for detectors to run:
vmSelfDefending: true,
vmDebugProtection: true,
vmDefenseHook: { name: '__vmDetection' }
});
Die Kurzform als reine Zeichenkette (vmDefenseHook: '__vmDetection') wird weiterhin als Abkürzung für { name: '__vmDetection' } akzeptiert, ist aber veraltet – bevorzugen Sie die Objektform.
Im Dashboard erscheint das Feld VM Defense Hook im VM-Optionsbereich, sobald mindestens eine Abwehrmaßnahme (vmSelfDefending, vmDebugProtection oder vmDomainLock) aktiviert ist.
Schritt 3 – das Signal auf Ihrem Backend entgegennehmen
Jede Erkennung ruft den Hook mit einem einzelnen signal-Objekt auf:
source– der konkrete Detektor:headless,node,agent,domain,debugger,sandbox,nativeHook,timingoderintegrity. Seit v7.4.0 melden die früheren Detektorenenvundinspectoruntersource: 'debugger'.category–automation,debugger,sandbox,domain,tamperoderintegrity. Die Quellenodemeldet untercategory: 'debugger'(v7.4.0+).score,threshold– der Erkennungswert und der überschrittene Schwellenwert
Ein minimaler empfangender Endpunkt (hier mit Express; jedes Backend, das ein POST annimmt, funktioniert). Er normalisiert den Body zu einem Array und verarbeitet damit auch die gebündelte Form, die das weiter unten beschriebene Puffer-Muster sendet:
app.post('/api/vm-defense', express.text({ type: '*/*' }), (req, res) => {
// a signal: { source: 'headless', category: 'automation', score: 7, threshold: 4 }
const signals = [].concat(JSON.parse(req.body));
for (const signal of signals) {
console.warn('vm-defense', { ...signal, ip: req.ip, ua: req.get('user-agent') });
}
res.sendStatus(204);
});
Die Signalfelder umbenennen (Aliase) v7.4.0+
Die voreingestellten Werte von source und category sind sprechende Namen, sodass jeder, der den Callback instrumentiert (oder die Ausgabe liest), den Schutz und den auslösenden Detektor erkennen kann. aliases benennt Signalfelder in undurchsichtige Tokens Ihrer Wahl um, und zwar innerhalb der VM bevor das Signal ausgegeben wird – diese Namen tauchen also weder in der Ausgabe auf noch erreichen sie den Callback. Ihre Anwendung kennt ihre eigene Zuordnung und leitet die Tokens an Ihr Backend weiter.
Aliase werden pro Feld vergeben: Jedes nimmt einen key entgegen (den Eigenschaftsnamen, den der Callback erhält); die String-Namensfelder source und category nehmen zusätzlich eine values-Zuordnung entgegen, während score und threshold Zahlen sind und nur einen key annehmen. Nicht gesetzte Einträge behalten ihre Standardnamen.
vmDefenseHook: {
name: '__vmDetection',
aliases: {
source: { key: 'a8Qm', values: { headless: 'xP4m9Q' } },
category: { key: 'p3Tx', values: { automation: 'bQ7s1M' } },
score: { key: 's1' },
threshold: { key: 't1' }
}
// the callback now receives e.g. { a8Qm: 'xP4m9Q', p3Tx: 'bQ7s1M', s1: <score>, t1: <threshold> }
}
Im Dashboard steht der Abschnitt Signal-Aliase unterhalb des Felds VM Defense Hook.
Rezept 2 – die Standardreaktionen anpassen
vmDefenseReaction legt fest, wie jede Erkennungskategorie reagiert. Die Option aktiviert nichts – die Abwehrmechanismen selbst werden über vmSelfDefending, vmDebugProtection und vmDomainLock eingeschaltet; diese Option wählt lediglich aus, wie eine aktivierte Abwehrmaßnahme reagiert. Die Steuerungseinheit ist die Kategorie: Jeder Detektor einer Kategorie setzt die Reaktion dieser Kategorie um, und eine Reaktion für eine Kategorie, deren Option ausgeschaltet ist, bleibt schlicht wirkungslos.
| Kategorie | Aktiviert durch | Reagiert, wenn |
|---|---|---|
automation | vmSelfDefending oder vmDebugProtection | Der Code wird von Software statt von einem Menschen gesteuert: ein Headless- oder automatisierter Browser, ein Scraping- oder Test-Framework oder ein KI-Coding-Agent, der die Seite durchschreitet. |
debugger | vmDebugProtection oder vmSelfDefending | Jemand hat einen Debugger oder den Inspektor der Browser-Entwicklerwerkzeuge geöffnet und geht den laufenden Code Schritt für Schritt durch, um ihn zu verstehen. |
sandbox | vmDebugProtection | Der Code läuft überhaupt nicht in einem echten Browser – er wurde in eine emulierte oder skriptgesteuerte JavaScript-Umgebung übertragen, um ihn dort offline auszuführen und zu untersuchen. |
domain | vmDomainLock | Der Code läuft auf einer Website, die Sie nicht autorisiert haben: einem Host, der nicht in Ihrer vmDomainLock-Freigabeliste steht (etwa Ihr Bundle, das auf die Domain einer anderen Person kopiert wurde). |
tamper | vmSelfDefending | Die JavaScript-Umgebung rund um die VM wurde verändert, um sie zu beobachten oder zu kapern – etwa indem native Browser-Builtins gegen instrumentierte Versionen ausgetauscht wurden. |
integrity | vmSelfDefending | Der Code des geschützten Bundles selbst wurde seit der Erzeugung bearbeitet oder gepatcht. |
Als Schlüssel dienen diese sechs Kategorienamen oder default (ein Rückfallwert für nicht angegebene Kategorien). Mögliche Werte sind:
break– sofort abbrechendecoy– mit vergiftetem Zustand weiterlaufen und stillschweigend falsche Ergebnisse liefernnone– lokal nichts tun (nur Telemetrie)
Eine Kategorie, die Sie nicht setzen, fällt auf die eingebauten Standardwerte zurück:
// built-in defaults
vmDefenseReaction: {
automation: 'break',
debugger: 'decoy',
sandbox: 'decoy',
domain: 'break',
tamper: 'break',
integrity: 'break'
}
default greift für jede Kategorie, auch für die konstruktionsbedingt eindeutigen (integrity, tamper); { default: 'none' } ergibt also einen wirklich unterbrechungsfreien, rein telemetrischen Build:
vmDefenseReaction: { default: 'none' } // never break - pair with vmDefenseHook
vmDefenseReaction: { automation: 'none' } // tolerate automation FPs; the rest keep their defaults (a bad domain still breaks)
Im Dashboard erscheinen die Auswahlfelder VM Defense Reactions im VM-Optionsbereich, sobald eine Abwehrmaßnahme aktiviert ist; jede Kategorie ist nur bearbeitbar, solange eine Abwehrmaßnahme aktiv ist, die deren Detektoren ausgibt.
Von der Telemetrie zur Durchsetzung
Sie müssen sich nicht von Tag eins an zwischen Sichtbarkeit und Durchsetzung entscheiden. Rollen Sie die Abwehrmechanismen in zwei Builds aus: zuerst einen, der nur meldet, und dann – sobald die Telemetrie sauber aussieht – einen, der reagiert.
Schritt 1 – einen rein beobachtenden Build ausliefern
Aktivieren Sie jede Abwehrmaßnahme, die Sie einsetzen möchten, richten Sie vmDefenseHook auf Ihren Endpunkt und schalten Sie alle Reaktionen ab. Jeder Detektor läuft weiterhin und meldet jeden Treffer an Ihr Backend – er bricht nur nie etwas ab:
JavaScriptObfuscator.obfuscate(source, {
vmObfuscation: true,
vmSelfDefending: true,
vmDebugProtection: true,
vmDomainLock: ['example.com'],
vmDefenseHook: '__vmDetection',
vmDefenseReaction: { default: 'none' } // observe only
});
Schritt 2 – die gesammelten Signale auswerten
Nachdem der Build echten Datenverkehr gesehen hat, achten Sie auf Erkennungen, die durch legitime Nutzung ausgelöst wurden. Die beiden häufigsten:
automation-Treffer aus Ihren eigenen End-to-End-Tests oder Ihrem Uptime-Monitoring – erzeugen Sie diese Artefakte ohne die Abwehrmechanismen, statt die Kategorie in der Produktion zu dulden.domain-Treffer von einem Staging- oder Preview-Host, den Sie in dervmDomainLock-Freigabeliste vergessen haben – tragen Sie den Host nach.
Beheben Sie lieber die Ursache, als eine Reaktion abzuschwächen: Jede Kategorie, die auf none stehen bleibt, ist ein Detektor, um den sich ein Angreifer nicht mehr kümmern muss.
Schritt 3 – die Reaktionen einschalten
Entfernen Sie die Überschreibung default: 'none', damit die eingebauten Reaktionen pro Kategorie gelten – die gesamte Umstellung ist diese eine Zeile. Falls eine Kategorie weiterhin Fehlalarme erzeugt, die Sie nicht beseitigen können, belassen Sie genau diese Kategorie auf none (z. B. vmDefenseReaction: { automation: 'none' }) und setzen Sie die übrigen durch.
