🔍 What is Dynamic Analysis in iOS?

Dynamic analysis involves inspecting the behavior of an iOS application while it is running on a device or emulator. This method helps uncover real-time vulnerabilities such as insecure API communication, insecure data storage, runtime manipulations, and more.

Unlike static analysis, which examines code or binaries, dynamic testing focuses on observing the app’s live behavior, interactions with the system, and network communications.

🛠️ Essential Tools for iOS Dynamic Analysis

🚀 Step-by-Step iOS Dynamic Testing Workflow

Step 1: Prepare the Environment

  • Use a jailbroken iOS device (e.g., via Checkra1n)
  • Install Cydia and required packages like Frida, OpenSSH, and SSL Kill Switch 2
  • Ensure USB tunneling or Wi-Fi SSH access is configured

Step 2: Monitor App Network Traffic

Use a proxy tool like Burp Suite or Charles:

# On your Mac:
sudo ifconfig en0 | grep "inet "  # Get IP address

# On iOS (proxy settings):
Settings > Wi-Fi > HTTP Proxy > Manual > Enter Mac IP and Port 8080

# In Burp:
- Enable proxy listener on 8080
- Install Burp CA on device for HTTPS interception

This lets you see API endpoints, sensitive data in transit, tokens, and more.

Step 3: Bypass SSL Pinning

Many modern iOS apps implement SSL pinning. Use SSL Kill Switch 2 or Frida scripts to bypass it.

# Disable SSL pinning using SSL Kill Switch 2
Install via Cydia, then reboot the device

# Or use Frida:
frida -U -n TargetApp -l ios-sslpinning-bypass.js

Step 4: Hook App Functions using Frida

Example: Hooking NSUserDefaults read/write actions

frida -U -n TargetApp -l hookNSUserDefaults.js

// hookNSUserDefaults.js
ObjC.classes.NSUserDefaults["- stringForKey:"].implementation = function(key) {
  console.log("[*] Reading key: " + key.toString());
  return this.stringForKey_(key);
};

⚙️ Advanced Techniques

🌐 Real-World Use Case

Scenario: Testing an iOS banking app revealed that after login, an auth token was stored in NSUserDefaults, which is insecure.

Using Frida, the token was intercepted during runtime:

[*] Reading key: auth_token
[*] Value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

This token could then be reused in API requests via Burp to simulate authenticated user actions.

💡 Tips for Effective Dynamic Analysis

📚 Recommended Resources