Explanation of the different ways to decompile an APK. Decompiling an APK means to recover the Java code (or another intelligible code) from an APK file.
This can be useful to analyse third-party apps, or to modify them (by compiling the decompiled code to an APK again).
What Is An APK?
APK stands for an Application Package, and it is the file format in which an app can be installed on an Android device.
An APK file is a ZIP file that contains a file called classes.dex
.
The classes.dex
file contains the entire code of an app in DEX bytecode.
DEX stands for Dalvik Executable, and DEX bytecode is the machine code of the Dalvik Virtual Machine running on Android devices.
How To Get The APK Of An App?
The Google Play Store does not provide the APKs of the apps that are distributed there.
In order to nevertheless get the APK of an app, you can use one of the following ways:
- APKMirror: a website providing the APKs of many common apps
- Apk Extractor: an app that allows to extract the APK of any app installed on your device
How To Decompile An APK?
There are two ways to decompile an APK.
1. d2j-dex2jar
The d2j-dex2jar
tool allows to view the decompiled Java code, but not to edit the Java code, or recompile the app.
Usage
- Change extension of APK from
.apk
to.zip
and unzip the file - Find
classes.dex
in the unzipped folder - Decompile
classes.dex
toclasses.jar
with the following command:d2j-dex2jar -f -o classes.jar classes.dex
- Now you can browse the Java code in
classes.jar
with the JD-GUI tool
Apktool
Apktool
allows to decompile everything of the app (including Manifest and resources), to edit the decompiled code, and to recompile the app.
However the target language of the decompilation is not to Java but smali.
Usage
- Decompile the APK with the following command:
apktool d app.apk -o out/ -f
- Now you can view and edit the smali code with any text editor
- For recompiling the app, use the following command:
apktool b out/
Code Obfuscation
There is a caveat to APK decompilation: code obfuscation.
Code obfuscation replaces all the identifers chosen by the developer (class names, method names, variable names, etc.) with short meaningless strings.
With both of the above decompilation methods, if the app has been obfuscated (for example with ProGuard), then the decompiled code contains only these obfuscated identifiers, and not the original ones.
This makes it much more difficult make sense of the decompiled code (however, not impossible).
On the other hand, if the app hasn’t been obsucated, then both of the above decompilation method can recover the original identifiers.
Levels of Obfuscation
Obfuscation can occur either on the Java-level or on the DEX-level.
Java-level means that the identifiers of the Java code are obfuscated before it is compiled to Java bytecode (and then to DEX bytecode).
DEX-level means that the obfuscation occurs on the DEX bytecode (that is, after the Java $\rightarrow$ Java bytecode $\rightarrow$ DEX bytecode compilation steps)
The common tools for Android code obfuscation are ProGuard for Java-level obfuscation and DexGuard for DEX-level obfuscation.
Notes
Supporting tools for editing and understanding smali code:
- Xposed: framework for modules that modify an existing app by decompiling its APK and recompiling it; to use these modules, a rooted device is necessary
- BurpSuite - intercept HTTPS requests
- SmaliEx - recombine multi-dexed files to a single DEX file
- Frida - for quick prototyping
- AndroidEagleEye - based on Xposed
- IDA - Interactive Disassembler
- smalidea - smali plugin for IntelliJ
Xposed modules:
- RootCloak - hide to an app that the current user is root (Xposed module)
- YouTube Background Playback - enable running YouTube video in backgrond
- YouTube AdAway - remove ads from YouTube app