<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: performing-ios-dynamic-analysis
description: >-
  Runtime instrumentation and dynamic testing of iOS applications using Frida,
  objection, and Cycript. Covers method tracing, keychain inspection, pasteboard
  monitoring, SSL pinning bypass, and runtime manipulation on jailbroken devices.
domain: cybersecurity
subdomain: mobile-security
tags:
  - ios
  - dynamic-analysis
  - frida
  - objection
  - cycript
  - runtime-hooking
  - keychain
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1407", "T1409", "T1417"]
  owasp-mobile: ["M1", "M2", "M4", "M5", "M9"]
  tools: ["frida", "objection", "cycript", "lldb", "iproxy"]
---

# Performing iOS Dynamic Analysis

## Overview

iOS dynamic analysis instruments a running application to inspect runtime behavior,
hook Objective-C/Swift methods, dump keychain items, bypass certificate pinning,
and identify data leaks. Requires a jailbroken device or Frida gadget injection.

## Prerequisites

```bash
pip install frida-tools objection
# Jailbroken device with frida-server running
# Or: inject FridaGadget.dylib into IPA for non-jailbroken testing
```

## Workflow

### Step 1: Device Setup and App Spawning

```bash
# List connected devices
frida-ls-devices

# List running apps
frida-ps -Ua

# Spawn and attach to app
frida -U -f com.target.app --no-pause
objection -g com.target.app explore
```

### Step 2: Runtime Exploration with Objection

```bash
# Environment info
objection -g com.target.app explore -s "env"

# List classes
objection -g com.target.app explore -s "ios hooking list classes"

# List methods of a class
objection -g com.target.app explore -s "ios hooking list class_methods ViewController"

# Watch a method
objection -g com.target.app explore -s "ios hooking watch method '+[KeychainHelper getToken]' --dump-args --dump-return"

# Dump keychain
objection -g com.target.app explore -s "ios keychain dump"

# Dump cookies
objection -g com.target.app explore -s "ios cookies get"

# SSL pinning bypass
objection -g com.target.app explore -s "ios sslpinning disable"

# Pasteboard monitor
objection -g com.target.app explore -s "ios pasteboard monitor"
```

### Step 3: Frida Scripting

```javascript
// Hook Objective-C method
if (ObjC.available) {
    var className = "KeychainManager";
    var methodName = "- getSecureToken";
    var hook = ObjC.classes[className][methodName];
    Interceptor.attach(hook.implementation, {
        onEnter: function(args) {
            console.log("[*] " + className + " " + methodName + " called");
        },
        onLeave: function(retval) {
            console.log("[*] Return: " + ObjC.Object(retval).toString());
        }
    });
}

// Dump all NSUserDefaults
if (ObjC.available) {
    var defaults = ObjC.classes.NSUserDefaults.standardUserDefaults();
    var dict = defaults.dictionaryRepresentation();
    console.log(JSON.stringify(dict, null, 2));
}

// Monitor file operations
Interceptor.attach(Module.findExportByName(null, "open"), {
    onEnter: function(args) {
        this.path = args[0].readUtf8String();
    },
    onLeave: function(retval) {
        if (this.path && this.path.indexOf("Documents") !== -1) {
            console.log("[FILE] " + this.path + " fd=" + retval);
        }
    }
});

// Bypass jailbreak detection
if (ObjC.available) {
    var paths = ["/Applications/Cydia.app", "/usr/sbin/sshd",
                 "/bin/bash", "/etc/apt"];
    var fileManager = ObjC.classes.NSFileManager;
    Interceptor.attach(fileManager["- fileExistsAtPath:"].implementation, {
        onEnter: function(args) {
            this.path = ObjC.Object(args[2]).toString();
        },
        onLeave: function(retval) {
            if (paths.some(p => this.path.includes(p))) {
                retval.replace(0x0);
            }
        }
    });
}
```

### Step 4: Binary and Memory Inspection

```bash
# Dump app binary
frida-dump -U -f com.target.app

# Search memory for strings
objection -g com.target.app explore -s "memory search 'password' --string"

# List loaded modules
objection -g com.target.app explore -s "memory list modules"

# Export module
objection -g com.target.app explore -s "memory list exports AppBinary"
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| Frida server port | Network scan | Default port 27042 open |
| Frida named pipes | Process list | frida-helper processes |
| Cycript injection | Crash logs | Unexpected dylib loads |
| Keychain access | Unified logs | Unusual keychain item reads |

```yaml
title: Ios Dynamic Analysis Detection
id: 41049372-7ab9-4515-b4d8-eff5a598bef6
status: experimental
description: Detects suspicious activity related to performing ios dynamic analysis techniques in mobile security context
logsource:
  category: application
  product: android
detection:
  selection:
    EventType: error
  condition: selection
level: medium
tags:
  - attack.t1407
  - attack.t1409
  - attack.t1417
  - attack.initial_access
falsepositives:
  - Mobile device management platform enforcing security policies
```

## Verification

- [ ] App spawned and attached via Frida/objection
- [ ] Keychain contents dumped and reviewed
- [ ] SSL pinning bypassed and traffic intercepted
- [ ] Sensitive method calls hooked and logged
- [ ] Data storage locations identified via env inspection
- [ ] Jailbreak detection bypass tested

## References

- [OWASP MASTG — iOS Dynamic Analysis](https://mas.owasp.org/MASTG/techniques/ios/MASTG-TECH-0055/)
- [Frida iOS](https://frida.re/docs/ios/)
- [objection](https://github.com/sensepost/objection)
- [MITRE T1407](https://attack.mitre.org/techniques/T1407/)
