You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android端Charles Proxy SSL抓包异常:浏览器正常App报信任错误

解决Android App HTTPS请求SSL信任错误的方案

这种情况我碰到过好多次,核心原因就是Android App的证书信任逻辑和浏览器不一样——浏览器会认可用户手动安装的证书,但很多App要么只认系统级证书,要么自己做了自定义校验。下面给你几个靠谱的解决办法:

1. 把Charles根证书安装到系统证书目录(最通用的方案)

绝大多数正规App都会优先信任系统级别的证书,而我们手动安装的证书属于用户证书,不在它们的信任列表里。所以得把Charles的证书移到系统证书目录,步骤如下:

  • 先导出Charles根证书:打开Charles,顶部菜单点HelpSSL ProxyingSave Charles Root Certificate,保存成.pem格式。
  • 给证书重命名:需要用证书的哈希值加.0作为文件名。你可以用openssl命令计算哈希:
    openssl x509 -subject_hash_old -in charles.pem | head -1
    
    比如算出哈希是a1b2c3d4,就把证书改成a1b2c3d4.0
  • 把证书推到设备的系统证书目录(前提是设备已经root):
    adb push a1b2c3d4.0 /sdcard/
    adb shell
    su
    # 重新挂载系统分区为可写
    mount -o remount,rw /system
    cp /sdcard/a1b2c3d4.0 /system/etc/security/cacerts/
    # 设置正确的权限,不然系统不认
    chmod 644 /system/etc/security/cacerts/a1b2c3d4.0
    # 恢复系统分区为只读
    mount -o remount,ro /system
    
  • 重启设备后,App应该就能信任Charles的证书了。

2. 绕过App的自定义证书校验

有些App会自己实现证书校验逻辑,完全忽略系统证书,这时候就得用工具绕过:

  • 用Frida快速绕过:写个简单的脚本就能禁用证书校验,比如这个通用脚本:
    Java.perform(function () {
        // Hook SSLContext的init方法,替换成信任所有证书的TrustManager
        var SSLContext = Java.use("javax.net.ssl.SSLContext");
        SSLContext.init.overload('[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom').implementation = function (keyManagers, trustManagers, secureRandom) {
            var trustAllCerts = [Java.use("javax.net.ssl.X509TrustManager").$new({
                checkClientTrusted: function () {},
                checkServerTrusted: function () {},
                getAcceptedIssuers: function () { return []; }
            })];
            this.init(keyManagers, trustAllCerts, secureRandom);
        };
    });
    
    保存成bypass-ssl.js,然后运行命令:
    frida -U -f com.your.app.package.name -l bypass-ssl.js --no-pause
    
    替换成你要抓包的App包名就行。
  • 用Xposed模块一键解决:如果不想写脚本,安装JustTrustMe模块(Xposed或EdXposed都支持),启用后它会自动禁用大部分App的证书校验逻辑,非常省心。

3. 确认Charles的SSL代理配置没遗漏

别忘检查Charles有没有开启对应App域名的SSL代理:

  • 打开Charles → ProxySSL Proxying Settings → 点击Add,输入App请求的域名(比如*.your-app-domain.com)和端口443,确保Enable SSL Proxying是勾选状态。

4. 修改App的网络安全配置(适合有源码/可反编译的情况)

Android 7.0之后,默认App只信任系统证书,如果能拿到App的源码或者可以反编译修改,可以调整它的网络安全配置:

  • res/xml目录下创建network_security_config.xml,内容如下:
    <network-security-config>
        <base-config>
            <trust-anchors>
                <!-- 同时信任系统和用户证书 -->
                <certificates src="system" />
                <certificates src="user" />
            </trust-anchors>
        </base-config>
    </network-security-config>
    
  • 然后在AndroidManifest.xmlapplication标签里添加:
    android:networkSecurityConfig="@xml/network_security_config"
    
    重新打包安装后,App就会信任你手动安装的Charles证书了。

内容的提问来源于stack exchange,提问作者Rajan M

火山引擎 最新活动