F: Wenn ich meine .class-Dateien verschlüssele und sie mit einem benutzerdefinierten Klassenladeprogramm lade und entschlüssele, verhindert dies die Dekompilierung?
A: Das Problem, die Dekompilierung von Java-Bytecode zu verhindern, ist fast so alt wie die Sprache selbst. Trotz einer Reihe von auf dem Markt erhältlichen Verschleierungstools denken unerfahrene Java-Programmierer weiterhin über neue und clevere Möglichkeiten zum Schutz ihres geistigen Eigentums nach. In diesem Java Q & A-Teil zerstreue ich einige Mythen über eine Idee, die häufig in Diskussionsforen aufgearbeitet wird.
Die extreme Leichtigkeit, mit der Java-Klassendateien in Java-Quellen rekonstruiert werden können, die den Originalen sehr ähnlich sind, hat viel mit den Zielen und Kompromissen beim Entwurf von Java-Bytecode zu tun. Java-Bytecode wurde unter anderem für Kompaktheit, Plattformunabhängigkeit, Netzwerkmobilität und einfache Analyse durch Bytecode-Interpreter und dynamische JIT- (Just-in-Time) / HotSpot-Compiler entwickelt. Die kompilierten .class-Dateien drücken wohl die Absicht des Programmierers so deutlich aus, dass sie leichter zu analysieren sind als der ursprüngliche Quellcode.
Es können verschiedene Dinge getan werden, um die Dekompilierung nicht vollständig zu verhindern, zumindest um sie schwieriger zu machen. Als Schritt nach der Kompilierung können Sie beispielsweise die .class-Daten massieren, um den Bytecode beim Dekompilieren entweder schwerer zu lesen oder in gültigen Java-Code (oder beides) zu dekompilieren. Techniken wie das Überladen extremer Methodennamen funktionieren bei ersteren gut, und das Manipulieren des Kontrollflusses zum Erstellen von Kontrollstrukturen, die nicht durch Java-Syntax dargestellt werden können, funktionieren bei letzteren gut. Die erfolgreicheren kommerziellen Verschleierer verwenden eine Mischung dieser und anderer Techniken.
Leider müssen beide Ansätze tatsächlich den Code ändern, den die JVM ausführen wird, und viele Benutzer befürchten (zu Recht), dass diese Umwandlung ihren Anwendungen neue Fehler hinzufügen könnte. Darüber hinaus kann das Umbenennen von Methoden und Feldern dazu führen, dass Reflection-Aufrufe nicht mehr funktionieren. Das Ändern der tatsächlichen Klassen- und Paketnamen kann mehrere andere Java-APIs (JNDI (Java Naming and Directory Interface), URL-Anbieter usw.) beschädigen. Zusätzlich zu geänderten Namen kann es schwierig werden, die ursprünglichen Ausnahmestapelspuren wiederherzustellen, wenn die Zuordnung zwischen Klassenbytecode-Offsets und Quellzeilennummern geändert wird.
Dann besteht die Möglichkeit, den ursprünglichen Java-Quellcode zu verschleiern. Grundsätzlich verursacht dies jedoch ähnliche Probleme. Verschlüsseln, nicht verschleiern?
Vielleicht hat Sie das oben Gesagte zum Nachdenken gebracht: "Nun, was ist, wenn ich anstelle der Manipulation des Bytecodes alle meine Klassen nach dem Kompilieren verschlüssele und sie im laufenden Betrieb in der JVM entschlüssele (was mit einem benutzerdefinierten Klassenladeprogramm möglich ist)? Dann führt die JVM meinen aus Original-Byte-Code und doch gibt es nichts zu dekompilieren oder zurückzuentwickeln, oder? "
Leider würden Sie sich irren, sowohl wenn Sie denken, dass Sie als erster auf diese Idee gekommen sind, als auch wenn Sie denken, dass sie tatsächlich funktioniert. Und der Grund hat nichts mit der Stärke Ihres Verschlüsselungsschemas zu tun.