修改Android源码,解放HTTPS抓包
⽂章⽬录
为什么HTTPS不能抓包了?
Google在Android 7.0以后的版本中,添加了“”的相关配置项。其旨在增强App的安全性,可以避免TargetSDK版本>=N的App内部⽹络请求在⾮测试环境下被恶意抓包。
Network Sercurity Configuration对安全性的保证,主要是通过以下⼏个途径:是否允许明⽂HTTP请求(⾮HTTPS)、HTTPS证书(区分系统、⽤户)信任设置、域名以及App的Debug或Release配置,只有符合Manifest中配置的NetworkConfig字段内容下的条件,才可以进⾏正常的HTTP请求,如果需要使⽤Charles、Fiddler等⼯具进⾏抓包,也需要利⽤NetworkConfig来配置可以信任的证书,否则HTTPS请求在CONNECT阶段,就会返回错误,同时LogCat会打印出类似以下的错误信息:
Caused by: CertificateException: xxx.
at nscrypt.TrustManagerImpl.verifyChain(TrustManagerImpl.java:661)
at nscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:539)
at nscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:605)
at nscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:495)
at nscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:321)
at fig.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:113)
at fig.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:87)
at fig.RootTrustManager.checkServerTrusted(RootTrustManager.java:116)
at com.huawei.secure.androidmon.ssl.SecureX509TrustManager.checkServerTrusted(:105)
at nscrypt.Platform.checkServerTrusted(Platform.java:212)
at nscrypt.ConscryptFileDescriptorSocket.verifyCertificateChain(ConscryptFileDescriptorSocket.java:404)
at nscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at nscrypt.NativeSsl.doHandshake(NativeSsl.java:375)
通常,Android开发者会将NetworkConfig按照以下XML⽂件进⾏配置:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 允许明⽂HTTP(⾮HTTPS)请求 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 其他情况只允许信任系统内置证书 -->
<certificates src="system"/>
</trust-anchors>
</base-config>
<!-- 仅Debug包允许⽤户证书 -->
<debug-overrides>
<trust-anchors>
<certificates src="user"/>
</trust-anchors>
</debug-overrides>
</network-security-config>
然⽽对于开发者来说,通常App发版上线会选择使⽤Release版本的安装包,如果希望对Release包抓包,只能使⽤Android 6.0及以下的⼿机,这样⼀来,有时候出现线上问题,便⽆法进⾏HTTPS抓包,并不利于测试和修正
如何解决这⼀问题?
基本的⼏个思路
反编译APK,修改NetworkConfig相关的XML⽂件,让App可以信任⽤户配置的证书
这个⽅案局限性⽐较⼤,现在很多App都对反编译技术(主要是apktool)进⾏了防御,有的App使⽤apktool解包以后,就⽆法成功打包了,还有的⽤上了加固技术,通⽤的反编译⼯具⽆法直接获取真正Apk内部的⽂件。不过,如果能够使⽤apktool成功获得解码后的XML⽂件,且进⾏修改后能够重新打包成可以运⾏的Apk,这样做也是可⾏的
使⽤Hook
使⽤Xposed框架在App请求过程中进⾏Hook,依赖的基础仍然是反编译,且Xposed框架需要建⽴在Root后的基础上,成功率⽐较低,且成本还⽐较⾼
修改Android源码
这个应该是最成功且⼀劳永逸的办法了,但成本不⼩,需要有⼀台性能不错的电脑(⾄少硬盘空间够⼤)和⼀台Google的⼿机,具体如何实现,下⾯详细来说
寻求⼀个适合⾃⼰的办法
这⾥并不是说修改源码就是最好的,举例来讲,能使⽤6.0⼿机,是最简单的办法,但随着现在最低SDK版本的提升,在不久的将来,⼀些App或许就不会再⽀持6.0了,所以我只是在寻⼀个更为靠谱的⽅案
如何改Android源码
准备⼯作
分析源码
AOSP的源码⾮常的庞⼤,如果是初次接触,可能会完全摸不着头脑,当然,我们也不可能完全把它的结构和内容摸索清楚再进⾏修改,学会⽤⽂本查很重要
这⾥安利VSCode,我们不需要使⽤Android Studio这样的⼯具,因为太慢!
⾸先去搜索⼀下NetworkSecurityConfig,就会发现有以下相关的⽂件
其中NetworkSucurityConfig.java和XmlConfigSource.java就和证书判断逻辑相关
仔细分析⼀波NetworkSucurityConfig类,可以发现这个类使⽤了Android中常见的Builder模式来进⾏创建,其中包括⼀个返回默认配置Builder的静态⽅法
public static final Builder getDefaultBuilder(ApplicationInfo info)
在Android 9以前,这个⽅法的参数为两个int型字段:int targetSdkVersion, int targetSandboxVesrsion
这⾥列出这个⽅法的详细代码
/**
* Return a {@link Builder} for the default {@code NetworkSecurityConfig}.
*
* <p>
* The default configuration has the following properties:
* <ol>
* <li>If the application targets API level 27 (Android O MR1) or lower then cleartext traffic
* is allowed by default.</li>
* <li>Cleartext traffic is not permitted for ephemeral apps.</li>
* <li>HSTS is not enforced.</li>404页面网站源码
* <li>No certificate pinning is used.</li>
* <li>The system certificate store is trusted for connections.</li>
* <li>If the application targets API level 23 (Android M) or lower then the user certificate
* store is trusted by default as well for non-privileged applications.</li>
* <li>Privileged applications do not trust the user certificate store on Android P and higher.
* </li>
* </ol>
*
* @hide
*/
public static Builder getDefaultBuilder(ApplicationInfo info){
Builder builder =new Builder()
.setHstsEnforced(DEFAULT_HSTS_ENFORCED)
// System certificate store, does not bypass static pins.
.addCertificatesEntryRef(
new Instance(),false));
final boolean cleartextTrafficPermitted = info.targetSdkVersion < Build.VERSION_CODES.P
&& info.targetSandboxVersion <2;
builder.setCleartextTrafficPermitted(cleartextTrafficPermitted);
// Applications targeting N and above must opt in into trusting the user added certificate
// store.
if(info.targetSdkVersion <= Build.VERSION_CODES.M &&!info.isPrivilegedApp()){
// User certificate store, does not bypass static pins.
builder.addCertificatesEntryRef(
new Instance(),false));
}
return builder;
}
可以看出以下⼏个特点:
1. Android 9(假设Target和系统版本⼀样)以下默认允许明⽂传输(⾮HTTPS)
2. 默认只信任系统内置的根证书,Android 7以下添加对⽤户配置的证书信任
3. HSTS不强制开启
于是再次搜索这个⽅法的调⽤
其中,第⼀个调⽤的地⽅是重写了XmlConfigSource实现的ConfigSource类中的⽅法getDefaultConfig
⽽第⼆个地⽅则是在private void parseNetworkSecurityConfig(XmlResourceParser parser)这个⽅法当中,根据⽅法名,就知道这是在解析XML配置中的⽹络安全配置
那么再分别查看它们的调⽤
那么,系统读取App⽹络安全配置的基本流程就可以猜想出来了:
1. ⾸先是解析l⽂件
2. 中间会初始化⼀个XmlConfigSource实例⽤来解析NetworkConfig
3. 当需要⽤到⽹络配置的具体内容时,会调⽤XmlConfigSource实例的getDefaultConfig⽅法,其中ensureInitialized会具体负责解析XML⽂
件中的证书、域名、是否允许明⽂等配置
4. parseNetworkSecurityConfig⽅法会⾸先利⽤NetworkSecurityConfig类的getDefaultBuilder⽅法获取⼀个通⽤的Builder,构建⼀个默认配
置,再根据XML中的实际情况进⾏补充
修改相关源码
了解了⽹络安全配置加载的流程,那么从理论上来说,我们可以在任⼀环境进⾏修改,即可去掉HTTPS的抓包限制,其中,修改的⼏个点如下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。