Skip to main content
Synced from an Obsidian vault

For graph and advanced features, download the full Intel Codex Vault and open it in Obsidian.

Mobile Security (iOS & Android)

Authorized environments only. Comprehensive guide to mobile application security testing, reverse engineering, and exploitation for iOS and Android platforms. Use against apps and devices you own or have written authorization to test. See Legal & Ethics.


Table of Contents

  1. Overview
  2. Pre-Engagement & Authorization
  3. Android Security Testing
  4. iOS Security Testing
  5. Common Mobile Vulnerabilities
  6. Network Analysis
  7. Dynamic Instrumentation
  8. Bypassing Security Controls
  9. Automated Testing
  10. Tools Reference

Overview

Mobile Security Testing Scope

Key areas:

  • App reverse engineering: Decompile, analyze code, find vulnerabilities
  • Runtime analysis: Hook functions, modify behavior, bypass protections
  • Network security: HTTPS interception, API security, certificate pinning bypass
  • Data storage: Analyze local databases, shared preferences, keychains
  • Authentication/authorization: Session management, token security
  • Cryptography: Weak algorithms, hardcoded keys, insecure random number generation
  • Platform-specific: Android intents, iOS URL schemes, deep linking

Testing Environments

Android:

  • Emulator: Android Studio AVD (x86_64/arm64, faster); Genymotion as alternative
  • Physical device: Rooted Android phone (Pixel preferred for AOSP-clean Magisk/KernelSU support)
  • OS version: Test on multiple Android versions; Android 8.0 minimum (system trust store CA enforcement, scoped storage shifts) [verify 2026-04-26]

iOS:

  • Simulator: Xcode Simulator (limited - no Secure Enclave, no Keychain semantics, no jailbreak-detection surface)
  • Physical device: Jailbroken iPhone — current public JBs land on iOS 15-17 via palera1n / Dopamine; iOS 18 public JB status [verify 2026-04-26]
  • OS version: Test on current and previous iOS versions; arm64e (A12+) devices required to exercise PAC-aware code paths

Authorized testing only:

  • ✅ Test apps you developed or have permission to test
  • ✅ Bug bounty programs (HackerOne, Bugcrowd)
  • ✅ Penetration testing engagements with signed contracts
  • ❌ Reverse engineering apps without authorization (may violate TOS)
  • ❌ Circumventing DRM or software protection for piracy

Responsible disclosure:

  • Report vulnerabilities to app developers/vendors
  • Allow 90 days for remediation before public disclosure
  • Use CVE process for significant vulnerabilities

Pre-Engagement & Authorization

Mobile testing inherits unique authorization wrinkles: rooting/jailbreaking is destructive and warranty-voiding, sideload/re-sign tooling can violate app-store ToS, and on-device data routinely contains real PII even on "test" accounts. The bullets below are pre-flight gates — do not skip them, and do not re-derive legal content here. See also the Legal & Ethical Considerations sub-block under Overview for the testing-only allow/deny list, and Legal & Ethics for the canonical jurisdictional framework.

Authorization Checklist

  • Target app, device, and backend covered by signed engagement letter, bug-bounty / VDP scope, or written owner permission; app-store ToS implications of sideload, re-sign, and tampering tooling acknowledged in writing.
  • Device root (Magisk, KernelSU) or jailbreak (checkra1n, palera1n, unc0ver, Dopamine) authorized on this device only — warranty-void and brick risk explicitly accepted by the asset owner.
  • App-data extraction scope (Keychain, Keystore, shared prefs, app sandbox, WebView caches) and PII handling defined; on-device user data treated per Collection Log chain-of-custody and OPSEC artifact rules.
  • Frida-server install, Objection injection, and IPA/APK re-signing scoped to the test device — not the analyst's daily driver or any device holding personal credentials.
  • Network MITM authorization (Burp/MITMproxy CA in system trust store, SSL pinning bypass) scoped separately from production API interception; out-of-scope endpoints, third-party SDK telemetry, and shared backend tenants explicitly excluded.
  • MDM bypass, biometric bypass, iOS arm64e PAC bypass, and Android FBE decryption are explicitly listed as in-scope or out-of-scope (default: out-of-scope unless the engagement letter says otherwise).
  • Halt criteria, emergency contact, and disclosure pathway (vendor PSIRT, app-store security inbox, OWASP MASA assessor [verify 2026-04-26]) identified before any tooling touches the device.

Lab Environment Requirements

  • Dedicated test devices matched to target OS version: jailbreak/root tooling is tightly version-pinned (checkra1n A7–A11 only, palera1n for arm64 iOS 15–17 [verify 2026-04-26], unc0ver legacy iOS 11–14, Dopamine for arm64 iOS 15–16.6.1 [verify 2026-04-26], Magisk + KernelSU per Android major version).
  • frida host CLI version matched to frida-server arch+version on device (mismatch silently no-ops or crashes the agent); Objection ridden on top.
  • Separate Apple ID provisioned for iOS testing — never sign in with personal iCloud; disable Find My, iMessage, and iCloud Keychain on the test device.
  • Android Studio AVD with system image matching target ABI (arm64-v8a vs x86_64) for automated dynamic runs; emulator proxy with Burp/MITMproxy CA installed into the system trust store (Android 7+ ignores user-store CAs for apps that don't opt-in via network_security_config.xml).
  • MobSF instance for static triage running containerized on an isolated bridge — never expose the MobSF web UI to a routable network.
  • Snapshot device/emulator state before each instrumentation campaign; revert after Frida hooks, re-signs, or kernel patches to keep evidence reproducible.

Disclosure-Ready Posture

Capture before you touch: app version + build identifier (aapt dump badging app.apk, apksigner verify --print-certs app.apk, codesign -dvvv App.app, otool -l App | grep -A2 LC_VERSION), acquisition provenance (store, vendor handoff, internal build URL), and device jailbreak/root state at test time. Version-pin every Frida script, Objection plugin, and re-sign cert (thumbprint + signing chain). Archive the decompiled APK/IPA, smali/Hopper exports, and the re-signed package alongside hashes per Collection Log. Stream device logs throughout (idevicesyslog or log collect --device on iOS; adb logcat -v threadtime on Android) so post-hoc reconstruction is unnecessary. Defang any URLs, package IDs, deep-link schemes, or endpoints that surface in the writeup (hxxp://, [.], [@]) and ship the package per Reporting, Packaging & Disclosure.


Android Security Testing

Android Application Structure

APK (Android Package) contents:

app.apk (ZIP file)

├── AndroidManifest.xml # App metadata, permissions, components
├── classes.dex # Dalvik bytecode (compiled Java/Kotlin)
├── resources.arsc # Compiled resources
├── res/ # Resources (images, layouts, strings)
│ ├── drawable/
│ ├── layout/
│ └── values/
├── lib/ # Native libraries (.so files)
│ ├── armeabi-v7a/
│ ├── arm64-v8a/
│ ├── x86/
│ └── x86_64/
├── assets/ # Raw asset files
├── META-INF/ # APK signature
│ ├── MANIFEST.MF
│ ├── CERT.RSA
│ └── CERT.SF
└── kotlin/ # Kotlin metadata (if Kotlin app)

Android Reverse Engineering

Step 1: Obtain APK

# Method 1: Download from device (requires adb)
adb shell pm list packages | grep <app_name>
# Output: package:com.example.app

adb shell pm path com.example.app
# Output: package:/data/app/com.example.app-xxx/base.apk

adb pull /data/app/com.example.app-xxx/base.apk app.apk

# Method 2: Download from APK mirror sites
# APKMirror, APKPure, APKMonk — verify integrity by re-checking
# the signing certificate fingerprint against vendor's known cert
# (`apksigner verify --print-certs app.apk`).

# Method 3: Extract from Play Store (requires tools)
# - gplaydl (Python; gplaycli successor) [verify 2026-04-26]
# - apkeep (Rust; supports Play, APKPure, F-Droid, Huawei AppGallery)
# - Aurora Store (anonymous Play client; not headless)

Step 2: Decompile APK with JADX

# Install JADX:
# https://github.com/skylot/jadx/releases

# Decompile APK to Java source:
jadx app.apk -d output_dir/

# Output structure:
# output_dir/
# ├── sources/ # Decompiled Java code
# │ └── com/example/app/
# │ ├── MainActivity.java
# │ ├── LoginActivity.java
# │ └── utils/
# ├── resources/ # Decoded resources
# └── AndroidManifest.xml

# Or use JADX-GUI:
jadx-gui app.apk

Step 3: Analyze decompiled code

// Example: LoginActivity.java (decompiled)
public class LoginActivity extends AppCompatActivity {
private static final String API_KEY = "sk_live_abc123xyz"; // Hardcoded API key!

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
}

public void loginUser(String username, String password) {
// Vulnerable: No input validation
String query = "SELECT * FROM users WHERE username='" + username + "'"; // SQL injection!

// Insecure: HTTP instead of HTTPS
String url = "http://api.example.com/login"; // Cleartext transmission!

// Weak crypto: MD5 for password hashing
String hashedPassword = MD5(password); // MD5 is broken!
}
}

Step 4: Decode with Apktool (for resources and smali)

# Install Apktool:
# https://ibotpeaches.github.io/Apktool/

# Decode APK:
apktool d app.apk -o app_decoded/

# Output structure:
# app_decoded/
# ├── AndroidManifest.xml # Decoded manifest (readable XML)
# ├── smali/ # Dalvik assembly code
# │ └── com/example/app/
# │ ├── MainActivity.smali
# │ └── LoginActivity.smali
# ├── res/ # Decoded resources
# │ ├── layout/
# │ ├── values/
# │ │ └── strings.xml # App strings
# └── original/ # Original files

# Analyze resources:
cat app_decoded/res/values/strings.xml

Step 5: Analyze AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">

<!-- Permissions (check for excessive permissions) -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_CONTACTS" /> <!-- Suspicious! -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Exported components (vulnerable if not protected) -->
<activity android:name=".MainActivity"
android:exported="true"> <!-- Exported = accessible by other apps! -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- Debuggable flag (should be false in production) -->
<application
android:debuggable="true" <!-- VULNERABLE! Allows debugging -->
android:allowBackup="true" <!-- Data can be backed up -->
android:networkSecurityConfig="@xml/network_security_config">
...
</application>
</manifest>

Key manifest checks:

CheckSecurity Impact
android:debuggable="true"Allows attaching debugger, inspecting memory
android:allowBackup="true"Data can be extracted via adb backup
android:exported="true"Component accessible by other apps (intent hijacking)
Excessive permissionsPrivacy violation, larger attack surface
android:usesCleartextTraffic="true"Allows HTTP traffic (MITM risk)

Android Dynamic Analysis

Step 1: Set up testing device

# Enable Developer Options on Android device:
# Settings → About Phone → Tap "Build number" 7 times

# Enable USB debugging:
# Settings → Developer Options → USB debugging (ON)

# Connect device via USB:
adb devices
# Output: List of devices attached
# ABC123XYZ device

# Root device (if not rooted):
# Use Magisk: https://github.com/topjohnwu/Magisk
# Flash Magisk via custom recovery (TWRP)

Step 2: Install app

# Install APK:
adb install app.apk

# Or install from device:
adb shell pm install /sdcard/app.apk

# Verify installation:
adb shell pm list packages | grep com.example.app

Step 3: Explore app filesystem

# App data directory (requires root):
adb shell
su # Switch to root
cd /data/data/com.example.app/

# Directory structure:
# /data/data/com.example.app/
# ├── cache/ # Cached data
# ├── databases/ # SQLite databases
# │ └── app.db
# ├── shared_prefs/ # SharedPreferences (XML)
# │ └── settings.xml
# ├── files/ # App files
# └── lib/ # Native libraries

# Check for sensitive data:
cat shared_prefs/settings.xml
# Example:
# <string name="api_token">eyJhbGciOiJIUzI1...</string> # Stored token!

cat databases/app.db
# Or use sqlite3:
sqlite3 databases/app.db
sqlite> .tables
sqlite> SELECT * FROM users;

Step 4: Monitor logcat (logs)

# View real-time logs:
adb logcat | grep com.example.app

# Common log leaks:
# - API keys, tokens
# - Passwords (if logged during debugging)
# - Sensitive user data (PII)

# Example log:
# D/LoginActivity: Logging in user: john@example.com with password: password123

Step 5: Intercept network traffic (see Network Analysis section)

Android Static Analysis (Automated)

MobSF (Mobile Security Framework):

# Install MobSF (Docker):
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest

# Access: http://localhost:8000

# Upload APK → Automated scan:
# - Permissions analysis
# - Manifest security checks
# - Code analysis (hardcoded secrets, SQL injection, etc.)
# - Binary analysis
# - Report generation (PDF)

AndroBugs:

# Install AndroBugs:
git clone https://github.com/AndroBugs/AndroBugs_Framework.git
cd AndroBugs_Framework

# Run analysis:
python androbugs.py -f app.apk

# Output: Detailed report (vulnerabilities, security misconfigurations)

Android Native Library Analysis

Analyzing .so files (ARM/x86 native libraries):

# Extract native library from APK:
unzip app.apk "lib/arm64-v8a/*" -d lib_extracted/

# Analyze with Ghidra:
# File → Import File → lib_extracted/lib/arm64-v8a/libnative.so
# Analyze with ARM:LE:64:v8A processor

# Look for:
# - Hardcoded strings (encryption keys, API endpoints)
# - JNI functions (Java Native Interface bridges)
# - Crypto implementations (custom or weak crypto)
# - Anti-tampering checks

JNI (Java Native Interface) reversing:

// Java side (loads native library):
public class NativeLib {
static {
System.loadLibrary("native"); // Loads libnative.so
}

// Native method declaration:
public native String decrypt(String encrypted);
}
// Native side (C/C++ in libnative.so):
#include <jni.h>

JNIEXPORT jstring JNICALL
Java_com_example_app_NativeLib_decrypt(JNIEnv *env, jobject thiz, jstring encrypted) {
const char *enc_str = (*env)->GetStringUTFChars(env, encrypted, 0);

// Hardcoded AES key (vulnerable!):
char aes_key[] = "0123456789ABCDEF0123456789ABCDEF";

// Decrypt with AES...
char *decrypted = aes_decrypt(enc_str, aes_key);

return (*env)->NewStringUTF(env, decrypted);
}

Modifying & Repackaging APKs

Step 1: Decompile with Apktool

apktool d app.apk -o app_decoded/

Step 2: Modify smali code

# Edit app_decoded/smali/com/example/app/LoginActivity.smali

# Original (license check):
.method public checkLicense()Z
# ... license validation code ...
const/4 v0, 0x0 # Return false (invalid)
return v0
.end method

# Modified (bypass license check):
.method public checkLicense()Z
const/4 v0, 0x1 # Always return true (valid)
return v0
.end method

Step 3: Rebuild APK

apktool b app_decoded/ -o app_modified.apk

Step 4: Sign APK (required for installation)

Modern Android (7.0+) requires APK Signature Scheme v2/v3/v4 — the legacy jarsigner v1 scheme alone is rejected on most installs. Use apksigner from build-tools, and align before signing (v2+ embeds the signature over the aligned file).

# Generate keystore (one-time):
keytool -genkey -v -keystore my.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000

# Align FIRST (required for v2/v3 signing):
zipalign -p -f -v 4 app_modified.apk app_aligned.apk

# Sign with apksigner (v1+v2+v3 by default, build-tools 24.0.3+):
apksigner sign --ks my.keystore --ks-key-alias mykey --out app_final.apk app_aligned.apk

# Verify signature scheme(s) attached:
apksigner verify --verbose --print-certs app_final.apk

# Install:
adb install app_final.apk

iOS Security Testing

iOS Application Structure

IPA (iOS App Store Package) contents:

app.ipa (ZIP file)

└── Payload/
└── App.app/
├── Info.plist # App metadata, bundle ID, permissions
├── App (Mach-O binary) # Main executable (ARM64)
├── embedded.mobileprovision # Provisioning profile
├── _CodeSignature/ # Code signature
├── Frameworks/ # Embedded frameworks
├── Assets.car # Compiled assets
└── Base.lproj/ # Localized resources

iOS Reverse Engineering

Step 1: Obtain IPA

# Method 1: Download from jailbroken device (requires Frida or SSH)
# SSH into device:
ssh root@&lt;device_ip&gt; # Default password: alpine (change it!)

# Locate app:
find /var/containers/Bundle/Application/ -name "*.app"

# Copy IPA:
scp -r root@&lt;device_ip&gt;:/var/containers/Bundle/Application/XXX/App.app ~/Desktop/

# Method 2: Decrypt from App Store (requires jailbroken device)
# Apps downloaded from App Store are encrypted (FairPlay DRM)
# Use frida-ios-dump or Clutch to decrypt:

# frida-ios-dump:
git clone https://github.com/AloneMonkey/frida-ios-dump.git
cd frida-ios-dump
pip3 install -r requirements.txt

# Configure device IP in dump.py
python3 dump.py &lt;bundle_id&gt;
# Example: python3 dump.py com.example.app
# Output: Decrypted IPA saved to current directory

# bagbak — modern frida-ios-dump alternative (Node, fewer config knobs):
# npm i -g bagbak && bagbak &lt;bundle_id&gt;
# r2flutch — frida-ios-dump variant focused on Flutter apps.

# Method 3: ipatool (download encrypted IPA from App Store with an Apple ID;
# purchase / "Get" must already be on the account; no jailbreak required):
# https://github.com/majd/ipatool
ipatool auth login -e &lt;appleid_email&gt;
ipatool download -b com.example.app -o ./app.ipa
# Resulting IPA is FairPlay-encrypted — still need a JB device + dumper to
# get plaintext Mach-O for static analysis.

# Method 4: Download from third-party sites (verify integrity!)

Step 2: Analyze with Hopper/Ghidra

# Extract IPA:
unzip app.ipa

# Analyze main binary:
# Payload/App.app/App (Mach-O ARM64 binary)

# Ghidra:
# File → Import File → Payload/App.app/App
# Analyze with AARCH64:LE:64:AppleSilicon processor

# Hopper (macOS/Linux):
hopper -e Payload/App.app/App

# IDA Pro (commercial):
ida64 Payload/App.app/App

Step 3: Class dump (Objective-C apps)

# class-dump (nygard/class-dump) — original, Objective-C runtime metadata only;
# upstream effectively unmaintained, fork ecosystem fragmented [verify 2026-04-26].
# Modern alternatives:
# - jtool2 — Mach-O swiss army knife (`jtool2 -d objc App` ≈ class-dump output)
# - Hopper / Ghidra / IDA — handle Objective-C metadata natively in disassembly
# - For Swift symbols: rely on Hopper/Ghidra/IDA Swift demangler (no class-dump
# equivalent — Swift uses different runtime metadata layout than Obj-C)

class-dump Payload/App.app/App -H -o headers/

# Example header:
# @interface LoginViewController : UIViewController
# - (void)loginWithUsername:(NSString *)username password:(NSString *)password;
# - (BOOL)validateLicense:(NSString *)license;
# @end

Step 4: Analyze Info.plist

# View Info.plist:
plutil -p Payload/App.app/Info.plist

# Or convert to XML:
plutil -convert xml1 Payload/App.app/Info.plist -o Info_readable.plist

# Key checks:
# - CFBundleIdentifier: Bundle ID
# - NSAppTransportSecurity: ATS settings (allows HTTP?)
# - UIRequiredDeviceCapabilities: Required capabilities
# - Entitlements: Permissions (location, camera, etc.)

Info.plist security checks:

<!-- Example Info.plist -->
<dict>
<!-- App Transport Security (ATS) disabled (VULNERABLE!) -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/> <!-- Allows HTTP connections! -->
</dict>

<!-- URL schemes (deep linking attack surface) -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string> <!-- myapp:// URL scheme -->
</array>
</dict>
</array>
</dict>

iOS Dynamic Analysis

Step 1: Jailbreak device

Jailbreak tooling is hardware- and iOS-version-pinned. Always confirm support matrix on the project's release page before flashing — the matrix below is a snapshot, verify against current upstream releases.

# Current public jailbreak tools (snapshot — [verify 2026-04-26]):
# - palera1n iOS 15-17 on A11 and below (tethered/semi-tethered);
# rootless mode for A12+ on iOS 15-17
# - Dopamine iOS 15-16.6.1 on A12+ (rootless, semi-untethered) [verify 2026-04-26]
# - checkra1n A7-A11 only (BootROM checkm8 exploit); last release pre-iOS 14;
# inactive but still works for in-scope hardware
# - unc0ver LEGACY — last support iOS 14.x, no modern updates
# - Taurine RETIRED (was iOS 14.0-14.3)
# - iOS 18 / arm64e A12+ on iOS 17.x late builds: public JB status [verify 2026-04-26]
# (research-only PAC bypasses exist, no consumer JB)

# Package managers on modern jailbreaks (Cydia is largely defunct on rootless):
# - Sileo (default on palera1n / Dopamine)
# - Zebra (alternative)
# - Cydia still ships on legacy checkra1n / unc0ver setups

# Essential tools to install post-JB:
# - OpenSSH (remote access; rootless path is /var/jb/usr/bin/ssh)
# - Frida + frida-server (dynamic instrumentation; server arch+major.minor must
# match host frida CLI exactly or hooks no-op/crash)
# - SSL Kill Switch 3 (modern fork of SSL Kill Switch 2 for rootless JBs)
# [verify 2026-04-26]
# - AppSync Unified (install unsigned IPAs)
# - Choicy / A-Bypass (per-app tweak injection control for JB-detection bypass)

iOS 16+ Lockdown Mode awareness: if the test device has Lockdown Mode enabled (Settings → Privacy & Security → Lockdown Mode), WebKit JIT is disabled, attachments/link-previews are stripped, FaceTime invitations from unknown senders blocked, and configuration profiles cannot be installed — turn it off on the test device or expect MITM-CA install and many WebView exploits to silently fail [verify 2026-04-26].

Step 2: SSH into device

# Install OpenSSH via Cydia

# Connect via SSH (default password: alpine):
ssh root@&lt;device_ip&gt;

# IMPORTANT: Change default password!
passwd # For root
passwd mobile # For mobile user

# Explore filesystem:
cd /var/mobile/Containers/Data/Application/
ls -la
# Each app has a UUID directory

# Find app by bundle ID:
find . -name "*.plist" -exec grep -l "com.example.app" {} \;

Step 3: Analyze app sandbox

# App data directory:
# /var/mobile/Containers/Data/Application/&lt;UUID&gt;/

# Documents/ # User documents
# Library/ # App data
# ├── Caches/ # Cached data
# ├── Preferences/ # User preferences (.plist files)
# └── Cookies/ # Cookies
# tmp/ # Temporary files

# Check for sensitive data:
cd /var/mobile/Containers/Data/Application/&lt;UUID&gt;/Library/Preferences/

# View .plist files:
plutil -p com.example.app.plist

# Example (leaked token):
# "api_token" => "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Step 4: Analyze Keychain (requires tool)

# Install Keychain-Dumper:
# https://github.com/ptoomey3/Keychain-Dumper

# Copy to device:
scp keychain_dumper root@&lt;device_ip&gt;:/tmp/

# Run on device:
ssh root@&lt;device_ip&gt;
cd /tmp
chmod +x keychain_dumper
./keychain_dumper

# Output: All keychain items accessible by current app
# Example:
# Generic Password
# Service: com.example.app
# Account: user@example.com
# Password: supersecret123

Step 5: Monitor system logs

# Install syslog on device (via Cydia)

# View logs:
ssh root@&lt;device_ip&gt;
tail -f /var/log/syslog | grep -i "app"

# Or use Xcode Devices (macOS):
# Xcode → Window → Devices and Simulators → Select device → Open Console

iOS Static Analysis (Automated)

MobSF (supports iOS):

# Upload IPA to MobSF (same as Android):
# http://localhost:8000

# Automated analysis:
# - Binary analysis (strings, symbols)
# - Info.plist checks
# - Code signing verification
# - Entitlements analysis
# - Hardcoded secrets detection

iMAS (iOS Mobile Application Security):

# https://github.com/project-imas/
# LEGACY — iMAS organisation has been inactive for years; treat as historical
# reference rather than current tooling [verify 2026-04-26].
# Modern equivalents:
# - Semgrep with mobile rulepack (multi-language SAST, actively maintained)
# - MobSF (also runs SAST passes on iOS source/IPA — see above)
# - r2 / Ghidra / IDA scripts for binary-side checks

Common Mobile Vulnerabilities

Insecure Data Storage

Android - SharedPreferences (plaintext):

<!-- /data/data/com.example.app/shared_prefs/settings.xml -->
<map>
<string name="username">john@example.com</string>
<string name="password">password123</string> <!-- PLAINTEXT! -->
<string name="api_token">sk_live_abc123</string>
</map>

Mitigation:

// Encrypt sensitive data with EncryptedSharedPreferences (Android):
import androidx.security.crypto.EncryptedSharedPreferences;
import androidx.security.crypto.MasterKeys;

String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
"secure_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);

iOS - NSUserDefaults (plaintext):

// Vulnerable (plaintext storage):
[[NSUserDefaults standardUserDefaults] setObject:@"password123" forKey:@"password"];

Mitigation:

// Store sensitive data in Keychain:
#import <Security/Security.h>

// Save to Keychain:
NSDictionary *query = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: @"com.example.app",
(__bridge id)kSecAttrAccount: @"user_token",
(__bridge id)kSecValueData: [@"secret_token" dataUsingEncoding:NSUTF8StringEncoding]
};
SecItemAdd((__bridge CFDictionaryRef)query, NULL);

Insecure Communication

Cleartext HTTP traffic:

// Vulnerable (Android):
URL url = new URL("http://api.example.com/login"); // HTTP!
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

Mitigation:

// Use HTTPS:
URL url = new URL("https://api.example.com/login");

// Android Network Security Config (res/xml/network_security_config.xml):
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" /> <!-- Block HTTP -->
</network-security-config>

iOS - App Transport Security (ATS) bypass:

<!-- Vulnerable Info.plist (allows HTTP): -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/> <!-- BAD! -->
</dict>

Mitigation:

<!-- Enforce HTTPS only: -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
</dict>

Hardcoded Secrets

API keys in code:

// Android (decompiled):
public class APIClient {
private static final String API_KEY = "sk_live_abc123xyz"; // Exposed!
private static final String SECRET = "mysecret";
}

Finding secrets:

# Android:
jadx app.apk
grep -r "api_key\|secret\|password\|token" output_dir/

# iOS:
strings Payload/App.app/App | grep -i "api\|key\|secret\|token"

Mitigation:

  • Store secrets server-side (fetch at runtime)
  • Use environment variables (build-time injection)
  • Obfuscate strings (minimal protection, not secure)

Weak Cryptography

MD5/SHA1 for passwords:

// Vulnerable:
String hashedPassword = MD5(password); // MD5 is broken!

Weak encryption:

// Vulnerable (hardcoded key, ECB mode):
SecretKeySpec key = new SecretKeySpec("1234567890123456".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // ECB mode!

Mitigation:

// Use bcrypt/Argon2 for passwords (server-side):
// For encryption, use AES-GCM with randomly generated keys:
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] iv = cipher.getIV(); // Save IV for decryption
byte[] encrypted = cipher.doFinal(plaintext.getBytes());

SQL Injection (Mobile)

Vulnerable SQLite query:

// Android:
String query = "SELECT * FROM users WHERE username='" + username + "'";
Cursor cursor = db.rawQuery(query, null); // SQL injection!

Exploitation:

Username: admin' OR '1'='1' --
Query becomes: SELECT * FROM users WHERE username='admin' OR '1'='1' --'
Result: Bypasses authentication

Mitigation:

// Use parameterized queries:
String query = "SELECT * FROM users WHERE username=?";
Cursor cursor = db.rawQuery(query, new String[]{username});

Intent Hijacking (Android)

Exported component without permission:

<!-- AndroidManifest.xml -->
<activity android:name=".PaymentActivity"
android:exported="true"> <!-- Accessible by other apps! -->
</activity>

Exploitation:

// Malicious app sends intent:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.app", "com.example.app.PaymentActivity"));
intent.putExtra("amount", 0.01); // Manipulate payment amount
intent.putExtra("recipient", "attacker@evil.com");
startActivity(intent);

Mitigation:

<!-- Require permission or set exported=false: -->
<activity android:name=".PaymentActivity"
android:exported="false"> <!-- Only accessible by app -->
</activity>

<!-- Or require custom permission: -->
<permission android:name="com.example.app.PAYMENT_ACCESS"
android:protectionLevel="signature" />

<activity android:name=".PaymentActivity"
android:permission="com.example.app.PAYMENT_ACCESS"
android:exported="true">
</activity>

Network Analysis

HTTPS Interception (MITM Proxy)

Setup Burp Suite for mobile:

Step 1: Configure proxy

# Burp Suite:
# Proxy → Options → Proxy Listeners
# Add: 0.0.0.0:8080 (all interfaces)

# Find computer IP:
ip addr show # Linux
ipconfig # Windows

Step 2: Configure device proxy

Android:

Settings → Wi-Fi → Long-press network → Modify network
→ Advanced → Proxy: Manual
Hostname: &lt;computer_ip&gt;
Port: 8080

iOS:

Settings → Wi-Fi → Tap (i) next to network
→ HTTP Proxy: Manual
Server: &lt;computer_ip&gt;
Port: 8080

Step 3: Install Burp CA certificate

Android:

# Export Burp CA cert:
# Burp → Proxy → Options → Import/Export CA certificate
# Export → Certificate in DER format → Save as burp.der

# Convert to PEM:
openssl x509 -inform DER -in burp.der -out burp.crt

# Get certificate hash (for Android 7+):
openssl x509 -inform PEM -subject_hash_old -in burp.crt | head -1
# Output: 9a5ba575 (example hash)

# Rename cert:
mv burp.crt 9a5ba575.0

# Push to device (requires root):
adb root
adb remount
adb push 9a5ba575.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/9a5ba575.0
adb reboot

iOS:

# Navigate to Burp CA cert URL on device:
# http://burp/cert
# Download burp.crt

# Install:
# Settings → General → Profile Downloaded → Install
# Settings → General → About → Certificate Trust Settings
# Enable full trust for Burp CA

Step 4: Intercept traffic

# Burp → Proxy → Intercept: ON
# Launch app, observe HTTP/HTTPS requests

# Example intercepted request:
POST /api/login HTTP/1.1
Host: api.example.com
Content-Type: application/json

{"username": "john", "password": "password123"}

# Modify and forward

Bypassing Certificate Pinning

Certificate pinning validates server certificate against known cert/public key.

Detection:

# Android: Search for keywords in decompiled code:
grep -r "CertificatePinner\|TrustManager\|PinningTrustManager" output_dir/

# iOS: Search in binary:
strings Payload/App.app/App | grep -i "pin\|certificate\|ssl"

Bypass methods:

1. Frida script (runtime hooking):

// Android - Bypass OkHttp CertificatePinner:
Java.perform(function() {
var CertificatePinner = Java.use("okhttp3.CertificatePinner");
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(str, list) {
console.log("[+] Bypassing SSL pinning for: " + str);
return; // Do nothing (skip pinning check)
};
});

// iOS - Bypass NSURLSession pinning:
Interceptor.attach(ObjC.classes.NSURLSession["- URLSession:didReceiveChallenge:completionHandler:"].implementation, {
onEnter: function(args) {
console.log("[+] Bypassing SSL pinning");
var completionHandler = new ObjC.Block(args[4]);
completionHandler.implementation = function(disposition, credential) {
// Accept any certificate
var NSURLSessionAuthChallengeDisposition = {
UseCredential: 0,
PerformDefaultHandling: 1,
CancelAuthenticationChallenge: 2,
RejectProtectionSpace: 3
};
return completionHandler(NSURLSessionAuthChallengeDisposition.UseCredential, credential);
};
}
});

2. Xposed/Magisk module (Android):

# Install TrustMeAlready (Magisk module):
# https://github.com/ViRb3/TrustMeAlready

# Or SSLUnpinning (Xposed module):
# Install via Xposed Installer app
# Reboot device

3. SSL Kill Switch (iOS):

# Install via Cydia:
# Search: SSL Kill Switch 2
# Install and reboot
# Toggle in Settings

4. Objection (automated):

# Install Objection:
pip3 install objection

# Patch APK to include Frida gadget:
objection patchapk -s app.apk

# Install patched APK:
adb install app_objection.apk

# Run Objection:
objection explore

# Disable SSL pinning:
android sslpinning disable

Dynamic Instrumentation

Frida Basics

Installation:

# Install Frida on computer:
pip3 install frida frida-tools # pin major.minor to match the frida-server you push

# Install Frida server on Android device:
# Download frida-server for your architecture and EXACT host CLI version:
# https://github.com/frida/frida/releases
# Filename pattern: frida-server-&lt;version&gt;-android-&lt;arch&gt; (e.g. -arm64, -arm, -x86_64)
# Mismatched server vs CLI = silent no-op or crashed agent.

adb push frida-server-&lt;version&gt;-android-arm64 /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "su -c '/data/local/tmp/frida-server &'" # detached as root; nohup if persistence needed

# Install Frida on iOS (jailbroken):
# Sileo / Zebra → Sources → add https://build.frida.re → install "Frida"
# (legacy Cydia repo URL is the same; Cydia itself is largely retired on rootless JBs)

Listing processes:

# List running apps:
frida-ps -U # USB device

# Output:
# PID Name
# ---- --------
# 1234 com.example.app

Attaching to app:

# Spawn app with Frida:
frida -U -f com.example.app -l script.js

# Attach to running app:
frida -U com.example.app -l script.js

Frida Scripting Examples

1. Hooking Java methods (Android):

// Hook LoginActivity.loginUser() method
Java.perform(function() {
var LoginActivity = Java.use("com.example.app.LoginActivity");

LoginActivity.loginUser.implementation = function(username, password) {
console.log("[+] loginUser called!");
console.log(" Username: " + username);
console.log(" Password: " + password);

// Call original method:
var result = this.loginUser(username, password);
console.log(" Result: " + result);
return result;
};
});

2. Bypassing root detection (Android):

Java.perform(function() {
// Hook common root detection methods:

// Method 1: Check for su binary
var File = Java.use("java.io.File");
File.exists.implementation = function() {
var path = this.getAbsolutePath();
if (path.indexOf("su") !== -1) {
console.log("[+] Hiding su binary: " + path);
return false; // Pretend su doesn't exist
}
return this.exists();
};

// Method 2: Check for Magisk/SuperSU
var PackageManager = Java.use("android.app.ApplicationPackageManager");
PackageManager.getPackageInfo.overload('java.lang.String', 'int').implementation = function(packageName, flags) {
if (packageName === "com.topjohnwu.magisk" || packageName === "eu.chainfire.supersu") {
console.log("[+] Hiding root package: " + packageName);
throw Java.use("android.content.pm.PackageManager$NameNotFoundException").$new();
}
return this.getPackageInfo(packageName, flags);
};
});

3. Hooking Objective-C methods (iOS):

// Hook UIViewController viewDidLoad
if (ObjC.available) {
var UIViewController = ObjC.classes.UIViewController;
Interceptor.attach(UIViewController['- viewDidLoad'].implementation, {
onEnter: function(args) {
var controller = new ObjC.Object(args[0]);
console.log("[+] viewDidLoad called on: " + controller.$className);
}
});

// Hook specific class method:
var LoginVC = ObjC.classes.LoginViewController;
Interceptor.attach(LoginVC['- loginWithUsername:password:'].implementation, {
onEnter: function(args) {
var username = new ObjC.Object(args[2]).toString();
var password = new ObjC.Object(args[3]).toString();
console.log("[+] Login attempt:");
console.log(" Username: " + username);
console.log(" Password: " + password);
}
});
}

4. Dumping memory:

// Dump all loaded modules:
Process.enumerateModules({
onMatch: function(module) {
console.log("Module: " + module.name + " @ " + module.base);
},
onComplete: function() {}
});

// Dump memory region:
var baseAddr = Module.findBaseAddress("libnative.so");
var size = 0x1000; // 4KB
console.log(hexdump(baseAddr, { length: size }));

5. Tracing all function calls:

// Android - Trace all methods in a class:
Java.perform(function() {
var LoginActivity = Java.use("com.example.app.LoginActivity");

LoginActivity.$init.implementation = function() {
console.log("[+] LoginActivity constructor");
return this.$init();
};

var methods = LoginActivity.class.getDeclaredMethods();
methods.forEach(function(method) {
var methodName = method.getName();
if (LoginActivity[methodName]) {
LoginActivity[methodName].implementation = function() {
console.log("[+] Called: " + methodName);
return this[methodName].apply(this, arguments);
};
}
});
});

Objection (Frida REPL)

Objection provides interactive Frida REPL with common commands.

# Launch Objection:
objection -g com.example.app explore

# Common commands:
android hooking list classes # List all classes
android hooking search classes LoginActivity # Search classes
android hooking list class_methods com.example.app.LoginActivity # List methods
android hooking watch class com.example.app.LoginActivity # Hook all methods

android sslpinning disable # Bypass SSL pinning
android root disable # Bypass root detection

ios hooking list classes # List Objective-C classes
ios hooking search classes LoginViewController
ios hooking watch class LoginViewController

memory dump all &lt;output_file&gt; # Dump memory

Bypassing Security Controls

Root/Jailbreak Detection Bypass

Android root detection methods:

1. Check for su binary:

File suFile = new File("/system/xbin/su");
if (suFile.exists()) {
// Rooted!
}

Bypass with Frida (see Frida examples above)

2. Check for root apps (Magisk, SuperSU):

PackageManager pm = getPackageManager();
try {
pm.getPackageInfo("com.topjohnwu.magisk", 0);
// Magisk installed = rooted
} catch (PackageManager.NameNotFoundException e) {
// Not rooted
}

3. Check build tags:

String buildTags = Build.TAGS;
if (buildTags.contains("test-keys")) {
// Custom ROM = likely rooted
}

iOS jailbreak detection:

1. Check for jailbreak package managers / artefacts — modern rootless JBs (palera1n, Dopamine) install to /var/jb/... rather than /, so well-written checks scan multiple paths:

NSArray *jbPaths = @[
@"/Applications/Cydia.app", @"/Applications/Sileo.app", @"/Applications/Zebra.app",
@"/var/jb/", @"/var/jb/Applications/Sileo.app",
@"/private/var/lib/apt", @"/usr/sbin/sshd", @"/bin/bash",
@"/etc/apt", @"/usr/libexec/ssh-keysign"
];
for (NSString *p in jbPaths) {
if ([[NSFileManager defaultManager] fileExistsAtPath:p]) { /* jailbroken */ }
}

2. Check for write access to /private:

if ([[NSFileManager defaultManager] isWritableFileAtPath:@"/private"]) {
// Jailbroken
}

3. Fork() restriction:

if (fork() >= 0) {
// Jailbroken (sandboxed apps can't fork)
}

4. ptrace(PT_DENY_ATTACH) / sysctl debugger check — canonical iOS anti-debug primitive; often paired with JB detection in the same routine. Bypass with Frida hook on ptrace, sysctl, or by patching PT_DENY_ATTACH constant out of the binary:

#include <sys/ptrace.h>
ptrace(PT_DENY_ATTACH, 0, 0, 0); // Will SIGKILL on debugger attach

Bypass with Frida:

// iOS jailbreak detection bypass — covers legacy + rootless paths:
var jbMarkers = ["Cydia", "Sileo", "Zebra", "/bin/bash", "/etc/apt", "/var/jb"];
var fopen = new NativeFunction(Module.findExportByName(null, 'fopen'), 'pointer', ['pointer', 'pointer']);
Interceptor.replace(fopen, new NativeCallback(function(path, mode) {
var pathStr = Memory.readUtf8String(path);
for (var i = 0; i < jbMarkers.length; i++) {
if (pathStr.indexOf(jbMarkers[i]) !== -1) {
console.log("[+] Hiding jailbreak file: " + pathStr);
return ptr(0);
}
}
return fopen(path, mode);
}, 'pointer', ['pointer', 'pointer']));

// Pre-built bypass scripts: r2frida + Frida CodeShare (e.g. `ios-jailbreak-detection-bypass`,
// `objection`'s `ios jailbreak disable`) — preferred over hand-rolled hooks for breadth. [verify 2026-04-26]

Attestation APIs (Play Integrity / App Attest / DeviceCheck)

Modern apps increasingly defer integrity verdicts to platform-attested signals rather than rolling their own root/JB checks. Bypassing these requires either control of the server-side verifier, a valid legitimate-device attestation token relayed from a clean device, or a known weakness in how the app consumes the verdict.

PlatformAPINotes
AndroidPlay Integrity APIReplaced SafetyNet Attestation; SafetyNet Attestation API decommissioned for new integrations in 2024 [verify 2026-04-26]. Returns device, app, and account integrity verdicts signed by Google.
AndroidSafetyNet (legacy)Deprecated/decommissioned — apps still calling it may degrade gracefully or hard-fail.
iOSApp AttestiOS 14+; per-install hardware-backed key in Secure Enclave; assertions signed and verified server-side via Apple.
iOSDeviceCheckOlder, lighter — 2 bits of per-device state.

Common testing notes:

  • Verify whether the app fails-closed (refuses to run on non-attested device) or fails-open (only blocks specific actions). Report fails-open as a finding.
  • Server-side verdict consumption is where most real bugs live: missing nonce, replay window too long, accepting verdicts without checking package name / bundle ID, accepting expired tokens. Test with intercepted/replayed verdicts in Burp/Caido.
  • Tools like PIBypass / Frida codeshare scripts target client-side verdict-handling functions [verify 2026-04-26]; they do not forge a server-acceptable verdict — they simulate "device is clean" to the app's local checker only.

Debugger Detection Bypass

Android debugger detection:

// Check if debugger attached:
if (Debug.isDebuggerConnected()) {
// Debugger detected
}

// Check debuggable flag:
if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
// App is debuggable
}

iOS debugger detection:

// Check for debugger via sysctl:
#include <sys/sysctl.h>

int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()};
struct kinfo_proc info;
size_t size = sizeof(info);
sysctl(mib, 4, &info, &size, NULL, 0);

if (info.kp_proc.p_flag & P_TRACED) {
// Debugger attached
}

Bypass:

  • Patch binary to remove checks (static analysis)
  • Hook detection functions with Frida (dynamic)

Emulator/Simulator Detection Bypass

Android emulator detection:

// Check for emulator properties:
String brand = Build.BRAND; // "generic" on emulators
String device = Build.DEVICE; // "generic" on emulators
String model = Build.MODEL; // "sdk" on emulators

// Check for Genymotion:
if (Build.PRODUCT.contains("vbox")) {
// Genymotion emulator
}

Bypass:

# Modify build.prop on emulator:
adb root
adb remount
adb shell

vi /system/build.prop
# Change:
# ro.build.product=generic -> ro.build.product=OnePlus7
# ro.product.model=sdk -> ro.product.model=OnePlus 7

reboot

Automated Testing

Mobile App Scanners

QARK (Quick Android Review Kit):

# Install QARK:
pip3 install qark

# Analyze APK:
qark --apk app.apk

# Output: Vulnerability report (manifest issues, code vulnerabilities, etc.)

MobSF (Mobile Security Framework):

# See Android/iOS Static Analysis sections for setup

# Features:
# - Automated vulnerability scanning
# - Code analysis (SAST)
# - Binary analysis
# - API testing (dynamic)
# - Report generation

Automated Fuzzing

Drozer (Android Intent fuzzing):

Drozer was effectively unmaintained for several years after MWR/F-Secure changes; current upstream is WithSecure Labs (WithSecureLabs/drozer). Still useful for IPC attack-surface enumeration but the Python 2 → 3 port history means flag and command parity drift between forks — verify against current README. [verify 2026-04-26]

# Install Drozer:
# https://github.com/WithSecureLabs/drozer

# Install agent APK on device:
adb install drozer-agent.apk

# Start drozer server on device (via agent app)

# Connect from computer:
drozer console connect

# List attack surface:
dz> run app.package.attacksurface com.example.app

# Output:
# Exported Activities: 3
# Exported Services: 1
# Exported Broadcast Receivers: 2

# Fuzz exported components:
dz> run app.activity.start --component com.example.app com.example.app.PaymentActivity --extra string amount "0.01"

Tools Reference

Android Tools

ToolPurposePlatform
JADXAPK decompiler (DEX to Java)Win/Linux/macOS
ApktoolAPK decoder/rebuilder (smali)Win/Linux/macOS
apksigner / zipalignModern v2/v3/v4 sign + align (build-tools)Win/Linux/macOS
MobSFAutomated security testing (SAST + dynamic)Web-based
Frida + frida-serverDynamic instrumentation (CLI/server versions must match)Win/Linux/macOS
ObjectionFrida REPL for mobileWin/Linux/macOS
r2fridaRadare2 ↔ Frida bridgeWin/Linux/macOS
Drozer (WithSecure fork)Android IPC / attack-surface assessmentWin/Linux/macOS
apkeep / gplaydlAPK acquisition (Play, APKPure, F-Droid, AppGallery)Linux/macOS
AndroBugsStatic analyzer (legacy, infrequent updates) [verify 2026-04-26]Linux
QARKQuick security scanner (legacy) [verify 2026-04-26]Linux
adbAndroid Debug BridgeWin/Linux/macOS
Magisk / KernelSURoot frameworks (KernelSU = kernel-level alternative)Android device

iOS Tools

ToolPurposePlatform
frida-ios-dump / bagbakDecrypt App Store IPAs (FairPlay → plaintext Mach-O)Linux/macOS + JB device
ipatoolDownload encrypted IPA from App Store via Apple IDLinux/macOS
ClutchLegacy IPA decryptor (largely superseded by frida-ios-dump/bagbak)iOS (jailbroken)
class-dumpExtract Objective-C headers (legacy; Swift unsupported)macOS/Linux
jtool2Mach-O analysis (codesign, entitlements, Obj-C metadata)macOS/Linux
HopperDisassembler/decompilermacOS/Linux
MobSFAutomated security testingWeb-based
Frida + frida-serverDynamic instrumentationWin/Linux/macOS
ObjectionFrida REPL for mobileWin/Linux/macOS
r2fridaRadare2 ↔ Frida bridgeWin/Linux/macOS
SSL Kill Switch 3Bypass SSL pinning (rootless-aware fork of SKS2)iOS (Sileo/Zebra)
Keychain-DumperExtract Keychain itemsiOS (jailbroken)
palera1n / Dopamine / checkra1nJailbreak (matrix in §iOS Security Testing)macOS/Linux + iOS device
libimobiledevice (idevicesyslog, ideviceinstaller, idevice_id)Non-JB device interaction & log streamingLinux/macOS

Multi-Platform Tools

ToolPurposePlatform
Burp SuiteHTTPS interception/fuzzingWin/Linux/macOS
GhidraBinary analysis (ARM/x86)Win/Linux/macOS
IDA ProDisassembler (commercial)Win/Linux/macOS
FridaRuntime hookingWin/Linux/macOS
Radare2RE frameworkWin/Linux/macOS
WiresharkNetwork traffic analysisWin/Linux/macOS

Learning Resources

Documentation

Books

  • Mobile Application Penetration Testing by Vijay Kumar
  • Android Hacker's Handbook by Joshua J. Drake et al.
  • iOS Hacker's Handbook by Charlie Miller et al.
  • The Mobile Application Hacker's Handbook by Dominic Chell et al.

Online Courses

  • Mobile Application Security and Penetration Testing (eLearnSecurity eMAPT)
  • SANS SEC575: Mobile Device Security and Ethical Hacking
  • Pentester Academy: Mobile Security

Practice Apps


Analysis:

Pentesting & Security:

Methodology & Authorization:


Version: 1.1 Last Updated: 2026-04-26 Review Frequency: Quarterly (mobile platform APIs, jailbreak tooling, and SSL-pinning bypass primitives churn quickly)