selftest 自检脚本
🧪 用独立 script 主动在目标进程内发 HTTPS 请求,验证抓包链路。
📎 源码在线查看:
r0capture.py#L433-L497(selftest)
为什么要独立 script
主 script.js 已导出 rpc.exports.setssllib,若 selftest 也用 rpc.exports.selftest,会冲突覆盖。所以 selftest 用一个独立 script 注册自己的 RPC。
触发条件
python
if selftest:
_SELFTEST_SCRIPT = r"""..."""
st_script = session.create_script(_SELFTEST_SCRIPT)
...
st_script.load()
r = st_script.exports_sync.selftest("https://example.com/")
print(f"[selftest] result={r}")
returnselftest 模式下,主 script 仍正常 load(装好 SSL hook),然后额外注入 selftest script 发请求验证。
脚本结构
selftest 实现
javascript
rpc.exports.selftest = function (url) {
return new Promise(function (resolve) {
try {
var J = Java; // 触发懒加载
J.perform(function () {
try {
var U = J.use("java.net.URL");
var H = J.use("java.net.HttpURLConnection");
var c = J.cast(U.$new(url || "https://example.com/").openConnection(), H);
c.setConnectTimeout(10000); c.setReadTimeout(10000);
c.setRequestMethod("GET");
var code = c.getResponseCode();
var is = c.getInputStream();
var R = J.use("java.io.BufferedReader");
var IR = J.use("java.io.InputStreamReader");
var r = R.$new(IR.$new(is));
var line, sb = ""; while ((line = r.readLine()) !== null) { sb += line; }
resolve({ code: code, bodylen: sb.length });
} catch (e) { resolve({ err: "" + e }); }
});
} catch (e) { resolve({ err: "" + e }); }
});
};用 java.net.URL + HttpURLConnection 发 GET,会经过系统 SSL 栈,从而被主 script 的 SSL_read/SSL_write hook 抓到。
桥接 post 回 st_script
selftest script 的 bridge 请求必须 post 回 st_script(而非主 script):
python
def on_selftest_message(message, data):
payload = message.get("payload") if message.get("type") == "send" else None
if isinstance(payload, dict) and payload.get("type") == "frida:load-bridge":
serve_bridge(payload.get("name"), st_script) # ← 注意是 st_script
return
if message.get("type") == "error":
print(f"[selftest script error] {message}")错位的后果
若误把 st_script 的 bridge 请求 post 回主 script,selftest 里 recv().wait() 永远收不到响应,会死锁卡住。