# iOS RE Cheatsheet

> ARM64 · Swift · ObjC · Frida · IDA Pro · SSL Pinning · Jailbreak Detection · Static & Dynamic Analysis

***

## 1. Toolchain Setup

### Static Analysis

| Tool             | Description                                     |
| ---------------- | ----------------------------------------------- |
| `IDA Pro`        | Primary disassembler + decompiler (Hex-Rays)    |
| `Ghidra`         | Free alternative, good Swift support via plugin |
| `Hopper`         | Lightweight, fast ObjC analysis on macOS        |
| `class-dump`     | ObjC header reconstruction from binary          |
| `dsdump`         | Swift + ObjC metadata dump, more detailed       |
| `jtool2`         | Mach-O swiss-army knife, better than otool      |
| `nm` / `strings` | Symbol listing, string extraction               |

### Dynamic Analysis

| Tool          | Description                                |
| ------------- | ------------------------------------------ |
| `Frida`       | Runtime instrumentation, hook injection    |
| `Objection`   | Frida-based toolkit, SSL bypass, mem dump  |
| `lldb`        | On-device debugger via Xcode / debugserver |
| `frida-trace` | Auto-trace ObjC methods & C functions      |
| `r2frida`     | radare2 + Frida combined analysis          |
| `Burp Suite`  | HTTP/S proxy for traffic interception      |
| `mitmproxy`   | Lightweight proxy, scriptable              |

### Utility / Support

| Tool                   | Description                                  |
| ---------------------- | -------------------------------------------- |
| `ipsw`                 | Download & extract iOS firmware, DYLD cache  |
| `ldid`                 | Sign binaries for sideloading / testing      |
| `frida-ios-dump`       | Decrypt & dump App Store IPAs                |
| `bfdecrypt`            | Inline decryption via Cydia tweak            |
| `Filza / iFile`        | On-device filesystem browser                 |
| `otool`                | Object file displaying tool (built-in macOS) |
| `xcrun swift-demangle` | Demangle Swift mangled symbol names          |

***

## 2. First Recon — Before Opening IDA

### Shell Commands

```bash
# Check encryption
otool -l Binary | grep -A4 LC_ENCRYPT

# Linked frameworks
otool -L Binary
jtool2 -L Binary

# Architecture & flags
otool -hv Binary
file Binary

# Mach-O sections
otool -l Binary | grep -E "sectname|segname|size|offset"

# String extraction
strings -a Binary | grep -iE "http|api|key|token|secret|jwt"
strings -a Binary | grep -E "^[A-Za-z0-9+/]{20,}={0,2}$"  # base64 candidates

# Exported symbols
nm -U Binary | grep " T "    # defined text symbols
nm -u Binary                 # undefined (imports)

# Swift demangle
xcrun swift-demangle _'$s3App12NetworkClientC11fetchToken...'
nm Binary | xcrun swift-demangle
```

### class-dump / dsdump

```bash
# ObjC header dump
class-dump -H Binary -o ./headers/

# Swift metadata (more detailed)
dsdump --swift Binary
dsdump --swift --verbose Binary
dsdump --objc Binary

# Filter interesting classes
dsdump --swift Binary | grep -iE \
  "Manager|Service|Client|Handler|Auth|Token|Crypto|Pin|Network|Session"

# jtool2 ObjC metadata
jtool2 -d objc Binary
jtool2 --analyze Binary     # full analysis

# Priority targets to find:
# *Manager  *Service  *Client  *Handler  *Provider
# *Auth     *Token    *Session *Crypto   *Pin
# *Network  *Request  *Interceptor       *Certificate
```

### Decryption — App Store IPAs

```bash
# Method 1 — frida-ios-dump (USB device)
frida-ios-dump -u mobile -H 127.0.0.1:2222 com.target.app

# Method 2 — bfdecrypt (Cydia tweak, install on device)
# Tap app → decrypted IPA in /var/mobile/Documents/

# Method 3 — Bagbak
bagbak --host 127.0.0.1:2222 com.target.app

# Verify decryption worked
otool -l DecryptedBinary | grep -A4 cryptid
# cryptid 0 → decrypted ✓
# cryptid 1 → still encrypted ✗

# Extract from DYLD shared cache (iOS system frameworks)
ipsw dyld extract dyld_shared_cache UIKit
```

### DYLD Cache & Imports

```bash
# Key imports → what security features the app uses
otool -L Binary | grep -iE \
  "Security|CommonCrypto|LocalAuth|CFNetwork|sqlite"

# Security.framework  → Keychain, cert pinning, SecTrust
# CommonCrypto        → AES/SHA/HMAC/RSA (CC_SHA256 etc.)
# CFNetwork/NSURLSession → networking stack
# LocalAuthentication → Touch/Face ID
# libsqlite3          → local database (may store tokens)

# List all C imports
nm -u Binary | grep -E "^.*U _" | sed 's/.* _//' | sort

# Check for interesting C functions directly
nm -u Binary | grep -E \
  "CC_SHA|CCCrypt|SecItem|SecTrust|SSL_|fork|ptrace|sysctl"
```

***

## 3. ARM64 Quick Reference

### Calling Convention

| Register(s) | Role                                             |
| ----------- | ------------------------------------------------ |
| `x0–x7`     | Function arguments (in order) / return values    |
| `x0–x1`     | Return values (Swift String = x0 low + x1 flags) |
| `x8`        | **sret pointer** — indirect struct return buffer |
| `x9–x15`    | Scratch / caller-saved (can be clobbered)        |
| `x16–x17`   | Intra-procedure-call temporaries (IPC)           |
| `x18`       | Platform reserved (iOS: thread-local)            |
| `x19–x28`   | Callee-saved — preserved across calls            |
| `x29 (fp)`  | Frame pointer                                    |
| `x30 (lr)`  | Link register — return address                   |
| `sp`        | Stack pointer (16-byte aligned)                  |

### Key Instructions

```asm
; Calls
BL   label          ; call (Branch + Link)
BLR  X8             ; indirect call (vtable dispatch)
RET                 ; return (branch to x30)

; Conditional branches
B.EQ / B.NE         ; equal / not equal (zero flag)
B.LT / B.GT         ; less / greater than (signed)
B.LO / B.HI         ; lower / higher (unsigned)
CBZ  X0, label      ; branch if X0 == 0
CBNZ X0, label      ; branch if X0 != 0
TBZ  W0, #0, label  ; test bit 0, branch if zero  ← Bool check
TBNZ W0, #0, label  ; test bit 0, branch if non-zero

; Load / Store
LDR  X1, [X0, #16]  ; load 64-bit from X0+16
LDP  X1, X2, [X0]   ; load pair (efficient struct read)
STR  X1, [X0, #24]  ; store 64-bit to X0+24
STP  X1, X2, [SP,#-16]! ; push pair to stack

; Address loading (typical IDA pattern for strings/data)
ADRP X0, page           ; load page address (4KB aligned)
ADD  X0, X0, :lo12:sym  ; add page offset
LDR  X0, [X0, :lo12:ptr]; indirect (pointer to data)
```

### sret — Struct Return (Critical for Swift)

```asm
; When a function returns a struct > 16 bytes:
; → caller allocates buffer on stack
; → passes pointer in X8 BEFORE the call
; → callee writes result to *X8
; → x0 may be unrelated (or the sret ptr itself)

; IDA signature of sret function:
; __int64 __usercall func@<X0>(__int64 x8_0@<X8>, ...)
```

```javascript
// In Frida — WRONG (crashes):
Interceptor.attach(addr, {
  onEnter(args) { args[0] // ← this is sret pointer, NOT arg1! }
})

// In Frida — CORRECT:
Interceptor.attach(addr, {
  onEnter(args) {
    this.sret = this.context.x8  // ← capture sret ptr
    this.arg0 = args[0]           // ← first real argument
  },
  onLeave(retval) {
    const field = this.sret.add(0x10).readU8()
  }
})
```

### Common Patterns in IDA

```asm
; NULL check (Optional unwrap)
CBZ  X0, nil_path    ; → guard let / if let

; Bool return — only bit 0 matters
AND  W0, W0, #1      ; mask Bool
TBZ  W0, #0, false_path

; Swift enum discriminant
LDRB W1, [X0, #last_byte]  ; read tag byte
CMP  W1, #0                 ; 0 = first case
CMP  W1, #1                 ; 1 = second case

; vtable dispatch (Swift class method)
LDR  X8, [X0]         ; load vtable pointer from object
LDR  X9, [X8, #0x40]  ; load method from vtable+0x40
BLR  X9               ; call method

; Swift object layout
; [+0x00] isa / metadata pointer
; [+0x08] reference count
; [+0x10] first stored property
```

***

## 4. Swift Internals — IDA Patterns

### Swift String Encoding in Registers

| `x1` top bits  | Type                      | `x0` content                     |
| -------------- | ------------------------- | -------------------------------- |
| `0xE0…0xEF`    | Small inline string       | ASCII bytes packed in x0+x1      |
| `0x8000 0001…` | Large heap String         | Pointer to Swift \_StringStorage |
| `0xF000…`      | Foreign (NSString bridge) | Pointer to NSString object       |
| `x1>>62 == 2`  | Data heap large           | Pointer to `__DataStorage`       |
| `x1>>62 == 1`  | Data medium               | Encoded inline                   |
| `x1>>62 == 0`  | Data inline/small         | `BYTE6(x1)` = length             |

```javascript
// Decode small inline Swift String (Frida)
function swiftSmolStr(lo, hi) {
  let s = '';
  for (let i = 0; i < 8; i++) {
    const c = lo.shr(i*8).and(0xFF).toUInt32();
    if (c > 0x1F && c < 0x80) s += String.fromCharCode(c);
  }
  for (let i = 0; i < 6; i++) {
    const c = hi.shr(i*8).and(0xFF).toUInt32();
    if (c > 0x1F && c < 0xE0) s += String.fromCharCode(c);
  }
  return s;
}
```

### Skip-Pattern Recognition

These are always boilerplate — **skip immediately** without further analysis:

```c
// 1. Lazy type metadata accessor → Swift_lazyTypeMetadataAccessor → SKIP
result = *a1;
if (!result) {
  result = swift_getTypeByMangledNameInContext(...);
  *a1 = result;
}
return result;

// 2. Lazy witness table accessor → Swift_lazyWitnessTableAccessor → SKIP
result = qword_XXXX;
if (!qword_XXXX) {
  result = swift_getWitnessTable(...);
  atomic_store(result, &qword_XXXX);
}

// 3. swift_once initialiser → Swift_once_* → SKIP body
if (qword_XXXX != -1)
  swift_once(&qword_XXXX, sub_YYYY);
return &qword_ZZZZ;

// 4. CoW array reallocator → Swift_Array_*_reallocateBuffer → SKIP
if ((a3 & 1) != 0) { /* grow */ }
swift_allocObject(...)
memmove(...)

// 5. ARC dispatch → Swift_arcRetain/ReleaseTaggedOrHeap → SKIP
if (a2 >> 62 != 1) {
  if (a2 >> 62 != 2) return;
  swift_release(a2 & 0x3FFF...);
}
```

### Function Size Heuristic

| Size          | Likely type                                 | Action     |
| ------------- | ------------------------------------------- | ---------- |
| `< 0x20`      | ARC helper / metadata thunk / getter        | **Skip**   |
| `0x20–0x60`   | CoW helper / Data wrapper / witness init    | **Skip**   |
| `0x60–0x100`  | String/Data utility, possible crypto helper | Quick scan |
| `0x100–0x400` | Real logic — check functions, parsers       | Analyze    |
| `> 0x400`     | Core logic, orchestrators, complex checks   | Deep dive  |

**First call in function body:**

| First call                    | Action               |
| ----------------------------- | -------------------- |
| `swift_getTypeByMangledName…` | **Skip**             |
| `swift_getWitnessTable`       | **Skip**             |
| `swift_once`                  | **Skip body**        |
| `swift_allocObject`           | Note type, continue  |
| `CC_SHA256` / `CCCrypt`       | **Priority analyze** |
| `_dyld_*` / `sysctl`          | **Security check**   |
| `objc_msgSend`                | Read selector        |

### Swift Memory Layouts

```
// Protocol value on stack (existential container) — 40 bytes
[+0x00] value word 0    // inline if ≤ 3 words, else heap ptr
[+0x08] value word 1
[+0x10] value word 2
[+0x18] type metadata   // pointer to TypeMetadata
[+0x20] witness table   // pointer to protocol conformance

// Swift Optional<T> (pointer-sized T):
//   .none  → 0 (nil)
//   .some  → non-zero value
// Check: CBZ X0, nil_branch

// Swift Array buffer layout
[+0x00] isa / refcount
[+0x10] count (Int)
[+0x18] capacity×2 (encoded)
[+0x20] elements start here   // buf + 32

// Swift Dictionary bucket layout
// Bitmap at buf+64: 1 bit per bucket (occupied flag)
// Keys array at metadata[+48]: [String] pairs
// Values array at metadata[+56]: [Value] pairs
```

***

## 5. ObjC Runtime Patterns

### `objc_msgSend` Patterns

```c
// Register assignment:
// x0 = receiver (self or class)
// x1 = SEL (selector — IDA shows as string)
// x2, x3, ... = arguments

// [NSURLSession sharedSession]
cls     = objc_opt_self(&OBJC_CLASS___NSURLSession);
session = objc_msgSend(cls, "sharedSession");

// [[MyClass alloc] initWithString:]
obj    = objc_allocWithZone(&OBJC_CLASS___MyClass);
result = objc_msgSend(obj, "initWithString:", str);

// Retain/release — skip these in analysis
objc_retain(x)
objc_release(x)
objc_retainAutoreleasedReturnValue(x)   // always after msgSend

// Static / class method
cls    = objc_opt_self(&OBJC_CLASS___NSBundle);
bundle = objc_msgSend(cls, "mainBundle");   // +mainBundle

// When IDA doesn't show the selector:
// Look at x1 register → reference to __TEXT.__objc_methnames
// Or: Search → Immediate value → address of selector
```

### Key ObjC Classes & Selectors

| Class / Selector                      | Security Relevance                             |
| ------------------------------------- | ---------------------------------------------- |
| `NSURLSession -dataTaskWithRequest:`  | HTTP requests — hook for traffic interception  |
| `NSURLSession -didReceiveChallenge:…` | SSL auth challenge — pinning bypass target     |
| `SecItemCopyMatching`                 | Keychain read — dump credentials               |
| `SecItemAdd`                          | Keychain write — trace stored secrets          |
| `SecTrustEvaluate / …WithError:`      | Certificate validation — pinning               |
| `NSBundle -pathForResource:ofType:`   | Reads embedded resources (plist, cert, config) |
| `NSFileManager -fileExistsAtPath:`    | Jailbreak filesystem checks                    |
| `UIDevice -systemVersion`             | OS version checks                              |
| `NSUserDefaults -objectForKey:`       | Persistent config / flags storage              |
| `FIRCrashlytics -recordError:`        | Security event telemetry reporting             |

***

## 6. Frida — Essential Scripts

### CLI — Device Setup

```bash
# List running processes
frida-ps -Uia           # USB, installed apps
frida-ps -H 127.0.0.1   # SSH tunnel

# Attach REPL
frida -U com.target.app
frida -U -f com.target.app --no-pause   # spawn + attach

# Auto-trace ObjC methods
frida-trace -U -f com.target.app \
  -m "*[NSURLSession *]" \
  -m "*[*Auth* *]" \
  -m "-[*ViewController *]"

# Trace by RVA (Swift functions)
frida-trace -U com.target.app \
  -a "FrameworkName!0x1234"

# Objection quick actions
objection -g com.target.app explore
  ios sslpinning disable
  ios keychain dump
  ios jailbreak simulate
  memory list modules
  ios hooking list classes
  ios hooking watch class NSURLSession
```

### Hook Template — Universal

```javascript
const base  = Module.getBaseAddress('TargetFramework');
const slide = base.sub(ptr('0x100000000'));

function hook(rva, name, enter, leave) {
  Interceptor.attach(ptr(rva).add(slide), {
    onEnter(args) {
      this.name = name;
      if (enter) enter.call(this, args);
    },
    onLeave(retval) {
      if (leave) leave.call(this, retval);
    }
  });
}

// Hook ObjC method
const cls = ObjC.classes.NSURLRequest;
Interceptor.attach(cls['- URL'].implementation, {
  onEnter(args) {
    console.log('[HTTP]', ObjC.Object(args[0]).URL().absoluteString());
  }
});

// Replace ObjC method return value
const orig = ObjC.classes.MyClass['- isJailbroken'].implementation;
Interceptor.replace(orig, new NativeCallback(function(self, sel) {
  return 0;  // force false
}, 'bool', ['pointer', 'pointer']));
```

### Runtime Introspection

```javascript
// Find all instances of a class at runtime
ObjC.choose(ObjC.classes.MyClass, {
  onMatch(obj) { console.log('found:', obj); },
  onComplete()  { console.log('done'); }
});

// Hook all methods of a class
const cls = ObjC.classes.NSURLSession;
for (const m of cls.$ownMethods) {
  Interceptor.attach(cls[m].implementation, {
    onEnter() { console.log(`[NSURLSession] ${m}`); }
  });
}

// Memory dump at address
console.log(hexdump(ptr('0x...'), {
  length: 64, header: true, ansi: true
}));

// List loaded modules + base addresses
Process.enumerateModules()
  .filter(m => m.name.includes('target'))
  .forEach(m => console.log(m.name, m.base, m.size));

// Read Swift String from memory (large heap)
function readSwiftString(ptr) {
  const len = ptr.add(0x10).readU64();
  return ptr.add(0x20).readUtf8String(Number(len));
}
```

### Keychain & CommonCrypto Hooks

```javascript
// Keychain read intercept
const SecItemCopyMatching = Module.findExportByName(
  'Security', 'SecItemCopyMatching');
Interceptor.attach(SecItemCopyMatching, {
  onEnter(args) { this.result = args[1]; },
  onLeave(retval) {
    if (retval.toInt32() === 0) {
      const item = this.result.readPointer();
      console.log('[Keychain]', ObjC.Object(item).toString());
    }
  }
});

// CC_SHA256 — log every hash input/output
const CC_SHA256 = Module.findExportByName(null, 'CC_SHA256');
Interceptor.attach(CC_SHA256, {
  onEnter(args) {
    const data = args[0];
    const len  = args[1].toUInt32();
    console.log('[SHA256 input]', hexdump(data, { length: len }));
  },
  onLeave(retval) {
    console.log('[SHA256 digest]', retval.readByteArray(32));
  }
});
```

***

## 7. SSL Pinning Bypass

### Bypass Levels — Try in Order

| Level | Method                                                    | Notes                                                    |
| ----- | --------------------------------------------------------- | -------------------------------------------------------- |
| **1** | `objection: ios sslpinning disable`                       | Patches common patterns automatically. Try first.        |
| **2** | SSL Kill Switch 2 (Cydia tweak)                           | System-wide hook on `SecTrustEvaluate`.                  |
| **3** | Hook `-URLSession:didReceiveChallenge:completionHandler:` | Force `NSURLSessionAuthChallengeUseCredential` with nil. |
| **4** | Hook `TSKSPKIHashCache` (TrustKit)                        | Return hash matching your proxy cert's SPKI.             |
| **5** | Hook `SecTrustEvaluateWithError` → force `true`           | Works for custom SecTrust implementations.               |
| **6** | Find embedded client cert via `SecPKCS12Import`           | Mutual TLS — cert embedded in `__DATA` or bundle.        |

### Bypass Code

```javascript
// SecTrustEvaluateWithError bypass
const SecTrust = Module.findExportByName(
  'Security', 'SecTrustEvaluateWithError');
Interceptor.replace(SecTrust, new NativeCallback(
  (trust, error) => { return 1; },  // always trusted
  'bool', ['pointer', 'pointer']
));

// NSURLSession delegate hook
const cls = ObjC.classes.YourAppDelegate;
const sel = 'URLSession:didReceiveChallenge:completionHandler:';
Interceptor.replace(cls['- '+sel].implementation,
  new NativeCallback(function(self, _sel, session, challenge, handler) {
    const disposition = 1; // NSURLSessionAuthChallengeUseCredential
    ObjC.Object(handler).call([disposition, NULL]);
  }, 'void', ['pointer','pointer','pointer','pointer','pointer'])
);
```

```bash
# Find embedded cert/key in binary
otool -l Binary | grep -A5 __DATA
# Look for suspiciously-sized sections in __DATA_CONST
# PKCS#12 header: 0x3082 (DER SEQUENCE)
# PEM: look for "CERTIFICATE" string
strings Binary | grep -E "BEGIN CERT|BEGIN RSA|BEGIN PRIV"
```

***

## 8. Jailbreak Detection — Bypass

### Detection Vectors

| Method                             | What to Spoof                                                         |
| ---------------------------------- | --------------------------------------------------------------------- |
| `stat` / `lstat` / `access`        | Return `ENOENT` for JB paths (`/bin/bash`, `/Applications/Cydia.app`) |
| `fopen` / `open`                   | Return `NULL`/`−1` for JB files                                       |
| `fork()`                           | Sandboxed apps can't fork → return `−1`                               |
| `ptrace(PT_DENY_ATTACH)`           | Hook ptrace → return `0` (allow debugger)                             |
| `sysctl(P_TRACED)`                 | Debugger presence → clear flag in returned struct                     |
| `dlopen(MobileSubstrate)`          | Return `NULL` for substrate/tweak libraries                           |
| `canOpenURL("cydia://")`           | Force return `NO`                                                     |
| `NSFileManager -fileExistsAtPath:` | Return `NO` for JB paths                                              |
| `vm_region_64`                     | Check `__DATA_CONST` writability → mask `VM_PROT_WRITE`               |
| `_dyld_image_count` / name         | Filter out Substrate/tweak dylibs from list                           |

### Universal Filesystem Bypass (Frida)

```javascript
const JB_PATHS = [
  '/Applications/Cydia.app', '/bin/bash',
  '/usr/sbin/sshd', '/etc/apt',
  '/private/var/lib/apt', '/var/lib/cydia',
  '/Library/MobileSubstrate', '/var/checkra1n',
  '/var/jb', '/bootstrap'
];

['stat', 'lstat', 'fopen', 'access', 'open'].forEach(sym => {
  const fn = Module.findExportByName(null, sym);
  if (!fn) return;
  Interceptor.attach(fn, {
    onEnter(args) {
      try { this.path = args[0].readUtf8String(); } catch(e) {}
    },
    onLeave(retval) {
      if (JB_PATHS.some(p => this.path?.includes(p)))
        retval.replace(ptr(-1));
    }
  });
});

// ptrace bypass
const ptrace = Module.findExportByName(null, 'ptrace');
Interceptor.replace(ptrace, new NativeCallback(
  () => 0, 'int', ['int','int','int','int']));

// sysctl debugger check bypass
// Clear P_TRACED flag (offset 32 in kinfo_proc, bit 0x800)
const sysctl = Module.findExportByName(null, 'sysctl');
Interceptor.attach(sysctl, {
  onLeave() {
    // Read & clear P_TRACED flag from returned kinfo_proc
  }
});
```

***

## 9. IDA Pro — Systematic Workflow

{% stepper %}
{% step %}

### Phase 1 — Orientation (30 min)

1. **Functions window** → sort by size DESC → largest = real logic, skip < 0x20 bytes
2. **Imports window** → identify security libraries: `Security.framework`, `CommonCrypto`, `CFNetwork`, `LocalAuthentication`, `sqlite3`
3. **Strings window** → filter: `https://`, `/api/`, `/v1/`, error messages, base64 patterns
4. **Search** → class names from `dsdump` output → jump directly to known interesting classes
5. **Segments** → check `__DATA.__const` and `__TEXT.__cstring` → embedded certs, keys, endpoints
   {% endstep %}

{% step %}

### Phase 2 — Function Analysis Flow

1. Check size → apply heuristic (`< 0x20` skip, `> 0x100` full analysis)
2. Check first call → `swift_getTypeByMangledName` → skip immediately
3. `xrefs_to` → caller context often explains purpose completely
4. `callgraph(depth=2)` → find `CC_SHA256`, `CCCrypt`, `_dyld_*`, `sysctl` in subtree
5. Rename locals immediately as you understand them (`v1→ptr_data`, `v2→len`)
6. `set_comments` at key addresses — document polarity, bypass points, data layout
   {% endstep %}
   {% endstepper %}

### IDA Shortcuts (macOS)

| Shortcut        | Action                                |
| --------------- | ------------------------------------- |
| `F5`            | Decompile current function (Hex-Rays) |
| `N`             | Rename symbol / variable              |
| `;`             | Add comment at cursor                 |
| `X`             | Cross-references TO current address   |
| `Ctrl+X`        | xrefs FROM current address            |
| `G`             | Go to address                         |
| `Alt+↑ / Alt+↓` | Navigate xref history                 |
| `Space`         | Toggle graph / linear view            |
| `Ctrl+F`        | Search text in current function       |
| `Alt+T`         | Search all text / strings             |
| `Ctrl+Alt+F`    | Search function names                 |
| `Tab`           | Switch between asm and pseudocode     |
| `Y`             | Change type of variable/function      |
| `H`             | Toggle hex display                    |

### Naming Conventions

| Prefix                    | Usage                                              |
| ------------------------- | -------------------------------------------------- |
| `ISS_Integrity_`          | Integrity check functions (SHA256, manifest)       |
| `ISS_Pipeline_`           | Security check orchestrators / dispatchers         |
| `ISS_Util_`               | Utility / support functions (base64, string parse) |
| `ISS_Crypto_`             | Cryptographic operations (AES, HMAC)               |
| `ISS_Thunk_`              | Thunks / stubs to real implementations             |
| `Swift_Array_`            | Generic array buffer helpers **(skip)**            |
| `Swift_Data_`             | Foundation Data helpers **(skip)**                 |
| `Swift_String_`           | String manipulation helpers **(skip)**             |
| `Swift_once_`             | Lazy initializers **(skip)**                       |
| `Swift_lazyType`          | Type metadata accessors **(skip)**                 |
| `Swift_arcRetain/Release` | ARC helpers **(skip)**                             |

***

## 10. Analysis Decision Tree

### Full Target — Where to Start

```
Got the binary
       │
       ├─ Encrypted? ──YES──▶ frida-ios-dump / bagbak ──▶ continue
       │
       ├─ strings ──▶ URLs/keys visible?
       │           ├── YES ──▶ static analysis first (IDA)
       │           └── NO  ──▶ dynamic analysis first (Frida trace)
       │
       ├─ class-dump / dsdump ──▶ meaningful class names?
       │           ├── YES ──▶ map to IDA, analyze those classes
       │           └── NO  ──▶ Frida trace → log all methods → map back to IDA
       │
       ├─ SSL pinning?
       │           └──▶ objection sslpinning disable
       │               ▶ Burp/mitmproxy ──▶ understand API ──▶ then map in IDA
       │
       └─ Security checks?
                   └──▶ Identify with Frida (log all returns)
                       ▶ IDA: analyze only flagged functions
                       ▶ Surgical bypass (not global hook)


For each suspicious function:

  size < 0x20?    ──YES──▶  SKIP
       │
       │ NO
       ▼
  first call = swift_getTypeByMangledName?  ──YES──▶  SKIP
       │
       │ NO
       ▼
  xrefs_to  ──▶  caller name tells you the purpose?  ──YES──▶  name it, done
       │
       │ NO
       ▼
  callgraph  ──▶  find CC_SHA256 / CCCrypt / _dyld_ / sysctl?
       ├── CC_SHA256  ──▶  integrity check
       ├── CCCrypt    ──▶  crypto/decryption
       ├── _dyld_*    ──▶  jailbreak / integrity
       ├── sysctl     ──▶  debugger detection
       ├── fork       ──▶  sandbox check
       └── none       ──▶  decompile and read carefully
```

### Priority Import Functions

| Function                    | Security Relevance           |
| --------------------------- | ---------------------------- |
| `CC_SHA256`                 | Integrity / certificate hash |
| `CCCrypt`                   | AES encrypt/decrypt          |
| `CCHmac`                    | HMAC signing                 |
| `SecItemCopyMatching`       | Keychain read                |
| `SecTrustEvaluateWithError` | Cert validation              |
| `ptrace`                    | Anti-debug                   |
| `sysctl`                    | Process flags / debugger     |
| `_dyld_get_image_name`      | Loaded dylib enumeration     |
| `vm_region_64`              | Memory protection check      |
| `fork` / `vfork`            | Sandbox detection            |

### Bypass Hook Priority

| Priority | Target                                           | Notes                                        |
| -------- | ------------------------------------------------ | -------------------------------------------- |
| **1**    | Result comparator (string equality)              | One hook kills all checks. Most surgical.    |
| **2**    | Orchestrator / scheduler function                | Return early before any check runs.          |
| **3**    | Individual check entry points                    | Per-check bypass. Handle polarity carefully. |
| **4**    | Low-level C functions (`stat`, `sysctl`, `fork`) | Coarse but reliable. Risk of side effects.   |

### Common Pitfalls

| Pitfall                                     | Explanation                                                                 |
| ------------------------------------------- | --------------------------------------------------------------------------- |
| **Inverting sret / first arg**              | `x8` = sret ptr. `args[0]` is NOT always the first argument in Swift.       |
| **Wrong polarity on check return**          | Some checks: `1=detected`, others: `1=clean`. Always verify before hooking. |
| **In-memory hash (not disk)**               | Patching binary on disk won't change the in-memory `__text` hash.           |
| **Result struct written before comparison** | Hook the struct init (sret), not just the final comparator.                 |
| **Unmapped checks causing crash**           | Full bypass mode needs ALL checks mapped first.                             |

***

*ARM64 · Swift · ObjC · Frida · IDA Pro*
