Comprehensive Android APK security audit with static analysis, dynamic instrumentation, source-to-sink tracing, IPC/component abuse analysis, and CVSS 4.0 reporting. Covers decompilation, manifest analysis, deep links and intent injection, secrets detection, crypto analysis, Frida/Objection integration, and APK repackaging. Use when user says "audit APK", "analyze android app", "mobile pentest", "APK security", "decompile APK", "android vulnerability assessment", "reverse engineer android", "modify APK", "intent injection", "deep link abuse", "bypass SSL pinning", "bypass root detection", or provides an APK for security review, decompiled Android sources, or decoded resources.
Resources
7Install
npx skillscat add dragonjar/android-pentesting-skill Install via the SkillsCat registry.
Android APK Security Audit
Overview
Deterministic 6-phase static analysis + optional dynamic confirmation workflow. Remove noise early, keep the package scope tight. Only report vulnerabilities where source, propagation, and sink are understood or clearly marked as needing dynamic confirmation.
When to Use
- User provides an APK file for security review
- User asks to analyze decompiled Android source code
- User needs to modify or repackage an APK for testing
- User wants mobile security testing or vulnerability assessment
- User needs help testing exported components, deep links, or intent injection
- User mentions Android reverse engineering or malware analysis
Critical Rules
- NEVER report bare grep hits without traced context
- ALWAYS constrain searches to the app namespace (avoid library noise)
- STOP and report immediately if decoding fails
- ALWAYS use imperative language in findings
- NEVER skip validation — if unsure, mark as "Needs Dynamic Confirmation"
- ALWAYS provide concrete PoC (adb command, Frida hook, or malicious intent)
- NEVER duplicate findings for the same root cause
Quality Note: Take your time to analyze thoroughly. Quality is more important than speed. Do not skip validation steps — a false positive is worse than a missed finding.
Execution Model
Tools to use: bash, write, edit, read, glob, grep for core workflow.
Toolchain Requirements
Before starting, verify these tools are installed:
- APKTool 3.0.1+ (
apktool --version) — aapt2-only mode; requires Java 17+ - JADX 1.5.5+ (
jadx --version) - Android SDK Platform Tools 36.0.2 (
adb,fastboot) - Android SDK Build Tools 36.0.0 (
apksigner,zipalign,aapt2,d8) - Frida 17.9.1 (
frida --version) — ⚠️ Frida-server on device must match frida-tools version exactly - Objection 1.12.4 (
objection --version) — Note: Objection is in maintenance mode - APKiD 3.0.0 (
apkid --version)
Run scripts/preflight-check.sh (bash), scripts/preflight-check.py (universal, JSON output), or scripts/preflight-check.ps1 (PowerShell) to verify all tools. See references/environment-setup.md for installation instructions.
Phase 0 — Decode and Detect Framework
Decode APK
apktool d app.apk -o decoded/ # Decode resources + smali
jadx -d jadx_output app.apk # Decompile to Java
apkid app.apk # Detect framework/packerFramework Detection
Identify the app's architecture early to tailor analysis.
React Native: grep -r "com.facebook.react" decoded/AndroidManifest.xml · Check for libhermes.so and index.android.bundle in assets/
Flutter: grep -r "io.flutter" decoded/AndroidManifest.xml · Check for libflutter.so and assets/flutter_assets/
Cordova/Ionic: grep -r "org.apache.cordova" decoded/AndroidManifest.xml · Check assets/www/ for cordova.js
Xamarin: grep -r "mono\|com.xamarin" decoded/AndroidManifest.xml · Check for libmonodroid.so
Reference:
references/hybrid-webview-frameworks.mdfor complete detection scripts, Frida detection hooks, and framework-specific security considerations.
Obfuscation Detection
- ProGuard/R8: Class names like
a.b.c,a$a,a$1 - DexGuard: Additional string encryption and native methods
- Custom obfuscation: Unusual patterns, mixed naming schemes
Reference:
references/static-analysis-patterns.mdfor detailed detection patterns.
Phase 1 — Attack Surface Mapping
Analyze AndroidManifest.xml
cat decoded/AndroidManifest.xml
aapt2 dump badging app.apkExported Components
Exported components are attack surfaces:
| Component | Exported If | Security Checks |
|---|---|---|
| Activities | android:exported="true" |
Intent filters, permission requirements |
| Services | android:exported="true" |
Intent filters, permission requirements |
| Receivers | android:exported="true" |
Intent filters, permission requirements |
| Providers | android:exported="true" |
Path permissions, read/write permissions |
Deep Link Schemes
Extract and document all deep link schemes:
<intent-filter>
<data android:scheme="scheme" android:host="host" />
</intent-filter>Security-Relevant XML Resources
Check res/xml/ for: network_security_config.xml (TLS/cleartext), file provider paths, preferences.
Reference:
references/android-manifest-checklist.mdfor complete 50+ manifest checks.
IPC / intent abuse: seereferences/intent-injection.mdandreferences/pendingintent-security.md.
Phase 2 — Targeted Triage
Scoped Grep Patterns
ALWAYS grep within the app namespace only. Use patterns from references/static-analysis-patterns.md:
| Category | Example Patterns | What to Look For |
|---|---|---|
| WebView sinks | loadUrl\(, evaluateJavascript |
Loading untrusted URLs |
| IPC sources | getIntent(), onNewIntent() |
Unsanitized data entry |
| Intent relays | getParcelableExtra, getSerializableExtra, startActivity\(, sendBroadcast\( |
Nested intent / confused deputy patterns |
| Hardcoded secrets | password\s*=, api[_-]?key |
Credentials in code |
| Encoded literals | Base64\.decode, "\x[0-9a-f]" |
Obfuscated strings |
| Weak crypto | DES/, MD5, "AES/ECB" |
Insecure algorithms |
| Insecure storage | SharedPreferences, MODE_WORLD_READABLE |
Unprotected data |
| Network/TLS | TrustManager, X509TrustManager |
SSL validation bypass |
| Native bridges | System\.loadLibrary, JNI methods |
Native code interfaces |
Resource File Analysis
Check res/values/strings.xml for secrets:
grep -iE "(key|token|secret|password|api)" decoded/res/values/strings.xmlReference:
references/static-analysis-patterns.mdfor 100+ grep patterns organized by vulnerability type.
Phase 3 — Data Flow Tracing
Source-to-Sink Methodology
Map data flow from untrusted sources to dangerous sinks:
Common Sources
| Source | Method | Example |
|---|---|---|
| IPC (Activities) | getIntent() |
Malicious intent data |
| IPC (Services) | onStartCommand() |
Start extras |
| Deep Links | getIntent().getData() |
URL parameters |
| WebView | JavascriptInterface |
Untrusted JS calls |
| Network | HttpResponse |
API responses |
| Storage | SharedPreferences |
Stored user input |
| External | Environment.getExternalStorageDirectory() |
File system data |
Common Sinks
| Sink | Method | Impact |
|---|---|---|
| Command Execution | Runtime.exec(), ProcessBuilder |
RCE |
| WebView Load | loadUrl(), loadData() |
XSS, Phishing |
| File Operations | FileWriter, FileOutputStream |
Path traversal, LFI |
| IPC Broadcast | sendBroadcast() |
Intent injection |
| Reflection | Class.forName(), getMethod() |
Code execution |
| Native Calls | JNI | Native code execution |
| SQL | SQLiteDatabase.execSQL() |
SQL injection |
Decision Rules
| Rule | Condition | Action |
|---|---|---|
| 1 | Direct flow source → sink | Report as Likely |
| 2 | Indirect flow via static analysis | Report as Likely if path clear |
| 3 | Dynamic/reflective call | Mark as Needs Dynamic Confirmation |
| 4 | Native boundary | Mark as Needs Dynamic Confirmation |
| 5 | Library code | Verify if app wraps securely |
| 6 | No sanitization | Escalate severity |
Manual Checks Grep Misses
| Check | Why grep misses | How to verify |
|---|---|---|
| Runtime permissions | requestPermissions() calls |
Trace onRequestPermissionsResult |
| Custom permission protections | checkPermission() |
Look for permission checks |
| Activity transitions & intent relays | startActivity() hides nested-intent forwarding and grant flags |
Follow intent construction, Parcelable relays, and FLAG_GRANT_* usage |
| File provider paths | XML + code | Map paths to exposed content URIs |
| Content provider queries | query() |
Trace URI construction |
Reference:
references/attack-patterns.mdfor modern attack vectors: intent injection, deep link abuse, WebView universal XSS, task hijacking, file provider path traversal, broadcast theft, component hijacking.
Phase 4 — Dynamic Analysis (Optional)
Use when static analysis hits a wall: obfuscation, reflection, native code, runtime protections.
Frida Integration
# Spawn app with hook
frida -U -f com.example.app -l script.js
# Attach to running process
frida -U com.example.app -l script.jsReference: bundled Frida scripts in
assets/frida-scripts/. Seereferences/frida-scripts-index.mdfor the canonical catalog.
Focused runtime triage: useandroid-file-access-monitor.jsfor filesystem/storage visibility,jni-tracer.jsfor JNI/native boundary discovery, andipc-abuse-helper.jsfor passive IPC logging plus intentional provider/deep-link validation.
Script Maturity Levels:
- STABLE: Production-ready (
ssl-pinning-bypass.js,root-detection-bypass.js,biometric-bypass.js,network-interceptor.js, etc.)- BETA: Functional but incomplete — use with caution
Objection Commands
objection -g com.example.app explore
# Enumerate components
android hooking list activities
android hooking list services
android hooking list receivers
# Bypass protections
android sslpinning disable
android keystore dumpADB Runtime Testing
# Test exported activity
adb shell am start -n com.example.app/.MainActivity -a android.intent.action.VIEW -d "scheme://host"
# Test exported receiver
adb shell am broadcast -a com.example.app.ACTION -e key "value"
# Monitor logs
adb logcat | grep com.example.appSSL Pinning bypass:
references/dynamic-analysis-setup.md+assets/frida-scripts/ssl-pinning-bypass.js
RASP bypass:references/rasp-bypass.md+assets/frida-scripts/native-root-detection-probe.jsfor anti-debug, anti-frida, emulator detection, and native root-check escalation.
Phase 5 — Classification and Reporting
Confidence Levels
| Level | Definition | Example Evidence |
|---|---|---|
| Confirmed | Full source-to-sink trace validated | Direct call chain from IPC source to Runtime.exec() with no sanitization |
| Likely | Strong evidence, minor gaps | Static trace clear but reflection obscures final sink |
| Needs Dynamic Confirmation | Static analysis inconclusive | Obfuscated code or native boundary requiring runtime verification |
Severity
Use CVSS 4.0. See references/cvss-scoring-guide.md for complete methodology and severity mapping.
Finding Template
## [ID] - [Title]
**Confidence**: [Confirmed/Likely/Needs Dynamic Confirmation]
**Severity**: [Critical/High/Medium/Low] (CVSS: [X.X])
**CWE**: [CWE-ID]
**OWASP**: [OWASP Category]
### Description
[1-2 sentences explaining what the vulnerability is]
### Affected Components
- **File**: `path/to/file.java`
- **Method**: `methodName()`
- **Component**: `[Activity/Service/Receiver/Provider]` (if applicable)
### Attack Scenario
1. Attacker [action, e.g., sends malicious intent with crafted data]
2. App [processing step, e.g., extracts parameter without validation]
3. Data propagates through [call chain]
4. Reaches sink [dangerous operation]
5. Results in [impact, e.g., arbitrary command execution]
### Proof of Concept
```bash
adb shell am start -n com.example.app/.MainActivity \
-a android.intent.action.VIEW \
-d 'exploit://host/path?payload=cmd%7Ccat%20/data/data/com.example.app/databases/db'Or provide Frida hook script for dynamic verification.
Impact
- Confidentiality: [High/Medium/Low/None] — [explanation]
- Integrity: [High/Medium/Low/None] — [explanation]
- Availability: [High/Medium/Low/None] — [explanation]
Remediation
// Provide secure code example
Intent intent = getIntent();
if (intent != null && intent.getData() != null) {
String input = intent.getData().getQueryParameter("path");
if (isValidPath(input)) {
loadUrl(input);
} else {
Log.w(TAG, "Invalid path detected");
}
}
private boolean isValidPath(String path) {
return path != null && !path.contains("..") &&
path.matches("^/safe/\\w+\\.html$");
}CVSS 4.0 Calculation
[Show vector string and score breakdown]
### Coverage Statement
End your report with:
Coverage Analysis:
- Static Analysis: Complete (all decompiled sources analyzed)
- Dynamic Analysis: [Complete/Partial/Not Performed] (reason if partial)
- Scope: [com.example.app.* namespace only]
- Framework: [React Native/Flutter/Native/Standard]
- Obfuscation: [ProGuard/R8/DexGuard/Custom/None]
Limitations:
- [List any limitations, e.g., "Native code analysis requires additional tools"]
- [Any components that could not be analyzed]
- [Any findings requiring additional verification]
Total Findings: X (Critical: Y, High: Z, Medium: A, Low: B)
> **Reference**: `references/reporting-templates.md` for executive summary format, remediation priority matrix, and presentation templates.
### Automated Report Generation
Use the `generate-report.py` script to generate professional HTML or Markdown reports from findings JSON:
```bash
# Generate HTML report
python3 scripts/generate-report.py \
--input findings.json \
--output report.html \
--app-name "My App" \
--package-name "com.example.app"
# Generate Markdown report
python3 scripts/generate-report.py \
--input findings.json \
--output report.md \
--app-name "My App" \
--package-name "com.example.app"The script supports both JSON array format and JSONL (one finding per line) and automatically:
- Sorts findings by severity (Critical first)
- Calculates CVSS 4.0 severity scores
- Generates executive summary with risk rating
- Maps OWASP MASTG categories
- Provides formatted proof of concept and remediation sections
See scripts/test-findings.json for the expected JSON structure.
APK Modification Workflow
1. Decode
apktool d app.apk -o app-modified/2. Modify — Smali Patching
Edit smali files in app-modified/smali/:
.method public checkSecurity()Z
.locals 1
# Original: iget-boolean v0, p0, Lcom/example/App;->securityEnabled:Z
# Patched — always return true
const/4 v0, 0x1
return v0
.end methodResource Modification
Edit XML or resource files in app-modified/res/:
<!-- Example: enable debug flag -->
<bool name="debug_mode">true</bool>3. Rebuild
apktool b app-modified/ -o app-modified.apk4. Sign
# Generate keystore (first time only)
keytool -genkeypair -v -keystore my-release-key.jks -alias androiddebugkey -keyalg RSA -keysize 2048 -validity 10000
# Align first
zipalign -v 4 app-modified.apk app-aligned.apk
# Sign (apksigner supports v1, v2, v3, v3.1 signatures)
apksigner sign --ks my-release-key.jks --ks-pass pass:myPassword --key-pass pass:myPassword --out app-signed.apk app-aligned.apk
# Verify signature
apksigner verify --verbose app-signed.apk5. Install and Verify
adb install -r app-signed.apkReference:
references/dynamic-analysis-setup.mdfor advanced repackaging, signature verification bypass, and ADB debugging. Seereferences/apk-modification-guide.mdfor smali editing edge cases and troubleshooting.
Troubleshooting
APK Decoding Fails
apktool d -f app.apk -o decoded/ -api 35 # Force mode with target Android API
aapt2 dump badging app.apk # Verify APK integrity
apkid app.apk # Detect packer/protectorIf packed → see references/packing-unpacking.md for unpacking techniques.
JADX Shows Bad Code
jadx --show-bad-code -v app.apk # Show code even with errors
jadx --decompilation-mode fallback app.apk
jadx-gui app.apk # GUI for manual inspectionFrida Cannot Attach
adb shell ps -A | grep frida
adb shell getprop ro.product.cpu.abi
adb shell "su -c 'killall frida-server'"
adb shell "su -c '/data/local/tmp/frida-server -D &'"Full setup:
references/dynamic-analysis-setup.md
Obfuscated Code Unreadable
- Identify obfuscator:
apkid app.apk - Enable JADX deobfuscation:
jadx --deobf app.apk - See
references/static-analysis-patterns.md→ "Obfuscation Patterns" - Switch to Phase 4 for runtime behavior
When to Escalate to Dynamic Analysis
Static analysis reaches limits when: obfuscation unclear, reflection, JNI boundaries, anti-debug/root detection, SSL pinning. → Proceed to Phase 4 using references/dynamic-analysis-setup.md.
Examples
Example 1: Quick Assessment
com.example.app.apk → Decode → Framework detect → Manifest audit → Secrets grep → CVSS report
Example 2: SSL Pinning Bypass
frida -U -f com.target.app -l ssl-pinning-bypass.js → See references/rasp-bypass.md if fails
Example 3: APK Repackaging
Decode → Modify → Rebuild → Sign → Install (see references/apk-modification-guide.md)
References Index
| Phase | Files | Phase | Files |
|---|---|---|---|
| 0 | environment-setup, tool-installation, opencode-tooling, static-analysis-patterns, hybrid-webview-frameworks, kotlin-*, apktool-3-0-migration-guide, cross-platform-testing-setup |
3 | attack-patterns, intent-injection, pendingintent-security, task-hijacking-tapjacking, firebase-security, drozer-guide, deep-link-exploitation |
| 1 | android-manifest-checklist, android-version-security, android-14-15-security-changes, android-16-security-guide, androidx-security-migration |
4 | dynamic-analysis-setup, forensics-data-extraction, native-code-analysis, native-analysis, rasp-bypass, boringssl-hooking, packing-unpacking, packer-modern-unpacking, zygisk-fridagadget-injection, root-hiding-modern, react-native-hermes-analysis, frida-version-matching-guide.md, android-keystore2-testing, biometric-testing-comprehensive |
| 2 | dependency-analysis, supply-chain-security |
5 | cvss-scoring-guide, reporting-templates, mastg-privacy-testing, frida-scripts-index, quick-commands |
| Mod | apk-modification-guide |
FW | react-native-security, react-native-new-arch, flutter-security, flutter-blutter-analysis, jetpack-compose-security-deep-dive, malware-analysis, arm-assembly-reference.md, fuzzing-guide, passkey-fido2-security.md, play-integrity-api-testing.md, privacy-sandbox-android, mobsf-integration |
| CI | automation-scripts, ci-cd-integration |
All | mastg-quick-reference, mastg-best-practices |
Scripts: preflight-check.sh, preflight-check.py, preflight-check.ps1, auto-audit-static.sh, generate-report.py, test-findings.json
Assets: curated Frida scripts in assets/frida-scripts/ (see references/frida-scripts-index.md for the canonical catalog, including native-root-detection-probe.js, android-file-access-monitor.js, jni-tracer.js, and ipc-abuse-helper.js)
Loading Strategy: Load reference files only when encountering the specific technical challenge they cover. Do NOT load all references at once.
Platform-Specific Notes
See
references/environment-setup.mdfor detailed Windows (PowerShell), macOS, and Linux setup. On macOS, userg(ripgrep) instead ofgrep -P— BSD grep does not support PCRE.