我应该向 Frida `ObjC.api.class_addMethod()` 提供什么参数才能让它开心?
What parameter should I feed to Frida `ObjC.api.class_addMethod()` to make it happy?
我想使用 Frida 在 Mac OS 上现有的 Objective C class 添加一个 class 方法。在我阅读了 Frida docs 之后,我尝试了以下代码:
const NSString = ObjC.classes.NSString
function func (n) { console.log(n) }
var nativeCb = new NativeCallback(func, 'void', ['int'])
ObjC.api.class_addMethod(
NSString.handle,
ObjC.selector('onTest:'),
nativeCb,
ObjC.api.method_getTypeEncoding(nativeCb)
)
上面的代码看起来很简单。然而,ObjC.api.class_addMethod()
调用后,附加的App和Frida REPL都卡住了,看来指针不对。
我试了很多可能的参数值一晚上,还是能解决问题。我的代码有什么问题?
只有两个问题:
method_getTypeEncoding()
只能在 Method
上调用,而 NativeCallback
则不能。您可以将现有 Objective-C 方法的句柄传递给它,该方法与您要添加的方法具有相同的签名,或者使用 Memory.allocUtf8String()
从头开始指定您自己的签名。
- Objective-C 方法,在 C ABI 级别,在方法参数之前有两个隐式参数。这些都是:
self
: class/instance 正在调用该方法。
_cmd
:选择器。
这是一个完整的 TypeScript 示例:
const { NSAutoreleasePool, NSString } = ObjC.classes;
const onTest = new NativeCallback(onTestImpl, "void", ["pointer", "pointer", "int"]);
function onTestImpl(selfHandle: NativePointer, cmd: NativePointer, n: number): void {
const self = new ObjC.Object(selfHandle);
console.log(`-[NSString onTestImpl]\n\tself="${self.toString()}"\n\tn=${n}`);
}
function register(): void {
ObjC.api.class_addMethod(
NSString,
ObjC.selector("onTest:"),
onTest,
Memory.allocUtf8String("v@:i"));
}
function test(): void {
const pool = NSAutoreleasePool.alloc().init();
try {
const s = NSString.stringWithUTF8String_(Memory.allocUtf8String("yo"));
s.onTest_(42);
} finally {
pool.release();
}
}
function exposeToRepl(): void {
const g = global as any;
g.register = register;
g.test = test;
}
exposeToRepl();
您可以将其粘贴到 https://github.com/oleavr/frida-agent-example,然后使用一个终端 运行 npm run watch
您可以使用 REPL 将其加载到 运行 应用程序:frida -n Telegram -l _agent.js
.然后,您可以从 REPL 调用 register()
插入新方法,然后调用 test()
试一试。
我想使用 Frida 在 Mac OS 上现有的 Objective C class 添加一个 class 方法。在我阅读了 Frida docs 之后,我尝试了以下代码:
const NSString = ObjC.classes.NSString
function func (n) { console.log(n) }
var nativeCb = new NativeCallback(func, 'void', ['int'])
ObjC.api.class_addMethod(
NSString.handle,
ObjC.selector('onTest:'),
nativeCb,
ObjC.api.method_getTypeEncoding(nativeCb)
)
上面的代码看起来很简单。然而,ObjC.api.class_addMethod()
调用后,附加的App和Frida REPL都卡住了,看来指针不对。
我试了很多可能的参数值一晚上,还是能解决问题。我的代码有什么问题?
只有两个问题:
method_getTypeEncoding()
只能在Method
上调用,而NativeCallback
则不能。您可以将现有 Objective-C 方法的句柄传递给它,该方法与您要添加的方法具有相同的签名,或者使用Memory.allocUtf8String()
从头开始指定您自己的签名。- Objective-C 方法,在 C ABI 级别,在方法参数之前有两个隐式参数。这些都是:
self
: class/instance 正在调用该方法。
_cmd
:选择器。
这是一个完整的 TypeScript 示例:
const { NSAutoreleasePool, NSString } = ObjC.classes;
const onTest = new NativeCallback(onTestImpl, "void", ["pointer", "pointer", "int"]);
function onTestImpl(selfHandle: NativePointer, cmd: NativePointer, n: number): void {
const self = new ObjC.Object(selfHandle);
console.log(`-[NSString onTestImpl]\n\tself="${self.toString()}"\n\tn=${n}`);
}
function register(): void {
ObjC.api.class_addMethod(
NSString,
ObjC.selector("onTest:"),
onTest,
Memory.allocUtf8String("v@:i"));
}
function test(): void {
const pool = NSAutoreleasePool.alloc().init();
try {
const s = NSString.stringWithUTF8String_(Memory.allocUtf8String("yo"));
s.onTest_(42);
} finally {
pool.release();
}
}
function exposeToRepl(): void {
const g = global as any;
g.register = register;
g.test = test;
}
exposeToRepl();
您可以将其粘贴到 https://github.com/oleavr/frida-agent-example,然后使用一个终端 运行 npm run watch
您可以使用 REPL 将其加载到 运行 应用程序:frida -n Telegram -l _agent.js
.然后,您可以从 REPL 调用 register()
插入新方法,然后调用 test()
试一试。