Android App Analysis

Android App Analysis

Static and dynamic analysis of Android applications, from pulling the APK off a device through decompiling Smali, inspecting the manifest, and dumping runtime state.

May 6, 2026
Updated Apr 8, 2026
2 min read

Getting the APK

If the app is in the Play Store, the lazy way is to install it on a device and pull it off:

adb shell pm list packages | grep target
adb shell pm path com.target.app
# package:/data/app/.../base.apk

adb pull /data/app/~~hash~~/com.target.app-xxx/base.apk

If the app ships split APKs (most do now), pull all of them:

adb shell pm path com.target.app
# package:/data/app/.../base.apk
# package:/data/app/.../split_config.arm64_v8a.apk
# package:/data/app/.../split_config.en.apk
# package:/data/app/.../split_config.xxhdpi.apk

# Pull each, or merge into a single APK with apkeditor or apkmirror tools

If the app is not in the store, the client should provide a build. If they will not, that is itself a finding worth raising.

First Pass: The Manifest

The manifest tells you the attack surface in two minutes.

apktool d base.apk -o target/
cat target/AndroidManifest.xml

What I look for, in order:

  1. android:debuggable="true", free game if present
  2. android:allowBackup="true", lets you adb backup the app data
  3. android:networkSecurityConfig, points to the cleartext and pinning config
  4. Exported components, anything with android:exported="true" and no permission is reachable from any app on the device
  5. Custom permissions, sometimes apps define a permission then forget to use it
  6. Deep links, look for <intent-filter> with <data> elements
  7. Custom URL schemes

Quick command for exported components:

grep -E 'android:exported="true"' target/AndroidManifest.xml

Decompiling

Two tools, two purposes.

apktool, for resources and Smali

apktool d base.apk -o target/
# target/smali/        - Smali assembly
# target/res/          - Resources
# target/AndroidManifest.xml

Smali is ugly to read but it is the ground truth. When jadx output is wrong (and it sometimes is), Smali is what is actually running.

jadx, for readable Java

jadx -d jadx-out base.apk
# or interactively
jadx-gui base.apk

jadx-gui is what I open first. Search across the decompiled source, jump to definitions, watch the call graph build out.

Useful searches in jadx

  • OkHttpClient and CertificatePinner, find SSL pinning
  • BuildConfig, hardcoded API URLs and keys
  • getSharedPreferences, local storage usage
  • Cipher.getInstance, crypto choices
  • Log.d and Log.e, what gets logged
  • Intent.parseUri, deep link handlers

Static Analysis Targets

Hardcoded secrets

# Search the unpacked resources and Smali
grep -r "api_key\|apiKey\|secret\|token\|password" target/
# Search strings in the original APK
strings base.apk | grep -i "api\|key\|secret"

Cleartext traffic

Look for usesCleartextTraffic="true" in the manifest, or HTTP URLs in the strings.

Crypto

Search for DES, ECB, MD5, hardcoded IVs (new IvParameterSpec(new byte[]), and hardcoded keys.

Logging

Log.d, Log.v, Log.i, sometimes including tokens or PII. Production builds should strip these but rarely do.

Dynamic Analysis

Watch logcat

# Filter by the app's PID
adb shell pidof com.target.app
adb logcat --pid=$(adb shell pidof com.target.app)

# Or filter by tag
adb logcat -s TargetApp:V

Inspect storage

adb shell run-as com.target.app
ls -la /data/data/com.target.app/
# shared_prefs/  databases/  files/  cache/
cat shared_prefs/prefs.xml
sqlite3 databases/main.db

If run-as does not work (release build), you need root.

Intercept traffic

Configure Burp or mitmproxy as the device proxy, push the CA into the system store (see Mobile Pentesting Fundamentals), and start the app. If pinning is in place, see SSL Pinning Bypass.

Trigger exported components

# Exported activity
adb shell am start -n com.target.app/.HiddenActivity

# Exported activity with extras
adb shell am start -n com.target.app/.WebViewActivity -e url "https://attacker.com"

# Exported service
adb shell am startservice -n com.target.app/.BackgroundService

# Broadcast receiver
adb shell am broadcast -a com.target.app.RECEIVE_DATA --es payload "evil"

# Content provider
adb shell content query --uri content://com.target.app.provider/users

Modifying the App

When hooking is not enough and you need to actually patch the binary:

# Decompile
apktool d base.apk -o target/

# Edit Smali in target/smali/...
# Common edit: change `const/4 v0, 0x0` (false) to `const/4 v0, 0x1` (true)

# Rebuild
apktool b target/ -o patched.apk

# Sign
keytool -genkey -v -keystore my.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000
apksigner sign --ks my.keystore patched.apk

# Install
adb install -r patched.apk

This is heavy-handed. I prefer Frida hooks first, patching second.

Common Findings

FindingHow I look for it
Hardcoded API keysgrep on BuildConfig and strings
Insecure data storageshared_prefs, databases, file mode MODE_WORLD_READABLE
Exported activity bypasses loginList exported activities, launch them directly
Deep link XSS or open redirectFind Intent.parseUri, test with crafted URIs
WebView with file accessSearch for setAllowFileAccess(true) or setJavaScriptEnabled(true)
Insecure broadcast receiversExported receivers handling sensitive intents
TapjackingActivities without filterTouchesWhenObscured

Last updated on