android-emulator-app-live-inspect
Skill11 starsChanged 3 months agoMITView on GitHub
Live-inspect an Android app's network on a rooted emulator — nixpkgs emulator + Magisk root + Frida TLS-unpinning + mitmproxy capture, then export decrypted flows. Use when you want to MITM/decrypt an app's HTTPS API, defeat certificate pinning, observe its cloud calls, or capture a login/session flow on an emulator. Generic across apps; complements (does not replace) the android-app-reverser static skill.
In this repository18 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- android-app-reverserSkill
- aula-pii-scanSkill
- de-ai-proseSkill
- de-ai-repoSkill
- drawio-figure-reviewerSkill
- explainer-videoSkill
- justfile-hygieneSkill
- model-raceSkill
- nix-scaffoldSkill
- phase1-prd-grillSkill
- phase2-backlog-snowballSkill
- phase3-backlog-ralphSkill
- readme-improverSkill
- refactor-smellerSkill
- scrub-for-publicSkill
- xterm-tmux-controlSkill
- zellij-controlSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 34
Run all just recipes from inside nix develop.
- Very specific: line 61
Follow the runbook in the justfile header: sdk-bootstrap → avd-create → emu → root → emu (cold-boot) → root-grant-bootstrap → frida-up.
- Very specific: line 63
After this, adb -s <serial> shell su -c id returns uid=0 and persists.
- Very specific: line 75
Export: run scripts/export-flows.py as a mitmproxy addon over the .mitm file with OUT=<dest>/flows.json (see its header).
- Very specific: line 89
Add [fully.qualified.Class, method] entries to EXTRA_BOOLEAN_HOOKS at the top of scripts/agent/agent.js, then just unpin-build and re-run.
- Distinctive: line 101
Zygisk often does NOT inject on a rootAVD/emulator Magisk: When it doesn't, Magisk DenyList and Shamiko are inert — system-wide root-hiding …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Android Emulator App Live Inspect
Stand up a rooted Android emulator from nixpkgs, run a target app under Frida with TLS unpinning + anti-tamper bypass, route it through mitmproxy, and export decrypted request/response flows. Dynamic counterpart to static APK reversing: it shows what the app actually sends.
Built and proven against a heavily-hardened Tuya-SDK app, but this skill is app-agnostic — the app-specific bits are isolated to one editable hook list.
When to use
- "Capture / decrypt this app's HTTPS traffic", "bypass its cert pinning", "see its API calls", "MITM the login", "what does it phone home".
- You have (or can run) a Linux box with Nix + KVM.
When NOT to use
- You only need static analysis (use the
android-app-reverserskill). - The data you want rides non-HTTP transports (MQTT/WebRTC/PPCS) — see Limitations.
Prerequisites
- Nix with flakes, and
/dev/kvmaccessible (x86_64 emulator). - A graphical
$DISPLAYfor the one-time Magisk GUI grant (or adapt — see Limitations). - Everything else (adb, emulator, frida, jadx, mitmproxy, node, python+frida) is
provided by
flake.nix— never install tools globally.
Files in this skill
Run all just recipes from inside nix develop. SKILL.md points at these; it
does not re-embed the commands — read the file for exact flags.
flake.nix/flake.lock— FHS dev shell. Provides the tools and the native libs Google's emulator/Qt need on NixOS (the non-obvious part). Pinned.justfile— every step as a recipe; its header is the ordered runbook.scripts/spawn-unpin.py— Frida harness: spawns the app, loads the agent, keeps the session alive, fails loud on detach. (just unpincalls it.)scripts/spawn-capture.py— same harness asspawn-unpin.py, but also appends the agent's structuredsend({tag,text})messages to a JSONL dump (<serial> <package> <script.js> <dump.jsonl>). Use it for custom capture agents (plaintext/crypto/signaling hooks) layered on the unpinner.scripts/agent/agent.js— the generic unpinning + anti-tamper agent (native BoringSSL + Java OkHttp/JSSE + RootBeer + a per-app hook list). This is the one file you edit per target. Compiled viascripts/agent/with frida-compile (bundlesfrida-java-bridge, which Frida 17 dropped as a global).scripts/export-flows.py— mitmproxy addon: dumps a.mitmcapture to structured JSON (parsed form fields, gunzipped bodies).OUT=<path>env sets output.scripts/magisk-grant-shell.sh— one-time GUI bootstrap that grants the adbshelluser root in Magisk (Android 14 blocks Magisk's background prompt).scripts/magisk-hide-root.sh— Zygisk + DenyList config (see Limitations re Zygisk).scripts/extract-xz-zip.py— extracts Magisk-module zips that use XZ/zstd ZIP entries (stockunzipcan't), for manual module installs.
Workflow
A. One-time host setup (per machine)
Follow the runbook in the justfile header: sdk-bootstrap → avd-create
→ emu → root → emu (cold-boot) → root-grant-bootstrap → frida-up.
After this, adb -s <serial> shell su -c id returns uid=0 and persists.
B. Per-app live inspection
- Install the target:
just install-xapk <dir-of-base+split-apks>(the Play x86_64 image translates arm64-only libs). - Build the agent once (and after any edit):
just unpin-build(compilesscripts/agent/agent.js→scripts/agent/unpin-compiled.js). - Capture in one shell:
just sniff(mitmproxy →flows.mitm). - Route + run in another:
just proxy-onthenjust unpin <pkg>—spawn-unpin.pylaunches the app from process start with the agent's hooks already installed, so flow #1 is captured and decrypted. - Interact (or let it idle); when done,
just proxy-offand stopsniff. - Export: run
scripts/export-flows.pyas a mitmproxy addon over the.mitmfile withOUT=<dest>/flows.json(see its header). Alsomitmdump -nr flows.mitm --flow-detail 4for a human-readable dump.
For most apps (OkHttp + Conscrypt, no serious anti-tamper) steps 1–6 yield decrypted plaintext JSON immediately — no per-app work.
C. If the app detects root / Frida / emulator (or still won't decrypt)
The generic agent already no-ops RootBeer and the common JSSE/OkHttp pinning. For a custom check:
- Decompile:
just decompile <apk>(jadx) — or use theandroid-app-reverserskill. - Grep the sources for the dialog/exit strings it shows ("rooted", "jailbroken",
"frida", "emulator") and for su-path arrays /
/proc/mapsscans; find the boolean method(s) that gate the block. - Add
[fully.qualified.Class, method]entries toEXTRA_BOOLEAN_HOOKSat the top ofscripts/agent/agent.js, thenjust unpin-buildand re-run. (A subagent over the decompiled tree finds these targets quickly.)
D. Read a capture
mitmproxy -nr flows.mitm (TUI) or open the exported flows.json. Every REST
call, endpoint, header and body is there — decrypted at the TLS layer.
Limitations & potential solutions
- Zygisk often does NOT inject on a rootAVD/emulator Magisk. When it
doesn't, Magisk DenyList and Shamiko are inert — system-wide root-hiding
silently does nothing (a stale "Do not remind" dismissal can mask this).
Solution: rely on the in-process agent bypass (
EXTRA_BOOLEAN_HOOKS), which works under instrumentation regardless of Zygisk. Verify hiding on a freshpm clearlaunch, not a cached one. If you need root hidden even when not under Frida, use a real device or a working-Zygisk setup. - App-layer payload encryption (e.g. Tuya
postData/result). Unpinning TLS reveals the HTTP envelope but the body may be separately AES/RSA- encrypted by the app, so you see ciphertext. Solution: hook the app's encrypt/sign function (e.g. alibthing_security-style JNIencryptPostData) to log plaintext before encryption — add anInterceptor/Java hook to the agent. Most apps don't do this; once TLS is stripped you see plaintext JSON. - Native / statically-linked TLS pinning. The native BoringSSL hook only
catches modules that export
SSL_*_set_custom_verify. A stripped, static TLS stack exposes nothing to hook by name (you'll see "0 hooks"). Solution: hook by offset after reversing the lib, or hook the higher Java caller, or patch the pin set in the app's assets. - Non-HTTP transports are invisible to the proxy. MQTT, PPCS/WebRTC video,
QUIC, raw sockets bypass an HTTP proxy entirely. Solution: native socket /
SSL_read/SSL_writehooks to dump plaintext, a transparent/tproxy setup, a dedicated MQTT proxy, or hook the SDK's decode function. - Per-app anti-tamper still needs decompilation. The generic layer covers
RootBeer + common JSSE pinning, but a bespoke check needs the manual step in
section C. Solution: the
EXTRA_BOOLEAN_HOOKSextension point + a decompile-and-grep subagent make this ~minutes for Java checks; native checks cost more. - Frida is itself detectable (checks that scan
/proc/mapsforfrida-agent). Solution: it's almost always easier to hook the boolean that consumes the check (section C) than to hide the agent; the agent does exactly this for known patterns. - Floating SDK/Magisk/agent versions.
cmdtools_verin the justfile can 404; platform-tools/emulator/system-image and Magisk (rootAVDmaster) float to "latest at bootstrap";frida-servermust match the hostfrida-tools. Solution:flake.lockpins the host toolchain; pin the rest by convention and bumpcmdtools_verwhen the download 404s. Thefrida-server-pushrecipe already version-matches the server to the tools. - NixOS-specific friction baked in. The FHS env + native-lib list exist because Google ships dynamically-linked prebuilts that don't run on NixOS. On a normal FHS distro this is simpler (the raw SDK runs) — but the flake still works and pins everything.
- One-time GUI grant needs a display.
root-grant-bootstrapdrives the Magisk app viauiautomator(it scrolls with coordinates tuned for the defaultre-pixelAVD). Solution: on a different DPI/AVD, adjust the swipes inscripts/magisk-grant-shell.sh, or grant once interactively then persist viajust root-grant-shell(sqlite, reboot-safe).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

