mobile-ssl-pinning-bypass

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: Mobile SSL Pinning Bypass — Expert Attack Playbook

SKILL: 移动端SSL固定绕过 —— 专家攻击手册

AI LOAD INSTRUCTION: Expert SSL pinning bypass techniques for mobile platforms. Covers Android and iOS bypass methods (Frida, Objection, Xposed, SSL Kill Switch), framework-specific bypasses (Flutter, React Native, Xamarin), and troubleshooting non-standard pinning implementations. Base models miss framework-specific hook points and multi-layer pinning configurations.
AI加载说明:适用于移动平台的专业SSL固定绕过技术,涵盖Android和iOS绕过方法(Frida、Objection、Xposed、SSL Kill Switch)、框架专属绕过方案(Flutter、React Native、Xamarin),以及非标准固定实现的故障排查。基础模型缺少框架专属hook点和多层固定配置的相关知识。

0. RELATED ROUTING

0. 相关关联技能

Before going deep, consider loading:
  • android-pentesting-tricks for broader Android testing beyond SSL bypass
  • ios-pentesting-tricks for broader iOS testing beyond SSL bypass
  • api-sec once traffic is intercepted for API-level testing

深入学习前,可考虑加载以下内容:
  • android-pentesting-tricks 了解除SSL绕过之外的更全面Android测试技巧
  • ios-pentesting-tricks 了解除SSL绕过之外的更全面iOS测试技巧
  • api-sec 流量拦截完成后用于API层面的测试

1. SSL PINNING TYPES

1. SSL固定类型

Pinning TypeWhat Is PinnedResilienceCommon In
Certificate pinningExact leaf certificate (DER/PEM)Low (breaks on cert rotation)Legacy apps
Public key pinningSubject Public Key InfoMedium (survives cert renewal if key unchanged)Modern apps
SPKI hash pinningSHA-256 of SPKIMedium (same as public key)OkHttp, AFNetworking
CA pinningIntermediate or root CA certHigh (any cert from that CA works)Enterprise apps
Multi-pin (backup pins)Primary + backup pinsHigh (fallback pins)HPKP-aware apps
固定类型固定内容抗破解能力常见使用场景
证书固定精确的叶子证书(DER/PEM格式)低(证书轮转时会失效)老旧应用
公钥固定主体公钥信息(SPKI)中等(密钥不变的情况下证书续期不受影响)现代应用
SPKI哈希固定SPKI的SHA-256哈希值中等(和公钥固定效果一致)OkHttp、AFNetworking
CA固定中间证书或根CA证书高(该CA签发的任意证书都可生效)企业级应用
多固定(备份固定)主固定+备份固定高(支持 fallback 到备份固定值)支持HPKP的应用

How Pinning Works

固定机制工作原理

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

TLS 握手
├── 服务端返回证书链
├── 标准校验(系统信任存储)
│   └── 校验通过?继续流程 : 连接失败
└── 固定值校验(应用层检查)
    ├── 提取服务端证书/公钥/SPKI哈希
    ├── 和应用内置的固定值对比
    └── 匹配成功?→ 允许连接 : → 拒绝连接

2. ANDROID BYPASS METHODS

2. Android 绕过方法

2.1 Frida Universal SSL Bypass

2.1 Frida通用SSL绕过脚本

javascript
// 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');
});
javascript
// Hooks TrustManager, OkHttp, Volley, Retrofit, Conscrypt
Java.perform(function() {

    // ── TrustManagerImpl (Android系统) ──
    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 (自定义实现) ──
    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 (One Command)

2.2 Objection(单命令执行)

bash
objection -g com.target.app explore --startup-command "android sslpinning disable"
bash
objection -g com.target.app explore --startup-command "android sslpinning disable"

2.3 Network Security Config (Debug Override)

2.3 网络安全配置(调试模式覆盖)

xml
<!-- AndroidManifest.xml: android:networkSecurityConfig="@xml/network_security_config" -->

<!-- res/xml/network_security_config.xml -->
<network-security-config>
  <base-config>
    <trust-anchors>
      <certificates src="system" />
      <certificates src="user" />     <!-- Trust user-installed CAs -->
    </trust-anchors>
  </base-config>
</network-security-config>
Workflow: decompile APK → add/modify config → repackage → re-sign → install.
bash
apktool d target.apk -o target_dir
xml
<!-- AndroidManifest.xml: android:networkSecurityConfig="@xml/network_security_config" -->

<!-- res/xml/network_security_config.xml -->
<network-security-config>
  <base-config>
    <trust-anchors>
      <certificates src="system" />
      <certificates src="user" />     <!-- 信任用户安装的CA -->
    </trust-anchors>
  </base-config>
</network-security-config>
工作流程:反编译APK → 添加/修改配置 → 重新打包 → 重签名 → 安装。
bash
apktool d target.apk -o target_dir

Edit res/xml/network_security_config.xml

Edit res/xml/network_security_config.xml

Add reference in AndroidManifest.xml if missing

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
undefined
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
undefined

2.4 Xposed / LSPosed Modules

2.4 Xposed / LSPosed 模块

ModuleMethodScopeRoot Required
JustTrustMeHooks TrustManager + OkHttpPer-appYes (Xposed)
SSLUnpinningHooks certificate validationPer-appYes (LSPosed)
TrustMeAlreadyGlobal TrustManager bypassSystem-wideYes (LSPosed)
模块实现方法生效范围需要Root
JustTrustMe钩子拦截TrustManager + OkHttp单应用是(Xposed)
SSLUnpinning钩子拦截证书校验单应用是(LSPosed)
TrustMeAlready全局TrustManager绕过全系统是(LSPosed)

2.5 Magisk + System CA Installation

2.5 Magisk + 系统CA安装

bash
undefined
bash
undefined

Install proxy CA as system cert (Android 7+ requires this for system-level trust)

将代理CA安装为系统证书(Android 7+需要此操作才能获得系统级信任)

Method 1: MagiskTrustUserCerts module

方法1: MagiskTrustUserCerts 模块

Moves user CAs to /system/etc/security/cacerts/ via Magisk overlay

通过Magisk overlay将用户CA移动到 /system/etc/security/cacerts/

Method 2: Manual (requires root)

方法2: 手动安装(需要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
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 # 哈希命名 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
openssl x509 -inform PEM -subject_hash_old -in burp_ca.pem | head -1

Output: 9a5ba575 → filename is 9a5ba575.0

Output: 9a5ba575 → 文件名为 9a5ba575.0

undefined
undefined

2.6 Manual Decompile → Patch → Repackage

2.6 手动反编译 → 补丁 → 重打包

bash
undefined
bash
undefined

Step 1: Decompile

步骤1: 反编译

jadx -d decompiled/ target.apk
jadx -d decompiled/ target.apk

Step 2: Find pinning code

步骤2: 查找固定代码

grep -r "CertificatePinner|X509TrustManager|checkServerTrusted|ssl" decompiled/
grep -r "CertificatePinner|X509TrustManager|checkServerTrusted|ssl" decompiled/

Step 3: Identify pinning implementation and patch

步骤3: 识别固定实现并打补丁

Use smali editing for precise control:

使用smali编辑实现精确控制:

apktool d target.apk
apktool d target.apk

Edit smali files to NOP out pinning checks

编辑smali文件,用NOP指令跳过固定检查

Look for invoke-virtual {checkServerTrusted} and replace with return-void

查找 invoke-virtual {checkServerTrusted} 并替换为 return-void

Step 4: Repackage and sign

步骤4: 重打包并签名

apktool b target_dir -o patched.apk apksigner sign --ks debug.keystore patched.apk

---
apktool b target_dir -o patched.apk apksigner sign --ks debug.keystore patched.apk

---

3. iOS BYPASS METHODS

3. iOS 绕过方法

3.1 Frida (SecTrust Hooks)

3.1 Frida(SecTrust钩子)

javascript
// 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) {}
javascript
// 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 (One Command)

3.2 Objection(单命令执行)

bash
objection -g com.target.app explore --startup-command "ios sslpinning disable"
bash
objection -g com.target.app explore --startup-command "ios sslpinning disable"

3.3 SSL Kill Switch 2 (Jailbreak Tweak)

3.3 SSL Kill Switch 2(越狱插件)

bash
undefined
bash
undefined

Install via Cydia/Sileo

通过Cydia/Sileo安装

Package: com.nablac0d3.sslkillswitch2

包名: com.nablac0d3.sslkillswitch2

Disables SSL pinning system-wide or per-app via Settings toggle

通过设置开关实现系统级或单应用的SSL固定禁用

Hooks:

钩子对象:

- SecTrustEvaluate

- SecTrustEvaluate

- SSLHandshake

- SSLHandshake

- SSLSetSessionOption

- SSLSetSessionOption

- tls_helper_create_peer_trust

- tls_helper_create_peer_trust

undefined
undefined

3.4 Library-Specific Hooks

3.4 专属库钩子

LibraryiOS Hook PointFrida Approach
AFNetworking
AFSecurityPolicy.evaluateServerTrust:forDomain:
Return YES
Alamofire
ServerTrustManager.evaluate(_:forHost:)
Skip evaluation
TrustKit
TSKPinningValidator verifyPublicKeyPin:
Return success
NSURLSession
URLSession:didReceiveChallenge:completionHandler:
Call completionHandler with .useCredential
iOS钩子点Frida实现方案
AFNetworking
AFSecurityPolicy.evaluateServerTrust:forDomain:
返回YES
Alamofire
ServerTrustManager.evaluate(_:forHost:)
跳过校验
TrustKit
TSKPinningValidator verifyPublicKeyPin:
返回成功
NSURLSession
URLSession:didReceiveChallenge:completionHandler:
传入.useCredential调用completionHandler

3.5 Manual Binary Patch

3.5 手动二进制补丁

bash
undefined
bash
undefined

Find pinning function in binary

在二进制文件中查找固定函数

strings decrypted_binary | grep -i "pin|cert|trust"
strings decrypted_binary | grep -i "pin|cert|trust"

Disassemble and find the validation function

反汇编找到校验函数

Replace comparison/branch instruction with NOP or unconditional pass

将比较/分支指令替换为NOP或无条件通过指令

LLDB runtime modification

LLDB运行时修改

lldb -n TargetApp (lldb) breakpoint set -n "SecTrustEvaluateWithError" (lldb) breakpoint command add 1
thread return 1 continue DONE

---
lldb -n TargetApp (lldb) breakpoint set -n "SecTrustEvaluateWithError" (lldb) breakpoint command add 1
thread return 1 continue DONE

---

4. FRAMEWORK-SPECIFIC BYPASSES

4. 框架专属绕过方案

4.1 Flutter

4.1 Flutter

Flutter uses Dart's
dart:io
library with BoringSSL underneath. Standard Frida hooks on Java/ObjC layers don't work.
javascript
// 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 tool (recommended for Flutter apps):
bash
pip install reflutter
reflutter target.apk
Flutter使用Dart的
dart:io
库,底层基于BoringSSL,Java/ObjC层的标准Frida钩子无效。
javascript
// Flutter SSL绕过 —— 必须直接钩子BoringSSL
// 在libflutter.so中查找ssl_crypto_x509_session_verify_cert_chain
var libflutter = Process.findModuleByName('libflutter.so');  // Android
// var libflutter = Process.findModuleByName('Flutter');       // iOS

// Hook ssl_verify_peer_cert (BoringSSL函数)
// 签名随Flutter版本变化 —— 使用模式匹配查找
var pattern = 'FF C3 ..';  // 示例模式,不同版本有差异
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() {}
});

// 替代方案: 使用reflutter工具自动打补丁
// reflutter target.apk
// 直接补丁Flutter引擎中的BoringSSL
reflutter工具(Flutter应用推荐使用):
bash
pip install reflutter
reflutter target.apk

Outputs patched APK that redirects traffic to your proxy

输出补丁后的APK,会将流量重定向到你的代理

Also disables SSL verification in the BoringSSL engine

同时禁用BoringSSL引擎中的SSL校验

undefined
undefined

4.2 React Native

4.2 React Native

React Native uses platform networking: OkHttp on Android, NSURLSession on iOS.
PlatformNetworking StackBypass Method
AndroidOkHttp3Standard OkHttp CertificatePinner hook
iOSNSURLSessionStandard SecTrust hooks
Android (Hermes)Same OkHttpSame hooks, but Hermes JIT may need additional handling
javascript
// 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) {}
});
React Native使用平台原生网络栈:Android用OkHttp,iOS用NSURLSession。
平台网络栈绕过方法
AndroidOkHttp3标准OkHttp CertificatePinner钩子
iOSNSURLSession标准SecTrust钩子
Android (Hermes)同OkHttp相同钩子,但Hermes JIT可能需要额外处理
javascript
// React Native Android —— 和OkHttp绕过逻辑一致
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

4.3 Xamarin

csharp
// Xamarin pinning typically via:
// ServicePointManager.ServerCertificateValidationCallback
// or custom HttpClientHandler
javascript
// 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)

csharp
// Xamarin固定通常通过以下方式实现:
// ServicePointManager.ServerCertificateValidationCallback
// 或自定义HttpClientHandler
javascript
// Xamarin的Frida绕过(Mono runtime)
// Hook Mono方法: System.Net.ServicePointManager.set_ServerCertificateValidationCallback
var mono_method = Module.findExportByName('libmonosgen-2.0.so',
    'mono_runtime_invoke');
// 更实用的方案: 在CIL层面钩子托管回调
// 使用Frida的Mono桥接或objection内置的Xamarin支持

// Objection内置Xamarin绕过:
// objection -g com.target.app explore
// > android sslpinning disable   (覆盖Android端Xamarin场景)

5. CERTIFICATE TRANSPARENCY & HPKP

5. 证书透明度与HPKP

TechnologyStatusImpact on Testing
Certificate Transparency (CT)Active, enforced by browsersMobile apps rarely enforce CT; not a bypass obstacle
HPKP (HTTP Public Key Pinning)Deprecated (2018)Legacy apps may still check; remove header from proxy response
Expect-CT headerDeprecated (2024)Minimal impact on mobile testing
CT in mobile appsRareOnly Google apps enforce via custom CT checks

技术状态对测试的影响
证书透明度(CT)活跃,浏览器强制要求移动应用很少强制CT校验,不会成为绕过障碍
HPKP(HTTP公钥固定)已废弃(2018年)老旧应用可能仍有校验,从代理响应中移除对应头即可
Expect-CT头已废弃(2024年)对移动测试影响极小
移动应用中的CT罕见只有Google系应用通过自定义CT检查强制要求

6. TROUBLESHOOTING

6. 故障排查

6.1 Common Failures

6.1 常见失败场景

SymptomCauseFix
Bypass script loaded but traffic still failsMultiple pinning layersHook ALL layers: TrustManager + OkHttp + custom checks
"Client certificate required"Mutual TLS (mTLS)Extract client cert from app bundle/keychain, import into proxy
Connection works but no HTTP trafficNon-HTTP protocol (MQTT, gRPC, WebSocket)Use Wireshark or protocol-specific proxy
App crashes after bypassAnti-tampering detects hooksBypass integrity checks first, then SSL
Proxy CA not trustedAndroid 7+ user CA restrictionsInstall CA as system cert (Magisk module)
Flutter app ignores hooksBoringSSL not hooked at native layerUse reflutter or native BoringSSL hooks
Certificate chain validation timeoutOCSP stapling mismatchDisable OCSP checks or mock OCSP responder
现象原因修复方案
绕过脚本加载成功但流量仍失败多层固定校验钩子覆盖所有层:TrustManager + OkHttp + 自定义校验
提示「需要客户端证书」双向TLS(mTLS)从应用包/钥匙串中提取客户端证书,导入到代理中
连接成功但没有HTTP流量非HTTP协议(MQTT、gRPC、WebSocket)使用Wireshark或对应协议的专属代理
绕过完成后应用崩溃反篡改检测识别到钩子先绕过完整性校验,再处理SSL绕过
代理CA不被信任Android 7+用户CA权限限制将CA安装为系统证书(Magisk模块)
Flutter应用忽略钩子没有在原生层钩子BoringSSL使用reflutter或原生BoringSSL钩子
证书链校验超时OCSP stapling不匹配禁用OCSP检查或模拟OCSP响应器

6.2 Diagnostic Steps

6.2 诊断步骤

bash
undefined
bash
undefined

Verify proxy CA is installed correctly

验证代理CA安装正确

Android:

Android:

adb shell "ls /system/etc/security/cacerts/ | grep $(openssl x509 -subject_hash_old -in ca.pem | head -1)"
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

iOS: 设置 → 通用 → 关于本机 → 证书信任设置

Check if target app is actually using SSL (vs. plain HTTP)

检查目标应用是否实际使用SSL(而非明文HTTP)

Wireshark filter: tcp.port == 443 and ip.addr == <device_ip>

Wireshark过滤规则: tcp.port == 443 and ip.addr == <设备IP>

Check if Frida is hooking the right process

检查Frida是否钩子到正确的进程

frida-ps -U | grep target
frida-ps -U | grep target

Verbose Frida output for debugging hooks

开启Frida详细输出调试钩子

frida -U -f com.target.app -l bypass.js --debug

---
frida -U -f com.target.app -l bypass.js --debug

---

7. SSL PINNING BYPASS DECISION TREE

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

需要拦截移动应用HTTPS流量
├── 平台?
│   ├── Android ↓
│   │   ├── 有Root设备可用?
│   │   │   ├── 是 → Frida通用绕过 (§2.1) [优先尝试]
│   │   │   │   ├── 生效? → 完成
│   │   │   │   └── 失败? → 添加Conscrypt + Volley钩子
│   │   │   ├── 仍失败? → LSPosed + TrustMeAlready (§2.4)
│   │   │   └── 仍失败? → 将CA安装为系统证书 (§2.5)
│   │   └── 无Root?
│   │       ├── 调试构建版本? → 网络安全配置修改 (§2.3)
│   │       └── 正式构建版本? → 反编译 + 补丁 + 重打包 (§2.6)
│   │
│   └── iOS ↓
│       ├── 有越狱设备可用?
│       │   ├── 是 → Objection ios sslpinning disable (§3.2) [优先尝试]
│       │   │   ├── 生效? → 完成
│       │   │   └── 失败? → Frida SecTrust钩子 (§3.1)
│       │   ├── 仍失败? → SSL Kill Switch 2 (§3.3)
│       │   └── 仍失败? → 专属库钩子 (§3.4)
│       └── 无越狱?
│           ├── 用Frida gadget重签名 → 运行Frida钩子
│           └── 二进制补丁 → 侧载安装 (§3.5)
├── 是框架专属应用?
│   ├── Flutter → reflutter工具或BoringSSL原生钩子 (§4.1)
│   ├── React Native → 标准平台钩子 (§4.2)
│   └── Xamarin → Objection或Mono runtime钩子 (§4.3)
├── 绕过后仍有问题?
│   ├── 需要客户端证书? → 提取 + 导入到代理 (§6.1)
│   ├── 非HTTP协议? → 对应协议专属工具 (§6.1)
│   └── 应用崩溃? → 先绕过反篡改校验 (§6.1)
└── 所有方法都失败?
    ├── 网络层面分析流量 (Wireshark/tcpdump)
    ├── 检查是否为自定义私有协议
    └── 考虑iptables + 透明代理方案

8. PROXY SETUP QUICK REFERENCE

8. 代理配置快速参考

Proxy ToolBest ForSSL Bypass Integration
Burp SuiteFull HTTP analysisImport CA to device
mitmproxyScripted interception
mitmproxy --set confdir=~/.mitmproxy
Charles ProxymacOS-native, easy setupBuilt-in CA installation
ProxymanmacOS/iOS nativeDirect iOS device support
HTTP ToolkitQuick Android setupAutomated CA + Frida bypass
bash
undefined
代理工具适用场景SSL绕过集成
Burp Suite全量HTTP分析导入CA到设备
mitmproxy脚本化拦截
mitmproxy --set confdir=~/.mitmproxy
Charles ProxymacOS原生,易上手内置CA安装功能
ProxymanmacOS/iOS原生直接支持iOS设备
HTTP ToolkitAndroid快速配置自动CA安装 + Frida绕过
bash
undefined

Android proxy setup

Android代理配置

adb shell settings put global http_proxy <host_ip>:8080
adb shell settings put global http_proxy <host_ip>:8080

Remove proxy

移除代理

adb shell settings put global http_proxy :0
adb shell settings put global http_proxy :0

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

iOS代理: 设置 → Wi-Fi → 配置代理 → 手动

undefined
undefined