| name | jadx |
| description | Decompile and reverse engineer Android APK, DEX, AAR, and JAR files using JADX (skylot/jadx, 43k+ stars). Use when performing mobile application security assessments, hunting for hardcoded secrets/API keys, analyzing AndroidManifest.xml for exported components, reverse engineering API calls, or preparing for dynamic analysis with Frida. Covers jadx CLI and jadx-gui, output structure, deobfuscation options, Smali vs Java output, Gradle export, thread tuning, secret/key hunting workflows, and integration with Frida for dynamic analysis following static review.
|
| metadata | {"author":"redhoundinfosec","version":"1.0","repo":"https://github.com/skylot/jadx"} |
jadx Agent Skill
When to Use This Skill
Use this skill when:
- Performing a mobile application security assessment on an Android APK
- Hunting for hardcoded API keys, tokens, credentials, or sensitive data in APK source
- Analyzing AndroidManifest.xml for attack surface (exported activities, deep links)
- Reverse engineering API endpoints, authentication flows, or cryptographic implementations
- Deobfuscating obfuscated Android code before dynamic analysis with Frida
- The user has a .apk, .dex, .aar, or .jar file to analyze
What JADX Does
JADX is a DEX to Java decompiler. It converts Dalvik bytecode (.dex files inside .apk) back into human-readable Java source code. Unlike Smali disassemblers (baksmali) that produce assembly-level output, JADX produces near-original Java, making it significantly easier to read business logic, API integrations, and security controls. JADX supports APK, DEX, AAR, JAR, ZIP, and class files. The GUI (jadx-gui) adds search, navigation, and cross-reference features critical for efficient code review.
Installation
sudo apt update && sudo apt install jadx
jadx --version
wget https://github.com/skylot/jadx/releases/latest/download/jadx-<version>.zip
unzip jadx-<version>.zip -d /opt/jadx
chmod +x /opt/jadx/bin/jadx /opt/jadx/bin/jadx-gui
ln -s /opt/jadx/bin/jadx /usr/local/bin/jadx
ln -s /opt/jadx/bin/jadx-gui /usr/local/bin/jadx-gui
brew install jadx
git clone https://github.com/skylot/jadx.git
cd jadx && ./gradlew dist
docker run --rm -v $(pwd):/work ghcr.io/skylot/jadx jadx --help
jadx --version
Core Concepts
Android APK Structure
An APK is a ZIP archive. JADX processes the following components:
target.apk (ZIP)
├── AndroidManifest.xml — App permissions, components, intents (binary XML)
├── classes.dex — Main Dalvik bytecode → JADX decompiles to Java
├── classes2.dex — Additional DEX (multidex apps)
├── classes3.dex — Further DEX shards
├── resources.arsc — Compiled string/layout resources
├── res/ — XML layouts, drawables, raw assets
│ ├── layout/
│ ├── values/strings.xml
│ └── raw/ — Potential: keys, certs, config files
├── assets/ — Arbitrary files bundled with app
│ └── config.json — Often contains URLs, tokens
├── lib/ — Native libraries (.so)
│ ├── arm64-v8a/
│ └── x86_64/
└── META-INF/ — Signing info (certificates)
├── CERT.RSA
└── MANIFEST.MF
Smali vs JADX Java Output
| Smali | JADX Java |
|---|
| Output level | Dalvik assembly (register-based) | Java source |
| Readability | Low — requires Dalvik expertise | High — readable business logic |
| Accuracy | Exact (1:1 with bytecode) | ~95% — some constructs can't round-trip |
| Use case | Patching, exact byte modification | Code review, logic analysis |
| Tool | baksmali / apktool | jadx |
JADX is preferred for static analysis. Use apktool + smali for patching/instrumentation.
Obfuscation
ProGuard/R8 obfuscation renames classes (com.example.MainActivity → a.b.c), methods, and fields. JADX's --deobf flag uses heuristics to restore readable names where possible and generates a mapping file. Third-party obfuscators (DexGuard, Obfuscapk) may require manual renaming.
CLI Reference
jadx -d /tmp/output target.apk
jadx -d /tmp/output classes.dex
jadx -d /tmp/output library.aar
jadx -d /tmp/output target.jar
--deobf
--deobf-min LEN
--deobf-max LEN
--deobf-rewrite-cfg
--deobf-use-sourcename
-t N / --threads-count N
--no-res
--no-src
-e / --export-gradle
--show-bad-code
--no-imports
--single-class CLASS
--output-format (folder|single-file)
-v
--log-level (quiet|progress|error|warn|info|debug)
--fs-case-sensitive
jadx -d /tmp/output --deobf --deobf-min 2 -t 8 -e target.apk
jadx -d /tmp/output --no-res -t 8 target.apk
jadx -d /tmp/output --no-src target.apk
JADX-GUI Usage
jadx-gui
jadx-gui target.apk
Output Structure
After jadx -d /tmp/output target.apk:
/tmp/output/
├── sources/ # Decompiled Java source
│ ├── com/
│ │ └── example/
│ │ └── app/
│ │ ├── MainActivity.java
│ │ ├── network/
│ │ │ └── ApiClient.java
│ │ └── utils/
│ │ └── CryptoUtils.java
│ └── kotlin/ # Kotlin standard library (decompiled)
├── resources/ # Decompiled resources
│ ├── AndroidManifest.xml # Decoded binary XML
│ ├── res/
│ │ ├── values/
│ │ │ └── strings.xml
│ │ └── layout/
│ └── assets/
└── jadx-input-mapping.txt # Deobfuscation mapping (if --deobf used)
Common Workflows
Initial APK Triage
cp target.apk target.zip && unzip target.zip -d raw_apk/
ls raw_apk/
jadx -d /tmp/decompiled --deobf -t 8 target.apk
cat /tmp/decompiled/resources/AndroidManifest.xml
grep "package=" /tmp/decompiled/resources/AndroidManifest.xml | head -1
Hunting for Hardcoded Secrets
grep -rE "(api_key|apikey|api-key|secret|token|password|passwd|credential)" \
/tmp/decompiled/sources/ \
--include="*.java" -i -l | head -20
grep -rE "AKIA[0-9A-Z]{16}" /tmp/decompiled/ --include="*.java" --include="*.xml"
grep -rE "AIza[0-9A-Za-z\\-_]{35}" /tmp/decompiled/
grep -rE "https://[a-z0-9-]+\.firebaseio\.com" /tmp/decompiled/
grep -rE "Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+" /tmp/decompiled/
grep -rE "BEGIN (RSA |EC )?PRIVATE KEY" /tmp/decompiled/
grep -rE "(jdbc|mongodb|postgresql|mysql)://" /tmp/decompiled/ -i
grep -rE "(password|passwd|secret)\s*=\s*['\"][^'\"]{4,}" /tmp/decompiled/sources/ -i
cat /tmp/decompiled/resources/res/values/strings.xml | grep -iE "key|token|secret|url|endpoint"
find /tmp/decompiled/resources/assets/ -type f | xargs grep -l "key\|secret\|token\|api" 2>/dev/null
cat /tmp/decompiled/resources/assets/config.json 2>/dev/null
find /tmp/decompiled/resources/assets/ -name "*.json" -exec cat {} \;
AndroidManifest.xml Analysis
cat /tmp/decompiled/resources/AndroidManifest.xml
grep -A5 "activity" /tmp/decompiled/resources/AndroidManifest.xml | grep -i "exported=\"true\""
grep -A5 "receiver" /tmp/decompiled/resources/AndroidManifest.xml | grep -i "exported\|intent-filter"
grep -A5 "provider" /tmp/decompiled/resources/AndroidManifest.xml | grep -i "exported\|authority"
grep -B2 -A10 "scheme" /tmp/decompiled/resources/AndroidManifest.xml
grep "permission\|uses-permission" /tmp/decompiled/resources/AndroidManifest.xml
grep -iE "CAMERA|READ_CONTACTS|RECORD_AUDIO|ACCESS_FINE_LOCATION|READ_CALL_LOG|SEND_SMS|READ_EXTERNAL" \
/tmp/decompiled/resources/AndroidManifest.xml
grep "allowBackup\|debuggable" /tmp/decompiled/resources/AndroidManifest.xml
grep "networkSecurityConfig" /tmp/decompiled/resources/AndroidManifest.xml
Reverse Engineering API Calls
grep -rl "OkHttpClient\|Retrofit\|HttpURLConnection\|Volley\|HttpClient" \
/tmp/decompiled/sources/ --include="*.java"
grep -rE "https?://[a-zA-Z0-9./_-]+" /tmp/decompiled/sources/ --include="*.java" | \
grep -v "//\s" | sort -u
grep -rE "@(GET|POST|PUT|DELETE|PATCH)\s*\([\"']" /tmp/decompiled/sources/ --include="*.java"
grep -rE "Authorization|Bearer|X-API-Key|X-Auth" /tmp/decompiled/sources/ -i --include="*.java"
grep -rE "CertificatePinner|TrustManager|X509|hostnameVerifier|checkServerTrusted" \
/tmp/decompiled/sources/ --include="*.java" -l
Gradle Export (For Android Studio)
jadx -d /tmp/gradle_project --export-gradle target.apk
Advanced Techniques
Deobfuscation Workflow
jadx -d /tmp/deobf --deobf --deobf-min 2 -t 8 target.apk
cat /tmp/deobf/jadx-input-mapping.txt | head -50
grep -r "extends Activity\|extends Fragment\|extends Service\|extends BroadcastReceiver" \
/tmp/deobf/sources/ --include="*.java" -l
Certificate Pinning Bypass Preparation
grep -rE "CertificatePinner|TrustManager|checkValidity|pin\(" \
/tmp/decompiled/sources/ --include="*.java" -l
grep -rA 20 "CertificatePinner" /tmp/decompiled/sources/ --include="*.java" | head -60
Integration with Frida (Static → Dynamic)
After static analysis with JADX, use Frida for dynamic instrumentation:
pip3 install frida-tools
frida --version
adb push frida-server-<version>-android-arm64 /data/local/tmp/frida-server
adb shell chmod +x /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &
frida-ps -Ua
frida -U -n com.example.app -l ssl_bypass.js
cat > hook.js << 'EOF'
Java.perform(function() {
var ApiClient = Java.use("com.example.app.network.ApiClient");
ApiClient.buildOkHttpClient.implementation = function() {
console.log("[*] buildOkHttpClient called — bypassing pin");
var client = this.buildOkHttpClient();
return client;
};
});
EOF
frida -U -n com.example.app -l hook.js
frida-trace -U -n com.example.app -j "com.example.app.auth.AuthManager!*"
APKTool Comparison (When JADX Isn't Enough)
apktool d target.apk -o /tmp/apktool_out
apktool b /tmp/apktool_out -o patched.apk
keytool -genkey -v -keystore debug.keystore -alias debug -keyalg RSA -keysize 2048 -validity 365
jarsigner -keystore debug.keystore patched.apk debug
zipalign -v 4 patched.apk patched_aligned.apk
adb install patched_aligned.apk
Troubleshooting
"No input files" or decompile produces empty output:
file target.apk
unzip -l target.apk | grep ".dex"
Out of memory during decompile:
export JAVA_OPTS="-Xmx4g"
jadx -d /tmp/out target.apk
Some classes show as "// couldn't decompile method":
jadx -d /tmp/out --show-bad-code target.apk
baksmali disassemble classes.dex -o /tmp/smali_out
cat /tmp/smali_out/com/example/ProblemClass.smali
GUI crashes on large APKs:
- Increase heap: add
-J-Xmx4g to jadx-gui launch command
- Use CLI (
jadx) instead for decompile, then browse output in VS Code or grep
Deobfuscation produces wrong names:
--deobf is heuristic — short identifiers renamed but may be wrong
- Use jadx-gui interactive renaming for accurate renaming based on code context
- Check ProGuard mapping file if available from the developer (
mapping.txt)
Built by Red Hound InfoSec — On-demand offensive security expertise for SMBs.
20+ years of Fortune 500 experience. Penetration testing, attack surface analysis, and security consulting.
redhound.us | GitHub | Book a consultation