0

我想使用 Frida 为 Mac OS 上现有的 Objective C 类添加一个类方法。阅读 Frida文档后,我尝试了以下代码:

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都卡住了,看来指针不对。

我已经尝试了一整晚的许多可能的参数值,但仍然可以解决问题。我的代码有什么问题?

4

1 回答 1

2

只有两个问题:

  • method_getTypeEncoding()只能在 a 上调​​用Method,而NativeCallback不是。您可以将现有的 Objective-C 方法的句柄传递给它,该方法与您正在添加的方法具有相同的签名,或者用于Memory.allocUtf8String()从头开始指定您自己的签名。
  • Objective-C 方法,在 C ABI 级别,在方法的参数之前有两个隐式参数。这些是:
      1. self:正在调用该方法的类/实例。
      1. _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()试一试。

于 2020-02-02T20:35:42.000 回答