Simply out of necessity I've written this mini-tutorial how debug android APKs using Eclipse and DDMS.
After hours of wild googling these are the steps to make your APK debuggable under Eclipse. I'll be using the
FakeBanker APK reverse-engineered in previous articles.
- UPDATE 2014-12-09:
Before looking at the next steps, make sure you'll have a look at ADUS. It will help you with the automation of several steps described in this post. Added some additional infos regarding the breakpoints.
Dump the APK
First of all make sure you'll have the latest version of
apktool. I've compiled it by myself:
# git clone git://github.com/iBotPeaches/Apktool.git oCloning into 'Apktool'... remote: Counting objects: 9605, done. remote: Compressing objects: 100% (3622/3622), done. remote: Total 9605 (delta 4556), reused 9494 (delta 4502) Receiving objects: 100% (9605/9605), 34.27 MiB | 3.89 MiB/s, done. Resolving deltas: 100% (4556/4556), done. Checking connectivity... done. # cd Apktool # ./gradlew build fatJar [o...]
Afterwards you'll get a new fresh
apktool to use within the next steps:
# find . -name "apktool-cli.jar" ./obrut.apktool/apktool-cli/build/libs/apktool-cli.jar # cp ./brut.apktool/apktool-cli/build/libs/apktool-cli.jar /tmp
After having installed the right tool it's time to dump the APK contents:
# java -jar /tmp/apktool-cli.jar d -d FakeBanker.apk -o source I: Using Apktool 2.0.0-3d2e93-SNAPSHOT on FakeBanker.apk I: Loading resource table... I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: /home/victor/apktool/framework/1.apk I: Regular manifest package... I: Decoding file-resources... I: Decoding values */* XMLs... I: Baksmaling classes.dex... I: Copying assets and libs... I: Copying unknown files... I: Copying original files...
Afterwards I got following file structure:
tree -L 2 source source ├── AndroidManifest.xml ├── apktool.yml ├── original │ ├── AndroidManifest.xml │ └── META-INF ├── res │ ├── drawable-hdpi │ ├── drawable-ldpi │ ├── drawable-mdpi │ ├── drawable-xhdpi │ ├── layout │ ├── menu │ ├── raw │ └── values └── smali ├── android └── com 14 directories, 3 files
Make APK debuggable
After dumping the APK now you'll have to mark your APK as debuggable. There are several ways in order to achieve that:
- using apktool
If you want to do it manually open the
AndroidManifest.xml file and search for the
application tag. Then insert new attribute
android:debuggable='true' like I did:
... <application android:theme="@style/AppTheme" android:label="@string/app_name" android:icon="@drawable/ic_launcher1" android:debuggable="true" android:allowBackup="false"> ...
Build new APP
Now you're ready to build you new debuggable APK using
java -jar /tmp/apktool-cli.jar b -d source FakeBanker.Debug.apk I: Using Apktool 2.0.0-3d2e93-SNAPSHOT on source I: Checking whether sources has changed... I: Smaling smali folder into classes.dex... I: Checking whether resources has changed... I: Building resources... Warning: AndroidManifest.xml already defines debuggable (in http://schemas.android.com/apk/res/android); using existing value in manifest. I: Building apk file...
A few explanations regarding the parameters:
- run apktool in build mode
- make APK debuggable (this is the 2nd way I was previously talking about)
I'll be using
jd-gui to undex the dex files inside the newly created package. First let's unpack
# unzip FakeBanker.Debug.apk -d unpacked Archive: FakeBanker.Debug.apk extracting: unpacked/res/drawable-hdpi/ic_launcher1.png extracting: unpacked/res/drawable-hdpi/logo.png extracting: unpacked/res/drawable-ldpi/ic_launcher1.png extracting: unpacked/res/drawable-mdpi/ic_launcher1.png extracting: unpacked/res/drawable-xhdpi/ic_launcher1.png inflating: unpacked/res/layout/actup.xml inflating: unpacked/res/layout/main.xml inflating: unpacked/res/layout/main2.xml inflating: unpacked/res/menu/main.xml extracting: unpacked/res/raw/blfs.key inflating: unpacked/res/raw/config.cfg inflating: unpacked/AndroidManifest.xml inflating: unpacked/classes.dex inflating: unpacked/resources.arsc
dex2jar do its job:
# cd unpacked # dex2jar classes.dex dex2jar classes.dex -> classes-dex2jar.jar
Now open the jar file using
jd-gui and save the sources as zip like I did:
Sign the APK
In order to push your APK to the device you'll have to sign it. I'll therefor using a test certificate:
# git clone https://github.com/appium/sign Cloning into 'sign'... remote: Counting objects: 49, done. remote: Total 49 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (49/49), done. Checking connectivity... done.
Now let's sign it:
# java -jar sign/dist/signapk.jar sign/testkey.x509.pem sign/testkey.pk8 FakeBanker.Debug.apk FakeBanker.Debug.Signed.apk
Install the APK
Having signed the APK now you're ready to push it to your device and have some fun.
# adb devices -l List of devices attached emulator-5554 device product:sdk model:sdk device:generic # adb install FakeBanker.Debug.Signed.apk 1628 KB/s (219033 bytes in 0.131s) pkg: /data/local/tmp/FakeBanker.Debug.Signed.apk Success
We'll add the Java sources to the
source directory structure:
# mkdir source/src # unzip classes-dex2jar.src.zip -d source/src Archive: classes-dex2jar.src.zip creating: source/src/android/ creating: source/src/android/support/ ...
The new directory structure will be:
# tree -L 2 source source ├── AndroidManifest.xml ├── apktool.yml ├── bin │ ├── android │ └── com ├── build │ └── apk ├── dist │ └── FakeBanker.apk ├── original │ ├── AndroidManifest.xml │ └── META-INF ├── res │ ├── drawable-hdpi │ ├── drawable-ldpi │ ├── drawable-mdpi │ ├── drawable-xhdpi │ ├── layout │ ├── menu │ ├── raw │ └── values ├── smali │ ├── android │ └── com └── src ├── android └── com 23 directories, 4 files
I had to active the debug settings for my targeted app. Go to
Device Settings ->
Select debug app. Also make sure you have
Wait for debugger activated.
This will prevent your app starting before any debugger gets connected to it.
Create new Java project
First create a new Java project and use
source as the location of the project.
Add src folder to build path
Make sure the
src folder is added as a source location to the build path.
Check project properties
You could also check the project properties by clicking on it and then
ALT+Enter. You should have sth similar to:
Having set up the Eclipse environment let's add some breakpoints.
Important note: As stated here you should pay attention where you set your breakpoint:
You must select line with some instruction, you can't set breakpoint on lines starting with ".", ":" or "#".
So be careful whet choosing your breakpoints otherwise you might ask yourself why your code doesn't get debugged.
First search for onCreate in all files:
Eclipse found several matches:
We'll now concentrate on
MainActivity.java and set a breakpoint:
Switching the perspective to
Debug you should be able to see your breakpoints (marked in red):
Before running our application we'll have a look at the already running processes on the device:
After starting the application in the
AVD you'll notice a new process:
The red "bug" indicates that the process isn't being debugged yet. Meanwhile the app waits for some debugger to get connected:
In order to be able to debug process you'll have to add a new debug configuration:
When setting up the configuration pay attention to the port your debugger should connect to. Make sure it matches with the port pair previously seen in the running process list (marked in red):
Now click on Debug and you're ready to go. Take a look at the running processes. You'll notice sth changed:
The bug is now "green" meaning you're ready to debug your application.
We've previously set a breakpoint at the
onCreate method. Now that the application is running I had to "trigger" that breakpoint. Switching to my AVD I took
a look at the application and filled in the fields:
Afterwards I've clicked Enter. Switching back to Eclipse I got following picture:
The execution stopped at the breakpoint. Success! Now I've typed F6 (Step over) and the execution moved on:
Using great tools like
dex2jar you can prepare your APK to inspect it dynamically in Eclipse. I think Eclipse (along with ADT) is a very powerful tool
when it comes to dynamic analysis. I can easily switch between code parts and analyze the execution flow. Keep in mind that when the original is obfuscated you may
want to debug smali code. In that case make sure you add the smali order instead of the src one (described earlier). For any questions feel free to write comments