Dokumentation
/
Rezepte
/

VM-Abwehr: Telemetrie & Reaktionen

VM-Abwehr: Telemetrie & Reaktionen

Pro
v7.4.0+

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 zu einem, der bei einem gestohlenen Bundle sofort abbricht.

Ansehen

Obfuscator.io Defense Reactions: Break, Decoy, and the VM Defense Hook

Auf YouTube ansehen

Das Problem

Die VM-Abwehrmaßnahmen - 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.

Zwei Optionen schließen 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, täuschen oder lokal nichts tun.

Beide Optionen wurden in v7.1.0 eingeführt, aber alle Beispiele hier verwenden die Objektform vmDefenseHook: { name }, die v7.4.0 erfordert. Frühere Versionen erwarteten einen bloßen String (vmDefenseHook: '__vmDetection'); diese Form wird ab v8.0.0 abgelehnt, verwenden Sie daher durchgehend die Objektform.

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 Abwehrmaßnahmen 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 Script-Tag des obfuskierten Codes:

HTML

Schritt 2 - vmDefenseHook darauf verweisen lassen

Die Option ist ein Objekt, dessen name die aufzurufende globale Funktion angibt (aliases ist optional - siehe unten):

JavaScript

Im Dashboard erscheint das Feld VM Defense Hook im Bereich Erweiterter Schutz, 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, agentBrowser, domain, debugger, sandbox, nativeHook, timing oder integrity. Seit v7.4.0 melden die früheren Detektoren env und inspector unter source: 'debugger'. agentBrowser meldet unter category: 'automation' und läuft auf Browser-Targets mit vmDebugProtection (v7.9.0+).
  • category - automation, debugger, sandbox, domain, tamper oder integrity. Die Quelle node meldet unter category: '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:

JavaScript

Der Hook dient nur der Meldung - sein Rückgabewert wird ignoriert, und ein fehlender oder fehlerwerfender Hook bleibt stillschweigend wirkungslos. Er kann niemals eine Abwehrmaßnahme deaktivieren, ein Angreifer gewinnt also nichts, wenn er Ihren Hook löscht oder beschädigt. Um zu ändern, was eine Abwehrmaßnahme tut, verwenden Sie vmDefenseReaction (Rezept 2).

Definieren Sie den Hook in der Host-Seite, nicht innerhalb des obfuskierten Quellcodes

Bei Telemetrie möchten Sie jede Erkennung erfassen, und viele lösen bereits beim Start aus - ein innerhalb des obfuskierten Bundles definierter Hook wird zu spät registriert, um diese zu erfassen, und wenn er per VM kompiliert wird, ist er erst erreichbar, sobald Ihr Programm läuft. Sicher bleibt es in beiden Fällen (ein fehlender Hook bleibt wirkungslos, und ein Hook, der selbst eine Erkennung auslöst, wird nicht erneut rekursiv aufgerufen), aber für vollständige Abdeckung registrieren Sie ihn vorab in der Host-Seite.

Die einzige Ausnahme ist ein Hook, der nur auf eine Laufzeiterkennung reagiert - etwa das Aufräumen, wenn während der Nutzung ein Debugger geöffnet wird. Ein solcher Hook kann innerhalb des obfuskierten Bundles liegen; siehe Rezept 3.

Um Ihre Meldelogik dennoch zu schützen, halten Sie den registrierten Hook als einzeiligen Puffer und leeren Sie ihn aus Ihrem obfuskierten Code heraus:

JavaScript

JavaScript

Die Signalfelder umbenennen (Aliase)

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.

JavaScript

Im Dashboard steht der Abschnitt Signal-Aliase unterhalb des Felds VM Defense Hook.

Das dient der Vermeidung von Fingerabdrücken, nicht der Geheimhaltung - die Zuordnung lässt sich durch wiederholtes Testen weiterhin erschließen, ihr einziger Nutzen besteht also darin, keine stabilen, selbsterklärenden Namen preiszugeben.

Rezept 2 - die Standardreaktionen anpassen

vmDefenseReaction legt fest, wie jede Erkennungskategorie reagiert. Die Option aktiviert nichts - die Abwehrmaßnahmen 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.

KategorieAktiviert durchReagiert, wenn
automationvmSelfDefending oder vmDebugProtectionDer 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.
debuggervmDebugProtection oder vmSelfDefendingJemand hat einen Debugger oder den Inspector der Browser-Entwicklerwerkzeuge geöffnet und geht den laufenden Code Schritt für Schritt durch, um ihn zu verstehen.
sandboxvmDebugProtectionDer 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.
domainvmDomainLockDer Code läuft auf einer Website, die Sie nicht autorisiert haben: einem Host, der nicht in der Zulassungsliste von vmDomainLock steht (etwa Ihr Bundle, das auf die Domain einer anderen Person kopiert wurde).
tampervmSelfDefendingDie 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.
integrityvmSelfDefendingDer 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 abbrechen
  • decoy - mit vergiftetem Zustand weiterlaufen und stillschweigend falsche Ergebnisse liefern. decoy erfordert vmDebugProtection oder vmDomainLock auf einem Browser-Target; andernfalls verhält es sich wie break.
  • none - lokal nichts tun (nur Telemetrie)

Eine Kategorie, die Sie nicht setzen, fällt auf die eingebauten Standardwerte zurück:

JavaScript

default greift für jede Kategorie, integrity und tamper eingeschlossen; { default: 'none' } ergibt also einen wirklich unterbrechungsfreien, rein telemetrischen Build:

JavaScript

JavaScript

Im Dashboard erscheinen die Auswahlfelder VM Defense Reactions im Bereich Erweiterter Schutz, sobald eine Abwehrmaßnahme aktiviert ist; jede Kategorie ist nur bearbeitbar, solange eine Abwehrmaßnahme aktiv ist, die deren Detektoren ausgibt.

Rezept 3 - eigene Logik ausführen, bevor eine Abwehrmaßnahme abbricht

Der Hook dient nicht nur der Meldung - er ist auch die einzige verlässliche Stelle, um Ihre eigene Reaktion vor dem Reagieren einer Abwehrmaßnahme auszuführen. Wenn auf einer laufenden Seite ein Debugger geöffnet wird, möchten Sie vielleicht das Angezeigte löschen oder die Ansicht durch eine 404-Seite ersetzen, bevor der Code abbricht.

Warum der Hook statt Code an anderer Stelle in Ihrer Anwendung: break stoppt allen nachfolgenden Bytecode, ein Aufräumvorgang, der nach dem Auslösen einer Abwehrmaßnahme läuft - besonders wenn er selbst VM-obfuskiert ist -, ist also genau das, was der Abbruch an der Ausführung hindert. Der Hook wird an der Erkennungsstelle vor der Ausführung der Reaktion ausgelöst, und zwar synchron - eine synchrone Funktion, die er aufruft, wird also zuerst fertig, dann stoppt break die VM.

Definieren Sie die Reaktion als Ihren vmDefenseHook. Da die debugger-Erkennung zur Laufzeit auslöst - nachdem Ihr Programm geladen wurde und den Hook definiert hat -, kann der Hook Teil Ihres obfuskierten Quellcodes sein und wird zusammen mit dem Rest des Bundles per Bytecode kompiliert. Verzweigen Sie über signal.category, damit jede Bedingung die richtige Reaktion erhält, halten Sie die Arbeit synchron und lassen Sie dann die Reaktion laufen:

JavaScript

JavaScript

Das gilt für Erkennungen, die auslösen, während Ihre Anwendung läuft - siehe Wann das Bytecode-Kompilieren des Hooks funktioniert unten.

Beachten Sie dabei folgende Punkte:

  • Nur synchrone Arbeit ist garantiert zuerst abgeschlossen. Die Reaktion läuft bei der Anweisung unmittelbar nachdem der Hook zurückkehrt. Fire-and-Forget-Aufrufe, die sofort übergeben, sind in Ordnung (navigator.sendBeacon, synchrone DOM- und Canvas-Änderungen); Arbeit, die Sie auf später einplanen - ein setTimeout, eine Promise-Fortsetzung, ein await -, ist es nicht, und alles, was weiteren VM-Bytecode benötigt, wird nicht ausgeführt, denn genau das stoppt break.
  • Der Hook läuft vor der Reaktion; er ersetzt sie nicht. Sein Rückgabewert wird ignoriert, und er kann nicht abbrechen, verzögern oder ändern, was die Reaktion tut. Nutzen Sie ihn, um vor dem Abbruch zu handeln, nicht um ihn zu verhindern - um die Reaktion selbst zu ändern, verwenden Sie vmDefenseReaction (Rezept 2).

Wann das Bytecode-Kompilieren des Hooks funktioniert

Den Hook auf diese Weise in das obfuskierte Bundle zu legen, funktioniert nur, weil die debugger-Erkennung zur Laufzeit auslöst. Die VM löst vmDefenseHook aus, während sie noch aktiv ist, nachdem Ihr Programm geladen wurde und den Hook definiert hat, sodass der per Bytecode kompilierte Hook zuerst decodiert und ausgeführt wird, dann break. Genau das schützt den Quellcode des Hooks selbst.

Es funktioniert nicht für Erkennungen, die beim Start auslösen - automation, sandbox, domain oder ein bereits beim Laden der Seite geöffneter Debugger -, denn zu diesem Zeitpunkt ist der per Bytecode kompilierte Hook noch nicht definiert, sodass die Abwehrmaßnahme keine Funktion zum Aufrufen findet. Registrieren Sie den Hook für solche Fälle stattdessen als einfache globale Funktion in der Host-Seite, wie in Rezept 1. Im Zweifel deckt eine einfache globale Funktion in der Host-Seite jede Erkennung ab, die den Hook erreicht; das Bytecode-Kompilieren fügt nur Schutz für den Quellcode des Hooks selbst hinzu, und das nur für Laufzeiterkennungen.

Von der Telemetrie zur Durchsetzung

Sichtbarkeit und Durchsetzung müssen nicht gemeinsam ausgeliefert werden. Rollen Sie die Abwehrmaßnahmen in zwei Stufen aus: zuerst einen Build, 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, aber nichts bricht ab:

JavaScript

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 Abwehrmaßnahmen, statt die Kategorie in der Produktion zu dulden.
  • domain-Treffer von einem Staging- oder Preview-Host, den Sie in der Zulassungsliste von vmDomainLock 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, den ein Angreifer gefahrlos ignorieren kann.

Schritt 3 - die Reaktionen einschalten

Entfernen Sie die Überschreibung default: 'none', damit die eingebauten Reaktionen pro Kategorie gelten; diese eine Zeile ist die gesamte Umstellung. 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.

Behalten Sie vmDefenseHook auch nach dem Einschalten der Durchsetzung bei - der Hook wird unabhängig von der Reaktion ausgelöst, sodass Sie weiterhin sehen, wer Ihr Bundle sondiert, während die Abwehrmaßnahmen wirken.