Skip to content

initializeGlobals() 符号解析 ​

🔧 解析并初始化所有需要 hook 的 Native 符号地址,构造 NativeFunction 包装。

📎 源码在线查看:script.js#L124-L183(initializeGlobals)

作用 ​

用 ApiResolver("module") 按 exports:库通配符!函数名 的方式枚举匹配地址,把结果存入全局 addresses 表,并构造对应的 NativeFunction 包装。

解析两组符号 ​

javascript
function initializeGlobals() {
  var resolver = new ApiResolver("module");
  var exps = [
    [Process.platform == "darwin" ? "*libboringssl*" : "*libssl*",
      ["SSL_read", "SSL_write", "SSL_get_fd", "SSL_get_session", "SSL_SESSION_get_id"]],
    [Process.platform == "darwin" ? "*libsystem*" : "*libc*",
      ["getpeername", "getsockname", "ntohs", "ntohl"]]
  ];
  ...
}
组库符号
SSL 组*libssl*(Android) / *libboringssl*(darwin)SSL_read, SSL_write, SSL_get_fd, SSL_get_session, SSL_SESSION_get_id
libc 组*libc*(Android) / *libsystem*(darwin)getpeername, getsockname, ntohs, ntohl

平台分支:Process.platform == "darwin" 走 iOS/macOS 分支,其余走 Android/Linux 分支。

三种匹配结果处理 ​

1. 零匹配 ​

javascript
if (matches.length == 0) {
  if (name == "SSL_get_fd") {
    addresses["SSL_get_fd"] = 0;   // 允许缺失,后续用桩
    continue;
  }
  throw "Could not find " + lib + "!" + name;  // 其它符号缺失直接抛异常
}
  • SSL_get_fd 允许缺失(个别 ROM 缺这个导出),置 0 后续用 return_zero 桩降级
  • 其它符号缺失直接抛异常,避免静默失败

2. 多匹配(关键逻辑) ​

javascript
else if (matches.length > 1) {
  var selectedMatch = null;
  for (var k = 0; k < matches.length; k++) {
    if (matches[k].name.indexOf("com.android.conscrypt") !== -1) {
      selectedMatch = matches[k];
      break;
    }
  }
  if (selectedMatch === null) {
    selectedMatch = matches[0];
  }
  addresses[name] = selectedMatch.address;
  console.log("[*] Selected " + name + " from: " + selectedMatch.name);
}

同名符号在多个库里都有匹配(常见于 Android 同时存在系统 libssl 与 Conscrypt 自带 SSL 实现)。优先选 com.android.conscrypt 的实现,因为 Android 上 App 流量实际走 Conscrypt。无 conscrypt 命中则退回第一个匹配。

3. 唯一匹配 ​

javascript
else {
  addresses[name] = matches[0].address;
}

构造 NativeFunction ​

javascript
if (addresses["SSL_get_fd"] == 0) {
  SSL_get_fd = return_zero;           // 桩,永远返回0
} else {
  SSL_get_fd = new NativeFunction(addresses["SSL_get_fd"], "int", ["pointer"]);
}
SSL_get_session = new NativeFunction(addresses["SSL_get_session"], "pointer", ["pointer"]);
SSL_SESSION_get_id = new NativeFunction(addresses["SSL_SESSION_get_id"], "pointer", ["pointer", "pointer"]);
getpeername = new NativeFunction(addresses["getpeername"], "int", ["int", "pointer", "pointer"]);
getsockname = new NativeFunction(addresses["getsockname"], "int", ["int", "pointer", "pointer"]);
ntohs = new NativeFunction(addresses["ntohs"], "uint16", ["uint16"]);
ntohl = new NativeFunction(addresses["ntohl"], "uint32", ["uint32"]);

每个 NativeFunction(address, retType, [argTypes]) 把 Native 地址包装成可调用的 JS 函数。

触发时机 ​

javascript
// 脚本加载时立即执行一次
initializeGlobals();

// setssllib RPC 时重新执行
rpc.exports = {
  setssllib: function (name) {
    libname = name;
    initializeGlobals();
  }
};

相关文档 ​

基于 VitePress 构建 · 教学用途