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 zu einem, der bei einem gestohlenen Bundle sofort abbricht.
Ansehen
Obfuscator.io Defense Reactions: Break, Decoy, and the VM Defense Hook
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:
Schritt 2 - vmDefenseHook darauf verweisen lassen
Die Option ist ein Objekt, dessen name die aufzurufende globale Funktion angibt (aliases ist optional - siehe unten):
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,timingoderintegrity. Seit v7.4.0 melden die früheren Detektorenenvundinspectoruntersource: 'debugger'.agentBrowsermeldet untercategory: 'automation'und läuft auf Browser-Targets mitvmDebugProtection(v7.9.0+).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:
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:
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.
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.
| 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 Inspector 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 der Zulassungsliste von vmDomainLock 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 liefern.decoyerfordertvmDebugProtectionodervmDomainLockauf einem Browser-Target; andernfalls verhält es sich wiebreak.none- lokal nichts tun (nur Telemetrie)
Eine Kategorie, die Sie nicht setzen, fällt auf die eingebauten Standardwerte zurück:
default greift für jede Kategorie, integrity und tamper eingeschlossen; { default: 'none' } ergibt also einen wirklich unterbrechungsfreien, rein telemetrischen Build:
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:
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 - einsetTimeout, eine Promise-Fortsetzung, einawait-, ist es nicht, und alles, was weiteren VM-Bytecode benötigt, wird nicht ausgeführt, denn genau das stopptbreak. - 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:
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 vonvmDomainLockvergessen 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.
