iOS
Objective-C 方法调用规范
Frida 通过将 Objective-C 方法选择器中的 :
替换为 _
来提供封装调用:
// 调用 +[NSJSONSerialization dataWithJSONObject:options:error:]
ObjC.classes.NSJSONSerialization.dataWithJSONObject_options_error_(...)
// NSString *helloWorldString = @"Hello, World!";
var helloWorldString = ObjC.classes.NSString.stringWithString_("Hello, World!");
// 调用 [helloWorldString characterAtIndex:0]
helloWorldString.characterAtIndex_(0)
提示:若运行结果不符合预期,可能是操作了错误的数据类型。可通过以下命令确认实际类型:
console.log('args[2] 类型 -> ' + new ObjC.Object(args[2]).$className)
数据类型转换
NSData 转字符串
const data = new ObjC.Object(args[2]);
data.bytes().readUtf8String(data.length());
提示:若字符串以 null 结尾,可不指定字节长度参数
NSData 转二进制数据
const data = new ObjC.Object(args[2]);
data.bytes().readByteArray(data.length(
集合操作
遍历 NSArray
const array = new ObjC.Object(args[2]);
/*
* 必须使用 valueOf() 转换,因为 NSUInteger 在
* 32 位进程中是 Number 类型,在 64 位进程中
* 是 UInt64 类型
*/
const count = array.count().valueOf();
for (let i = 0; i !== count; i++) {
const element = array.objectAtIndex_(i);
}
遍历 NSDictionary
const dict = new ObjC.Object(args[2]);
const enumerator = dict.keyEnumerator();
let key;
while ((key = enumerator.nextObject()) !== null) {
const value = dict.objectForKey_(key);
}
解档 NSKeyedArchiver
const parsedValue = ObjC.classes.NSKeyedUnarchiver.unarchiveObjectWithData_(value);
内存操作
读取结构体数据
// 读取 args[0] 指针偏移 4 字节处的 uint32 值
args[0].add(4).readU32();
UI 交互示例
iOS 7 弹窗实现
const UIAlertView = ObjC.classes.UIAlertView;
const view = UIAlertView.alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles_(
'Frida',
'Hello from Frida',
NULL,
'OK',
NULL);
view.show();
view.release();
iOS 8+ 弹窗实现
// 定义作为 handler 参数的 Block
const handler = new ObjC.Block({
retType: 'void',
argTypes: ['object'],
implementation() {}
});
// 获取类引用
const UIAlertController = ObjC.classes.UIAlertController;
const UIAlertAction = ObjC.classes.UIAlertAction;
const UIApplication = ObjC.classes.UIApplication;
// 使用 GCD 在主线程执行
ObjC.schedule(ObjC.mainQueue, () => {
// 使用枚举数值指定弹窗样式
const alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_('Frida', 'Hello from Frida', 1);
const defaultAction = UIAlertAction.actionWithTitle_style_handler_('OK', 0, handler);
alert.addAction_(defaultAction);
UIApplication.sharedApplication().keyWindow().rootViewController()
.presentViewController_animated_completion_(alert, true, NULL);
});
方法拦截示例
监控 openURL: 调用
const openURL = ObjC.classes.UIApplication['- openURL:'];
Interceptor.attach(openURL.implementation, {
onEnter(args) {
// Objective-C 方法参数结构:
// 0: 'self'
// 1: 方法选择器 (openURL:)
// 2: NSURL 参数
const url = new ObjC.Object(args[2]).absoluteString().toString();
console.log('正在打开 URL: ' + url);
}
});
关键术语说明:
选择器(Selector) - Objective-C 的方法名标识
Block - Objective-C 的匿名函数对象
GCD (Grand Central Dispatch) - iOS 的多线程技术
主线程队列(mainQueue) - UI 操作必须执行的线程队列
NSKeyedArchiver - 苹果的对象序列化方案
原文链接:iOS | Frida • A world-class dynamic instrumentation toolkit
翻译来源:DeepSeek