| name | mobile-pentest |
| description | Mobile app security testing with Frida instrumentation, OWASP MASVS compliance, and SSL pinning/root detection bypass for Android/iOS |
| license | MIT |
| metadata | {"category":"web-security","locale":"en","phase":"v1"} |
What this skill does
Performs end-to-end penetration testing of Android and iOS mobile applications covering static analysis, dynamic instrumentation, network traffic interception, and data storage inspection. Maps findings to OWASP MASVS categories and produces a structured report.
When to use
- Security assessment of a mobile app before production release
- Bug bounty testing against Android APKs or iOS IPAs
- Verifying that cert pinning, root/jailbreak detection, and secure storage controls are implemented correctly
- Compliance validation against OWASP MASTG / MASVS
Prerequisites
Common tools
frida / frida-tools — dynamic instrumentation framework
objection — runtime mobile exploration toolkit (wraps Frida)
Burp Suite — HTTP/S proxy for traffic interception
MobSF (Mobile Security Framework) — automated static/dynamic analysis
Android-specific
jadx — APK decompiler (Java/Kotlin source recovery)
apktool — APK disassembly and smali analysis
adb (Android Debug Bridge) — device communication
drozer — Android attack surface assessment
iOS-specific
class-dump — Objective-C class headers from Mach-O binaries
otool — binary inspection (protections, linked libraries)
ipatool / Frida iOS Dump — IPA extraction from a jailbroken device
- Jailbroken device or iOS simulator with Frida server
Install common tools
pip3 install frida-tools objection
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it --rm -p 8000:8000 opensecurity/mobile-security-framework-mobsf
apktool --version
pip3 install drozer
Inputs
| Field | Description | Example |
|---|
TARGET_APP | Path to APK (Android) or IPA (iOS) | /tmp/target.apk |
DEVICE_ID | ADB device ID or Frida device name | emulator-5554 |
PACKAGE_NAME | Application package / bundle ID | com.example.app |
BURP_HOST | Burp Suite proxy address | 127.0.0.1:8080 |
Workflow
Step 1: Set up the test environment
TARGET_APP="${TARGET_APP:-/tmp/target.apk}"
PACKAGE_NAME="${PACKAGE_NAME:-com.example.app}"
DEVICE_ID="${DEVICE_ID:-emulator-5554}"
BURP_HOST="${BURP_HOST:-127.0.0.1:8080}"
OUTPUT_DIR="/tmp/mobile-pentest-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUTPUT_DIR"
adb -s "$DEVICE_ID" shell echo "[+] Device connected" 2>/dev/null \
|| echo "[!] Device not found — start emulator or connect physical device"
echo "[+] Output directory: $OUTPUT_DIR"
Step 2: Static analysis
Android
jadx -d "$OUTPUT_DIR/jadx-output" "$TARGET_APP"
echo "[+] JADX decompilation complete: $OUTPUT_DIR/jadx-output"
apktool d "$TARGET_APP" -o "$OUTPUT_DIR/apktool-output" --no-src
echo "[+] apktool disassembly complete"
MANIFEST="$OUTPUT_DIR/apktool-output/AndroidManifest.xml"
echo "[*] Checking AndroidManifest.xml..."
grep -i 'android:debuggable="true"' "$MANIFEST" \
&& echo "[FINDING] App is debuggable — remove for production" \
|| echo "[OK] android:debuggable not set to true"
grep -i 'android:allowBackup="true"' "$MANIFEST" \
&& echo "[FINDING] android:allowBackup=true — sensitive data may be backed up" \
|| echo "[OK] android:allowBackup not set to true"
echo "[*] Exported components:"
grep -E 'exported="true"' "$MANIFEST" | grep -oE 'android:name="[^"]*"'
echo "[*] Scanning for hardcoded secrets..."
grep -rE '(api[_-]?key|secret|password|token|private[_-]?key)\s*=\s*"[^"]{6,}"' \
"$OUTPUT_DIR/jadx-output" --include="*.java" -l \
| tee "$OUTPUT_DIR/hardcoded-secrets.txt"
grep -rn "CertificatePinner\|TrustManager\|X509TrustManager\|checkServerTrusted\|pinnedCertificates" \
"$OUTPUT_DIR/jadx-output" --include="*.java" \
| tee "$OUTPUT_DIR/cert-pinning-refs.txt"
grep -rn "isRooted\|RootBeer\|/su\|Superuser.apk\|com.topjohnwu.magisk" \
"$OUTPUT_DIR/jadx-output" --include="*.java" \
| tee "$OUTPUT_DIR/root-detection-refs.txt"
grep -rn "setJavaScriptEnabled\|addJavascriptInterface\|setAllowFileAccess" \
"$OUTPUT_DIR/jadx-output" --include="*.java" \
| tee "$OUTPUT_DIR/webview-refs.txt"
echo "[+] Static analysis artifacts saved to $OUTPUT_DIR"
iOS
unzip -q "$TARGET_APP" -d "$OUTPUT_DIR/ipa-contents"
APP_BINARY=$(find "$OUTPUT_DIR/ipa-contents" -name "*.app" -type d | head -1)
BINARY_NAME=$(basename "$APP_BINARY" .app)
BINARY_PATH="$APP_BINARY/$BINARY_NAME"
echo "[+] Binary: $BINARY_PATH"
echo "[*] Binary protection flags:"
otool -hv "$BINARY_PATH" | grep -E "PIE|ASLR" || echo " PIE: check MHEXECUTABLE flags manually"
otool -lv "$BINARY_PATH" | grep -A5 "LC_ENCRYPTION_INFO" | grep cryptid
class-dump -H "$BINARY_PATH" -o "$OUTPUT_DIR/class-dump/" 2>/dev/null \
&& echo "[+] class-dump output: $OUTPUT_DIR/class-dump/" \
|| echo "[!] class-dump failed — binary may be Swift-only or encrypted"
INFOPLIST="$APP_BINARY/Info.plist"
echo "[*] Info.plist — ATS exceptions:"
plutil -p "$INFOPLIST" | grep -A3 "NSAppTransportSecurity" \
|| echo " No ATS exceptions found"
echo "[*] URL schemes:"
plutil -p "$INFOPLIST" | grep -A2 "CFBundleURLSchemes"
strings "$BINARY_PATH" | grep -iE '(api[_-]?key|secret|password|token|private[_-]?key)' \
| tee "$OUTPUT_DIR/ios-hardcoded-secrets.txt"
strings "$BINARY_PATH" | grep -iE '(cydia|substrate|jailbreak|/bin/bash|/etc/apt)' \
| tee "$OUTPUT_DIR/jailbreak-detection-refs.txt"
Step 3: Dynamic analysis with Frida
Android — SSL pinning bypass and root detection bypass
frida-ps -U -a
objection -g "$PACKAGE_NAME" explore
Reference: See REFERENCE.md for the standalone Frida SSL pinning bypass script (OkHttp3 + Conscrypt) and iOS Keychain dump script.
Android — Intent interception and content provider testing
echo "[+] drozer command reference saved to $OUTPUT_DIR/drozer-commands.txt"
Reference: See REFERENCE.md for the full drozer command reference (attack surface, activities, content providers, broadcast receivers, SQL injection).
iOS — Frida dynamic analysis
frida-ps -U
objection -g "$PACKAGE_NAME" explore
Reference: See REFERENCE.md for the iOS Keychain dump Frida script.
Step 4: Network traffic analysis
Step 5: Data storage inspection
Android
adb -s "$DEVICE_ID" shell "run-as $PACKAGE_NAME find /data/data/$PACKAGE_NAME -type f" \
| tee "$OUTPUT_DIR/app-files.txt"
adb -s "$DEVICE_ID" shell "run-as $PACKAGE_NAME cat /data/data/$PACKAGE_NAME/shared_prefs/*.xml 2>/dev/null" \
| tee "$OUTPUT_DIR/shared-prefs.txt"
grep -iE '(password|token|secret|key)' "$OUTPUT_DIR/shared-prefs.txt" \
&& echo "[FINDING] Sensitive data found in SharedPreferences"
adb -s "$DEVICE_ID" shell "find /data/data/$PACKAGE_NAME -name '*.db'" \
| while read db; do
adb -s "$DEVICE_ID" shell "run-as $PACKAGE_NAME sqlite3 $db '.tables'" 2>/dev/null
done | tee "$OUTPUT_DIR/sqlite-tables.txt"
adb -s "$DEVICE_ID" shell "find /sdcard/Android/data/$PACKAGE_NAME -type f" \
| tee "$OUTPUT_DIR/external-storage.txt"
adb -s "$DEVICE_ID" backup -noapk "$PACKAGE_NAME" -f "$OUTPUT_DIR/backup.ab"
echo "[+] Backup saved — decode with: java -jar abe.jar unpack $OUTPUT_DIR/backup.ab $OUTPUT_DIR/backup-extracted.tar"
iOS
cat <<'EOF'
ios nsuserdefaults get
ios keychain dump
ios cookies get
EOF
echo "[*] iOS data storage checklist:"
cat <<'EOF'
[ ] Keychain items classified with correct accessibility setting (kSecAttrAccessibleWhenUnlocked)
[ ] NSUserDefaults contains no sensitive data
[ ] Core Data / SQLite databases encrypted or contain no PII
[ ] Cache files do not persist sensitive responses
[ ] Background screenshots do not expose sensitive screens
[ ] Pasteboard not used for sensitive data
EOF
Step 6: Generate MASVS-mapped findings report
Reference: See REFERENCE.md for the Python report template generator that produces a structured findings-report.md with per-finding tables and MASVS mapping sections.
python3 generate-report.py
Reference: See REFERENCE.md for the full MASVS Coverage Checklist (7 categories: STORAGE, CRYPTO, AUTH, NETWORK, PLATFORM, CODE, RESILIENCE).
Done when
- Static analysis complete: manifest reviewed, secrets scanned, pinning/root detection identified
- Dynamic analysis complete: Frida/objection sessions recorded, pinning bypassed
- Network traffic captured via Burp Suite with proxy certificate installed
- Data storage inspected: SharedPreferences/NSUserDefaults, SQLite, Keychain reviewed
- All findings documented with MASVS mapping, severity, PoC, and remediation
- Report saved to
$OUTPUT_DIR/findings-report.md
Failure modes
| Problem | Cause | Solution |
|---|
frida-server not running | Server not started on device | adb shell "/data/local/tmp/frida-server &" |
objection can't attach | Package name wrong or app not running | Verify with frida-ps -U -a |
| SSL bypass not working | Custom pinning implementation | Inspect pinning code in JADX output and write targeted hook |
adb: device not found | USB debugging disabled | Enable USB debugging in Developer Options |
| JADX out of memory | Large APK | jadx --deobf --threads-count 2 -Xmx4g target.apk |
| iOS Frida server disconnects | USB connection drops | Use frida-server over network (-H device-ip) |
Notes
- All testing must be performed only against applications you own or have explicit written authorization to test.
- Root/jailbreak bypass techniques are for security validation only — document findings and recommend mitigations, do not weaponize.
- Frida scripts and objection sessions should be conducted in an isolated test environment, not on production devices with real user data.
- Reference: OWASP MASTG and OWASP MASVS