apktool
APKs entpacken, Ressourcen lesen und modifizierte Apps bauen
Lernziel
Nach dieser Seite weißt du, wie du mit apktool eine APK vollständig dekodierst, AndroidManifest.xml und Ressourcen liest, BLE-Permissions erkennst und — falls nötig — eine modifizierte APK neu baust und signierst.
Was ist apktool?
apktool ist ein Open-Source-Tool zum Reverse Engineering von Android-APK-Dateien. Im Gegensatz zu JADX, das den Dalvik-Bytecode in lesbares Java zurückübersetzt, macht apktool zwei andere Dinge:
- Ressourcen dekodieren — XML-Dateien (AndroidManifest, Layouts, Strings) werden aus dem kompilierten Binärformat zurück in lesbares XML umgewandelt
- Smali-Disassemblierung — der Bytecode wird in Smali dekompiliert, eine assemblerähnliche Darstellung des Dalvik-Befehlssatzes
Für die BLE-Sicherheitsanalyse ist apktool primär interessant wegen AndroidManifest.xml: Dort sind alle angeforderten Permissions, deklarierte Services und declared BLE-Capabilities sichtbar — exakt so, wie sie zur Laufzeit gelten.
apktool vs. JADX — wann was?
JADX gibt dir lesbaren Java-Code: gut für Kryptoanalyse, UUID-Suche und Logikverständnis. apktool gibt dir die Original-Ressourcen und Smali: gut für Manifest-Analyse, String-Ressourcen und APK-Modifikation. In der Praxis nutzt du beide — JADX für den Code, apktool für das Manifest und die Ressourcen.
Installation
Voraussetzungen
apktool ist ein Java-Tool. Du brauchst Java 8 oder neuer:
java -version
# Sollte "openjdk version 11.x.x" oder höher ausgebenFalls Java fehlt:
# Debian/Ubuntu
sudo apt install default-jre
# macOS (Homebrew)
brew install openjdkapktool installieren
# Linux/macOS: Wrapper-Script und JAR herunterladen
wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool \
-O /usr/local/bin/apktool
wget https://github.com/iBotPeaches/Apktool/releases/download/v2.10.0/apktool_2.10.0.jar \
-O /usr/local/bin/apktool.jar
chmod +x /usr/local/bin/apktool
# Version prüfen
apktool --version
# 2.10.0Windows
Auf Windows: apktool.bat als Wrapper-Script statt apktool verwenden. Der Befehl ist identisch, nur der Dateiname des Scripts unterscheidet sich.
Praxisbeispiel: LED-Strip-APK dekodieren
Die App wl.smartled steuert den LED-Strip. Extrahiere die APK mit ADB und dekodiere sie mit apktool:
# APK vom Gerät extrahieren
adb shell pm path wl.smartled
# /data/app/wl.smartled-1/base.apk
adb pull /data/app/wl.smartled-1/base.apk ./ledstrip.apk
# APK mit apktool dekodieren
apktool d ledstrip.apk -o ledstrip_decodedDas erzeugt folgende Verzeichnisstruktur:
ledstrip_decoded/
├── AndroidManifest.xml ← decodiertes Manifest (lesbares XML)
├── apktool.yml ← Metadaten für den Rebuild
├── res/ ← decodierte Ressourcen
│ ├── layout/ ← XML-Layouts
│ ├── values/
│ │ ├── strings.xml ← String-Ressourcen
│ │ └── public.xml ← Ressourcen-IDs
│ └── drawable/
├── smali/ ← Smali-Code (Dalvik-Assembly)
│ └── wl/smartled/...
└── lib/ ← native .so-Dateien (falls vorhanden)
└── arm64-v8a/
AndroidManifest.xml lesen
cat ledstrip_decoded/AndroidManifest.xmlRelevante Abschnitte für die BLE-Analyse:
<manifest package="wl.smartled" ...>
<!-- Permissions: Welche BLE-Rechte verlangt die App? -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- Feature-Deklaration: App setzt BLE voraus -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<application ...>
<!-- Deklarierte Services (Background-Prozesse) -->
<service android:name=".service.BleService"
android:enabled="true"
android:exported="false"/>
</application>
</manifest>Aus dem Manifest erkennst du:
- Die App verlangt
BLUETOOTH_SCANundBLUETOOTH_CONNECT— das sind die Android-12-BLE-Permissions ACCESS_FINE_LOCATIONist angegeben — die App scannt nach Geräten- Ein deklarierter
BleServiceläuft im Hintergrund — BLE-Verbindungen werden dort verwaltet
Exported Services sind potenzielle Angriffspunkte
android:exported="true" an einem Service bedeutet, dass andere Apps (oder du via ADB) den Service direkt aufrufen können — ohne durch die normale App-UI zu gehen. Für die Sicherheitsanalyse ist das interessant: Ein exportierter BLE-Service könnte sich von außen instruieren lassen.
String-Ressourcen durchsuchen
grep -i "ble\|bluetooth\|uuid\|key\|secret" ledstrip_decoded/res/values/strings.xmlManchmal liegen UUIDs oder API-Keys in den String-Ressourcen statt im Java-Code:
<string name="ble_service_uuid">0000fff0-0000-1000-8000-00805f9b34fb</string>
<string name="ble_char_write">0000fff3-0000-1000-8000-00805f9b34fb</string>APK modifizieren und neu bauen
In manchen Analyseszenarien willst du die APK verändern: Debug-Logging aktivieren, ein Certificate-Pinning entfernen oder das Netzwerk-Security-Config patchen, damit du Traffic intercepten kannst.
Schritt 1: Smali-Code anpassen
Smali ist die Assemblersprache von Dalvik. Ein einfaches Beispiel: eine boolean-Return-Methode auf true zwingen:
# Original:
.method public isDevMode()Z
.registers 2
const/4 v0, 0x0 # return false
return v0
.end method
# Modifiziert:
.method public isDevMode()Z
.registers 2
const/4 v0, 0x1 # return true
return v0
.end method
Schritt 2: Netzwerk-Security-Config patchen
Um HTTPS-Traffic mit einem Proxy (z. B. Burp Suite) zu intercepten, musst du das Network Security Profile der App auf User-Certificates erweitern:
# res/xml/network_security_config.xml anlegen (oder anpassen)
mkdir -p ledstrip_decoded/res/xml<!-- ledstrip_decoded/res/xml/network_security_config.xml -->
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="system"/>
<certificates src="user"/> <!-- User-Certs werden akzeptiert -->
</trust-anchors>
</base-config>
</network-security-config>Dann im AndroidManifest.xml das Attribut eintragen:
<application
android:networkSecurityConfig="@xml/network_security_config"
...>Schritt 3: APK neu bauen
apktool b ledstrip_decoded -o ledstrip_modified.apkSchritt 4: Mit Debug-Keystore signieren
Android verweigert unsignierte APKs. Zum Testen reicht ein selbst-generierter Debug-Keystore:
# Keystore einmalig erstellen (falls noch nicht vorhanden)
keytool -genkey -v -keystore debug.keystore \
-alias androiddebugkey -keyalg RSA -keysize 2048 \
-validity 10000 -storepass android -keypass android \
-dname "CN=Android Debug,O=Android,C=US"
# APK signieren
apksigner sign \
--ks debug.keystore \
--ks-key-alias androiddebugkey \
--ks-pass pass:android \
--key-pass pass:android \
--out ledstrip_signed.apk \
ledstrip_modified.apk
# APK auf Gerät installieren (vorher Original deinstallieren!)
adb uninstall wl.smartled
adb install ledstrip_signed.apkSignature-Mismatch bei Updates
Eine mit einem anderen Keystore signierte APK kann nicht als Update über die Original-App installiert werden — Android prüft die Signatur. Deinstalliere die Original-App zuerst. Dabei gehen App-Daten (Login-Sessions, Cache) verloren.
Split-APKs aus App Bundles
Moderne Android-Apps werden oft als App Bundle (AAB) ausgeliefert und vom Google Play Store in mehrere Split-APKs aufgeteilt. Mit ADB holst du alle:
# Alle APK-Pfade der App anzeigen
adb shell pm path wl.smartled
# Ausgabe (Beispiel):
# package:/data/app/wl.smartled-1/base.apk
# package:/data/app/wl.smartled-1/split_config.arm64_v8a.apk
# package:/data/app/wl.smartled-1/split_config.de.apk
# Alle APKs extrahieren
adb pull /data/app/wl.smartled-1/ ./apks/
# Jede APK separat dekodieren
for apk in apks/*.apk; do
apktool d "$apk" -o "decoded_$(basename "$apk" .apk)"
doneNative Bibliotheken liegen oft in split_config.arm64_v8a.apk — nicht in base.apk. Wenn du in base.apk kein lib/-Verzeichnis findest, schau in den Split-APKs.
Häufige Probleme
| Problem | Ursache | Lösung |
|---|---|---|
brut.androlib.err.UndefinedResObject | Framework fehlt | apktool if framework-res.apk ausführen |
Build schlägt fehl mit already installed | Framework-Konflikt | apktool empty-framework-dir und neu versuchen |
| APK nach Modifikation startet nicht | Smali-Syntaxfehler | Smali-Diff prüfen; Android-Logcat lesen: `adb logcat |
apksigner nicht gefunden | Android SDK fehlt | Aus Android SDK: build-tools/<version>/apksigner |
INSTALL_PARSE_FAILED_NO_CERTIFICATES | APK unsigniert | APK mit apksigner signieren |
| Zipalign-Fehler | Alignment fehlt | zipalign -v 4 in.apk out.apk vor dem Signieren |
Framework-Installation
Manche Hersteller-Apps (insbesondere auf Samsung oder Xiaomi) nutzen herstellerspezifische Framework-Ressourcen. apktool benötigt dafür das Framework-APK des Geräts, das du einmalig mit apktool if /system/framework/framework-res.apk installierst (APK via ADB vom Gerät ziehen).
Zusammenfassung
- apktool dekodiert APKs in lesbares XML (Manifest, Ressourcen) und Smali-Assembler — keine Java-Dekompilierung wie JADX
- AndroidManifest.xml zeigt alle BLE-Permissions, deklarierte Services und Feature-Anforderungen
- String-Ressourcen (
res/values/strings.xml) können UUIDs und API-Konfigurationen enthalten - Der Decode → Modify → Build → Sign-Zyklus ermöglicht APK-Patching für Debug-Logging oder Certificate-Pinning-Bypass
- Split-APKs aus App Bundles müssen separat extrahiert und dekodiert werden
- Signatur-Mismatch erfordert Deinstallation der Original-App vor der Installation der modifizierten Version