mcpField
M
mobile-ssl-pinning-bypass

mobile-ssl-pinning-bypass

github.com/yaklang安全2.6k3.7k 次安装6 周前更新
代码仓库

关于 mobile-ssl-pinning-bypass

面向移动安全测试的指南,介绍 Android 和 iOS 应用的 SSL Pinning 绕过方法。涵盖运行时钩子、应用补丁、框架专用方案,以及流量拦截失败时的排查。

主要功能

  1. 01Android 和 iOS 绕过方法
  2. 02Frida 与 Objection 钩子
  3. 03应用反编译和重新打包流程
  4. 04Flutter、React Native 和 Xamarin 指南
  5. 05Pinning 失败诊断

适用场景

  1. 01在授权测试中拦截应用 HTTPS 流量
  2. 02测试具有多层 Pinning 的应用
  3. 03检查 Flutter 应用的网络验证
  4. 04排查代理证书信任问题

安装

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

$npx skills add https://github.com/yaklang/hack-skills --skill mobile-ssl-pinning-bypass

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

详细介绍

技能:移动端 SSL Pinning 绕过——专家攻击手册

AI LOAD INSTRUCTION:移动平台 SSL pinning 绕过专家技术。涵盖 Android 和 iOS 绕过方法(Frida、Objection、Xposed、SSL Kill Switch)、特定框架的绕过方法(Flutter、React Native、Xamarin),以及非标准 pinning 实现的故障排查。基础模型容易遗漏特定框架的 hook 点和多层 pinning 配置。

0. 相关路由

深入分析前,可考虑加载:


1. SSL PINNING 类型

Pinning 类型Pinning 的内容抗攻击能力常见于
证书 pinning精确的叶证书(DER/PEM)低(证书轮换时会失效)旧版应用
公钥 pinningSubject Public Key Info中(密钥不变时,证书续期后仍有效)现代应用
SPKI 哈希 pinningSPKI 的 SHA-256中(与公钥 pinning 相同)OkHttp、AFNetworking
CA pinning中间 CA 或根 CA 证书高(该 CA 颁发的任意证书均可)企业应用
多 pin(备用 pin)主 pin + 备用 pin高(备用 pin 可回退使用)支持 HPKP 的应用
Pinning 的工作原理
TLS Handshake
│
├── Server presents certificate chain
│
├── Standard validation (system trust store)
│   └── Passes? continue : connection fails
│
└── Pin validation (app-level check)
    ├── Extract server cert/pubkey/SPKI hash
    ├── Compare against embedded pins
    └── Match found? → allow : → reject connection

2. ANDROID 绕过方法

2.1 Frida 通用 SSL 绕过
// Hooks TrustManager, OkHttp, Volley, Retrofit, Conscrypt
Java.perform(function() {

    // ── TrustManagerImpl (Android system) ──
    try {
        var TMI = Java.use('com.android.org.conscrypt.TrustManagerImpl');
        TMI.verifyChain.implementation = function() {
            console.log('[Bypass] TrustManagerImpl.verifyChain');
            return arguments[0]; // return untouched chain
        };
    } catch(e) {}

    // ── X509TrustManager (custom implementations) ──
    var TrustManager = Java.registerClass({
        name: 'com.bypass.TrustManager',
        implements: [Java.use('javax.net.ssl.X509TrustManager')],
        methods: {
            checkClientTrusted: function() {},
            checkServerTrusted: function() {},
            getAcceptedIssuers: function() { return []; }
        }
    });

    var SSLContext = Java.use('javax.net.ssl.SSLContext');
    SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;',
        '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom')
        .implementation = function(km, tm, sr) {
        console.log('[Bypass] SSLContext.init');
        this.init(km, [TrustManager.$new()], sr);
    };

    // ── OkHttp3 CertificatePinner ──
    try {
        var CP = Java.use('okhttp3.CertificatePinner');
        CP.check.overload('java.lang.String', 'java.util.List').implementation = function() {
            console.log('[Bypass] OkHttp3 CertificatePinner.check: ' + arguments[0]);
        };
        // check$okhttp variant (OkHttp 4.x)
        try { CP['check$okhttp'].implementation = function() {}; } catch(e) {}
    } catch(e) {}

    // ── Retrofit / OkHttp interceptor ──
    try {
        var OkHttpClient = Java.use('okhttp3.OkHttpClient$Builder');
        OkHttpClient.certificatePinner.implementation = function(pinner) {
            console.log('[Bypass] OkHttpClient.Builder.certificatePinner');
            return this; // return builder without pinner
        };
    } catch(e) {}

    // ── Volley (HurlStack) ──
    try {
        var HurlStack = Java.use('com.android.volley.toolbox.HurlStack');
        HurlStack.createConnection.implementation = function(url) {
            console.log('[Bypass] Volley HurlStack: ' + url);
            var conn = this.createConnection(url);
            // Remove hostname verifier
            conn.setHostnameVerifier(Java.use(
                'javax.net.ssl.HttpsURLConnection').getDefaultHostnameVerifier());
            return conn;
        };
    } catch(e) {}

    // ── Conscrypt / BoringSSL (modern Android) ──
    try {
        var Conscrypt = Java.use('org.conscrypt.ConscryptFileDescriptorSocket');
        Conscrypt.verifyCertificateChain.implementation = function() {
            console.log('[Bypass] Conscrypt verifyCertificateChain');
        };
    } catch(e) {}

    // ── Apache HttpClient (legacy) ──
    try {
        var AbstractVerifier = Java.use('org.apache.http.conn.ssl.AbstractVerifier');
        AbstractVerifier.verify.overload('java.lang.String', '[Ljava.lang.String;',
            '[Ljava.lang.String;', 'boolean').implementation = function() {
            console.log('[Bypass] Apache AbstractVerifier');
        };
    } catch(e) {}

    // ── HostnameVerifier ──
    try {
        var HV = Java.use('javax.net.ssl.HttpsURLConnection');
        HV.setDefaultHostnameVerifier.implementation = function(v) {
            console.log('[Bypass] Ignoring custom HostnameVerifier');
        };
    } catch(e) {}

    console.log('[+] Android universal SSL bypass loaded');
});
2.2 Objection(一条命令)
objection -g com.target.app explore --startup-command "android sslpinning disable"
2.3 Network Security Config(调试覆盖)



<network-security-config>
  <base-config>
    <trust-anchors>
      <certificates src="system" />
      <certificates src="user" />     
    </trust-anchors>
  </base-config>
</network-security-config>

工作流:反编译 APK → 添加/修改配置 → 重新打包 → 重新签名 → 安装。

apktool d target.apk -o target_dir
# Edit res/xml/network_security_config.xml
# Add reference in AndroidManifest.xml if missing
apktool b target_dir -o target_patched.apk
zipalign -v 4 target_patched.apk target_aligned.apk
apksigner sign --ks my-key.keystore target_aligned.apk
adb install target_aligned.apk
2.4 Xposed / LSPosed 模块
模块方法范围是否需要 Root
JustTrustMeHook TrustManager + OkHttp单个应用是(Xposed)
SSLUnpinningHook 证书验证单个应用是(LSPosed)
TrustMeAlready全局 TrustManager 绕过系统范围是(LSPosed)
2.5 Magisk + 系统 CA 安装
# Install proxy CA as system cert (Android 7+ requires this for system-level trust)
# Method 1: MagiskTrustUserCerts module
# Moves user CAs to /system/etc/security/cacerts/ via Magisk overlay

# Method 2: Manual (requires root)
adb push burp_ca.pem /sdcard/
adb shell
su
mount -o remount,rw /system
cp /sdcard/burp_ca.pem /system/etc/security/cacerts/9a5ba575.0  # hash-named
chmod 644 /system/etc/security/cacerts/9a5ba575.0
mount -o remount,ro /system

# Get correct hash filename:
openssl x509 -inform PEM -subject_hash_old -in burp_ca.pem | head -1
# Output: 9a5ba575 → filename is 9a5ba575.0
2.6 手动反编译 → 修补 → 重新打包
# Step 1: Decompile
jadx -d decompiled/ target.apk

# Step 2: Find pinning code
grep -r "CertificatePinner\|X509TrustManager\|checkServerTrusted\|ssl" decompiled/

# Step 3: Identify pinning implementation and patch
# Use smali editing for precise control:
apktool d target.apk
# Edit smali files to NOP out pinning checks
# Look for invoke-virtual {checkServerTrusted} and replace with return-void

# Step 4: Repackage and sign
apktool b target_dir -o patched.apk
apksigner sign --ks debug.keystore patched.apk

3. IOS 绕过方法

3.1 Frida(SecTrust Hooks)
// Hook core iOS SSL validation functions
var SecTrustEvaluateWithError = Module.findExportByName('Security', 'SecTrustEvaluateWithError');
Interceptor.attach(SecTrustEvaluateWithError, {
    onLeave: function(retval) {
        retval.replace(ptr(1));
    }
});

var SecTrustEvaluate = Module.findExportByName('Security', 'SecTrustEvaluate');
Interceptor.attach(SecTrustEvaluate, {
    onLeave: function(retval) {
        retval.replace(ptr(0));
    }
});

// Hook SSLHandshake (lower-level)
var SSLHandshake = Module.findExportByName('Security', 'SSLHandshake');
if (SSLHandshake) {
    Interceptor.attach(SSLHandshake, {
        onLeave: function(retval) {
            if (retval.toInt32() === -9807) { // errSSLXCertChainInvalid
                retval.replace(ptr(0));
            }
        }
    });
}

// Hook NSURLSession delegate method
try {
    var cls = ObjC.classes.NSURLSession;
    // Hook URLSession:didReceiveChallenge:completionHandler: on delegates
    ObjC.enumerateLoadedClasses({
        onMatch: function(name) {
            try {
                var methods = ObjC.classes[name].$ownMethods;
                for (var i = 0; i < methods.length; i++) {
                    if (methods[i].indexOf('didReceiveChallenge') !== -1 &&
                        methods[i].indexOf('completionHandler') !== -1) {
                        console.log('[SSL] Found delegate: ' + name + ' ' + methods[i]);
                    }
                }
            } catch(e) {}
        },
        onComplete: function() {}
    });
} catch(e) {}
3.2 Objection(一条命令)
objection -g com.target.app explore --startup-command "ios sslpinning disable"
3.3 SSL Kill Switch 2(越狱插件)
# Install via Cydia/Sileo
# Package: com.nablac0d3.sslkillswitch2
# Disables SSL pinning system-wide or per-app via Settings toggle

# Hooks:
# - SecTrustEvaluate
# - SSLHandshake
# - SSLSetSessionOption
# - tls_helper_create_peer_trust
3.4 特定库的 Hook
库iOS Hook 点Frida 方法
AFNetworkingAFSecurityPolicy.evaluateServerTrust:forDomain:返回 YES
AlamofireServerTrustManager.evaluate(_:forHost:)跳过评估
TrustKitTSKPinningValidator verifyPublicKeyPin:返回成功
NSURLSessionURLSession:didReceiveChallenge:completionHandler:使用 .useCredential 调用 completionHandler
3.5 手动二进制修补
# Find pinning function in binary
strings decrypted_binary | grep -i "pin\|cert\|trust"
# Disassemble and find the validation function
# Replace comparison/branch instruction with NOP or unconditional pass

# LLDB runtime modification
lldb -n TargetApp
(lldb) breakpoint set -n "SecTrustEvaluateWithError"
(lldb) breakpoint command add 1
> thread return 1
> continue
> DONE

4. 特定框架的绕过方法

4.1 Flutter

Flutter 使用 Dart 的 dart:io 库,底层依赖 BoringSSL。在 Java/ObjC 层使用标准 Frida Hook 不起作用。

// Flutter SSL bypass — must hook BoringSSL directly
// Find ssl_crypto_x509_session_verify_cert_chain in libflutter.so
var libflutter = Process.findModuleByName('libflutter.so');  // Android
// var libflutter = Process.findModuleByName('Flutter');       // iOS

// Hook ssl_verify_peer_cert (BoringSSL function)
// Signature varies by Flutter version — use pattern scanning
var pattern = 'FF C3 ..';  // Example pattern, varies
var matches = Memory.scan(libflutter.base, libflutter.size, pattern, {
    onMatch: function(address, size) {
        console.log('[Flutter] Potential verify function at: ' + address);
        Interceptor.attach(address, {
            onLeave: function(retval) {
                retval.replace(ptr(0));  // SSL_VERIFY_OK
            }
        });
    },
    onComplete: function() {}
});

// Alternative: use reflutter tool for automated patching
// reflutter target.apk
// This patches BoringSSL in the Flutter engine directly

reflutter 工具(推荐用于 Flutter 应用):

pip install reflutter
reflutter target.apk
# Outputs patched APK that redirects traffic to your proxy
# Also disables SSL verification in the BoringSSL engine
4.2 React Native

React Native 使用平台网络栈:Android 上使用 OkHttp,iOS 上使用 NSURLSession。

平台网络栈绕过方法
AndroidOkHttp3标准 OkHttp CertificatePinner Hook
iOSNSURLSession标准 SecTrust Hooks
Android(Hermes)同样使用 OkHttp使用相同的 Hooks,但 Hermes JIT 可能需要额外处理
// React Native Android — same as OkHttp bypass
Java.perform(function() {
    try {
        var CP = Java.use('okhttp3.CertificatePinner');
        CP.check.overload('java.lang.String', 'java.util.List').implementation = function() {};
    } catch(e) { console.log('OkHttp3 not found, trying okhttp2...'); }

    try {
        var CP2 = Java.use('com.squareup.okhttp.CertificatePinner');
        CP2.check.overload('java.lang.String', 'java.util.List').implementation = function() {};
    } catch(e) {}
});
4.3 Xamarin
// Xamarin pinning typically via:
// ServicePointManager.ServerCertificateValidationCallback
// or custom HttpClientHandler
// Frida bypass for Xamarin (Mono runtime)
// Hook Mono method: System.Net.ServicePointManager.set_ServerCertificateValidationCallback
var mono_method = Module.findExportByName('libmonosgen-2.0.so',
    'mono_runtime_invoke');
// More practical: hook the managed callback at CIL level
// Use Frida's Mono bridge or objection's built-in Xamarin support

// Objection has built-in Xamarin bypass:
// objection -g com.target.app explore
// > android sslpinning disable   (covers Xamarin on Android)

5. 证书透明度与 HPKP

技术状态对测试的影响
证书透明度(CT)正在使用,由浏览器强制执行移动应用很少强制执行 CT;这不会成为绕过障碍
HPKP(HTTP 公钥 Pinning)已弃用(2018)旧版应用可能仍会检查;从代理响应中移除该标头
Expect-CT 标头已弃用(2024)对移动端测试影响极小
移动应用中的 CT少见只有 Google 应用会通过自定义 CT 检查来强制执行

6. 故障排查

6.1 常见故障
症状原因解决方法
已加载绕过脚本,但流量仍然失败存在多个固定层Hook 所有层:TrustManager + OkHttp + 自定义检查
“需要客户端证书”双向 TLS(mTLS)从应用包/钥匙串中提取客户端证书,并导入代理
连接正常,但没有 HTTP 流量使用了非 HTTP 协议(MQTT、gRPC、WebSocket)使用 Wireshark 或特定协议代理
绕过后应用崩溃防篡改机制检测到了 Hook先绕过完整性检查,再绕过 SSL
不信任代理 CAAndroid 7+ 对用户 CA 的限制将 CA 作为系统证书安装(Magisk 模块)
Flutter 应用忽略 HookNative 层未 Hook BoringSSL使用 reflutter 或 Native BoringSSL Hook
证书链验证超时OCSP stapling 不匹配禁用 OCSP 检查或模拟 OCSP 响应器
6.2 诊断步骤
# Verify proxy CA is installed correctly
# Android:
adb shell "ls /system/etc/security/cacerts/ | grep $(openssl x509 -subject_hash_old -in ca.pem | head -1)"

# iOS: Settings → General → About → Certificate Trust Settings

# Check if target app is actually using SSL (vs. plain HTTP)
# Wireshark filter: tcp.port == 443 and ip.addr == <device_ip>

# Check if Frida is hooking the right process
frida-ps -U | grep target

# Verbose Frida output for debugging hooks
frida -U -f com.target.app -l bypass.js --debug

7. SSL 固定绕过决策树

Need to intercept mobile app HTTPS traffic
│
├── Platform?
│   ├── Android ↓
│   │   ├── Rooted device available?
│   │   │   ├── Yes → Frida universal bypass (§2.1) [FIRST TRY]
│   │   │   │   ├── Works? → done
│   │   │   │   └── Fails? → add Conscrypt + Volley hooks
│   │   │   ├── Still fails? → LSPosed + TrustMeAlready (§2.4)
│   │   │   └── Still fails? → install CA as system cert (§2.5)
│   │   └── No root?
│   │       ├── Debug build? → Network Security Config (§2.3)
│   │       └── Release build? → decompile + patch + repackage (§2.6)
│   │
│   └── iOS ↓
│       ├── Jailbroken device available?
│       │   ├── Yes → Objection ios sslpinning disable (§3.2) [FIRST TRY]
│       │   │   ├── Works? → done
│       │   │   └── Fails? → Frida SecTrust hooks (§3.1)
│       │   ├── Still fails? → SSL Kill Switch 2 (§3.3)
│       │   └── Still fails? → library-specific hooks (§3.4)
│       └── No jailbreak?
│           ├── Re-sign with Frida gadget → run Frida hooks
│           └── Binary patch → sideload (§3.5)
│
├── Framework-specific app?
│   ├── Flutter → reflutter tool or BoringSSL native hooks (§4.1)
│   ├── React Native → standard platform hooks (§4.2)
│   └── Xamarin → Objection or Mono runtime hooks (§4.3)
│
├── Bypass works but issues remain?
│   ├── Client cert required? → extract + import to proxy (§6.1)
│   ├── Non-HTTP protocol? → protocol-specific tooling (§6.1)
│   └── App crashes? → fix anti-tampering first (§6.1)
│
└── All methods fail?
    ├── Analyze traffic at network level (Wireshark/tcpdump)
    ├── Check for custom proprietary protocol
    └── Consider iptables + transparent proxy approach

8. 代理设置速查表

代理工具适用场景SSL 绕过集成方式
Burp Suite全面的 HTTP 分析将 CA 导入设备
mitmproxy脚本化拦截mitmproxy --set confdir=~/.mitmproxy
Charles Proxy原生支持 macOS,易于设置内置 CA 安装
Proxyman原生支持 macOS/iOS直接支持 iOS 设备
HTTP Toolkit快速设置 Android自动配置 CA + Frida 绕过
# Android proxy setup
adb shell settings put global http_proxy <host_ip>:8080

# Remove proxy
adb shell settings put global http_proxy :0

# iOS proxy: Settings → Wi-Fi → Configure Proxy → Manual

评论

支持 Markdown