Wie sperre ich kompilierte Java-Klassen, um eine Dekompilierung zu verhindern?


96

Wie sperre ich kompilierte Java-Klassen, um eine Dekompilierung zu verhindern?

Ich weiß, dass dieses Thema im Internet sehr gut diskutiert werden muss, aber ich konnte nach dem Verweisen zu keinem Ergebnis kommen.

Viele Leute schlagen Obfuscator vor, aber sie benennen nur Klassen, Methoden und Felder mit schwer zu merkenden Zeichenfolgen um, aber was ist mit sensiblen konstanten Werten?

Beispielsweise haben Sie die Verschlüsselungs- und Entschlüsselungskomponente basierend auf einer kennwortbasierten Verschlüsselungstechnik entwickelt. In diesem Fall kann jede durchschnittliche Java-Person JAD verwenden, um die Klassendatei zu dekompilieren und den Kennwortwert (definiert als Konstante) sowie Salt einfach abzurufen. Die Daten können wiederum entschlüsselt werden, indem ein kleines unabhängiges Programm geschrieben wird!

Oder sollten solche sensiblen Komponenten in nativem Code (z. B. VC ++) erstellt und über JNI aufgerufen werden ?


Selbst wenn der zerlegte native Code für manche Leute ohnehin gut lesbar ist, müssten Sie wahrscheinlich einen Obfuscator oder eine handgemachte Assembly verwenden, um ihn nicht offensichtlich zu machen (allgemeines C ++, das mit Optimierung kompiliert wurde, ist lesbar genug). Welcher Code auch immer auf dem Gerät des Benutzers ausgeführt wird, kann abgefangen werden. Obwohl die Kosten- / Fähigkeitsanforderungen für ein solches Abfangen ziemlich hoch sein können, ist es beispielsweise nicht trivial, in den manipulationssicheren Chipkartencode von Smartcards einzudringen, sondern nur mit Top-Ausrüstung und Fähigkeiten. Mit Java-Klassen ... würde ich nicht viel stören, Sie können sie wahrscheinlich genug verschlüsseln, um Skriptkinder abzuweisen, nicht mehr.
Ped7g

Antworten:


95

Einige der fortschrittlicheren Java-Bytecode-Verschleierer leisten viel mehr als nur das Mangeln von Klassennamen. Zelix KlassMaster zum Beispiel kann Ihren Code-Fluss auch so verschlüsseln, dass es wirklich schwierig ist, ihm zu folgen, und als hervorragender Code-Optimierer fungiert ...

Viele der Verschleierer sind auch in der Lage, Ihre Zeichenfolgenkonstanten zu verschlüsseln und nicht verwendeten Code zu entfernen.

Eine andere mögliche Lösung (die die Verschleierung nicht unbedingt ausschließt) besteht darin, verschlüsselte JAR-Dateien und einen benutzerdefinierten Klassenladeprogramm zu verwenden, das die Entschlüsselung durchführt (vorzugsweise unter Verwendung der nativen Laufzeitbibliothek).

Drittens (und möglicherweise mit dem stärksten Schutz) sollten native Compiler wie GCC oder Excelsior JET verwendet werden, die Ihren Java-Code direkt in eine plattformspezifische native Binärdatei kompilieren.

Auf jeden Fall muss man sich daran erinnern, wie das Sprichwort auf Estnisch lautet: "Schlösser sind für Tiere". Das bedeutet, dass jedes Codebit zur Laufzeit verfügbar ist (in den Speicher geladen wird) und bei ausreichender Geschicklichkeit, Entschlossenheit und Motivation den Code dekompilieren, entschlüsseln und hacken kann und wird. Ihre Aufgabe besteht einfach darin, den Prozess so unangenehm wie möglich zu gestalten Sie können und halten das Ding am Laufen ...


13
+1 für "Schlösser sind für Tiere". Ich denke, der passende Begriff hier wäre Script Kiddies.
Antimon

Du meinst GCJ und es ist tot.
Marquis von Lorne

1
Die Componio-JAR-Dateiverschlüsselung ist ebenfalls tot. Verwenden Sie stattdessen JarProtector .
J.Profi

16

Solange sie Zugriff auf die verschlüsselten Daten und die Software haben, die sie entschlüsselt, können Sie dies grundsätzlich nicht vollständig sicher machen. Dies wurde bereits gelöst, indem eine externe Blackbox für die Verschlüsselung / Entschlüsselung verwendet wurde, z. B. Dongles, Remote-Authentifizierungsserver usw. Aber selbst dann, wenn der Benutzer vollen Zugriff auf sein eigenes System hat, macht dies nur Dinge schwierig, nicht unmöglich - es sei denn, Sie können Ihr Produkt direkt an die in der "Black Box" gespeicherte Funktionalität binden, wie beispielsweise Online-Gaming-Server.


13

Haftungsausschluss: Ich bin kein Sicherheitsexperte.

Das klingt nach einer schlechten Idee: Sie lassen jemanden Sachen mit einem 'versteckten' Schlüssel verschlüsseln, den Sie ihm geben. Ich denke nicht, dass dies sicher gemacht werden kann.

Vielleicht könnten asymmetrische Schlüssel funktionieren:

  • Stellen Sie eine verschlüsselte Lizenz mit einem öffentlichen Schlüssel zum Entschlüsseln bereit
  • Lassen Sie den Kunden eine neue Lizenz erstellen und diese zur Verschlüsselung an Sie senden
  • Senden Sie eine neue Lizenz an den Client zurück.

Ich bin nicht sicher, aber ich glaube, der Client kann den Lizenzschlüssel tatsächlich mit dem öffentlichen Schlüssel verschlüsseln, den Sie ihm gegeben haben. Sie können es dann mit Ihrem privaten Schlüssel entschlüsseln und ebenfalls neu verschlüsseln.

Sie können ein separates öffentliches / privates Schlüsselpaar pro Kunde führen, um sicherzustellen, dass Sie tatsächlich Informationen vom richtigen Kunden erhalten - jetzt sind Sie für die Schlüssel verantwortlich ...


2
Ich habe diese Technik schon einmal benutzt und sie funktioniert gut. Aus Angriffssicht besteht der erste Ansatz jedoch darin, nur den Code zu ändern, der die Lizenzprüfung durchführt, und ihn zu entfernen. Es gibt Dinge, die Sie tun können, um diesen Angriffsvektor zu erschweren. Wenn Sie dem Angreifer jedoch die Kontrolle über die Hardware geben, ist dies dazu bestimmt, mit einem entsprechend motivierten und erfahrenen Angreifer zu scheitern. In der Praxis geht es nur darum, die meist ehrlichen Menschen ehrlich zu halten.
Jim Rush

12

Egal was Sie tun, es kann "dekompiliert" werden. Du kannst es einfach zerlegen. Oder schauen Sie sich einen Speicherauszug an, um Ihre Konstanten zu finden. Sie sehen, der Computer muss sie kennen, also muss auch Ihr Code.

Was tun?

Versuchen Sie, den Schlüssel nicht als fest codierte Konstante in Ihrem Code zu versenden: Behalten Sie ihn als Benutzereinstellung bei. Machen Sie den Benutzer für die Pflege dieses Schlüssels verantwortlich.


6

@jatanp: oder noch besser, sie können dekompilieren, den Lizenzcode entfernen und neu kompilieren. Ich glaube nicht, dass es mit Java eine richtige, hackfeste Lösung für dieses Problem gibt. Nicht einmal ein böser kleiner Dongle konnte dies mit Java verhindern.

Meine eigenen Geschäftsleiter machen sich darüber Sorgen, und ich denke zu viel. Andererseits verkaufen wir unsere Anwendung an große Unternehmen, die dazu neigen, die Lizenzbedingungen einzuhalten - im Allgemeinen eine sichere Umgebung dank der Bohnenzähler und Anwälte. Das Dekompilieren selbst kann illegal sein, wenn Ihre Lizenz korrekt geschrieben ist.

Also, ich muss fragen, brauchen Sie wirklich einen gehärteten Schutz, wie Sie ihn für Ihre Anwendung suchen? Wie sieht Ihr Kundenstamm aus? (Unternehmen? Oder die jugendlichen Spielermassen, wo dies eher ein Problem wäre?)


Tatsächlich gibt es eine richtige, hackfeste Lösung, die übrigens wie ein Dongle aussieht: excelsior-usa.com/blog/excelsior-jet/…
Dmitry Leskov

@DmitryLeskov 'hack resistent' vielleicht. Aber es ist nur ein Speedbump für jeden, der den Code haben will. Am Ende des Tages muss der Bytecode unverschlüsselt auf einer Hostplattform ausgeführt werden. Punkt.
Stu Thompson

Sie haben den Beitrag, auf den ich verlinkt habe, nicht gelesen. Der Bytecode wird in den CPU-Code des Dongles konvertiert und verschlüsselt. Wenn der Endbenutzer die geschützte App ausführt, wird dieser verschlüsselte Code auf den "Dongle" übertragen. Der Dongle entschlüsselt und führt ihn auf seiner CPU aus.
Dmitry Leskov

2
Corporate Teenage Gamer.
Odiszapc

3

Wenn Sie nach einer Lizenzierungslösung suchen, können Sie die TrueLicense-API überprüfen . Es basiert auf der Verwendung asymmetrischer Schlüssel. Dies bedeutet jedoch nicht, dass Ihre Anwendung nicht geknackt werden kann. Jede Anwendung kann mit genügend Aufwand geknackt werden. Was wirklich wichtig ist, ist, wie Stu antwortete , herauszufinden, wie stark Sie Schutz brauchen.


2

Ich glaube nicht, dass es eine effektive Offline-Antipiraterie-Methode gibt. Die Videospielbranche hat schon oft versucht, dies herauszufinden, und ihre Programme wurden immer geknackt. Die einzige Lösung besteht darin, dass das Programm online in Verbindung mit Ihren Servern ausgeführt werden muss, damit Sie den Weihrauchschlüssel überprüfen können und dass jeweils nur eine aktive Verbindung durch den Lizenznehmer besteht. So funktioniert World of Warcraft oder Diablo . Selbst wenn es schwierig ist, werden private Server entwickelt, um die Sicherheit zu umgehen.

Trotzdem glaube ich nicht, dass mittelständische / große Unternehmen illegale kopierte Software verwenden, da die Lizenzkosten für sie minimal sind (vielleicht weiß ich nicht, wie viel Sie für Ihr Programm verlangen müssen) die Kosten für eine Testversion.


2

Sie können die Bytecode-Verschlüsselung ohne Angst verwenden.

Tatsache ist, dass das oben zitierte Papier „Cracking Java Byte-Code-Verschlüsselung“ einen logischen Irrtum enthält. Der Hauptanspruch des Papiers besteht darin, dass vor dem Ausführen alle Klassen entschlüsselt und an die ClassLoader.defineClass(...)Methode übergeben werden müssen . Aber das ist nicht wahr.

Die hier übersehene Annahme wird vorausgesetzt, dass sie in einer authentischen oder Standard-Java-Laufzeitumgebung ausgeführt werden . Nichts kann die geschützte Java-App dazu verpflichten, diese Klassen nicht nur zu starten, sondern sogar zu entschlüsseln und an sie weiterzugeben ClassLoader. Mit anderen Worten, wenn Sie sich in einer Standard-JRE befinden, können Sie die defineClass(...)Methode nicht abfangen , da die Standard-Java zu diesem Zweck keine API hat. Wenn Sie eine modifizierte JRE mit gepatchten ClassLoaderoder anderen „Hacker-Tricks“ verwenden, können Sie dies nicht tun, da sie geschützt sind Die Java-App funktioniert überhaupt nicht und Sie müssen daher nichts abfangen. Und es spielt absolut keine Rolle, welcher „Patch Finder“ verwendet wird oder welcher Trick von Hackern verwendet wird. Diese technischen Details sind eine ganz andere Geschichte.


Wie genau wollen Sie eine gepatchte JVM erkennen? Auf jeden Fall macht das alles die Dinge etwas schwieriger.
Antimon

Können Sie nicht einfach einen Aufruf von defineClass () in Ihrem App Launcher finden? Wenn Sie diesen Anruf tätigen, müssen Sie ohnehin ein Array entschlüsselter Bytes abgeben. Ist das nicht ein weiterer Punkt, an dem die ursprüngliche Quelle auslaufen könnte?
Aszendent

4
Ich stimme dieser Antwort nicht wirklich zu. Für mich klingt das wie: "Frage: Was ist der einfachste Weg, um Pi zu finden? Antwort: Nimm 2 * Pi und dividiere durch zwei." Ich bin mit der Idee nicht einverstanden, aber könnten Sie weitere Details hinzufügen? Erwarten Sie zum Beispiel, dass das Hauptprogramm in reinem Java geschrieben wird? Enthält das den Code, der nach Änderungen sucht?
Patrick M

-1

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.