Frida 17 兼容性
Frida 17 是个破坏性大版本:
Java桥接不再内置,导致 r0capture 的所有 Java 层 hook 失效。本篇讲清楚问题与修复。
问题:Java 桥接消失了
Frida 16 及之前,脚本里直接用 Java.use(...) 是理所当然的——Java 对象由 frida-java-bridge 提供,内置在运行时。Frida 17 改了:
Frida 17 把 frida-java-bridge 从运行时里拿掉了,改为按需加载:脚本第一次访问 Java 时,向 host 发请求要桥接源码,host 把源码注入进来。
加载协议:frida:load-bridge
这是 Frida 17 新增的 host↔script 协议:
关键:frida CLI(frida 命令)实现了这个 host 逻辑,但 r0capture.py 作为独立 host 没实现——所以 Frida 17 下 r0capture 的 Java 层 hook 全废。
后果:哪些功能失效
script.js 里这一行决定了 Java hook 生死:
if (typeof Java !== 'undefined' && Java.available) { ... }Frida 17 下 Java 未定义,整个 if 块不执行,导致:
修复方案
r0capture.py 加两处改动即可:
1. host 端:实现 bridge 服务
import frida_tools
from pathlib import Path
_bridges_dir = Path(frida_tools.__file__).parent / "bridges"
def serve_bridge(name, script):
bridge_path = _bridges_dir / f"{name.lower()}.js"
if not bridge_path.exists():
return
source = bridge_path.read_text(encoding="utf-8")
script.post({
"type": "frida:bridge-loaded",
"filename": bridge_path.name,
"source": source,
})
def on_message(message, data):
payload = message.get("payload")
# 识别 bridge 请求
if isinstance(payload, dict) and payload.get("type") == "frida:load-bridge":
serve_bridge(payload.get("name"), script)
return
# ... 正常处理 SSL 明文2. 脚本端:注入 lazy getter 引导
在 script.js 加载前,注入一段引导代码,让 Java 变成一个"用到时才加载"的 lazy getter:
(function () {
if (typeof Java !== 'undefined') return; // 老版本已有,跳过
function defineBridge(name) {
Object.defineProperty(globalThis, name, {
configurable: true,
get: function () {
send({ type: "frida:load-bridge", name: name }); // ① 请求
var b;
recv("frida:bridge-loaded", function (s) { // ② 等回传
b = Script.evaluate(s.filename,
"(function () { " + s.source + "\nreturn bridge; })()");
}).wait();
Object.defineProperty(globalThis, name, // ③ 替换成真值
{ value: b, configurable: true, writable: true });
return b;
}
});
}
defineBridge("Java");
})();多 script 不共享 globalThis
Frida 17 下每个 script 有独立 globalThis,引导代码要在每个 script 里都注入一次(包括 selftest 用的独立 script)。
验证:--selftest
修复后用 --selftest 一键验证整个链路(Java 桥接 + SSL hook + pcap 写入):
python3 r0capture.py -H 127.0.0.1:27042 7033 --selftest -v -p st.pcap
# 看到 [selftest] result={'code': 200, 'bodylen': 558} 就是全通了selftest 脚本本身也自带 defineBridge 引导,且它的 bridge 请求由独立的 on_selftest_message 处理(post 回 selftest script 而非主 script)——避免多 script 串扰。
推荐版本搭配
| Frida | Android |
|---|---|
| 17.x | 16 |
| 16.5.2 | 14 |
| 15.2.2 | 12 |