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.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/mobile-pentesting/ios-pentesting/frida-configuration-in-ios/SKILL.MDiOS 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
- Jailbroken iOS device (or Corellium VM)
- Frida server running on the device
- 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):
- Search for strings in memoryfindString(str)
- Search for byte patternsfindBytes(pattern)
- Dump memory regiondumpMemory(address, size)
- Write to memorypatchMemory(address, [bytes])
- Monitor memory changeswatchMemory(address, size)
- List loaded modulesenumerateModules()
- Find pointers to addressfindPointers(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
variable to filter by substringfilterClass - 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
to target class namespecificClass - Set
to filter methods by substringfilterMethod
hook-objc.js
Hooks common Objective-C methods for security testing.
Pre-configured hooks:
LoginViewController.authenticate:AuthManager.validatePassword:
methodsNSUserDefaultsNSString.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
to the dylib nameMODULE_NAME - Set
to the mangled Swift symbolFUNCTION_NAME - Use
to discover mangled namesfrida-trace
simple-fuzzer.js
Standalone fuzzer without fpicker dependency.
Usage:
frida -U <app> -l scripts/simple-fuzzer.js
Configuration:
- App binary nameTARGET_MODULE
- Function to fuzzTARGET_FUNCTION
- Number of fuzz iterationsITERATIONS
- Maximum payload sizeMAX_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
flag:--no-pausefrida -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
- Start with enumeration - Use
to understand the app structureenumerate-classes.js - Trace before hooking - Use
to find relevant functionsfrida-trace - Test hooks incrementally - Hook one method at a time
- Save crash-inducing inputs - Check
/private/var/mobile/Library/Logs/CrashReporter/ - Use coverage feedback - AFL++ mode in fpicker for better fuzzing
- Monitor for hangs - Add timeouts to detect infinite loops
- 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