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


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:

APIPurpose
ObjC.classes.ClassNameGet ObjC class wrapper
cls['- methodName:']Instance method reference
cls['+ methodName:']Class (static) method reference
.implementationGet/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() / .$classNameStringify 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

AspectiOS (ObjC/Swift)Android (Java/Kotlin)
Runtime APIObjC.*Java.*
Entry pointDirect (ObjC.classes)Requires Java.perform()
Method lookupcls['- name:']cls.methodName
Instance fieldsVia ObjC propertiesinstance.field.value
Stack traceThread.backtrace() + DebugSymbol.fromAddress()Log.getStackTraceString(new Exception())
Selector typeObjC.selector('name:')N/A