Java-Tipp 22: Schützen Sie Ihre Bytecodes vor Reverse Engineering / Dekompilierung

Wenn Sie Java-Klassen schreiben und über das Internet verteilen, sollten Sie wissen, dass Benutzer Ihre Klassen in Java-Quellcode zurückentwickeln, disassemblieren oder dekompilieren können. Der am weitesten verbreitete Dekompiler (zumindest öffentlich) ist Mokka. Mocha liest eine oder mehrere Dateien mit Bytecodes (Klassen) und konvertiert sie zurück in Java-Quellcode. Obwohl der von Mocha generierte Code nicht genau mit dem ursprünglichen Quellcode übereinstimmt, ist er nah genug, damit jemand ihn verstehen und ändern kann. Wenn Sie daran interessiert sind, Java-Klassen zu entwickeln und über das Internet zu verteilen - und sie vor dem Dekompilieren schützen möchten - lesen Sie weiter.

Mokka: ein Beispiel

Bevor wir Crema vorstellen, werden wir ein Beispiel mit Mokka durchgehen. Das folgende einfache Programm zeigt die Zeichenfolge "Hi there" auf dem Bildschirm an:

Klassentest {public static void main (String argv []) {System.out.println ("Hi there"); }}

Wenn die obigen vier Zeilen in einer Datei gespeichert würden test.java, test.javawürde beim Kompilieren eine neue Datei generiert test.class, die die Java-Bytecodes enthält, die diesen Java-Quellcode darstellen. Lassen Sie uns nun Mocha für die Klassendatei ausführen und die Mocha-Ausgabe sehen:

% java mocha.Decompiler test.class //% ist meine C-Shell-Eingabeaufforderung unter UNIX. 

Der obige Befehl generiert eine aufgerufene Datei test.mocha, die den von Mocha generierten Java-Quellcode enthält:

% mehr test.mocha / * Von Mocha aus test.class dekompiliert * / / * Ursprünglich aus test.java kompiliert * / import java.io.PrintStream; Klassentest {public static void main (String astring []) {System.out.println ("Hi there"); } Prüfung() { } }

Wie Sie dem obigen Beispiel entnehmen können, hat Mocha uns Java-Quellcode gegeben, der leicht zu lesen und zu verstehen ist. Wenn Sie diese Datei kopieren test.java, erneut kompilieren und ausführen, wird sie kompiliert und einwandfrei ausgeführt.

Crema zur Rettung!

Wie können Sie Ihre Klassen vor dem Dekompilieren schützen? Eine Antwort ist Crema. Crema verschlüsselt die symbolischen Informationen in Ihren .classDateien, sodass sie weniger anfällig für Dekompilierung sind. Zu den symbolischen Informationen, die Crema verschlüsselt, gehören der Name der Klasse, ihre Oberklasse, Schnittstellen, Variablennamen, Methoden usw. Diese symbolischen Namen werden von der Java Virtual Machine (JVM) benötigt, um Ihre Klassen mit Bibliothekspaketen zu verknüpfen. Crema verschlüsselt diese symbolischen Namen und verweist auf dieselbe Weise auf sie, damit die JVM weiterhin die korrekte Verknüpfung zwischen Klassen und Paketen erreichen kann.

Wie funktioniert Crema? Führen Sie Crema grundsätzlich aus, bevor Sie Ihre Klassendateien im Internet verteilen. Crema verschlüsselt die darin enthaltenen symbolischen Informationen und platziert jede neue Klasse in der Datei 1.crema. Ihre Aufgabe ist es dann, vor dem Verteilen im Internet 1.cremain etwas umzubenennen filename.class.

Lassen Sie uns Crema in unserem test.classoben gezeigten Beispiel ausführen und dann versuchen, es mit Mocha zu dekompilieren:

% java Crema -v test.class // -v ist eine Option zum Aktivieren des ausführlichen // Modus. Es gibt viel mehr Möglichkeiten. CREMA - The Java Obfuscator - EVALUATION VERSION Copyright (c) 1996 Hanpeter van Vliet Ladetest.class Verschleierungstest Speichertest als 1.crema HINWEIS: Klassen, die mit der Evaluierungsversion von Crema verarbeitet wurden, können nur lokal verwendet werden, da die meisten Browser dies ablehnen lade sie. Zeigen Sie für die Vollversion von Crema mit Ihrem Browser auf: //www.inter.nl.net/users/HPvan.Vliet/crema.html (siehe Ressourcen)

Der obige Befehl hat eine neue Datei generiert 1.crema, die die Bytecodes mit verschlüsselten symbolischen Informationen enthält. Beachten Sie, dass Crema über viele Befehlszeilenoptionsparameter verfügt, die Sie verwenden können. Weitere Informationen zu Crema finden Sie im Abschnitt Ressourcen.

Verschieben wir diese Datei nun test.classerneut und dekompilieren sie mit Mocha:

% mv 1.crema test.class% java mocha.Decompiler test.class java.lang.NullPointerException SIGSEGV 11 * Segmentierungsverletzung si_signo [11]: SIGSEGV 11 * Segmentierungsverletzung si_errno [0]: Fehler 0 si_code [1]: SEGV_ACCERR [ addr: 0x0] stackbase = EFFFF35C, stackpointer = EFFFF040 Vollständiger Thread-Dump: "Finalizer-Thread" (TID: 0xee3003b0, sys_thread_t: 0xef490de0) prio = 1 "Async Garbage Collector" (TID: 0xee300368, sys_thr00: Thread "(TID: 0xee300320, sys_thread_t: 0xef4f0de0) prio = 0" Clock-Handler "(TID: 0xee3001f8, sys_thread_t: 0xef5b0de0) prio = 11" main "(TID: 0xee3000a0, sys_tx8 *) .lang.Throwable.printStackTrace (Throwable.java) java.lang.ThreadGroup.uncaughtException (ThreadGroup.java) java.lang.ThreadGroup.uncaughtException (ThreadGroup).Java) Monitor-Cache-Speicherauszug: Registrierter Monitor-Speicherauszug: Finalisieren Sie mich Warteschlangensperre: nicht besessen Thread-Warteschlangensperre: nicht besessen Klassensperre: nicht besessen Java-Stack-Sperre: nicht besessen Code-Rewrite-Sperre: nicht besessen Heap-Sperre: nicht besessen Hat Finalisierungs-Warteschlangensperre: nicht besessen Monitor-E / A-Sperre: nicht besessen Kindstod-Monitor: nicht besessen Ereignismonitor: nicht besessen E / A-Monitor: nicht besessen Alarmmonitor: nicht besessen Warten auf Benachrichtigung: "Clock Handler" Sbrk-Sperre: nicht besessen Monitor-Cache-Sperre: nicht besessen Monitor-Registrierung: Monitor-Besitzer: "main" Thread Alarm F: Abbruch (Core Dumped)nicht besessener Alarmmonitor: nicht besessen Warten auf Benachrichtigung: "Clock Handler" Sbrk-Sperre: nicht besessen Monitor-Cache-Sperre: nicht besessen Monitor-Registrierung: Monitor-Besitzer: "Haupt" Thread-Alarm F: Abbruch (Core Dumped)nicht besessener Alarmmonitor: nicht besessen Warten auf Benachrichtigung: "Clock Handler" Sbrk-Sperre: nicht besessen Monitor-Cache-Sperre: nicht besessen Monitor-Registrierung: Monitor-Besitzer: "Haupt" Thread-Alarm F: Abbruch (Core Dumped)

Wie Sie im obigen Code sehen können, ist das erste, worüber sich Mocha beschwert, ein, NullPointerExceptionweil es über die symbolischen Informationen verwirrt war. Damit ist unser Ziel erreicht, die Dekompilierung unseres Codes zu erschweren.

Es sei darauf hingewiesen, dass der Autor von Mokka, Hanpeter van Vliet, auch der Autor von Crema ist! Mokka wird kostenlos verteilt. Eine Testversion von Crema ist kostenlos erhältlich, die Vollversion ist jedoch ein kommerzielles Produkt.

Wenn Sie Java-Klassen über das Internet verteilen, können Sie Ihren Java-Bytecode vor dem Risiko eines Reverse Engineerings schützen. Die obigen Codebeispiele zeigen, wie Mokka zur Dekompilierung verwendet wird und wie Crema durch Verhinderung solcher Aktivitäten zur Rettung kommen kann.

Qusay H. Mahmoud ist ein Doktorand der Informatik an der Universität von New Brunswick, Saint John Campus, Kanada.

Erfahren Sie mehr über dieses Thema

  • Anmerkung des Herausgebers Seit dem Tod von Herrn van Vliet (an Krebs) existieren die Standorte, die er für die Verbreitung von Mokka und Crema eingerichtet hat, nicht mehr.
  • Eric Smiths Mocha-Distributionsseite //www.brouhaha.com/~eric/computers/mocha.html
  • Crema auf der CERN-Site //java.cern.ch:80/CremaE1/DOC/quickstart.html

Diese Geschichte "Java-Tipp 22: Schützen Sie Ihre Bytecodes vor Reverse Engineering / Dekompilierung" wurde ursprünglich von JavaWorld veröffentlicht.