Dokumentation
/
VM-Obfuskierung
/

Register-Based VM

Register-Based VM

Pro
v7.12.0+

Schalten Sie die VM auf ein registerbasiertes Ausführungsmodell um, für eine schnellere Laufzeit und eine VM-Struktur, die sich von der Standardvariante unterscheidet.

Die Option vmRegisterBased schaltet die VM von ihrem standardmäßigen stapelbasierten Bytecode auf ein registerbasiertes Ausführungsmodell um. In manchen Fällen verbessert dies die Laufzeitperformance der VM um etwa 10-20 %, auf Kosten eines etwas größeren obfuskierten Bundles.

Das Aktivieren schaltet Stateful Opcodes (vmStatefulOpcodes) aus: Die beiden sind nicht miteinander vereinbar, daher verwirft der registerbasierte Build vmStatefulOpcodes stillschweigend, falls es aktiviert war.

Stapelbasiert vs. registerbasiert

Eine stapelbasierte VM hält Operanden auf einem impliziten Stapel: Jeder Wert wird abgelegt, von der nächsten Anweisung verbraucht, und das Ergebnis wird wieder abgelegt. Eine registerbasierte VM adressiert ihre Operanden dagegen direkt, sodass dieselbe Arbeit mit weniger Anweisungen und ohne Push/Pop-Verkehr dazwischen ausgedrückt wird. Daher kommt der Laufzeitgewinn, und deshalb wächst auch der Bytecode leicht: Jede Anweisung muss nun ausdrücklich angeben, welche Register sie liest und schreibt, statt dies implizit dem Stapel zu überlassen.

Keines der beiden Modelle ändert, was Ihr Code tut oder was die VM schützt. Es sind zwei Codierungen derselben virtualisierten Logik; die registerbasierte tauscht lediglich etwas Größe gegen etwas Geschwindigkeit.

Wann Sie sie einsetzen sollten

Greifen Sie darauf zurück, wenn die Laufzeitkosten der VM ins Gewicht fallen. Virtualisierter Code ist konstruktionsbedingt langsamer als einfaches JavaScript. Auf einem häufig ausgeführten Pfad, etwa einer Animationsschleife, einem Handler pro Frame oder einer engen Parsing-Routine, sind die rund 10-20 %, die der registerbasierte Executor einsparen kann, das größere Bundle wert. Bei selten ausgeführtem Code lohnt sich der Größenaufwand meist nicht. Der Gewinn hängt vom Code ab, messen Sie ihn also an Ihren eigenen häufig ausgeführten Pfaden.

Sie variiert außerdem die Struktur der VM. Da sie strukturell anderen Bytecode und einen anderen Executor erzeugt, trägt die Ausgabe einen Fingerabdruck, der sich von der verbreiteten stapelbasierten VM unterscheidet. Generische, musterbasierte Analysen, die auf diese stapelbasierte Struktur abgestimmt sind, erkennen einen registerbasierten Build weniger leicht, daher ist dies eine Möglichkeit, die ausgelieferte VM vom Standard abzuheben.

Funktionsweise im Detail

Dies ist kein nativer registerbasierter Compiler. Der reguläre stapelbasierte Compiler erzeugt den Bytecode weiterhin genau so wie ohne die Option; eine separate Transformationsstufe schreibt diesen Bytecode anschließend in registerbasierte Form um. Da die registerbasierte Stufe all dem nachgelagert ist, bleibt der Großteil der VM-Obfuskierung (Funktionsauswahl, Bytecode Encoding, die Dispatcher-Optionen) unberührt (abgesehen von Stateful Opcodes, siehe oben).

Voraussetzungen

  • Erfordert vmObfuscation: Diese Option formt nur die VM um, die vmObfuscation erzeugt.
  • Obfuscator-Version 7.12.0 oder neuer.

Diese Option ist experimentell. Die registerbasierte Umschreibung ist neuer und weniger praxiserprobt als der standardmäßige stapelbasierte Pfad. Testen Sie daher, ob Ihr Code mit aktiviertem vmRegisterBased korrekt läuft, bevor Sie ihn ausliefern. Das gilt für jede VM-Option, hier aber ganz besonders.

Beispiel

JavaScript

Die registerbasierte Ausführung lässt sich mit dem Rest der VM-Obfuskierung kombinieren: Bytecode Encoding, Compact Dispatcher, VM Self Defending und VM Domain Lock funktionieren genau so wie mit der standardmäßigen stapelbasierten VM. Sie ändert, wie der Bytecode ausgeführt wird, nicht welche Schutzmaßnahmen ihn umgeben.