是时候升级到下一个主版本了。

首先要解决一个长期存在的问题:当多个 Frida 客户端附加到同一进程时,它们不得不相互协调,确保其中一个客户端仍在使用会话时,其他客户端都不会调用 detach()。

对大多数 Frida 用户而言,这可能不算大问题。然而,当多个客户端共享同一个正在运行的 frida-server 时,也会遇到同样的问题。你可能在一个终端中运行 frida-trace,同时在另一个终端中使用 REPL,两者都附加到同一个进程;这时你显然不会希望其中一方调用 detach(),就导致另一方也被踢出。

有些人可能尝试过,并观察到它确实按预期工作,但那是因为 frida-server 中存在一些复杂得惊人的逻辑:它会跟踪有多少客户端对同一进程感兴趣,从而在其他客户端仍订阅同一会话时忽略 detach() 调用。如果某个客户端突然断开,它还有一些逻辑用于清理该客户端的资源,例如脚本。

从 8.0 开始,我们把会话感知移入了 agent,并保持面向客户端的 API 不变,只调整了一个小细节。现在每次调用 attach() 都会获得自己的 Session,而注入的 agent 能够识别该会话。这意味着你可以随时调用 detach(),只有在你的会话中创建的脚本会被销毁。此外,如果你的会话是最后一个存活的会话,Frida 会从目标进程卸载 agent。

这是本次发布的重大变化,但我们并未止步于此。

Frida 脚本的一项重要功能是可以与脚本交换消息。脚本可以调用 send(message[, data]) 发送可序列化为 JSON 的 message,并可选择附带一个二进制 data 数据块。这样一来,你就无需浪费 CPU 周期把二进制数据转换成文本再放进 message。

还可以朝另一个方向通信:脚本调用 recv(callback),当应用向它调用 post_message() 时,通过 callback 获得通知。这样可以向脚本发送可序列化为 JSON 的 message,但无法同时发送二进制 data 数据块。

为弥补这一不足,我们将 post_message() 重命名为 post(),并为其添加了可选的第二个参数,让你可以随消息一起发送二进制 data 数据块。

我们还改进了 C API,把普通 C 数组迁移到了 GBytes,从而尽可能减少数据流经 API 时的复制次数。

最后来总结一下这些变更:

8.0.0:

  • core:添加对多个并行会话的支持
  • core:将 Script 的 post_message() 重命名为 post(),并支持向脚本传递带外二进制数据
  • core:用 GBytes 替换 C 数组以提升性能
  • core:修复 libgee 中释放后使用导致的堆损坏
  • core:修复多处崩溃
  • core:修复 macOS Sierra 上的导出枚举崩溃
  • core:添加在 Valgrind 上运行的基本支持
  • core:将 macOS 最低要求提升至 10.9,以便依赖 libc++
  • node:更新到新的 8.x API
  • python:更新到新的 8.x API
  • swift:更新到新的 8.x API
  • swift:升级到 Swift 3
  • qml:更新到新的 8.x API
  • clr:更新到新的 8.x API
  • clr:修复泄漏

8.0.1:

  • node:修复 Script#post()

8.0.2:

  • core:修复从 JS 线程调用 recv().wait() 时的死锁

8.0.3:

  • core:将 Interceptor 的基础开销最多降低 65%
  • core:在 V8 运行时中尽量减少 Interceptor 引发的 GC 抖动,采用与 Duktape 运行时相同的回收和写时复制技巧
  • core:加快 macOS 和 iOS 上的 gum_process_get_current_thread_id()

尽情使用吧!