Back to lab
Tutorial Android 10 min

Static APK Analysis with JADX and Ghidra

May 26, 2026

Why static analysis

Before instrumenting an app with Frida, static analysis lets you map:

  • Security implementations (SSL Pinning, root detection, encryption)
  • Hardcoded secrets (API keys, tokens, internal endpoints)
  • Authentication and authorization logic
  • Native libraries requiring analysis with Ghidra

The JADX (Java/Kotlin code) + Ghidra (native C/C++ code) combination covers practically 100% of an APK's attack surface.


JADX — Decompiling Java and Kotlin code

Installation

# Via package manager (Linux)
sudo apt install jadx

# Or download the release at: https://github.com/skylot/jadx/releases

Opening the APK

jadx app.apk -d jadx_output/
jadx-gui app.apk  # GUI (recommended for exploration)

Output structure

jadx_output/
├── sources/
│   └── com/example/app/
│       ├── MainActivity.java
│       ├── network/ApiClient.java
│       └── security/PinManager.java
└── resources/
    ├── AndroidManifest.xml
    └── res/values/strings.xml

What to look for in decompiled code

1. Hardcoded secrets

grep -r "api_key\|apiKey\|secret\|password\|token\|Bearer" jadx_output/sources/ -i
grep -r "key\|secret\|endpoint" jadx_output/resources/ -i

2. SSL Pinning implementation

grep -r "CertificatePinner\|checkServerTrusted\|TrustManager\|X509" \
     jadx_output/sources/ -l
// PinManager.java
new CertificatePinner.Builder()
    .add("api.company.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
    .build();

3. Root and Frida detection

grep -r "su\|superuser\|RootBeer\|frida\|/proc/maps\|magisk" \
     jadx_output/sources/ -i -l

4. Cryptography — watch for hardcoded keys

// Vulnerable: hardcoded AES key
byte[] key = "1234567890abcdef".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");

AndroidManifest.xml — Permissions and exposed components

cat jadx_output/resources/AndroidManifest.xml

What to check:

  • android:exported="true" on Activities, Services and BroadcastReceivers
  • android:debuggable="true" — critical vulnerability in production
  • Excessive permissions without justification

Ghidra — Analyzing native libraries (.so)

Apps with native code compile to .so (ARM/ARM64 shared objects). JADX does not decompile C/C++ — this is where Ghidra comes in.

Installation

# Download at: https://ghidra-sre.org/ (requires Java 17+)
unzip ghidra_*.zip
./ghidra_*/ghidraRun

Extracting libs from APK

unzip app.apk "lib/*" -d extracted_libs/
# extracted_libs/lib/arm64-v8a/libnative.so

Ghidra analysis workflow

  1. New Project → Import File → select libnative.so
  2. Accept auto-analysis (~30s for large libs)
  3. In Symbol TreeFunctions to see exported functions

JNI function naming pattern

Java_com_example_app_SecurityManager_validateToken
Java_com_example_app_CryptoUtils_decrypt

Example: hardcoded AES key in native code

// Decompiled by Ghidra
void Java_com_example_CryptoUtils_decrypt(JNIEnv *env, jobject obj) {
    char key[16] = {0x41, 0x42, 0x43, 0x44, ...}; // "ABCD..."
    AES_set_decrypt_key(key, 128, &aes_key);
}

Use Search → For Strings to find URLs, keys and internal error messages.


Complete static analysis workflow

1. Extract APK
   └── unzip app.apk / adb pull

2. JADX — Java/Kotlin code analysis
   ├── Hardcoded secrets and keys
   ├── SSL Pinning implementation (hosts and hashes)
   ├── Root/Frida detection (methods and libs used)
   └── Exported components in Manifest

3. Ghidra — Native library analysis (.so)
   ├── Exported JNI functions
   ├── Cryptographic keys in memory
   └── Validation logic in C/C++

4. Document findings for report
   └── Mapping: attack surface → bypass via Frida

Complementary tools

| Tool | Use | |------|-----| | apkanalyzer | Android SDK CLI for quick inspection | | MobSF | Automated static + dynamic analysis | | objection | Frida wrapper with ready-to-use pentest commands | | apksigner | Verifies APK signature and integrity |


References

Static APK Analysis with JADX and Ghidra — APCosta Lab — APCosta