Module 17 — Hacking Mobile Platforms · Guided Lab Walkthrough¶
A step-by-step, do-it-in-order lab against your own environment only. Use an Android emulator (Android Studio AVD / Genymotion) or a device you own, and a deliberately-vulnerable training app you build or download for learning (e.g. an intentionally-broken "DIVA"-style app or one you write). Never decompile, tamper with, or MITM an app or account that isn't yours — that is illegal and violates the EC-Council Candidate Agreement. Outputs shown are representative — yours will differ. See
../../labs/.
Goal: walk the mobile app-attack chain — static triage → secrets on the device → traffic off the device — then watch an MDM/MAM + PAM control turn each win into a loss.
Setup: an Android emulator running, adb devices shows it, and jadx, apktool, and Burp Suite are installed. A vulnerable training APK named vuln.apk is on your Kali/host box.
Prereqs (host):
adb devices # your emulator/device is listed as "device"
which jadx apktool # static tools present
# Burp Suite running with its CA exportable; MobSF optional (docker or local)
Part A — Static triage (decompile & read the package)¶
A1. Decompile the APK to Java and to smali/resources¶
jadx -d out_jadx vuln.apk # readable Java + resources
apktool d vuln.apk -o out_apktool # smali + decoded AndroidManifest.xml
out_apktool/AndroidManifest.xml and out_jadx/sources/:
INFO: Using Apktool 2.x on vuln.apk
I: Decoding AndroidManifest.xml with resources...
I: Baksmaling classes.dex...
Hint if jadx throws decompile errors
Partial decompilation is normal on obfuscated apps — jadx still emits most classes. If a class fails, read its smali under `out_apktool/smali/` instead. Confirm the file is really an APK with `file vuln.apk` (should say "Android package").A2. Read the manifest for the classic misconfigurations¶
grep -Ei 'debuggable|exported=|cleartextTraffic|usesCleartextTraffic' out_apktool/AndroidManifest.xml
android:debuggable="true"
<activity android:name=".AdminActivity" android:exported="true">
android:usesCleartextTraffic="true"
debuggable=true (should never ship in prod), exported=true (component reachable by other apps — IPC surface), and cleartext traffic permitted — all M8 Security Misconfiguration (cleartext also feeds M5).
Hint: no matches?
Some apps set cleartext via a `networkSecurityConfig` XML instead of the attribute. Open `res/xml/network_security_config.xml` and look for `A3. Grep the decompiled source for hardcoded secrets¶
grep -riE "http://|password|api[_-]?key|secret|BEGIN (RSA|PRIVATE) KEY|AES" out_jadx/sources/ | head
LoginActivity.java: String API_KEY = "AIzaSyD...hardcoded...";
CryptoUtil.java: private static final String KEY = "0123456789abcdef"; // AES key in code
NetworkClient.java: BASE_URL = "http://api.vuln.local/v1/";
http:// base URL is M5.
Defender/PAM view: these are caught pre-release by static scanning in CI (MobSF/MASTG checks). From a PAM lens, an embedded API key is a credential that should never live on the endpoint — it belongs in a vaulted secret fetched JIT, not compiled into the binary.
Part B — Secrets on the device (Insecure Data Storage, M9)¶
B1. Install the app and exercise the login on the emulator¶
adb install vuln.apk
adb shell monkey -p com.vuln.app -c android.intent.category.LAUNCHER 1
# now log in inside the app with a test account you created (e.g. tester / Test1234)
Success
Performing Streamed Install
B2. Pull the app's private storage and read it¶
# works when the app is debuggable (run-as) or the device/emulator is rooted
adb shell run-as com.vuln.app cat shared_prefs/user_session.xml
adb shell run-as com.vuln.app ls databases/
adb exec-out run-as com.vuln.app cat databases/users.db > users.db
sqlite3 users.db "select * from users;"
<string name="auth_token">eyJhbGciOiJIUzI1NiIsInR5cCI6...</string>
1|tester|Test1234|eyJhbGci... <-- password stored in cleartext
Hint: run-as denied?
`run-as` only works if the app is `debuggable="true"` (you confirmed this in A2). On a non-debuggable app use a **rooted emulator** and `adb root` then `adb shell cat /data/data/com.vuln.app/shared_prefs/*.xml`. Never do this to an app that isn't your training target.B3. Confirm log leakage¶
adb logcat -d | grep -iE "token|password|Authorization"
D/AuthDebug: sending Authorization: Bearer eyJhbGci...
Defender/PAM view: the corporate fix isn't per-app patching — it's MAM containerization (corporate data encrypted in a managed container, no run-as), no secrets in logs, and using the Keystore/Keychain. For privileged users, JIT tokens mean any token skimmed off the device is short-lived and useless after the window closes.
Part C — Traffic off the device (MITM + SSL-pinning bypass, M5)¶
C1. Route emulator traffic through Burp and read the API¶
Set the emulator proxy to your host's Burp listener and install Burp's CA as a user cert, then use the app.
# push Burp's exported CA (DER) — user store; then use the app and watch Burp's HTTP history
adb push burp_ca.der /sdcard/burp_ca.der
# emulator: Settings > Wi-Fi > proxy = <host-ip>:8080 ; then Security > install CA cert
POST http://api.vuln.local/v1/login 200
{"user":"tester","token":"eyJhbGci..."}
Hint: HTTPS calls not showing?
Two causes: (1) on Android 7+ apps ignore **user** CAs unless the app opts in — test apps usually do, or use a rooted emulator to place the CA in the **system** store; (2) the app uses **certificate pinning** and drops the connection — that's Part C2.C2. Bypass certificate pinning with Objection/Frida¶
When the app pins and C1 shows connection failures, disable pinning at runtime.
# frida-server running on the emulator; then:
objection -g com.vuln.app explore
# inside the objection REPL:
android sslpinning disable
(agent) Custom, or modified SSL Pinning method found. Overriding.
(agent) [OkHttp] Bypassing OkHTTP pinner
Hint: objection can't attach?
Confirm the matching `frida-server` is running on the emulator (`adb shell "/data/local/tmp/frida-server &"`) and that `frida-ps -U` lists the app. Version-match the Frida client and server.C3. (Optional) Cross-check with a MobSF report¶
# MobSF web UI (local/docker): upload vuln.apk → run static, then dynamic
Defender/PAM view: the durable controls are TLS + certificate pinning + a network-security-config, MDM conditional access that blocks rooted/jailbroken (so Frida can't run on a managed device), and phishing-resistant MFA (FIDO2/passkeys) so a skimmed token or SMS OTP isn't enough. Full mapping in ../../defender-pam/attack-to-control-matrix.md.
What you should conclude¶
Every "win" above has a specific control that turns it into a logged, contained "loss":
| You did | The control that stops it |
|---|---|
| Decompiled the app, found hardcoded secrets (A) | No secrets in the binary; vaulted/JIT credentials; static scanning in CI |
| Read cleartext token/password from prefs & SQLite (B) | Keystore/Keychain, MAM containerization, no secrets in logs |
| MITM'd the API, bypassed pinning with Frida (C) | TLS + cert pinning + net-security-config; MDM block on rooted/jailbroken |
| Replayed a stolen session token | JIT short-lived tokens + phishing-resistant MFA |
Mobile findings cluster into secrets on the device and traffic off the device — and the corporate defense is MDM/MAM policy + phishing-resistant MFA, not fixing each app one at a time.
Cleanup¶
adb uninstall com.vuln.app
rm -rf out_jadx out_apktool users.db
# remove the Burp CA from the emulator and reset its proxy to none
# if you used a rooted emulator/AVD snapshot, revert it to a clean snapshot
Record it¶
Log commands, outputs, and what surprised you in the My lab log table at the bottom of README.md, and note any misses in PROGRESS.md.