Hacktricks-skills ios-frida-pentesting

iOS mobile security testing with Frida instrumentation. Use this skill whenever the user needs to perform iOS app pentesting, hook Objective-C/Swift methods, bypass jailbreak detection, fuzz iOS applications, inspect memory, or analyze iOS binaries. Trigger for any iOS security assessment, reverse engineering, or dynamic analysis tasks involving Frida.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/mobile-pentesting/ios-pentesting/frida-configuration-in-ios/SKILL.MD
source content

iOS Frida Pentesting Skill

A comprehensive skill for iOS mobile security testing using Frida instrumentation framework.

When to Use This Skill

Use this skill when the user:

  • Needs to perform iOS application security testing
  • Wants to hook or trace Objective-C/Swift methods
  • Needs to bypass jailbreak or Frida detection
  • Wants to fuzz iOS applications
  • Needs to inspect or manipulate iOS app memory
  • Is doing iOS reverse engineering or dynamic analysis
  • Needs to enumerate iOS app classes, methods, or exports

Quick Start

Prerequisites

  1. Jailbroken iOS device (or Corellium VM)
  2. Frida server running on the device
  3. Frida tools installed on your machine:
    pip install frida frida-tools
    

Verify Connection

frida-ls-devices    # List connected devices
frida-ps -Uia       # List running processes

Core Tasks

1. Enumerate Classes and Methods

Use the bundled scripts to discover app internals:

# List all Objective-C classes
frida -U <app-bundle> -l scripts/enumerate-classes.js

# List methods for a specific class
frida -U <app-bundle> -l scripts/enumerate-methods.js

2. Hook Objective-C Methods

Intercept and modify method calls:

# Hook authentication methods
frida -U <app-bundle> -l scripts/hook-objc.js

The script hooks common patterns:

  • Login/Authentication methods
  • Data storage (NSUserDefaults)
  • Crypto operations
  • Network requests

3. Bypass Jailbreak Detection

Use LLDB + Frida combination for production builds:

# Forward SSH to device
iproxy 2222 22 &
ssh root@localhost -p 2222

# On device, spawn debugger
debugserver *:5678 --waitfor <BundleName>

# On macOS, attach LLDB
iproxy 1234 5678 &
lldb
(lldb) process connect connect://localhost:1234
(lldb) finish  # Run until constructors complete

Then patch Swift detection functions:

(lldb) breakpoint set --name '*systemSanityCheck'
(lldb) c
(lldb) finish
(lldb) register write x0 0  # Force return false
(lldb) c

4. Trace Function Calls

Use

frida-trace
for quick tracing:

# Trace functions containing "log"
frida-trace -U <app> -i "*log*"

# Trace all Objective-C methods
frida-trace -U <app> -m "*[* *]"

# Trace specific class methods
frida-trace -U <app> -m "*[NE* *authentication*]"

5. Fuzz iOS Applications

Use the bundled fuzzer scripts:

# Simple standalone fuzzer
frida -U <app> -l scripts/simple-fuzzer.js

# Advanced fuzzer with crash monitoring
frida -U <app> -l scripts/advanced-fuzzer.js

For production fuzzing with fpicker:

# Compile fuzzer script
frida-compile scripts/myfuzzer.js -o harness.js

# Run with fpicker
fpicker -v --fuzzer-mode active -e attach -p <app> -D usb \
  -o ./out/ -i ./in/ -f harness.js \
  --standalone-mutator cmd --mutator-command "radamsa"

6. Memory Inspection

Scan and manipulate process memory:

frida -U <app> -l scripts/memory-scan.js

Available functions (use in Frida console):

  • findString(str)
    - Search for strings in memory
  • findBytes(pattern)
    - Search for byte patterns
  • dumpMemory(address, size)
    - Dump memory region
  • patchMemory(address, [bytes])
    - Write to memory
  • watchMemory(address, size)
    - Monitor memory changes
  • enumerateModules()
    - List loaded modules
  • findPointers(address)
    - Find pointers to address

Script Reference

enumerate-classes.js

Lists all Objective-C classes in the target app.

Usage:

frida -U <app> -l scripts/enumerate-classes.js

Configuration:

  • Set
    filterClass
    variable to filter by substring
  • Leave empty to list all classes

enumerate-methods.js

Lists all methods for a specific Objective-C class.

Usage:

frida -U <app> -l scripts/enumerate-methods.js

Configuration:

  • Set
    specificClass
    to target class name
  • Set
    filterMethod
    to filter methods by substring

hook-objc.js

Hooks common Objective-C methods for security testing.

Pre-configured hooks:

  • LoginViewController.authenticate:
  • AuthManager.validatePassword:
  • NSUserDefaults
    methods
  • NSString.dataUsingEncoding:
  • NSURLSession.dataTaskWithRequest:completionHandler:

To add custom hooks:

hookMethod("YourClass", "- yourMethod:")

hook-swift.js

Hooks Swift functions using mangled names.

Usage:

frida -U <app> -l scripts/hook-swift.js

Configuration:

  • Set
    MODULE_NAME
    to the dylib name
  • Set
    FUNCTION_NAME
    to the mangled Swift symbol
  • Use
    frida-trace
    to discover mangled names

simple-fuzzer.js

Standalone fuzzer without fpicker dependency.

Usage:

frida -U <app> -l scripts/simple-fuzzer.js

Configuration:

  • TARGET_MODULE
    - App binary name
  • TARGET_FUNCTION
    - Function to fuzz
  • ITERATIONS
    - Number of fuzz iterations
  • MAX_PAYLOAD_SIZE
    - Maximum payload size

Mutation strategies:

  • Buffer overflow (long strings)
  • Format string bugs
  • Null bytes and boundary characters
  • SQL injection patterns
  • XSS payloads
  • Path traversal
  • Invalid Unicode
  • Random binary data

advanced-fuzzer.js

Fuzzer with crash monitoring and signal handlers.

Features:

  • Exception handler for crashes
  • Hooks dangerous functions (abort, malloc, free)
  • Timeout detection for hangs
  • Detailed crash reporting with backtraces

memory-scan.js

Memory inspection and manipulation toolkit.

Exported functions:

findString(str)           // Search for string
findBytes(pattern)        // Search for byte pattern
dumpMemory(addr, size)    // Dump memory region
patchMemory(addr, bytes)  // Write to memory
watchMemory(addr, size)   // Monitor changes
enumerateModules()        // List modules
findPointers(addr)        // Find pointers to address
getProtection(addr)       // Get memory protection
changeProtection(addr, size, prot)  // Change protection

Common Patterns

Bypass Authentication

// Hook authentication method
ObjC.classes.AuthManager["- isAuthenticated"].implementation = function() {
  console.log("[!] Bypassing authentication!")
  return 1  // Always return true
}

Intercept Network Requests

ObjC.classes.NSURLSession["- dataTaskWithRequest:completionHandler:"].implementation = function(request, handler) {
  console.log("[+] Network request:", request.URL)
  console.log("[+] Headers:", request.allHTTPHeaderFields)
  return this.$super["- dataTaskWithRequest:completionHandler:"](request, handler)
}

Capture Sensitive Data

// Hook string encoding to capture data before encryption
ObjC.classes.NSString["- dataUsingEncoding:"].implementation = function(encoding) {
  var str = this.toString()
  console.log("[+] String being encoded:", str)
  return this.$super["- dataUsingEncoding:"](encoding)
}

Read Keychain Data

// Hook SecItemCopyMatching
Interceptor.attach(Module.findExportByName(null, "SecItemCopyMatching"), {
  onEnter: function(args) {
    console.log("[+] Keychain query:", JSON.stringify(args[0].readUtf8String()))
  },
  onLeave: function(retval) {
    console.log("[+] Keychain result:", retval)
  }
})

Troubleshooting

Device Not Detected

# Check USB connection
frida-ls-devices

# For Corellium, ensure frida-gadget is in correct location
cp frida-gadget-*.dylib /Users/[user]/.cache/frida/gadget-ios.dylib

App Crashes on Attach

  • Try LLDB-assisted approach for anti-instrumentation apps
  • Use
    --no-pause
    flag:
    frida -U -f <app> --no-pause
  • Check for jailbreak detection and bypass it first

Swift Functions Not Found

# Discover mangled names
frida-trace -U <app> -i "*function_name*"

# Use the mangled name in your script
Module.findExportByName("<module>", "$s16App11ContentViewV13functionNameySS_tF")

Memory Scan Returns Nothing

  • Ensure you're scanning readable ranges:
    Process.enumerateRanges('r--')
  • Try different memory permissions:
    r-x
    ,
    rw-
    ,
    rwx
  • Check if the data is in a different module

Best Practices

  1. Start with enumeration - Use
    enumerate-classes.js
    to understand the app structure
  2. Trace before hooking - Use
    frida-trace
    to find relevant functions
  3. Test hooks incrementally - Hook one method at a time
  4. Save crash-inducing inputs - Check
    /private/var/mobile/Library/Logs/CrashReporter/
  5. Use coverage feedback - AFL++ mode in fpicker for better fuzzing
  6. Monitor for hangs - Add timeouts to detect infinite loops
  7. Reset state between tests - Restart app after crashes

References

Logs and Crashes

iOS Crash Logs

# On device
/private/var/mobile/Library/Logs/CrashReporter/

# Via Settings
Settings → Privacy → Analytics & Improvements → Analytics Data

Enable Private Logging

# Edit logging config
vim /Library/Preferences/Logging/com.apple.system.logging.plist

# Add:
<key>Enable-Private-Data</key>
<true/>

# Restart logging
killall -9 logd

macOS Console

# View logs
log show --predicate 'process == "<app-name>"' --last 1h

# Check crash reports
/Library/Logs/DiagnosticReports/
~/Library/Logs/DiagnosticReports/

Notes

  • iOS only stores 25 crashes per app - clean old reports regularly
  • Frida hooks may prevent iOS crash report generation
  • For production testing, use LLDB + Frida combination
  • Swift ABI: small strings (≤15 bytes) inline in x0, large strings heap-backed at x1+32