又到了发布时刻。本次我们为所有平台带来了大幅性能提升、一个全新的函数查找 API,以及 iOS 9 上的重要稳定性改进。
先谈最后一项。有些用户可能注意到,在 iOS 9 上使用 Frida 时会出现奇怪的错误和死锁。根本原因很简单:内联挂钩会让进程失去其代码签名状态中的 CS_VALID 位。在 iOS 8 及更早版本中,这不是问题,因为越狱工具总能修补内核,放宽代码签名要求。从本次发布开始,我们实现了一些技巧,可以在不破坏代码签名状态的情况下进行内联挂钩。对技术细节感兴趣的读者:我们会动态生成一个临时 .dylib 文件,写入希望修改的内存页的新版本,例如包含 open() 的 libc 内存页;然后对该二进制文件进行伪签名,请求内核对它执行 F_ADDFILESIGS,最后从该文件 mmap() 到原始内存页之上。
这就引出了下一个话题:性能。刚才介绍的技巧仅仅为了挂钩一个函数,就会增加不少额外开销。它与在支持读写执行内存页、代码签名要求宽松的系统上所采用的方法也截然不同,显然需要进行重大的架构调整。我也一直在考虑一次应用整批挂钩,以提高效率,并更精确地控制挂钩何时激活。
从本次发布开始,Interceptor API 支持事务。只需调用 begin_transaction(),挂钩所有函数,再调用 end_transaction() 一次性激活。这会大幅提升性能,而且无需修改现有代码就能自动受益。因为每当进入 JavaScript 运行时,我们会隐式开始一个事务;离开时(以及 send() 消息或从 RPC 方法返回前)结束事务。因此,除非通过定时器或 Memory.scan() 等异步 API 附加挂钩,否则所有挂钩都会合并到单个事务中并获得性能提升。
下面是我们与 CydiaSubstrate 的性能对比:
请注意,如果通过 C 或 C++ 使用插桩引擎,就必须自行调用 begin_transaction() 和 end_transaction() 才能获得这项提升;即使不调用,代码仍可工作,因为每项操作都会隐式包含一个事务,而且 API 允许嵌套这些调用。
以上是函数挂钩性能,但我们并未止步于此。如果你曾用 frida-trace 跟踪 Objective-C API,或在所有已加载库中使用 glob 查找函数,可能会发现解析所有函数要花很长时间。结合早期插桩时,甚至可能耗时过长,超过系统的启动超时。现在这一切都已优化:典型的 Objective-C 场景过去需要数秒,如今只需几毫秒。
最后一项消息。动态发现待挂钩函数是一种非常常见的场景,并非只有 frida-trace 会这样做,因此我们现在为此提供了全新 API:


最后汇总一下变更:
6.2.0:
- core:改进 Interceptor,避免破坏 iOS 9 上的动态代码签名
- core:迁移到基于事务的 Interceptor API,以提升性能
- core:修复延迟释放已调度回调时的崩溃(V8 和 Duktape)
- frida-trace:移除 setTimeout() 逻辑以提升性能,使多个挂钩可在同一事务中应用
- frida-trace:以 50 ms 为单位批量处理日志事件,以提升性能
6.2.1:
- core:添加 ApiResolver API
- frida-trace:使用新的 ApiResolver API 提升性能
6.2.2:
- core:修复导致无法注入 Windows Store/Universal 应用的疏忽
- core:修复 32 位 ARM 上拆卸时的崩溃
- core:添加 frida-inject,用于将 Agent 注入运行中进程,其语义类似 frida-gadget
- core:(Linux)阻止 libdl 卸载,以规避 TLS 析构函数错误
- core:(Linux)修复快速取消注入时的竞态条件
6.2.3:
- core:修复 eval 代码的源映射处理问题,该问题会导致未处理异常被吞掉,例如运行 frida-trace 时
- core:修复 Python 3.x 构建系统回归
- frida-trace:修复路径转义问题
- frida-trace:改进错误处理程序异常时的错误处理
6.2.4:
- frida-trace:监视处理程序,不再轮询
6.2.5:
- core:支持通过向 Interceptor.attach() 传入函数而非回调对象来挂钩任意指令
- core:支持分离由 Interceptor.attach() 添加的单个监听器,甚至可从其回调中同步分离
- core:添加 Memory.scanSync()
- core:改进 Interceptor,保留 ARM 上的 r12(即 IP),修复寄存器破坏
- core:向 JavaScript 运行时公开 r8 到 r12
- core:修复不支持未对齐字访问的架构上的崩溃
- frida-repl:使用 RPC 功能简化逻辑
- node:升级到 prebuild 3.x
6.2.6:
- core:修复未越狱 iOS 系统上的回归
- core:修复 Duktape 运行时中的 Interceptor 回归
- core:修复解析后导入项的模块名称
- core:添加用于指定连接主机的 API
- core:改进 QNX 支持并修复构建回归
- core:修复 Mac 上的 frida-inject 构建系统
- core:(Windows)修复获取 USB 设备位置失败时的崩溃
- frida-server:允许覆盖默认监听地址
- frida-node:向 DeviceManager 添加 addRemoteDevice() 和 removeRemoteDevice()
- frida-python:添加 -H 开关,用于指定要连接的主机
- frida-python:向 DeviceManager 添加 add_remote_device() 和 remove_remote_device()
- frida-python:修复与 Duktape 运行时的兼容性问题
- frida-python:规范化请求的 RPC 方法名称
尽情使用吧!
oleavr