Android端Charles Proxy SSL抓包异常:浏览器正常App报信任错误
解决Android App HTTPS请求SSL信任错误的方案
这种情况我碰到过好多次,核心原因就是Android App的证书信任逻辑和浏览器不一样——浏览器会认可用户手动安装的证书,但很多App要么只认系统级证书,要么自己做了自定义校验。下面给你几个靠谱的解决办法:
1. 把Charles根证书安装到系统证书目录(最通用的方案)
绝大多数正规App都会优先信任系统级别的证书,而我们手动安装的证书属于用户证书,不在它们的信任列表里。所以得把Charles的证书移到系统证书目录,步骤如下:
- 先导出Charles根证书:打开Charles,顶部菜单点
Help→SSL Proxying→Save Charles Root Certificate,保存成.pem格式。 - 给证书重命名:需要用证书的哈希值加
.0作为文件名。你可以用openssl命令计算哈希:
比如算出哈希是openssl x509 -subject_hash_old -in charles.pem | head -1a1b2c3d4,就把证书改成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,然后运行命令:
替换成你要抓包的App包名就行。frida -U -f com.your.app.package.name -l bypass-ssl.js --no-pause - 用Xposed模块一键解决:如果不想写脚本,安装
JustTrustMe模块(Xposed或EdXposed都支持),启用后它会自动禁用大部分App的证书校验逻辑,非常省心。
3. 确认Charles的SSL代理配置没遗漏
别忘检查Charles有没有开启对应App域名的SSL代理:
- 打开Charles →
Proxy→SSL 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.xml的application标签里添加:
重新打包安装后,App就会信任你手动安装的Charles证书了。android:networkSecurityConfig="@xml/network_security_config"
内容的提问来源于stack exchange,提问作者Rajan M




