Let’s have a look at three different scenario:
As an attacker, you want to analyze and modify the app’s behavior. In this case, I prefer Frida because it is much simpler and works most of the time. However, sometimes an app can detect Frida. Of course, you can hook the method(s) that trigger the Frida detection to bypass it, but that’s often not simple. Moreover, debugging allows you to access local variables inside a method, which Frida does not allow.
A user has a debuggable application installed on own device. If the application is debuggable you can:
Note: This scenario is often impossible because no release application on the Play Store can have
android:debuggable="true"[↗] [↗]. It means that the user has installed the app from a third-party store.
You might have the app Java source code. Again, this scenario is highly unlikely, but not impossible.
You need to have an application debuggable. If the app is not debuggable you can [↗]:
android:debuggable="true"
in AndroidManifest.xml. You don’t need to be
root.ro.debuggable property set to 1.
In some cases, this may not suffice as OS or app components may
check the Manifest’s debuggable flag before or during
execution.ro.debuggable.
Normally this value is read only. However with
magisk we can use resetprop.
# Set ro.debuggable
resetprop ro.debuggable 1
# Restart Android zygote process
stop; startYou can debug an application to a different levels:
If you don’t have the original Java code, you can debug the smali code. To do this, you can use IntelliJ/Android Studio + smalidea plugin or jadx.
jadx-gui guide
For more info: https://github.com/skylot/jadx/wiki/Smali-debugger.
You need to have the original java code. You can use tools like Android studio and jdb.
This is the simpler approach. You can follow the official guide: Debug pre-built APKs.
Set app to wait (optional).
adb shell am set-debug-app -w app_package_nameIf we open the app, we’re going to get waiting for debugger.
Find app process id.
adb shell ps | grep -i app_package_nameSet Up Port Forwarding.
adb forward tcp:8000 jdwp:<PROCESS_ID>Start JDB.
jdb -attach localhost:8000 -sourcepath <source_file>
# If you set app to wait you also need to suspend all threads
{ echo "suspend" ; cat ; } | jdb -attach localhost:8000 -sourcepath <source_file>Tip: Other useful commands:
# List all forward socket connections adb forward --list # Remove specific/all forward socket connection forward --remove LOCAL forward --remove-all
jdb command examples
# List loaded class
classes
# Show methods of a class
methods ClassName
# Set a breakpoint
# Even if the class NameClass has not yet been loaded,
# JDB will register the breakpoint and activate it
# as soon as the class is loaded by the JVM.
stop in ClassName.NameMethod
# print source code
list
# Dumps the stack of the current thread
where
# list all commands
help