Skip to content

SSL Pinning 定位 hook ​

🔍 Hook File.$init(File, String),定位证书绑定(SSL Pinning)的关键代码。

📎 源码在线查看:script.js(Pinning locator)

作用 ​

当 App 读取 cacert 文件做证书校验,且调用栈里出现 X509TrustManagerExtensions.checkServerTrusted 时,认为这是 pinning 校验点,把文件路径与调用栈 send 回 Python,帮助逆向定位绑定逻辑。

实现 ​

javascript
Java.use("java.io.File").$init.overload('java.io.File', 'java.lang.String').implementation =
function (file, cert) {
  var result = this.$init(file, cert)
  var stack = Java.use("android.util.Log").getStackTraceString(
              Java.use("java.lang.Throwable").$new());
  if (file.getPath().indexOf("cacert") >= 0 &&
      stack.indexOf("X509TrustManagerExtensions.checkServerTrusted") >= 0) {
    var message = {};
    message["function"] = "SSLpinning position locator => " + file.getPath() + " " + cert;
    message["stack"] = stack;
    var data = Memory.alloc(1);
    send(message, Memory.readByteArray(data, 1))
  }
  return result;
}

双条件过滤 ​

javascript
if (file.getPath().indexOf("cacert") >= 0 &&
    stack.indexOf("X509TrustManagerExtensions.checkServerTrusted") >= 0)

只有同时满足两个条件才上报:

条件含义
路径含 cacertApp 在读自定义 CA 证书文件(pinning 常见做法:内置固定证书)
栈含 checkServerTrusted调用栈经过证书校验逻辑

双条件避免误报——单纯读 cacert 不一定是 pinning,单纯过 checkServerTrusted 也不一定是文件型 pinning。

事件 message ​

function: "SSLpinning position locator => /data/.../cacert.bks mycert"
stack:    "at com.app.security.Pinning.checkServerTrusted(Pinning.java:88)\n..."

stack 直接指出 App 哪个类哪个方法在做证书绑定——逆向时据此定位绑定逻辑,进而绕过。

r0capture 不绕过 pinning,只定位 ​

注意区分

r0capture 的 SSL hook 在 SSL_read/SSL_write 层,本身就无视 pinning(pinning 在 hook 点之上,校验失败也照样能 hook 到明文)。这个 hook 的目的是定位 pinning 代码位置,便于逆向研究 App 的绑定实现,不是为了抓包而绕过。

1 字节占位 ​

与证书导出一样,用 Memory.alloc(1) + readByteArray(data, 1) 发 1 字节 data,触发 Python 端事件分支。

相关文档 ​

基于 VitePress 构建 · 教学用途