# Schutz vor Dekompilierung?



## hdi (7. Feb 2009)

Hallo,

ich hab mir grad das Programm "JAD" runtergeladen, und mit erschrecken festgestellt dass mir das Ding
in 1 Sekunde mein .class in eine .java Datei umgewandelt hat, die EXAKT so aussieht wie das Original,
bis auf Kommentare. Sogar vom kompletten Aufbau her, der einzige Unterschied ist dass die Member-
Variablen am Ende stehen.

Jetzt wollte ich mal fragen wie man sich davor schützen kann? Gibt es dafür Tools, oder muss man
mit einem gewissen "Style" coden, um das zu verhindern?

Ich hab danach nämlich meine main dekompilieren wollen, und diese startet einen Thread auf dem EDT.
Diesen Code konnte JAD nicht wiederherstellen, in der .java steht nur:



> SwingUtilities.invokeLater(new  Object()     /* anonymous class not found */
> class _anm1 {}
> );



Aber kann ja nicht sein dass ich anfangen muss alles als inner classes zu schreiben 

Spontan hab ich bei google mit "anti jad" o.ä. nichts finden können. Was wisst ihr über Schutz
vor Dekompilierungen?


----------



## Wildcard (7. Feb 2009)

Decompilieren kann man alles, da ist nichts gegen zu machen (die VM muss es ja schließlich ausführen können).
Man kann den Code schwerer lesbar machen mit einem Obfuscator, aber bist du dir sicher dafür auch einen guten Grund zu haben?


----------



## hdi (7. Feb 2009)

Nein ich hab grad keinen guten Grund sowas mit irgendeinem Programm zu tun.
Aber ich wollte mal wissen wie das generell so ist. Ich schätze mal komplexere kommerzielle
Java-Produkte sind mit so einem Obfuscator alle versehen oder?
Oder sperren die da schon vorher ab, beim jar? Sowas kann man doch auch cracken denk ich..


----------



## Illuvatar (7. Feb 2009)

Mehr als einen Obfuscator kannst du nicht verwenden. Was du meinst mit "beim jar absperren" weiß ich nicht 
Mit etwas Glück kann der Obfuscator so schlimmen Spaghetti-Bytecode erzeugen, dass sich der Decompiler daran verschluckt, aber heutige Jad-Versionen packen glaub alles was die JVM auch packt.
Dass die inner class nicht dekompiliert werden konnte, liegt vermutlich eher an einem Bedienungsfehler beim Jad. (Ich hab den nur einmal testhalber ausprobiert - aber das müsste er locker können)


----------



## Wildcard (8. Feb 2009)

hdi hat gesagt.:
			
		

> Aber ich wollte mal wissen wie das generell so ist. Ich schätze mal komplexere kommerzielle
> Java-Produkte sind mit so einem Obfuscator alle versehen oder?


Nein


----------



## Marco13 (8. Feb 2009)

@Wildcard: Kannst du zu dem "Nein" noch mehr sagen?
@Topic: Sowas wie http://www.retrologic.com/ erzeugt bytecode, den man zwar theoretisch decompilieren kann, aber wenn man dann solche Codestücke wie

```
package a.c.f;
class a
{
    void int()
    {
        int while = 5;
        for (class a=0; class<5; class++)
        {
            b.f(class);
        }
    }
```
ruaskriegt, hilft einem das nicht viel...


----------



## 0x7F800000 (8. Feb 2009)

wenn du einen relativ-geheimen algo für dich behalten willst, dann könntest du den in c schreiben und bs-abhängig in irgendwas völlig undekompilierbares umwandeln  Oder einen dämlichen Thin-Client an den kunden ausliefern, und den top-geheimen algo nur auf deinem eigenen server laufen lassen^^ :roll: 

(ich hab keine Ahnung, mir ist grad bloß ein wenig langweilig)
(hehe, da unten hängt grad passende werbung herum^^ http://www.excelsior-usa.com/landing/jet-obfuscator.html?gclid=CMjM88_ty5gCFdKR3wod3D4t1Q )


----------



## foobar (8. Feb 2009)

Mit ProGuard(http://proguard.sourceforge.net/) kann man seinen Code schon ganz gut schützen.
Man muß eben nur wissen, ob es einem das wert ist. Denn je nach Software ist das obfuscaten nicht ganz trivial, da man erstmal feststellen muß welche APIs nach aussen sichtbar sein müssen, damit andere Libs noch korrekt damit arbeiten können.


----------



## slawaweis (8. Feb 2009)

Java-Programme kann man nicht wirklich vor dem Dekompilieren schützen. Die Frage ist auch, ob es den Aufwand wert ist. Aus persönlicher Erfahrung weis ich, dass ein guter Programmierer 90% der Funktionalität eines Programms bloß vom Hinsehen oder Benutzen verstehen würde und die restlichen 10% kann man sich dann selber zusammenreimen oder das Fachwissen einkaufen. Oft ist es sinnvoller etwas nach dem Gefühl zu kopieren, als den Quelltext zu studieren, den dann vermeidet man einerseits fremde Fehler und andererseits integriert man es besser in die eigenen Anwendungen.

Es gibt natürlich Obfuskatoren und auch ich habe diese regelmäßig eingesetzt, aber nicht um den Code zu schützen, sondern um meine J2ME-Anwendungen noch kleiner zu bekommen. Die Probleme die dabei auftreten, sollten nicht außer acht gelassen werden. Einerseits tauchen nach dem Verwenden des Obfuskators plötzlich Fehler bei der Ausführung auf, die auf eine zu starke Veränderung im Programm zurückzuführen sind. Besonders bei J2ME tritt dieses Problem häufig auf. Dann kann man natürlich die Programme nur sehr schlecht warten. Wenn z.B. beim Kunden ein Fehler in das Log kommt: "NullPointerException in a.b.c.d(int)", was dann? Manche machen an dieser Stelle den Fehler dem Log zusätzliche Informationen über die Fehlerquelle beizulegen, was aber am Ende die ganze Funktionalität von alleine verrät, ohne dekompilieren. Für Frameworks oder Systeme die Klassen dynamisch laden, ist ein Obfuskator sowieso nicht verwendbar.

Der einzige Weg seinen Quelltext zu schützen, ist das Urheberrecht und ein guter Anwalt. Wenn man viel Geld mit seinen Programmen verdient und jemand diese Programme teilweise kopiert und auch viel Geld damit verdient, dann sollte man die anderen Programme analysieren und beweisen, dass der Quelltext geklaut ist. Dazu ist es manchmal sinnvoller, seinen Quelltext gar nicht zu verschleiern, damit man es leichter hat bei zu dummen Kopierern. Doch wenn jemand einen Quelltext dekompiliert und bestimmte Algorithmen nachahmt/nachbaut, ohne diese zu kopieren, dann kann man in Deutschland nichts machen, denn Algorithmen kann man hier nicht patentieren. Das fordert aber in einer gewissen Hinsicht Open Source. So ist es effizienter einen neuen Algorithmus unter der GPL3 freizugeben und damit quasi den Erfinderanspruch zu untermauern. Viele kommerzielle Anbieter würden es scheuen, so etwas zu kopieren.

Slawa


----------



## hdi (8. Feb 2009)

Sehr aufschlussreicher Text, danke


----------



## Wildcard (8. Feb 2009)

Marco13 hat gesagt.:
			
		

> @Wildcard: Kannst du zu dem "Nein" noch mehr sagen?


Die Frage war doch:





> Ich schätze mal komplexere kommerzielle
> Java-Produkte sind mit so einem Obfuscator alle versehen oder?


Was sind die großen, komplexen non Open Source Projekte in Java?
Am häufigsten eben spezielle Middleware, J2EE in allen Spielarten. Was nützt dort ein Obfuscator? Die Algorithmen sind nicht ultra komplex und hochgeheim, viel mehr das System an sich muss leistungsfähig sein.
Ist doch völlig unrentabel für einen Konkurrent dort zu versuchen Quellcode zu klauen, zumal sich große Unternehmen an soetwas wohl gar nicht im großen Stil herantrauen würden.
Und würde man es tun, wer würde die Million Zeilen fremden, kommentarlosen Quellcode Warten? Das ist doch viel zu teuer.
Wer könnte das System weiterentwickeln, betreuen, anpassen?
Wer würde die Aufgabe übernehmen das System soweit zu verändern, dass nicht mehr sofort offensichtlich ist, das es sich um eine schlecht Kopie handelt?
Ausserdem wurde ja bereits auf die Logging Problemmatik hingewiesen. In den "großen, kommerziellen" Java Projekten wie ich sie kenne, ist Logging unverzichtbar und schon dadurch scheidet der Obfuscator aus.
Der Anwendungsfall die Software kleiner zu machen (J2ME) ist hingegen ein durchaus valider. Eventuell auch noch meinen kleinen, superschlauen Algorithmus zu schützen, aber für komplexe Systeme? Eher nicht.


----------



## Marco13 (8. Feb 2009)

OK. Es gibt aber auch Closed-Source-Programme, die in Java geschrieben sind, und deren Source auch closed bleiben soll. Die Aussage war nur so pauschal, dass sie (falsch war und) ein Nachhaken rechtfertigte.


----------



## Wildcard (8. Feb 2009)

Marco13 hat gesagt.:
			
		

> OK. Es gibt aber auch Closed-Source-Programme, die in Java geschrieben sind, und deren Source auch closed bleiben soll. Die Aussage war nur so pauschal, dass sie (falsch war und) ein Nachhaken rechtfertigte.


Warum pauschal? Die Frage war, ob alle "komplexen, kommerziellen" Java Programme solche Techniken einsetzen und das tun sie bei Leibe nicht alle (IMO eher die Ausnahme), insofern halte ich 'nein' immer noch für die richtige Antwort.


----------



## Marco13 (8. Feb 2009)

<korinthenKack>
Ich hatte vorher schon nachgesehen, und jetzt nochmal: Das Wort "alle" hast du dazuinterpretiert. Es tauchte in der ursprünglichen Frage nicht auf. DANN wäre die Antwort "Nein" berechtigt gewesen, sofern es mindestens EIN "komplexeres" nicht-obfuskiertes closed-source-Programm gibt. Es GIBT aber auch welche, die obfuskiert sind. Für eine "ein-Wort-Antwort" war die Frage eben zu unpräzise formuliert :roll:
</korinthenKack>


----------



## Wildcard (9. Feb 2009)

hdi hat gesagt.:
			
		

> Ich schätze mal komplexere kommerzielle
> Java-Produkte sind mit so einem Obfuscator *alle* versehen oder?


Das ist zwar kreative Grammatik, aber ich habe mir den Satz ca. 10 mal durchgelesen und kam zu dem Schluß, dass 'alle' sich auf die "komplexen kommerziellen Java Produkte" bezieht. Oder kann man das Wort noch irgendwo sonst ankleben?  ???:L


----------



## Spacerat (9. Feb 2009)

Lese ich hier (so zwischen den Zeilen) etwa was von reverse Engineering? Dazu kann man leider nur sagen, das dagegen wirklich kein Kraut gewachsen ist. Die hier angesprochene "Verschleierungs-Methode" ist sogar schon angesichts "JAD" völlig sinnlos (hat jemand jemals eine aktuellere Version als 1.5.8 gefunden?). Es genügt auch nicht, sich darauf zu verlassen, alles mit JNI verstecken zu können. Das ist 1. nicht Sinn und zweck von Java-Bytecode und 2. gibt es auch noch Tools wie "IDA-Pro". Die bisher erfolgreichste Methode, diesen RE-Entwicklern das leben schwer zu machen liegt in der Verschlüsselung von Klassen-Dateien (.class), die für die Ausführung der Applikation benötigt werden. Das Verfahren ist allerdings recht aufwendig, da 1. ein eigener "ClassLoader" (die einzige Schwachstelle) entwickelt werden muss, der die verschlüsselten Klassen wieder in für die JVM lesbaren Code umwandelt und 2. die Klassen nicht zur Kompilierzeit verschlüsselt werden können (soweit ich weiss, existiert noch kein entsprechender Kompiler). Wenn man nun noch den entwickelten "ClassLoader" in einer ausfürbaren Anwendung (z.B. .exe) versteckt, beissen sich schon etliche RE-Entwickler mehr die Zähne aus. Leider immer noch nicht alle. Bleibt also die Frage zu klären, ob sich der ganze Aufwand lohnt. Diskussionen darüber, RE strafrechtlich zu verfolgen, können nur im Sande verlaufen. Denn wenn man feststellen will, ob ein anderer Code bei einem selber "geklaut" hat, muß man zwangsläufig selbst zum Täter werden.

mfg Spacerat


----------



## Spacerat (10. Feb 2009)

Ich hab' da noch mal ein bissl was vorbereitet, als kleinen Denkanstoss. Dieses Archiv habe ich mal bei mir in "Eigene Dateien" gepackt. Es kann mit
	
	
	
	





```
% java -jar AntiDecompile.jar
```
ausgeführt werden. Wenn es korrekt funktioniert, sollte es schlicht "Hello World" ausgeben. Das ist aber nicht das "weltbewegende" an diesem Archiv. Das interessante ist, dass das eigentliche Programm (die Klasse "pseudoclasses.TestClass"), wenn auch relativ simpel, gegen dekompilieren "geschützt" (Anführungszeichen sind hier unheimlich wichtig  ) ist. Wie das geht soll der folgende Quelltext der Klasse "AntiDecompileTest" zeigen.

```
import java.io.InputStream;
import java.nio.ByteBuffer;

public final class AntiDecompileTest
{
    @SuppressWarnings("unchecked")
    public static void main(String ... args)
    throws Throwable
    {
        ClassLoader cl = new ADClassLoader();
        Class c = Class.forName("pseudoclasses.TestClass", true, cl);
        c.getMethod("main", new Class[] {args.getClass()}).invoke(c, (Object) args);
    }

    private static final class ADClassLoader
    extends ClassLoader
    {
        private ADClassLoader()
        {
            super();
        }

        public synchronized Class<?> loadClass(String name)
        throws ClassNotFoundException
        {
            return loadClass(name, false);
        }

        @SuppressWarnings("unchecked")
        protected synchronized Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
        {
            Class rc = findLoadedClass(name);
            if(rc == null) {
                try {
                    InputStream in = getResourceAsStream(name.replace('.', '/') + ".class");
                    ByteBuffer b = ByteBuffer.allocate(in.available());
                    int n = 0;
                    while((n = in.read()) != -1) {
                        byte p = (byte) ((n & 0xFF) ^ 0xFF);
                        b.put(p);
                    }
                    b.position(0);
                    in.close();
                    try {
                        rc = defineClass(name, b, null);
                    } catch(ClassFormatError e) {
                        // nothing
                    }
                } catch(Exception e) {
                    rc = super.loadClass(name, resolve);
                }
            }
            return rc;
        }
    }
}
```
Wie man beim studieren des Quelltextes unschwer erkennen kann, beruht die Verschlüsselung auf einer simplen Exklusiv-Oder-Verknüpfung. Trotzdem hätte jeder andere "ClassLoader" Probleme beim Laden von auf diese Art verschlüsselter Klassen. In der Praxis ist aber jedwede Art von Verschlüsselung denkbar. Des weiteren lassen sich auch Lizenz abhängige Kriterien einbinden. Was die hier vorgestellte Klasse im übrigen noch recht "unbrauchbar" macht, ist die Tatsache, das alle Fremdklassen nun in verschlüsselter Form vorliegen müssen, weil weder eine entsprechende Abfrage der Paket-Zugehörigkeit noch irgendwelche Pakete in "ADClassLoader" definiert wurden. Was soll's ist ja auch nur ein Beispiel. Natürlich müssen die Klassen bisher noch alle von Hand verschlüsselt werden weil es wie gesagt noch keinen Kompiler dafür gibt.
Als Letztes noch ein Hinweis: Das von mir veröffentlichte Archiv war zum Zeitpunkt der Veröffentlichung absolut Virenfrei. Für eventuelle Schäden, die durch die Benutzung des Archives an Geräten, Gegenständen oder Personen auftreten übernehme ich keinerlei Haftung.

mfg Spacerat


----------



## Saxony (10. Feb 2009)

Hiho,

ich verwende hier auf Arbeit ein Framework, welches mit ProGuard obfuskiert wurde. Zufällig ist der Entwickler von ProGuard auch Angestellter bei dieser belgischen Firma (Luciad), wo ich das Framework her habe. 
Das Framework selbst ist zusätzlich noch verdongelt und man braucht einen USB Stick zum starten. Dafür gibt es extra Development Dongles und Deployment Dongles
Und noch einmal zusätzlich, muss ich ebenfalls meinen eigenen Code, welcher dieses Framework verwendet, mit ProGuard obfuskieren, bevor ich die Anwendung mit einem Deployment Dongle ausliefern darf/kann.

Man kann es also schon recht komplex gestalten wenn man will.

bye Saxony


----------



## HoaX (10. Feb 2009)

Spacerat hat gesagt.:
			
		

> Diskussionen darüber, RE strafrechtlich zu verfolgen, können nur im Sande verlaufen. Denn wenn man feststellen will, ob ein anderer Code bei einem selber "geklaut" hat, muß man zwangsläufig selbst zum Täter werden.



Nö. In jedem Code stecken Fehler, und die werden auch mitkopiert. So kannst du teilweise auch schon am Verhalten einer Anwendung erkennen dass da Code von dir drin Steckt. Ansonsten wenn das Kompilat das selbe ist, dann wird der Code darunter wohl auch gleich sein, das erkennt man auch ohne RE.

Und RE ist nicht wirklich das Selbe wie Urheberrechtsverletzungen/Codeklau. Das sind zwei Paar Stiefel.


----------

