iOS Examples
Frida iOS Examples
Note: The original source file for this page references an external template (
{% tf _docs/examples/ios.md %}) that is not included in this documentation snapshot. The content below documents canonical Frida iOS patterns.
Prerequisites
- Device: iOS device or simulator with Frida server running (
frida-server) - Connect via USB:
frida.get_usb_device()or by device UDID - Frida version: 16.x+ recommended
ObjC.availablemust betrue(always true on iOS)
Hook an Objective-C Method
Pattern: Get a class wrapper via ObjC.classes, then replace .implementation.
1// Attach to a running app by bundle ID or PID
2// Run from host: frida -U -n "TargetApp" -l hook_objc.js
3
4Java.perform(() => {}); // not needed for ObjC — use ObjC.classes directly
5
6const NSString = ObjC.classes.NSString;
7
8// Hook -[NSString stringWithString:]
9const stringWithString = NSString['+ stringWithString:'];
10Interceptor.attach(stringWithString.implementation, {
11 onEnter(args) {
12 // ObjC args: 0=self (Class), 1=SEL, 2=first param
13 const input = new ObjC.Object(args[2]);
14 console.log('[+] NSString stringWithString: ' + input.toString());
15 },
16 onLeave(retval) {
17 const result = new ObjC.Object(retval);
18 console.log('[+] => ' + result.toString());
19 }
20});
Replace ObjC Method Implementation (Swizzle)
1const UIViewController = ObjC.classes.UIViewController;
2
3// Replace -[UIViewController viewDidLoad]
4const viewDidLoad = UIViewController['- viewDidLoad'];
5const origImpl = viewDidLoad.implementation;
6
7viewDidLoad.implementation = ObjC.implement(viewDidLoad, function (self, sel) {
8 console.log('[+] viewDidLoad called on: ' + new ObjC.Object(self).$className);
9 origImpl(self, sel); // call original
10});
Key APIs:
| API | Purpose |
|---|---|
ObjC.classes.ClassName | Get ObjC class wrapper |
cls['- methodName:'] | Instance method reference |
cls['+ methodName:'] | Class (static) method reference |
.implementation | Get/set raw function pointer for a method |
ObjC.implement(method, fn) | Create a replacement implementation callback |
new ObjC.Object(ptr) | Wrap a raw pointer as an ObjC object |
.toString() / .$className | Stringify object / get class name |
Enumerate All Classes and Methods
1// List all loaded ObjC classes
2ObjC.enumerateLoadedClasses({
3 onMatch(name, owner) {
4 console.log('Class: ' + name + ' (from ' + owner + ')');
5 },
6 onComplete() {
7 console.log('Done.');
8 }
9});
10
11// List all methods on a specific class
12const methods = ObjC.classes.NSURLRequest.$ownMethods;
13methods.forEach(m => console.log(m));
Trace All Calls to a Specific Selector
1// Intercept every -[* description] call across all classes
2const sel = ObjC.selector('description');
3
4ObjC.enumerateLoadedClasses({
5 onMatch(name) {
6 const cls = ObjC.classes[name];
7 if (cls && cls['- description']) {
8 try {
9 Interceptor.attach(cls['- description'].implementation, {
10 onEnter() {
11 console.log('[' + name + ' description]');
12 }
13 });
14 } catch (_) {}
15 }
16 },
17 onComplete() {}
18});
Read ObjC Object Properties at Runtime
1Interceptor.attach(ObjC.classes.NSURLRequest['- URL'].implementation, {
2 onLeave(retval) {
3 if (!retval.isNull()) {
4 const url = new ObjC.Object(retval);
5 console.log('URL: ' + url.absoluteString().toString());
6 }
7 }
8});
Python Host Script Pattern (iOS)
1import frida, sys
2
3def on_message(message, data):
4 print("[{}] => {}".format(message, data))
5
6def main(target):
7 device = frida.get_usb_device()
8 session = device.attach(target) # bundle ID or PID
9
10 script = session.create_script("""
11 const NSFileManager = ObjC.classes.NSFileManager;
12 const defaultManager = NSFileManager['+ defaultManager'];
13 Interceptor.attach(defaultManager.implementation, {
14 onLeave(retval) {
15 console.log('[+] NSFileManager defaultManager called');
16 }
17 });
18 """)
19 script.on('message', on_message)
20 script.load()
21 print("[!] Ctrl+C to detach")
22 sys.stdin.read()
23 session.detach()
24
25if __name__ == '__main__':
26 main('com.example.TargetApp')
Key Differences: iOS vs Android
| Aspect | iOS (ObjC/Swift) | Android (Java/Kotlin) |
|---|---|---|
| Runtime API | ObjC.* | Java.* |
| Entry point | Direct (ObjC.classes) | Requires Java.perform() |
| Method lookup | cls['- name:'] | cls.methodName |
| Instance fields | Via ObjC properties | instance.field.value |
| Stack trace | Thread.backtrace() + DebugSymbol.fromAddress() | Log.getStackTraceString(new Exception()) |
| Selector type | ObjC.selector('name:') | N/A |