Den meisten Android-Entwicklern ist nicht bewusst, dass es relativ einfach ist, eine Android App aus dem Google Play Store zu laden und den Source-Code wieder zu rekonstruieren. Es gibt zwar Möglichkeiten, den Sourcecode mit Hilfe von Obfuscation zu schützen, aber selbst ein so verschleierter Code kann von erfahrenen Entwicklern recht gut verstanden werden.
Obfuskation beschreibt die absichtliche Veränderung von Programmcode, so dass der Quelltext für Menschen schwer verständlich oder schwer rückgewinnbar wird. Ziel ist es, den Aufwand für Reverse Engineering stark zu erhöhen, um Veränderung, unerwünschtes Kopieren von Programmteilen oder Diebstahl von geistigem Eigentum zu erschweren oder um die Funktionalität z. B. von Schadsoftware zu verschleiern.
https://de.wikipedia.org/wiki/Obfuskation_(Software)
Für das Reverse-Engineering einer Android App wird nur die APK Datei benötigt. Diese kann ganz einfach aus dem Google Play Store, dem Amazon App Store oder anderer Seite heruntergeladen werden. Um kein Copyright oder ähnliches zu verletzen nehme ich für das Beispiel eine Open Source App, die ich aus dem alternativen App Store für Android (F-Droid) herunterlade.
F-Droid ist ein alternativer App Store für das mobile Betriebssystem Android. Die Besonderheit von F-Droid besteht darin, dass im offiziellen und standardmäßig aktivierten Repository ausschließlich freie Software angeboten wird, üblicherweise nach GNU GPL oder Apache-Lizenz. Der Quellcode jeder App im F-Droid-Repositorium steht nicht nur dem Endnutzer zur Einsichtnahme und Modifikation zur Verfügung, sondern es wird auch garantiert, dass die heruntergeladene apk-Datei vom F-Droid-Server aus diesen Quellen generiert wurde. Entsprechend ist diese Datei auch von F-Droid signiert und nicht wie üblich vom ursprünglichen Entwickler. Dieses Konzept soll für Transparenz und Sicherheit sorgen.
https://de.wikipedia.org/wiki/F-Droid
Schritt 1: APK Download
Für den Download von APK Dateien aus dem Google Play Store oder dem Amazon Store kann man z.B. Online Dienste, verwenden. So muss man sich nicht die Mühe machen, eine eigene Software wie z.B. https://github.com/rehmatworks/gplaydl zu installieren (Was aber auch sinn machen kann, wenn man öfter darauf zugreifen muss oder unabhängig sein möchte). Für eine gelegentliche Nutzung empfehle ich eher einen Online Dienst wie z.B. https://apkcombo.com/de/apk-downloader/ zu verwenden. Für die von mir ausgewählte App benötige ich keines dieser Werkzeuge, da man F-Droid APK Dateien einfach auf der Webseite herunterladen kann.
Die Beispiel App „Suntimes Sunlight and moonlight times (and alarms)“ kann ich also einfach unter https://f-droid.org/de/packages/com.forrestguice.suntimeswidget/ herunterladen ( https://f-droid.org/repo/com.forrestguice.suntimeswidget_86.apk ).
Schritt 2: AKP Datei entpacken
Die 6,6MB große APK Datei ist laut „file“ eine Zip Datei.
file com.forrestguice.suntimeswidget_86.apk
com.forrestguice.suntimeswidget_86.apk: Zip archive data, at least v0.0 to extract, compression method=deflate
Also kann man sie ja mal entpacken und checken was in der Datei so enthalten ist. Mit dem folgenden Befehl wird die APK Datei entpackt und alle enthaltenen Dateien auf die Platte geschrieben. (PS: Windows Nutzer, die den Befehl unzip nicht haben, können ja mal in den folgenden Beitrag schauen 🙂 https://www.jentsch.io/magie-mit-der-git-bash/ )
unzip com.forrestguice.suntimeswidget_86.apk
Das Ergebnis sind 3126 Dateien die sich bei genauerer Betrachtung wie folgt aufteilen.
1 .MF Datei
1 .RSA Datei
1 .SF Datei
1 .arsc Datei
6 .data Dateien
1 .dex Datei
3 .jpg Dateien
864 .png Dateien
1224 .properties Dateien
1 .repository Datei
1 .ser Datei
1 .tab Datei
1 .txt Datei
1021 .xml Dateien
Wie man sieht haupsächlich XML, Properties und Bilder. Keine Spur von .class Files oder .java Files. So kommt man also nicht an die Sourcen :-(. Irgendwo muss der Programmcode aber sein – und genau so ist es auch. Das Geheimnis ist die .dex Datei. Diese enthält alle Java Klassen mit dem enthaltenen Programmcode.
file classes.dex
classes.dex: Dalvik dex file version 035
Schritt 3: Java Code decompilieren
Die DEX-Datei (Dalvik Executable) enthält den kompilierten Java-Code. In ihr sind alle Klassen enthalten und man kann den Sourcecode der Dex-Datei mit einem Decompiler wieder rekonstruieren. Genau wie unter Schritt 1 gibt es auch hier wieder die Möglichkeit sich ein Programm auf dem Computer zu installieren (https://github.com/skylot/jadx) oder ein Online Tool zu verwenden. Ich verwende normalerweise den http://www.javadecompilers.com/apk Decompiler. Auf der Webseite kann man einfach die komplette APK Datei hochladen und bekommt eine Zip Datei zurück, die alle Resourcen (XML, Bilder, etc.) und Java Sourcen enthält.
Nach dem Download kann man die Datei com.forrestguice.suntimeswidget_86_source_from_JADX.zip entpacken und die Sourcen im Editor lesen. Die Extrahierte Zip Datei enthält 4513 Dateien. Also schon mal deutlich mehr als nach dem Entpacken mit unzip. Ein detaillierter Blick auf die Dateien bring folgendes zutage.
1 .MF Datei
1 .RSA Datei
1 .SF Datei
6 .data Dateien
1 .dex Datei
988 .java Dateien
3 .jpg Dateien
864 .png Dateien
1224 .properties Dateien
1 .repository Datei
1 .ser Datei
1 .tab Datei
1 .txt Datei
1414 .xml Dateien
Spannend sind hier die 988 Java Dateien in denen die Java-Sourcen enthalten sind und die AndroidManifest.xml Datei, in der Alle Activities, Services, Provider, Permissions, etc. aufgelistet sind. Eine ausführliche Beschreibung der Manifest Datei findet man unter https://developer.android.com/guide/topics/manifest/manifest-intro.
Im Sources Ordner befinden sich nun die Sourcen der App. Allerdings befinden sich hier auch die Sourcen der verwendeten Bibliotheken, die natürlich auch alle dekompiliert wurden. Darunter unter anderem auch die Support Library die wohl in fast Allen Android Apps verwendet wird und noch eine Reihe anderer Bibliotheken, die von dem Entwickler verwendet wurden.
- time4j (https://github.com/MenoData/Time4J)
- Color Picker (https://github.com/QuadFlask/colorpicker)
- GravitySnapHelper (https://github.com/rubensousa/GravitySnapHelper)
- SunriseSunset (https://github.com/caarmen/SunriseSunset)
- Sunrise/SunsetLib (https://github.com/mikereedell/sunrisesunsetlib-java)
Vergleicht man das mit der build.gradle Datei (https://github.com/forrestguice/SuntimesWidget/blob/master/app/build.gradle) sieht man schnell, dass. hier genau die oben beschriebenen Bibliotheken zum Einsatz kommen. (Dies ist normalerweise nicht möglich, aber da in dem Beispiel eine Open Source App genutzt wird kann man ja mal kurz vergleichen 🙂 )
implementation 'com.android.support:design:25.4.0'
implementation 'com.android.support:appcompat-v7:25.4.0'
implementation 'com.android.support:recyclerview-v7:25.4.0'
implementation 'com.android.support:cardview-v7:25.4.0'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
implementation 'com.github.forrestguice:sunrisesunsetlib-java:SunriseSunsetCalculator-1.2-p0-fixdst'
implementation 'com.github.caarmen.SunriseSunset:lib-sunrise-sunset:1.1.0'
implementation group: 'net.time4j', name: 'time4j-android', version: '4.4.2-2019c'
Reduziert man den sources Ordner um die Java Klassen der Bibliotheken, bleiben noch 213 Java Klassen übrig, die man nun in Ruhe studieren kann. Dazu kommen noch die Resource Files (Bilder, Layouts, Animationen, Übersetzungen, etc.) die auch hilfreich sein können.
Schutz vor App Reverse Engineering
Einen echten Schutz vor den Reverse Engineering einer Android App (die in Java geschrieben ist) gibt es nicht, aber es gibt Möglichkeiten, das Reverse Engineering deutlich zu erschweren. Dazu kann man die sog. Obfuscation Technik verwenden (wie oben schon beschrieben). Um den Sourcecode also schwerer lesbar zu machen kann man im Android Studio einfach ProGuard verwenden. Der Beitrag „Shrink, obfuscate, and optimize your app“ unter https://developer.android.com/studio/build/shrink-code beschreibt sehr gut, was zu tun ist, um es dem Angreifer nicht ganz so einfach zu machen den Sourcecode einer App in wenigen Minuten im Klartext vorliegen zu haben.
Ist eine App oder ein Teil einer App besonders schützenswert, sollte man darüber nachdenken, den Teil in C/C++ zu programmieren, denn Android Apps müssen nicht unbedingt in Java geschrieben werden. Eine Anleitung zur Integration von C/C++ Code kann man unter https://developer.android.com/studio/projects/add-native-code finden.
Fazit
Wie in dem Beispiel zu sehen ist, ist das Reverse Engineering einer „normalen“ Android App mit einfachen Mitteln möglich und dank der Online Dienst für „APK Download“ und „APK Java Decompiler“ ohne die Installation von irgendwelchen komplizierten Werkzeugen möglich.
Wichtig ist, dass man hier immer das Copyright der Quellen beachtet und nicht irgendwelche Sourcen kopiert und in eigenen Apps verwendet oder anderweitig nutzt.