Decompiling an Android™ App
When I wanted to take a look at an app which is installed on my HTC I got the impression that the knowledge required to decompile an app is scattered over several websites. If you search you can find it, but it is not very obvious. That’s why I want to give a clear overview on how to do so.
Before you start, please don’t worry about any version numbers that appear in commands. The versions may (or better: will) change.
Why should I decompile an app
There can be several reasons why you might want to decompile an app. I will mention some here:
- simply because you are curious and want to see what the source code looks like (at least roughly, because decompiling won’t give you exactly the same source code)
- to see if there are any security problems in your app, like keys written directly as strings in the source code
- to find a way to utilize undocumented functions
- to find some secrets ;)
I only tried this way with my HTC Wildfire (yeah, I’m not up to date ;) ) attached via USB to my MacBook Pro. And I only decompiled an app with no invocation of native methods.
Now some requirements:
- baksmali and smali (http://code.google.com/p/smali/)
- baksmali for converting .odex -> .smali
- smali for converting .smali -> .dex
- dex2jar (http://code.google.com/p/dex2jar/)
- for converting .dex -> .jar
- JD-GUI (http://java.decompiler.free.fr/?q=jdgui)
- for reading class files, respectively jars
- AXMLPrinter2 (http://code.google.com/p/android4me/)
- to be able to read XML-files, which are already in Android binary format
And having your Eclipse IDE with ADT is of course obligatory.
Now what you have to do:
Plug your smartphone in your computer and start Eclipse. To be able to browse the files stored on your smartphone you have to enable debug mode. Open the files explorer view in Eclipse. Now you should see something like this (if your file explorer stays empty you have to select your device in the devices view):
You can browse for the app you would like to decompile in this view. This view doesn’t show every folder and file on your device. To see everything you have to use the adb shell command in your terminal (my device is not rooted, so I cannot access every folder, if you can’t access a certain folder you’ll have to root your device; see: http://stackoverflow.com/questions/1043322/why-do-i-get-access-denied-to-data-folder-when-using-adb).
If I want to decompile the flashlight app, for example, I will find it under /system/app:
Pull both files from your device with the symbol in the top right corner of the view (if you’re not interested in the XML-files - like AndroidManifest or the layouts - you won’t need the .apk file). Don’t disconnect your phone yet, because you will need some more .odex files.
First the XML-files:
Rename your .apk file into .zip and extract it. To see the content of an XML-file you’ll have to type the following in your terminal, assuming the AXMLPrinter2.jar is in your current folder:
java -jar AXMLPrinter2.jar [path to the xml]/someFile.xml > [preffered output file name]
java -jar AXMLPrinter2.jar Flashlight/AndroidManifest.xml > Manifest.txt
Now to the source files:
Before you use baksmali on your .odex file, you have to get some more .odex files from your smart phone. The baksmali documentation (http://code.google.com/p/smali/wiki/DeodexInstructions) mentions at least 5 additional files: core.jar, ext.jar, framework.jar, android.policy.jar and services.jar
If you take the .odex equivalent, it’ll work, too (In fact, I only used the .odex-versions).
It could be possible that you’ll need some more files. Baksmali will show you an error message with the name of the missing file, like:
Cannot locate boot class path file core.odex
Now, let’s see how to use baksmali. I assume that the baksmali-1.3.2.jar is in your current location. Also, you should create a folder for the required .odex files. In my example, that folder will be “odexs” (you could also name the files separately, but that’s tedious):
java -jar baksmali-1.3.2.jar -d [your .odex folder]-x someFile.odex
java -jar baksmali-1.3.2.jar -d odexs/ -x Flashlight.odex
To work for me, I also had to explicitly name the API level. If you see this exception:
ExceptionWithContext: regCount does not match the number of arguments of the method
Add the desired API:
java -jar baksmali-1.3.2.jar -a [API lvl] -d [your .odex folder]-x someFile.odex
java -jar baksmali-1.3.2.jar -d odexs -a 10 -x HtcFMRadio.odex
This will produce a folder called “out”. In "out" you can see the starting of a package name, like “com” and so on. If you reach the end, there will be several .smali files. Those files are already human-readable, but I prefer Java source code ;)
Now we gotta start with smali. Smali will produce an out.dex file. Just type (with the smali-1.3.2.jar in the same folder):
java -jar smali-1.3.2.jar out
Now that we have a .dex file, we can use dex2jar on it and get a jar as output. I would leave dex2jar in its folder, so the command looks like this:
Your terminal will show you something like this:
dex2jar out.dex -> out_dex2jar.jar
And, as you can guess, you now have a jar-file containing the classes. Just open this file with JD-GUI and you can enjoy source-code ;)
I’d like to thank these two sources:
These sources were of great help, and of course thanks to the guys who invented bak-/smali, dex2jar and JD-GUI.