希望你们当中已经有人开始享受 frida.Compiler 了!如果你完全不知道它是什么,请查看 15.2.0 版本说明。

性能

回到 15.2.0,当时 frida.Compiler 有一点让我很困扰:即便在我的 i9-12900K Linux 工作站上,仅仅编译一个很小的“Hello World”也需要几秒钟:

$ time frida-compile explore.ts -o _agent.js

real	0m1.491s
user	0m3.016s
sys	0m0.115s

经过大量性能剖析和难以想象的繁琐打磨后,我终于得到了这样的结果:

$ time frida-compile explore.ts -o _agent.js

real	0m0.325s
user	0m0.244s
sys	0m0.109s

差别相当大!这意味着 frida -l explore.ts 这类即时编译场景现在顺畅了很多。更关键的是,基于 Frida 的工具可以用这种方式加载用户脚本,而不会让用户忍受数秒的启动延迟。

快照

你或许想知道我们是如何让编译器如此快速启动的。查看内部实现会发现,它使用 TypeScript 编译器。启动时需要解析并运行的代码相当多。而且,加载和处理定义所有相关类型的 .d.ts 文件,开销其实还要更高。

我们在 15.2 中实现的第一项优化,是在 V8 运行时可用时直接使用它。仅这一项就带来了可观的提速。不过,稍加性能剖析便能看出,当我们开始处理 .d.ts 文件时,V8 意识到自己面对的是繁重工作负载,因此花费了大量时间来优化 TypeScript 编译器的代码。

这让我想起很久以前注意到的一个非常酷的 V8 功能:自定义启动快照。简单来说,如果我们能够预先预热 TypeScript 编译器,并在构建 Frida 时提前创建所有 .d.ts 源文件,就可以在那个时间点为虚拟机状态制作快照,并嵌入生成的启动快照。之后在运行时,我们便可以从快照启动,立即进入工作状态。

在实现这项功能的过程中,我扩展了 GumJS,使 create_script() 可以同时接收快照和 agent 源代码。另有 snapshot_script(),用于首先创建快照。

例如:

import frida

session = frida.attach(0)

snapshot = session.snapshot_script("const example = { magic: 42 };",
                                   warmup_script="true",
                                   runtime="v8")
print("Snapshot created! Size:", len(snapshot))

随后可以将该快照保存到文件,并像这样在以后加载:

script = session.create_script("console.log(JSON.stringify(example));",
                               snapshot=snapshot,
                               runtime="v8")
script.load()

请注意,创建快照时使用的操作系统、架构和 V8 版本必须与之后加载快照时相同。

V8 10.x

另一个令人兴奋的消息是,我们已将 V8 升级到 10.x,这意味着可以享用最新的虚拟机改进和 JavaScript 语言特性。考虑到上一次升级已经是两年多以前,这次无疑是一次相当扎实的升级。

多构建系统的诅咒,第二部分

你或许还记得 15.1.15 版本说明 中提到,我们前所未有地接近“整个 Frida 都能使用单一构建系统完成构建”这一里程碑。当时唯一剩下的组件是 V8,我们过去使用 Google 的 GN 构建系统来构建它。很高兴地告诉大家,我们终于到达了这个里程碑。现在,我们为 V8 配备了一套全新的 Meson 构建系统。太棒了!

结语(EOF)

此外还有许多令人兴奋的变化,务必查看下面的更改日志。

用得开心!

更改日志

  • compiler:使用快照缩短启动时间。
  • compiler:升级 frida-compile 和其他依赖项。
  • 增加对 JavaScript 虚拟机快照的支持。目前只有 V8 后端实现了该功能,因为 QuickJS 暂不支持。
  • 将调试器 API 从 Session 移至 Script。这是必需的,因为 V8 的调试器按 Isolate 工作,而为了支持快照,现在每个 Script 都需要一个 Isolate。
  • server+portal:修复守护进程父进程就绪失败时的退出问题。感谢 @pachoo!
  • resource-compiler:增加压缩支持。我们将其用于 frida.Compiler 的堆快照。
  • ipc:增大 UNIX 套接字缓冲区以提高吞吐量。
  • meson:将 frida-payload 提升为公共 API。这样就能为 frida-agent 和 frida-gadget 不适用的场景实现自定义 payload。
  • windows:迁移到 Visual Studio 2022。
  • windows:将工具链/SDK 逻辑改为使用细粒度 SDK。
  • windows:不再依赖 .py 文件关联。
  • darwin:修复与 macOS 13 和 iOS >= 15.6.1 的兼容性。
  • darwin:如果存在 Apple 的 libffi-trampolines.dylib,则使用它,从而支持 iOS 15 及更高版本。感谢 @hsorbo 带来的愉快结对编程时光!
  • fruity:修复 USBMUXD_SOCKET_ADDRESS 的处理。感谢 @0x3c3e!
  • fruity:停止支持 USBMUXD_SERVER_* 环境变量。感谢 @as0ler!
  • droidy:改进 ADB 环境变量的处理。感谢 @0x3c3e!
  • java:(android) 修复 Android 11 和 12 上 ClassLinker 偏移量的检测(#264)。感谢 @sh4dowb!
  • java:(android) 修复 Android 13 上的早期插桩。
  • java:处理以 $ 为前缀的方法和字段。感谢 @eybisi!
  • android:迁移到 NDK r25。
  • arm64:优化内存复制实现。
  • stalker:确保 EventSink 在拆卸时停止。
  • stalker:修复分支涉及移位时 ARM 栈遭破坏的问题。
  • stalker:处理涉及移位寄存器的 ARM PC 加载。
  • stalker:应用回填补丁时通知 ARM observer。
  • stalker:收到通知时应用 ARM 回填补丁。
  • stalker:为 switch block 回调增加 ARM 支持。
  • arm-reader:公开 disassemble_instruction_at()。
  • thumb-reader:公开 disassemble_instruction_at()。
  • memory:重新调整 API,使其与当前 V8 语义一致。
  • gumjs:将 V8 后端改为每个脚本使用一个 Isolate。
  • gumjs:支持通过环境变量传递 V8 标志:FRIDA_V8_EXTRA_FLAGS。
  • gumjs:在 Darwin/arm* 上使用 V8 写保护。
  • gumjs:增加对动态定义脚本的支持。
  • prof:支持 Linux/MIPS 上的旧系统头文件。
  • devkit:改进示例在 UNIX 上的编译文档。
  • ci:将其余旧版 CI 迁移到 GitHub Actions。
  • quickjs:修复模块求值期间出错时的释放后使用问题。
  • v8:升级到最新的 V8 10.x。
  • v8:增加 Meson 构建系统。
  • usrsctp:将 Windows 要求降低到 XP,与其他组件保持一致。
  • xz:避免使用 ANSI 时代的 Windows API。
  • libc-shim:支持 Linux/MIPS 上的旧系统头文件。
  • glib:为 MIPS 增加 Linux libc 回退实现。
  • 增加 config.mk 选项,以便在 Android 上禁用模拟 agent,从而构建更小的二进制文件。感谢 @muhzii!
  • python:停止支持 Python 2,现代化代码,增加文档字符串和类型标注,使用现代工具增加 CI,以及其他许多改进。感谢 @yotamN!
  • python:构建 Python wheel,而不是 egg。感谢 @oriori1703!
  • python:修复 Device.get_bus()。此前的实现调用了并不存在的 _Device.get_bus()。感谢 @oriori1703!
  • python:迁移到稳定版 Python C API。
  • python:增加使用 frida-core devkit 从源代码构建的支持。
  • python:增加对新快照 API 的支持。
  • node:增加对新快照 API 的支持。
  • node:修复与 Electron v20 的兼容性。