mcpField
B
bypassing-mobile-pinning

bypassing-mobile-pinning

github.com/trilwu安全17754 次安装12 周前更新
代码仓库

关于 bypassing-mobile-pinning

面向经授权移动应用测试的技能,用于诊断和处理 TLS 代理流量不可见的问题。它先区分证书信任、代理设置、双向 TLS 等原因,再根据 Android 或 iOS 的网络栈选择验证和绕过方法。

主要功能

  1. 01诊断代理流量不可见的原因
  2. 02识别 Android 与 iOS TLS 网络栈
  3. 03按网络栈选择挂钩位置
  4. 04排查双向 TLS 与代理绕行
  5. 05通过请求修改验证拦截效果

适用场景

  1. 01调查移动应用的 TLS 握手失败
  2. 02为授权测试查看应用 API 请求
  3. 03区分证书固定与其他网络问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/trilwu/secskills --skill bypassing-mobile-pinning

安装后在 Claude Code 中输入/bypassing-mobile-pinning确认已加载。

详细介绍

绕过移动应用证书固定

在这里浪费的时间,大多花在绕过根本不存在的证书固定上。代理为空至少有六种原因,每种原因的解决方法都不同——其中一种根本不是证书固定,而是 Android 默认不信任用户 CA;另一种则是应用使用了自己的 TLS 栈,根本没有经过你的代理。先诊断,再考虑使用绕过脚本。

仅对你获准测试的应用执行此操作。

适用场景

  • Burp/mitmproxy/Charles 显示来自移动应用的 TLS 握手失败
  • 应用显然正在访问网络,但代理中什么也没有
  • 配置代理后,应用报告“网络错误”“连接不安全”或类似信息
  • 你知道目标应用采用了证书固定,需要针对其协议栈选择合适的 Hook

不适用场景

  • Flutter 目标应用——使用 reversing-flutter-apps;Flutter 的故障表现完全相同,但原因和解决方法针对其引擎
  • 更广泛的移动应用安全评估——使用 testing-mobile-applications
  • 流量可见后的后端测试——使用 testing-apis
  • 深入逆向原生 .so 文件——使用 analyzing-binaries

先诊断

在安装任何内容之前先运行此操作。症状会告诉你原因。

症状可能原因解决方法
代理收到 CONNECT,随后出现 TLS 警报 unknown_ca / bad_certificate你的 CA 不受信任将其安装为系统 CA,或修补 Network Security Config
代理收到 CONNECT,随后只有部分域名出现警报真正的证书固定,且仅针对这些主机Hook 证书固定检查
代理完全没有收到任何内容,但应用正常运行应用忽略了系统代理在网络层强制转发流量(Flutter、gRPC、某些 SDK)
代理收到握手,但服务器拒绝客户端双向 TLS——应用提供了客户端证书提取客户端证书;这不是证书固定
在模拟器上正常,在设备上失败(或反之)Root/模拟器检测,不是 TLS这是另一类问题——请参阅检测章节
仅在登录后失败证书固定仅应用于 API 主机执行 Hook,然后再次检查
# What does the app actually declare?
apktool d target.apk -o out
cat out/res/xml/network_security_config.xml 2>/dev/null
rg -n 'networkSecurityConfig|usesCleartextTraffic' out/AndroidManifest.xml

# Which TLS stack is in play?
rg -l 'okhttp3|CertificatePinner|TrustKit|AFNetworking|Alamofire' out/ 2>/dev/null | head
unzip -l target.apk | rg 'libssl|libcrypto|libconscrypt|libflutter|libil2cpp|libmonodroid'

不要在排查证书固定之前,先检查 Network Security Config。 Android 7 起,应用默认不信任用户安装的 CA。即使应用完全没有证书固定代码,流量拦截仍然会失败。有两种解决方法:

# A. Install your CA as a SYSTEM certificate (no app modification — preferred)
#    Emulator:
emulator -avd <name> -writable-system
adb root && adb remount
openssl x509 -inform PEM -subject_hash_old -in burp.pem | head -1   # → e.g. 9a5ba580
cp burp.pem 9a5ba580.0 && adb push 9a5ba580.0 /system/etc/security/cacerts/
adb shell chmod 644 /system/etc/security/cacerts/9a5ba580.0
#    Rooted device: use a Magisk module so the change survives reboot

# B. Patch the config and repack (when you cannot get a system CA)
#    Add to network_security_config.xml:
#      <base-config><trust-anchors>
#        <certificates src="system"/><certificates src="user"/>
#      </trust-anchors></base-config>
apktool b out -o patched.apk && apksigner sign --ks debug.keystore patched.apk

方案 A 更好:它不会修改应用,因此完整性检查、签名检查和 Play Integrity 不会受到影响。只有在无法向设备安装系统 CA 时,才考虑方案 B。

Android:按技术栈 Hook

先识别技术栈,再进行 Hook。通用脚本如果没有命中,看起来就像是“绕过失败”,但实际上只是针对了错误的层。

# Start here — covers the common Java-layer stacks in one shot
objection -g com.target.app explore
# then: android sslpinning disable

# Or a maintained universal script
frida -U -f com.target.app -l android-ssl-bypass.js --no-pause
技术栈标记Hook 点
OkHttp 3/4okhttp3.CertificatePinnerCertificatePinner.check() — 正常返回
HttpURLConnectionjavax.net.ssl.*自定义 X509TrustManager.checkServerTrusted()
Conscryptlibconscrypt_jni.soPlatform.checkServerTrusted,或原生层
Apache HttpClientorg.apache.httpSSLSocketFactory 验证器
WebViewonReceivedSslError强制执行 handler.proceed()
原生 / BoringSSLlibssl.so,自定义 .soSSL_CTX_set_custom_verify、ssl_verify_peer_cert
Xamarinlibmonodroid.so、libxamarin*Mono 层的 ServicePointManager / HttpClientHandler
Unitylibil2cpp.soUnityWebRequest 证书处理器,或 BestHTTP 的验证器
gRPClibgrpc.so通道凭据;通常也会忽略代理

原生证书固定是通用脚本失效的地方。 当 objection 报告成功但流量仍然失败时,检查位于某个 .so 中。BoringSSL 的验证入口点没有导出,因此脚本会通过模式扫描来定位它们——而模式与版本有关。请确认你遇到的情况:

# Is a native TLS stack even present?
unzip -j target.apk 'lib/arm64-v8a/*' -d libs && rg -l 'SSL_|BoringSSL|s2n' libs/
# Trace the native calls to see which library terminates TLS
frida-trace -U -f com.target.app -i 'SSL_*' -i '*verify*'

对于 Unity、Xamarin 和 Flutter 构建版本,先恢复符号——reversing-unity-il2cpp、reversing-flutter-apps——然后 Hook 命名函数,而不是盲目进行模式扫描。

iOS

# Frida-based, covers NSURLSession and the common libraries
objection -g com.target.app explore
# then: ios sslpinning disable

# Jailbroken device, no Frida
# SSL Kill Switch 3 — system-wide, survives app updates
库Hook 点
NSURLSession(默认)URLSession:didReceiveChallenge: → 使用服务器信任的 .useCredential
TrustKitTSKPinningValidator 结果
AFNetworkingAFSecurityPolicy.evaluateServerTrust:
AlamofireServerTrustManager / ServerTrustEvaluating
原生/BoringSSL与 Android 相同 — Hook 验证回调

对于非越狱设备:使用 Frida gadget 重新打包 IPA(objection patchipa)、重新签名并侧载。请预期这会触发安全加固应用中的完整性或证明检查。

仍然失败时

按顺序排查,不要继续尝试更多绕过脚本。

  1. 应用根本没有使用你的代理。 某些技术栈完全忽略系统代理设置。强制转发流量:使用 iptables 进行透明重定向,或使用基于 VPN/tun 的代理。
    adb shell su -c 'iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to <proxy>:8080'
    
  2. 证书透明度强制检查。 某些 SDK 要求 SCT;你的 CA 没有。查找 CT 库,并专门 Hook CT 验证器。
  3. 双向 TLS。 服务器要求客户端证书。从应用包中提取 .p12 或密钥库,找回其密码(通常在代码或 strings 中),并将其载入代理的客户端证书设置。这是独立于证书固定的机制,任何证书固定绕过都不会影响它。
  4. Root/越狱或 Frida 检测。 应用检测到插桩后会安全失败,看起来像是 TLS 问题。检查是否扫描 frida 字符串、探测端口 27042、检查 /proc/self/maps,或进行 Play Integrity 检查。先绕过检测,再重试证书固定绕过。
  5. 流量不是 HTTP。 可能是 WebSockets、gRPC、MQTT 或基于 TLS 的自定义协议。HTTP 代理不会显示这些流量——请在套接字层捕获,或使用支持相应协议的代理。
  6. 证书固定仅应用于特定主机。 分析流量正常,但 API 失败。对比代理中出现的主机,确认这一点。

验证是否真正成功

只有当你能端到端地查看并修改请求时,才算确认绕过成功——应用仅仅不再报错并不足够。

1. Proxy shows the API host, not just analytics and CDN traffic
2. Request and response bodies are readable
3. A modified request produces a different server response
4. Authenticated flows still work through the proxy

如果只有第 1 步通过,你看到的可能是备用路径,而真正的 API 流量走了其他路径。

应拒绝的错误说法

  • “绕过失败了,应用一定用了强证书固定。” 可能有六种原因,其中一种是证书固定。请根据症状表进行诊断。
  • “我安装了 CA,TLS 就应该能正常工作。” 如果它是用户证书,且应用运行在 Android 7+ 上又未选择启用相关支持,那就无法正常工作。
  • “objection 说证书固定已禁用。” 它禁用的是自己能识别的 Java 层检查。原生代码中的证书固定不受影响。
  • “代理中没有流量,说明应用处于离线状态。” 这说明应用没有使用你的代理。
  • “我直接修补 APK 就行。” 重新打包会破坏签名并触发完整性检查。优先使用系统 CA 和运行时 Hook;只有作为最后手段时才修补。
  • “证书固定已绕过,评估完成。” 绕过证书固定只是准备工作,不是发现项。证书固定是一种纵深防御措施;缺少这项措施只需作为低严重性说明记录——真正的发现项在它后面的 API 中。

参考资料

  • testing-mobile-applications — 解锁后续评估所需的更广泛测试
  • reversing-flutter-apps — Flutter 独立的 TLS 栈和代理行为
  • reversing-unity-il2cpp、reversing-react-native-apps — 在 Hook 框架专属栈之前恢复符号
  • testing-apis — 查看流量后,真正发现项所在之处
  • objection、Frida、SSL Kill Switch 3、apktool、apksigner、Magisk

评论

支持 Markdown