Android app pentest environment. Python CLI built with uv.
- Python 3.11+
- uv
- CachyOS / Arch Linux (for
setupcommand — uses pacman/yay)
uv sync
uv run androidlab --helpThe frida-server binaries and the jadx jar are not tracked in git (too large for GitHub). Download them manually and place them in the expected locations:
frida-server — download from frida releases, decompress, and place in frida-server/:
frida-server/frida-server-android-arm
frida-server/frida-server-android-arm64
frida-server/frida-server-android-x86
frida-server/frida-server-android-x86_64
jadx — download from jadx releases and place the jar in tools/jadx/lib/:
tools/jadx/lib/jadx-1.5.5-all.jar
Alternatively, run uv run androidlab setup — it handles these downloads automatically.
Install all tools and download frida-server binaries.
uv run androidlab setupOptions:
--skip-system— skip pacman packages (adb, nmap, etc.)--skip-aur— skip AUR packages (apktool, jadx, burpsuite, dex2jar)--skip-frida— skip frida-server binary downloads
Also installs: frida-tools, objection, mitmproxy, semgrep, drozer via pipx.
Check which tools are installed.
uv run androidlab doctorList connected ADB devices.
uv run androidlab devicesPersist the active device serial across commands so you don't need -s every time.
uv run androidlab session --serial emulator-5554 # set active device
uv run androidlab session # show current session
uv run androidlab session --clear # clear saved stateThe session also tracks the active proxy and last-used package.
One-shot session start: deploy frida-server, set proxy, install CA cert, and launch the target app — all in a single command.
uv run androidlab pentest com.target.app
uv run androidlab pentest com.target.app --proxy-host 10.0.2.2 --proxy-port 8080
uv run androidlab pentest com.target.app --root-bypass # also load root bypass script
uv run androidlab pentest com.target.app --no-launch # setup only, don't start appFiltered logcat for a specific app (by PID when running, by tag otherwise).
uv run androidlab logcat com.target.app
uv run androidlab logcat com.target.app --level W # warnings and aboveExtract an installed APK from the device.
uv run androidlab pull-apk com.target.app
uv run androidlab pull-apk com.target.app -o /tmp/target.apkSaved to apks/<package>.apk by default.
Pull /data/data/<package>/ from the device (requires root). Extracts shared preferences, SQLite databases, cache, and files.
uv run androidlab pull-data com.target.app
uv run androidlab pull-data com.target.app -o /tmp/appdata/Saved to workspaces/<package>/device-data/ by default.
Send an intent to an exported component.
uv run androidlab intent com.target.app -c .MainActivity
uv run androidlab intent com.target.app -a android.intent.action.VIEW -d https://example.com
uv run androidlab intent com.target.app -c .DeepLinkActivity -e token=abc123 -e user=adminDecompile an APK with apktool + jadx and extract interesting strings.
uv run androidlab analyze app.apk
uv run androidlab analyze app.apk --name myapp
uv run androidlab analyze app.apk --name myapp --scan # also run scan after decompileOutput goes to workspaces/<name>/:
apktool/— smali + resourcesjadx/— decompiled Javamanifest/AndroidManifest.xmlstrings/interesting.txt— URLs, hardcoded secrets, Firebase refs
Run static analysis on a decompiled workspace. The pipeline runs three checks in order:
- Manifest analysis — parses
AndroidManifest.xmlfordebuggable=true,allowBackup=true, exported components without permissions, and dangerous permission declarations. - Network Security Config — parses
network_security_config.xmlfor cleartext-traffic permissions, certificate pinning config, and debug overrides. - Semgrep — runs community rulesets then custom Android-specific rules.
uv run androidlab scan myapp # full pipeline
uv run androidlab scan myapp --nsc-only # Network Security Config only
uv run androidlab scan myapp --semgrep-onlyCommunity rulesets: auto, r/java, p/secrets, p/owasp-top-ten.
SARIF saved to workspaces/<name>/scan/semgrep.sarif.
Custom rules (rules/android-pentest.yaml) — 25 Android-specific rules
derived from real vulnerable app patterns. Rules cover both Java and Kotlin
source produced by JADX decompilation:
| Category | Rules |
|---|---|
| Hardcoded secrets | Crypto keys, passwords |
| Insecure logging | Sensitive data in Logcat (Log.d/v/i/e/w) / stdout — Java & Kotlin |
| Insecure communication | Cleartext HTTP, trust-all certs, hostname verifier bypass |
| Insecure data storage | World-readable prefs, external storage, unencrypted SQLite, credential storage in SharedPrefs |
| Insufficient cryptography | DES/ECB/Blowfish, weak hash (MD5/SHA-1), static IV, weak PRNG |
| WebView | JS enabled, addJavascriptInterface, HTTP loadUrl, universal file access — Java & Kotlin |
| Injection | SQL injection via string concat, Runtime.exec |
| Broadcast & intent | Implicit broadcast without permission, mutable PendingIntent |
| Dynamic code | DEX class loading from untrusted paths |
Custom SARIF saved to workspaces/<name>/scan/semgrep-custom.sarif.
Third-party library directories (androidx, kotlin, okhttp3, etc.) are
excluded from the custom scan to reduce false positives.
List or open workspaces.
uv run androidlab workspace # list all workspaces
uv run androidlab workspace myapp # open in file managerInstall drozer on the host and deploy the agent APK to the device.
uv run androidlab drozer install
uv run androidlab drozer install -s emulator-5554Enumerate the attack surface: exported activities, content providers, services, and broadcast receivers.
uv run androidlab drozer surface com.target.appQuery a content provider URI directly.
uv run androidlab drozer query content://com.target.app.provider/usersOpen an interactive drozer console.
uv run androidlab drozer shellStart or stop the MobSF Docker container.
uv run androidlab mobsf start # starts container, web UI at http://127.0.0.1:8000
uv run androidlab mobsf stopUpload an APK to MobSF and download the JSON report. Auto-starts the container if not running.
uv run androidlab mobsf scan app.apk
uv run androidlab mobsf scan app.apk --api-key <key> -o reports/Report saved to workspaces/<name>/mobsf/mobsf_report.json.
Deploy and start frida-server on a connected rooted device.
uv run androidlab frida push
uv run androidlab frida push -s emulator-5554List running apps via frida-ps.
uv run androidlab frida psConfigure the device HTTP proxy.
uv run androidlab proxy set 192.168.1.10 8080
uv run androidlab proxy clearPush the mitmproxy CA certificate to the device.
uv run androidlab proxy cert # push to /sdcard/ (user trust)
uv run androidlab proxy cert --system # install to system trust store (root)Start mitmproxy with the web UI at http://127.0.0.1:8081.
uv run androidlab mitmweb
uv run androidlab mitmweb --port 8080 --web-port 8081Download Android SDK command-line tools and install the emulator. Only needed once (~500 MB).
uv run androidlab avd install-sdkInstalls to ~/Android/Sdk/ (override with ANDROID_HOME).
Create a pentest AVD. Auto-installs the SDK and system image if missing (~1 GB).
uv run androidlab avd create # name=pentest, API 34
uv run androidlab avd create --name myavd --api 33
uv run androidlab avd create --tag default # pure AOSP, no Google APIsOptions:
--name— AVD name (default:pentest)--api— Android API level (default:34)--tag— system image tag:google_apis(default) ordefault--abi— CPU ABI (default:x86_64)
Uses google_apis images (userdebug builds) — adb root works out of the box.
Start an AVD emulator.
uv run androidlab avd start # starts 'pentest', waits for boot
uv run androidlab avd start --frida # also pushes frida-server after boot
uv run androidlab avd start --no-window # headless
uv run androidlab avd start --name myavd --no-wait # fire and forgetuv run androidlab avd list
uv run androidlab avd list-images
uv run androidlab avd delete pentestscripts/frida-ssl-bypass.js — bypass SSL pinning (TrustManager, OkHttp3, WebViewClient).
frida -U -f com.target.app -l scripts/frida-ssl-bypass.js --no-pause
# or via objection
objection -g com.target.app explore --startup-script scripts/frida-ssl-bypass.jsscripts/frida-root-bypass.js — bypass root detection (RootBeer, file checks, Runtime.exec).
frida -U -f com.target.app -l scripts/frida-root-bypass.js --no-pauseAndroidLab/
├── androidlab/ # CLI source
│ ├── cli.py # command definitions
│ ├── setup.py # tool installation
│ ├── analyze.py # APK static analysis
│ ├── scanner.py # Semgrep + NSC parser
│ ├── pentest.py # pentest workflows (start, logcat, pull-*)
│ ├── drozer.py # drozer integration
│ ├── mobsf.py # MobSF integration
│ ├── avd.py # AVD management
│ ├── adb.py # adb wrappers
│ ├── frida_helpers.py # frida-server deploy
│ ├── session.py # persistent session state
│ └── config.py # paths and constants
├── rules/
│ └── android-pentest.yaml # 23 custom Semgrep rules
├── scripts/
│ ├── frida-ssl-bypass.js
│ └── frida-root-bypass.js
├── apks/ # drop APKs here
├── workspaces/ # per-app analysis output
├── certs/ # mitmproxy CA cert
├── frida-server/ # frida-server binaries (arm/arm64/x86/x86_64)
├── tools/ # standalone tools (jadx, drozer agent)
└── pyproject.toml
# 1. Install tools (first time)
uv run androidlab setup
# 2. Pin device serial for the session
uv run androidlab session --serial <serial>
# 3. One-shot pentest start (frida + proxy + cert + launch)
uv run androidlab pentest com.target.app
# 4. In a second terminal — intercept traffic
uv run androidlab mitmweb
# 5. Attack surface (exported components)
uv run androidlab drozer install
uv run androidlab drozer surface com.target.app
# 6. Static analysis
uv run androidlab pull-apk com.target.app
uv run androidlab analyze apks/com.target.app.apk --name target --scan
# 7. Automated deep scan
uv run androidlab mobsf scan apks/com.target.app.apk
# 8. Pull app data
uv run androidlab pull-data com.target.app# 1. Install tools + SDK (first time, ~1.5 GB total)
uv run androidlab setup
uv run androidlab avd create --name pentest --api 34
# 2. Start emulator — waits for boot, then pushes frida-server
uv run androidlab avd start --name pentest --frida
# 3. Pin the emulator serial
uv run androidlab session --serial emulator-5554
# 4. One-shot pentest start
uv run androidlab pentest com.target.app --proxy-host 10.0.2.2
# 5. Continue as above from step 4