Android 7 开始系统有了一个非常安全(讨厌)的限制,所有应用默认情况下不再信任用户自行安装的证书,而仅信任系统预装的。因此,即便我们安装证书后也无法愉快地抓包了:confused:

但是这一限制仅对 targetSdkVersion>=24 的应用生效。

下面提供几种方案绕过这一限制。

添加证书信任

本方案需要修改 AndroidManifest,推荐用于自己的应用,其他应用需要重新打包了。

首先在 res/xml 中创建一个网络安全配置文件,信任用户证书:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <certificates src="system" />
            <certificates src="user" /> <!--信任用户添加的证书-->
        </trust-anchors>
    </base-config>
</network-security-config>

然后在 Manifestapplication 节点新增一个 android:networkSecurityConfig 属性指向刚才创建的配置文件即可:

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    <application 
        android:networkSecurityConfig="@xml/network_security_config">
    </application>
</manifest>

使用子系统

此方案本质上是降低系统的版本,例如 平行空间 等双开应用,会创建一个独立的运行环境,相当于子系统。这个环境内的系统版本不一定与手机系统相同。目前,平行空间 4.0.8625 版本以下系统 API < 24,应该可以正常使用。

同理,你也可以使用模拟器抓包,或者干脆找一个旧系统的手机。

修改系统证书

此方案需要 ROOT.

既然默认只信任系统证书,那我们何不直接把自己的证书导入为系统级别?

注意,Android 系统证书使用的是 .0 格式,不同于常见的 .cer/pem,需要使用 openssl 命令行工具转换下。

确定文件名

.cer 格式证书执行:

openssl x509 -inform DER -subject_hash_old -in xxx.cer

.pem 格式证书执行:

openssl x509 -inform PEM -subject_hash_old -in xxx.pem

输出的一个行8位字符串就是文件名,例如 269953fb 则最终文件名应该是 269953fb.0.

转换格式

同样,CER 与 PEM 请分别执行下面两个命令:
注意替换证书文件名与目标文件名。

CER: openssl x509 -inform DER -text -in xxx.cer > 269953fb.0
PEM: openssl x509 -inform PEM -text -in xxx.pem > 4bb9877f.0

最后编辑一下输出的文件,把 -----BEGIN CERTIFICATE----- 到最后的这部分移动到开头。

安装证书

  • 导入到手机 sd 卡:adb push e:/269953fb.0 /sdcard
  • 复制到系统证书目录:

    adb shell
    su
    mount -o remount,rw /system
    cp /sdcard/269953fb.0 /system/etc/security/cacerts/
  • 修改文件权限:

    cd /system/etc/security/cacerts/
    chmod 644 269953fb.0
  • 重启设备

其他问题

对于应用固定证书、双向加密等问题,参考这篇更全面的教程

Last modification:November 27, 2019