Skip to content

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}")
    return

selftest 模式下,主 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() 永远收不到响应,会死锁卡住。

相关文档 ​

基于 VitePress 构建 · 教学用途