tools:ignore="InsecureBaseConfiguration" />
<!--证书校验-->
<domain-config>
<domain includeSubdomains="true">www.ttt.com</domain>
<trust-anchors>
<certificates src="@raw/ttt"/>
</trust-anchors>
</domain-config>
<!--公钥校验-->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">ttt.com</domain>
<!--利用xml校验证书公钥的hash值-->
<pin-set expiration="2099-01-01"
tools:ignore="MissingBackupPin">
<pin digest="SHA-256">7VMdvZE3PGbxb0Pgf1PlCp+MI8KZ2ZC5psM8TIylNDA=</pin>
</pin-set>
<!--利用xml校验证书的公钥文件-->
<trust-anchors>
<certificates src="@raw/ttt"/>
</trust-anchors>
</domain-config>
复制代码
这两种校验机制出现一种即可,从代码中可以看出,ttt.com就是安卓自己要校验绑定的域名。
如果只是在这个文件进行校验,有两种解决方案:一是直接将文件中校验的部分或注释掉,再重新打包和签名即可,但是这过程又有些麻烦,并不是上上策,如果遇到了不能重打包的apk就尴尬了。。。二是最常用的也是最好用的frida来hook关键函数进行绕过,后面会讲解。当然有些人会直接在真机或者模拟器上安装xposed模块,但是我个人觉得每次使用都要软重启,可能还会造成卡机,所以感觉还是使用frida最方便。
##### 在代码中检验的两种方法
1.利用代码校验证书的公钥hash
String hostname = “www.ttt.com”;
CertificatePinner certificatePinner = new CertificatePinner.Builder()
.add(hostname, “sha256/7VMdvZE3PGbxb0Pgf1PlCp+MI8KZ2ZC5psM8TIylNDA=”)
.build();
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(certificatePinner)
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).build();
复制代码
2.利用代码校验证书的公钥证书文件
// 获取证书输入流
InputStream openRawResource = getApplicationContext().getResources().openRawResource(R.raw.ttt);
Certificate ca = CertificateFactory.getInstance(“X.509”).generateCertificate(openRawResource);
// 创建 Keystore 包含我们的证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry(“ca”, ca);
// 创建一个 TrustManager 仅把 Keystore 中的证书 作为信任的锚点
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); // 建议不要使用自己实现的X509TrustManager,而是使用默认的X509TrustManager
trustManagerFactory.init(keyStore);
// 用 TrustManager 初始化一个 SSLContext
sslContext = SSLContext.getInstance(“TLS”); //定义:public static SSLContext sslContext = null;
sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
OkHttpClient client = new OkHttpClient.Builder()
.sslSocketFactory(sslContext.getSocketFactory(),
(X509TrustManager) trustManagerFactory.getTrustManagers()[0] )
.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}).build();
复制代码
通过frida进行hook,这种绕过的脚本也很多,比较熟悉的有JustTrustMe和`DroidSSLUnpinning`,他们的底层原理都是一样的,通过hook关键的验证函数,进行逻辑绕过。
frida的安装过程就不详细讲解了,网上很多教程。这里我使用的是`frida 12.8.0 + frida-tools=5.3.0`
这里我使用的hook.js的脚本如下:
/* Android ssl certificate pinning bypass script for various methods
by Maurizio Siddu modify by Ch3nYe
Run with:
frida -U -f [APP_ID] -l frida_multiple_unpinning.js --no-pause
*/
setTimeout(function() {
Java.perform(function () {
console.log(‘’);
console.log(‘‘);
console.log(’[#] Android Bypass for various Certificate Pinning methods [#]‘);
console.log(’’);
var X509TrustManager = Java.use(‘javax.net.ssl.X509TrustManager’);
var SSLContext = Java.use(‘javax.net.ssl.SSLContext’);
// TrustManager (Android < 7) //
var TrustManager = Java.registerClass({
// Implement a custom TrustManager
name: ‘dev.asd.test.Trus