这是一次疯狂的发布,带来了大量改进。

先说一项面向用户的变化。名为 frida-repl 的 CLI 工具已更名为 frida,而且现在支持 Tab 补全!这项功能以及其他一些出色的 REPL 改进由 @fitblip 贡献。

现在还集成支持直接从 shell 启动脚本:

$ frida Calculator -l calc.js
    _____
   (_____)
    |   |    Frida 4.0.0 - A world-class dynamic
    |   |                  instrumentation framework
    |`-'|
    |   |    Commands:
    |   |        help      -> Displays the help system
    |   |        object?   -> Display information about 'object'
    |   |        exit/quit -> Exit
    |   |
    |   |    More info at https://frida.re/docs/home/
    `._.'

# The code in calc.js has now been loaded and executed
[Local::ProcName::Calculator]->
# Reload it from file at any time
[Local::ProcName::Calculator]-> %reload
[Local::ProcName::Calculator]->

或者,你可能已经厌倦了 console.log(),想在脚本中设置断点,以帮助理解正在发生什么? 现在可以了,因为 Frida 刚刚集成了兼容 Node.js 的调试器。

(此处应出现“Yo Dawg”梗图。)

没错,而且它确实非常实用。所有 CLI 工具都提供 --debug 开关来启用它:

# Connect Frida to a locally-running Calculator.app
# and load calc.js with the debugger enabled
$ frida Calculator -l calc.js --debug
    _____
   (_____)
    |   |    Frida 4.0.0 - A world-class dynamic
    |   |                  instrumentation framework
    |`-'|
    |   |    Commands:
    |   |        help      -> Displays the help system
    |   |        object?   -> Display information about 'object'
    |   |        exit/quit -> Exit
    |   |
    |   |    More info at https://frida.re/docs/home/
    `._.'

Debugger listening on port 5858
# We can now run node-inspector and start debugging calc.js
[Local::ProcName::Calculator]->

效果如下:

Frida 调试器会话

你是否曾想直接从 shell 使用 frida-trace 跟踪 Objective-C API?感谢 @Tyilo,现在可以了:

# Trace ObjC method calls in Safari
$ frida-trace -m '-[NSView drawRect:]' Safari

还有其他好东西,例如全新的回溯生成功能,以及使用调试符号对地址进行符号化:

const f = Module.getExportByName('libcommonCrypto.dylib',
    'CCCryptorCreate');
Interceptor.attach(f, {
    onEnter(args) {
        console.log('CCCryptorCreate called from:\n' +
            Thread.backtrace(this.context, Backtracer.ACCURATE)
            .map(DebugSymbol.fromAddress).join('\n') + '\n');
    }
});

又或者,你正在 Windows 上尝试找出谁访问了某些内存区域?那就看看全新的 MemoryAccessMonitor。严格来说,这段代码 并不是新的,只是直到现在才向 JavaScript API 公开。

另一项不错的功能是,从本次发布开始,在其他设备(例如 Android)上运行 frida-server 时,不再需要转发多个 TCP 端口。

错误反馈也得到了显著改善,现在会从远程进程一路传播到例如 Python 中不同的异常类型。 在上一个版本中,如果在 Mac 上附加到不存在的 pid,会得到:

SystemError: GDBus.Error:org.gtk.GDBus.UnmappedGError.Quark._g_2↩
dio_2derror_2dquark.Code0: task_for_pid() for remote pid failed w↩
hile trying to make pipe endpoints: (os/kern) failure (5)

太疯狂了。现在则简化为:

frida.ProcessNotFoundError: unable to find process with pid 1234

好多了。接下来谈谈性能。你可能使用过 frida-trace,并疑惑它为什么在“Resolving functions…”上花费这么长时间。在典型 iOS 应用中,只解析一个函数通常就要约 8 秒, 现在降到了约 1 秒。虽然还有一些优化空间,但我很快意识到,无论函数导出枚举得多快, 数据仍需要传输,而仅传输时间本身就可能令人难以接受。解决办法是什么?把逻辑移到目标 进程中,传输逻辑而不是数据。很简单。 Dalvik 和 ObjC 接口也经过优化,耗时从数秒降至数毫秒。简而言之,我们进一步推迟了查询 语言运行时的时机。ObjC 接口在这方面走得很远,现在使用 ES6 代理来提供更符合习惯、效率 更高的 API。

这就引出了下一个话题。ObjC 接口有一些变化。主要是:

const NSString = ObjC.use("NSString");

现在改为:

const NSString = ObjC.classes.NSString;

你仍可使用 ObjC.classes 枚举当前已加载的类,但它现在的行为类似一个对象,将类名映射到 JavaScript ObjC 绑定。

此外,不再需要类型转换,因此不再这样写:

const NSSound = ObjC.use('NSSound');
const sound = ObjC.cast(ptr("0x1234"), NSSound);

只需这样写:

const sound = new ObjC.Object(ptr("0x1234"));

没错,不再需要试图模拟 ObjC 类层次结构。现在使用完全动态的包装器,首次访问时才构建 方法包装器;只有尝试枚举对象属性时,才会获取方法列表。

这篇文章已经很长了,下面汇总其他主要变化:

  • Dalvik 接口现在可以处理可变参数方法。感谢 @dmchell 报告并协助追踪此问题。
  • 感谢 @Tyilo,NativePointer 现在还提供 .and()、 .or() 和 .xor()。
  • Interceptor 的 onEnter/onLeave 回调过去通过 this.registers 公开 CPU 寄存器, 现已更名为 this.context,而且现在也允许写入寄存器。
  • 为保持一致,Process.enumerateThreads() 返回的线程对象已将 CPU 上下文字段从 registers 更名为 context。
  • enumerateFoo() API 现在提供同步版本 enumerateFooSync(),直接返回包含所有项目的数组。
  • 现在可使用 Memory.readCString() 读取 ASCII C 字符串。
  • 可以查询 Frida.version 来检查正在运行的版本;frida-core 端也提供该信息,例如 frida-python 通过 frida.__version__ 将其公开。
  • Stalker 现在支持 jecxz 和 jrcxz 指令。这对 CryptoShark 是个好消息,它应该很快就会提供 捆绑最新版 Frida 的更新二进制文件。
  • V8 已更新到 4.3.62,并启用了许多 ES6 功能。
  • 现在使用即将发布的 Capstone 4.0 的开发版本。
  • 所有第三方依赖都已更新到最新版本。
  • 现在支持 Windows XP。这不是玩笑。我意识到我们其实没有使用任何 XP 之后才提供的 API; 既然必须在 Windows 上重新构建依赖,不妨降低操作系统要求,帮助仍在 XP 上对软件进行 插桩的用户。

尽情使用吧!