-
-
[原创]抖音抓包LSPosed插件多版本可用的技术刨析
-
-
[原创]抖音抓包LSPosed插件多版本可用的技术刨析
如果只需要插件,不想看技术实现,可以关注公众号,发送“抖音插件”,获取编译好的插件

libsscronet.so 会引用 BoringSSL 的 SSL API,比如 SSL_CTX_set_custom_verify 和 SSL_do_handshake;真实实现位于 libttboringssl.so。所以这里 hook 的不是 Cronet 的导入符号,而是 BoringSSL 里的 custom_verify setter。
直接 hook Cronet 的 CertVerify 语义上最直观,但稳定性不如 BoringSSL setter。
Cronet 的证书校验不只是一个 bool。它还会填充证书链、host、OCSP、SCT、verify flags、SSLInfo 等状态。高层粗暴截断,很容易让后续逻辑拿到不完整状态。
custom_verify setter 更干净:


这两个函数的特点很适合 hook:
核心 detour:
BoringSSL 的 verify callback 有 per-CTX 和 per-SSL 两种注册粒度。抖音 Cronet 的主流量都通过 SSL_CTX_set_custom_verify 在 CTX 级注册,所以只 hook 这一个 setter 就能覆盖。
不要丢掉原始 callback。原 callback 后面还要被调用,用来维持 Cronet / BoringSSL 内部状态。
不能只用一个全局变量保存“最后一次看到的 callback”。
同一个进程里可能有多套 TLS 使用者:
它们各自创建自己的 SSL_CTX,注册各自的 verify callback。如果只保存一个全局 callback,后注册的组件会覆盖前面的组件。结果就是:
所以要按 CTX 对象保存:
但握手时 BoringSSL 交给回调的是 SSL*,不是 SSL_CTX*。要回到这张表,还得先从 SSL* 反查出它的 SSL_CTX*——这就是下一节的事。
主流量通常走 SSL_CTX_set_custom_verify。注册时我们保存的是 ctx -> callback,但握手时 MyVerifyCb 收到的是 SSL* ssl,所以需要从 ssl 反查 ctx。
SSL_get_SSL_CTX 很短:

代码里直接按偏移读取:
然后用这个 ctx 去 g_ctx_cb 里找原始 callback,这个值目前看到抖音39.1.0-39.3.0目前最新版本没变化,其余版本我就不一一测试了,需要自行测试。
MyVerifyCb 做三件事:
核心逻辑:
查找路径只有一条:ssl -> ctx(按 §4 的偏移)-> g_ctx_cb。如果没找到(orig == nullptr),通常意味着 hook 晚于 CTX 创建,或偏移变了;这种情况应当打诊断暴露出来,而不是悄悄放行。
这一步的重点是先调原 callback。它会继续执行 Cronet 的证书校验逻辑,填充后续还会使用的状态。我们只是在它返回之后改最终结果。
custom verify callback 的返回值不是普通 bool:
同步失败可以覆盖:
[招生]科锐逆向工程师培训(2026年7月3日实地,远程教学同时开班, 第56期)!