参考链接:
https://blog.nviso.eu/2018/01/31/using-a-custom-root-ca-with-burp-for-inspecting-android-n-traffic/
https://gist.github.com/akabe1/5632cbc1cd49f0237cbd0a93bc8e4452
1.安装系统证书抓包
1)root你的手机
我使用的是小米mix2s,将它刷成了开发版系统,这样就可以很方便的获取root权限了。路径为:手机管家--应用管理--权限--开启root权限--开启root--等待重启完成
我们adb root和adb remount看一下是否成功:
2)设置抓包工具,这里抓包工具用的是burp suite
proxy--intercept关掉拦截模式
proxy--HTTP histoty显示所有类型的包(可以根据自己的需要筛选)
proxy--options--proxy listeners设置监听ip与端口号
proxy--options--miscellaneous把下面这些选项都勾上
user options--connections--socks proxy,要是需要挂海外代理,在这里设置
3)进入手机系统设置--网络设置,给手机挂上对应的代理(注意,这里手机与电脑需要在能互相ping通的局域网下)
ip与端口号与前面抓包工具上设置的一致
其实现在已经能抓到包了,我们手机上打开浏览器看一下:
一般直接挂上代理,能直接抓到http的包或者没做证书校验的https的包。
但是如何抓到https呢?我们需要安装证书,而且由于我们root了手机,我们可以将其安装为系统证书,这将会获得比用户证书更高的权限
4)生成和安装证书
首先你需要安装openssl,我ubantu系统里自带了openssl,可以直接开始。
使用openssl version判断你电脑里有没有openssl:
$ openssl version
OpenSSL 1.1.0g 2 Nov 2017 (Library: OpenSSL 1.1.1 11 Sep 2018)
新建一个文件夹用来存放后续的文件,进入该文件夹下:
$ mkdir cacerts
$ cd cacerts
复制openssl.cnf文件到当前目录下:
这里报了一个错误,说没有权限,所以我改了一下这个文件夹的权限,就可以了。
#这个openssl.cnf所在的位置不一定在这儿,可以使用whereis openssl.cnf或者where openssl.cnf查找它的实际位置
$ cp /usr/lib/ssl/openssl.cnf ./
cp: cannot create regular file './openssl.cnf': Permission denied
$ cd ..
$ sudo chmod 777 cacerts
$ cd cacerts/
$ cp /usr/lib/ssl/openssl.cnf ./
$ ls
openssl.cnf
生成CA证书
#生成私钥,后面会需要填写一些信息,可以跟我写一样的
$ openssl req -x509 -days 730 -nodes -newkey rsa:2048 -outform der -keyout server.key -out ca.der -extensions v3_ca -config openssl.cnf
Generating a 2048 bit RSA private key
..............................................................................+++++
...................+++++
writing new private key to 'server.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:BE
State or Province Name (full name) [Some-State]:NVISO CA
Locality Name (eg, city) []:NVISO CA
Organization Name (eg, company) [Internet Widgits Pty Ltd]:NVISO CA
Organizational Unit Name (eg, section) []:NVISO CA
Common Name (e.g. server FQDN or YOUR name) []:NVISO CA
Email Address []:NVISO CA
#看看生成的文件
$ ls
ca.der openssl.cnf server.key
#转换成der格式
$ openssl rsa -in server.key -inform pem -out server.key.der -outform der
writing RSA key
#转换成pkcs8格式
$ openssl pkcs8 -topk8 -in server.key.der -inform der -out server.key.pkcs8.der -outform der -nocrypt
#看看生成的文件
$ ls
ca.der openssl.cnf server.key server.key.der server.key.pkcs8.der
#浏览一下生成的证书(浏览.0格式的可以用这个命令:$ openssl x509 -in d58e1f78.0 -inform PEM -noout -text)
$ openssl x509 -in ca.der -inform der -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
a7:4d:f4:90:65:bb:f2:68
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = BE, ST = NVISO CA, L = NVISO CA, O = NVISO CA, OU = NVISO CA, CN = NVISO CA, emailAddress = NVISO CA
Validity
Not Before: Jun 26 09:07:06 2021 GMT
Not After : Jun 26 09:07:06 2023 GMT
Subject: C = BE, ST = NVISO CA, L = NVISO CA, O = NVISO CA, OU = NVISO CA, CN = NVISO CA, emailAddress = NVISO CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:b5:e9:67:ba:8d:fd:6c:30:ae:a5:25:93:9c:4e:
33:88:9a:a9:f9:91:f0:42:83:4f:ba:bd:0a:3f:e5:
21:78:d7:83:1d:65:86:63:dc:64:9c:6a:28:80:30:
3b:4d:b1:2f:76:f3:b9:51:af:7d:f8:11:a4:11:bc:
fe:ea:bb:8f:f8:ec:90:2a:bb:17:84:10:95:93:55:
41:28:9d:f0:e7:6e:6b:19:8d:55:f2:ff:b3:eb:b1:
e6:8c:21:0e:eb:68:fe:a9:49:e6:a1:6b:c6:21:3d:
cc:78:af:a5:77:56:ea:2f:f7:48:89:9b:e9:4b:75:
de:1c:14:14:6f:4e:75:70:fd:be:83:5f:9f:b8:03:
88:87:f8:47:1c:f9:04:04:35:fa:28:c7:01:27:c4:
13:bc:db:5e:d7:bb:ce:8b:20:6c:ed:7e:25:a5:82:
58:1e:36:12:da:05:81:9f:d9:17:c2:ee:1e:89:76:
a0:98:a6:9b:c6:15:5a:41:fd:10:8d:c9:81:90:f5:
78:cb:99:d5:1a:b1:36:8e:04:87:87:92:d4:dc:cc:
2c:ff:fb:a7:ea:1f:9b:57:c4:13:d9:c5:44:3d:52:
73:4b:1b:95:33:7c:6c:88:9d:15:b8:c5:4f:5d:a0:
22:b3:6b:66:01:ba:9d:dc:19:96:d9:77:e3:9f:f9:
ae:bb
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
09:A6:67:C8:2D:86:42:03:19:26:61:A8:D5:5F:F3:E3:21:2C:1D:24
X509v3 Authority Key Identifier:
keyid:09:A6:67:C8:2D:86:42:03:19:26:61:A8:D5:5F:F3:E3:21:2C:1D:24
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
24:b4:38:0e:5c:5e:8f:a7:7b:a6:66:13:b5:86:d1:6c:05:61:
83:85:e5:33:7d:e4:5f:65:43:fe:d3:7e:09:42:83:47:7a:1a:
35:db:bf:c4:c5:25:86:78:60:d7:40:8d:b7:65:d4:5a:f5:44:
51:ee:c2:0e:7e:57:75:31:ad:67:08:21:f7:5d:48:cd:06:c1:
52:2d:35:47:9b:ed:d2:a8:e0:54:06:18:50:5c:4a:6a:24:43:
a9:47:82:93:cb:45:01:56:aa:db:23:95:df:1f:d4:63:7f:24:
7f:ae:4c:ad:e3:4a:98:74:ca:a2:f8:25:de:09:a9:9d:ad:81:
e6:12:9c:f0:a7:61:6e:e0:93:43:ff:6d:a2:90:b6:42:b2:2b:
57:76:1c:09:e7:21:35:f9:f9:d3:fd:de:a6:f6:9f:1b:84:37:
9a:31:c0:28:66:85:39:42:3d:b4:55:d3:23:4a:92:a1:25:45:
03:3b:08:3b:62:17:ba:57:8d:e4:8e:9a:fd:0a:21:57:96:8d:
03:1c:83:34:51:54:c2:7a:69:60:2a:18:a9:83:92:78:f3:e2:
b3:fb:12:fc:a8:c0:f9:69:1a:67:ce:8f:7e:8f:a8:de:91:1f:
f7:c7:f7:2d:8b:60:12:73:09:58:11:fb:07:26:09:e2:57:c1:
b8:15:35:a5
假如是windows系统,那么需要下载openssl工具,比如win64的:http://slproweb.com/products/Win32OpenSSL.html
下载完后安装到非中文目录,一路next,我这里就不贴图了。
将安装目录/bin这个目录配到环境变量里,或者直接给出openssl.exe的路径来执行以下的命令,
like this:
进入 安装目录/bin/cnf目录,或者把openssl.cnf文件拷贝到一个英文目录下:
按住shift鼠标右键打开powershell窗口,开始依次执行上面的生成CA证书的命令
由于过程相同我就不贴图了,注意如果没有配环境变量,每次调openssl都要给出它的实际执行文件的位置才行。(所以把环境变量配上吧!我这里只是做个演示)
将生成的证书导入burp,路径:proxy--options:
导入完成后重启一下burp,按照之前的步骤重新设置一下burp。
手机浏览器访问:https://burp下载证书,假如下载失败,可以改成访问你上面burp里设置的ip+端口号,如我的:192.168.1.105:8080
进入系统的证书管理,不同的手机可能有所不同,可以搜索“证书”或者“加密凭据”等关键字寻找。
我的手机路径是:系统设置--密码、隐私与安全--系统安全--加密与凭据
选择从存储设备安装证书:
安装的时候发现手机需要cer格式的证书,而下载的是der格式的,手机识别不了,给它重命名转化一下就可以了。
给证书命名:
可以看到用户凭据里已经有这个证书了:
看看信任的凭据里:
这个就是我们刚刚安装的证书了:
这个安装的位置实际在哪儿呢?adb shell进入手机系统,cd /data/misc/user/0/cacerts-added就可以看到我们的用户证书了
这样也能抓到一部分https的包,但是大部分应用还是不行的,比如我浏览器访问https://baidu.com,他会提示:
哔哩哔哩会显示加载失败:
我们将用户证书升级成系统证书,其实就是把系统证书移到系统证书目录下,毕竟我们是root用户,为所欲为!
系统证书在哪儿呢?cd /system/etc/security/cacerts 就可以看到我们的系统证书了:
把用户证书copy到系统证书目录下:
adb shell cp -f /data/misc/user/0/cacerts-added/d58e1f78.0 /system/etc/security/cacerts/
OPPO手机上是成功的,但是小米手机上,copy过去之后我也没看见我的证书,无奈我只好自己生成了一个.0格式的证书:
#转换成PEM格式
$ openssl x509 -inform DER -in ca.der -out ca.pem
#获取subject_hash_old
$ openssl x509 -inform PEM -subject_hash_old -in ca.pem |head -1
d58e1f78
#将文件重命名成subject_hash_old.0
$ mv ca.pem d58e1f78.0
#浏览一下生成的证书(跟上面结果一样,我就不贴了)
$ openssl x509 -in d58e1f78.0 -inform PEM -noout -text
直接push到/system/etc/security/cacerts下
adb push D:\1security\cacerts\d58e1f78.0 /system/etc/security/cacerts/
D:\1security\cacerts\d58e1f78.0: 1 file pushed, 0 skipped. 4.2 MB/s (1407 bytes in 0.000s)
再去系统证书目录下看,奇了个怪的还是没有:
说不定隐形存在?cat查看一下:
还真的有这个文件,但是看起来似乎不太完整?所以没显示?查看目录下随便一个证书的对比:
我重启手机试了试,不能说毫无改变吧,它居然消失了,我只好重新push了一遍。
无奈,试试抓包能不能行吧。
抓包还是阔以的,就是不知道为啥子目录下看不见,有点怪,后面再研究,说不定只是我最近升级了开发版系统的原因。
2.拯救sslpinning
sslpinning,其实就是客户端在收到服务端的证书后,对这个证书进行校验,如果不是客户端承认的证书,就会直接断开连接,这样直接使用系统证书的方式无法抓包,所以我们可以使用frida去hook校验的函数,将校验的结果直接返回true,从而绕过校验。
1)sslpinning的表现
操作app,停在某个功能处无法继续操作或者显示无网络(一般是进首页,或者账号登录),burp上也没有抓到任何包,或者出现SSL443这样的错误log。而其他的没做sslpinning的应用还是可以正常抓包。
比如我找了一款APP,它的登录就有做sslpinning,安装了系统证书之后burp也没有抓到任何包,通过logcat日志,可以看到以下打印,这个时候就可以试试objection的disable sslpinning
2)安装objection库
这里我们使用python3,我的版本是python3.7.9,安装objection就会自动带上frida
pip install objection
pip list看一下frida的版本,我们要下一个对应的frida-server的版本
3)下载frida-server
下载与自己的frida版本和手机cpu版本对应的frida-server的版本:https://github.com/frida/frida/releases
确定自己的手机cpu版本可以用:
adb shell getprop ro.product.cpu.abi
4)启动frida-server
#pushfrida-server到手机
adb push frida-server-14.2.18-android-arm64 /data/local/tmp/frida-server
#shell进手机启动frida-server
adb shell
$ cd data/local/tmp
$ chmod 777 ./frida-server
$ ./frida-server -D
#转发端口
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
来启一下objection看一下效果,成功的话会进入这个界面,且会自动拉起目标应用。
没成功的话检查一下frida-server是否与frida版本匹配,是否启动成功,是否转发了端口,包名是否打错,端口是否被占用······
objection -g 应用包名 explore
假如你不知道当前应用的包名,也可以打开应用,然后使用以下命令获取当前运行应用的包名和activity
adb shell dumpsys window | findstr mCurrentFocus
想把应用包拷出来分析使用以下命令获取包的位置,然后使用adb pull 路径 存储路径拷贝
adb shell pm path 包名
adb pull xxx.apk D:\xxx
分析应用可以使用jeb,这个下载链接暂时找不到了,可以上国内外的破解站找找
5)使用objection的disable sslpinning
先直接尝试一下
android sslpinning disable
行吧没有阻碍,它将校验函数返回true,直接就成功了,刚刚抓包毫无反应的应用登录页面已经成功的走到了验证码流程,burp里也抓到了相应的包
由于这个disable开启了之后会一直调用,假如你想关掉它可以使用以下命令。其它的任务关闭也是这个方法。
com. on (Xiaomi: 9) [usb] # jobs list
Job ID Hooks Type
-------- ------- --------------------------
424555 7 android-sslpinning-disable
com. on (Xiaomi: 9) [usb] # jobs kill 424555
6)直接使用frida
从上面objection的log可以看到校验的时候调用了com.android.org.conscrypt.TrustManagerImpl.verifyChain()方法,那么我们新建一个js文件命名为sslpinning.js,hook这个函数,顺便把绕过校验的域名打印出来
/*
Run with:frida -U -f [package_name] -l sslpinning.js --no-pause
*/
Java.perform(function(){
try{
var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl")
TrustManagerImpl.verifyChain.implementation = function (arg1, arg2, host, arg3, arg4, arg5) {
console.log("[*] hooked TrustManagerImpl "+host)
return arg1;
}
}catch (err) {
console.log("[×] TrustManagerImpl pinner not found")
}
});
在cmd里运行一下:
证明使用frida去hook校验函数这个办法可行,参考网上的脚本,我写(主要是复制粘贴,不要骂我)了一个总的,代码如下:
/*
Run with:frida -U -f [package_name] -l sslpinning.js --no-pause
*/
Java.perform(function(){
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
//安卓7以下的版本适用
var TrustManager = Java.registerClass({
// Implement a custom TrustManager
name: 'dev.asd.test.TrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function (chain, authType) {},
checkServerTrusted: function (chain, authType) {},
getAcceptedIssuers: function () {return []; }
}
});
// Prepare the TrustManager array to pass to SSLContext.init()
var TrustManagers = [TrustManager.$new()];
// Get a handle on the init() on the SSLContext class
var SSLContext_init = SSLContext.init.overload(
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');
try {
// Override the init method, specifying the custom TrustManager
SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {
console.log('[*]hooked Trustmanager');
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom);
};
} catch (err) {
console.log('[×] TrustManager pinner not found');
}
// OkHTTP3
try{
var okhttp3_1 = Java.use("okhttp3.CertificatePinner");
okhttp3_1.check.overload("java.lang.String","java.util.List").implementation = function(arg1,arg2){
console.log("[*] hooked okhttp3_1 "+arg1)
return true
};
}catch (err) {
console.log("[×] okhttp3_1 pinner not found")
}
try{
var okhttp3_2 = Java.use("okhttp3.CertificatePinner");
okhttp3_2.check.overload("java.lang.String","java.security.cert.Certificate").implementation = function(arg1,arg2){
console.log("[*] hooked okhttp3_1 "+arg1)
return true
};
}catch (err) {
console.log("[×] okhttp3_2 pinner not found")
}
try{
var okhttp3_3 = Java.use("okhttp3.CertificatePinner");
okhttp3_3.check.overload("java.lang.String","[Ljava.security.cert.Certificate;").implementation = function(arg1,arg2){
console.log("[*] hooked okhttp3_3 "+arg1)
return true
};
}catch (err) {
console.log("[×] okhttp3_3 pinner not found")
}
try{
var okhttp3_4 = Java.use("okhttp3.CertificatePinner");
okhttp3_4["check$okhttp"].implementation = function(arg1,arg2){
console.log("[*] hooked okhttp3_4 "+arg1)
};
}catch (err) {
console.log("[×] okhttp3_4 pinner not found")
}
// Trustkit
try{
var trustkit_1 = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier")
trustkit_1.verify.overload("java.lang.String","javax.net.ssl.SSLSession").implementation = function (arg1,arg2){
console.log("[*] hooked trustkit_1 "+arg1)
return true
};
}catch (err) {
console.log("[×] trustkit_1 pinner not found")
}
try{
var trustkit_2 = Java.use("com.datatheorem.android.trustkit.pinning.OkHostnameVerifier")
trustkit_2.verify.overload("java.lang.String","java.security.cert.X509Certificate").implementation = function (arg1,arg2){
console.log("[*] hooked trustkit_2 "+arg1)
return true
};
}catch (err) {
console.log("[×] trustkit_2 pinner not found")
}
try{
var trustkit_3 = Java.use("com.datatheorem.android.trustkit.pinning.PinningTrustManager")
trustkit_1.checkServerTrusted.implementation = function (){
console.log("[*] hooked trustkit_3 ")
};
}catch (err) {
console.log("[×] trustkit_3 pinner not found")
}
// Appcelerator Titanium
try {
var appcelerator_PinningTrustManager = Java.use('appcelerator.https.PinningTrustManager');
appcelerator_PinningTrustManager.checkServerTrusted.implementation = function () {
console.log("[*] hooked appcelerator_PinningTrustManager ");
};
} catch (err) {
console.log("[×] Appcelerator PinningTrustManager pinner not found");
}
// OpenSSLSocketImpl Conscrypt
try{
var OpenSSLSocketImpl = Java.use("com.android.org.conscrypt.OpenSSLSocketImpl")
OpenSSLSocketImpl.verifyCertificateChain.implementation = function (arg1, arg2, arg3) {
console.log("[*] hooked OpenSSLSocketImpl Conscrypt");
};
}catch (err) {
console.log("[×] OpenSSLSocketImpl pinner not found");
}
// OpenSSLEngineSocketImpl Conscrypt
try {
var OpenSSLEngineSocketImpl = Java.use('com.android.org.conscrypt.OpenSSLEngineSocketImpl');
OpenSSLEngineSocketImpl.verifyCertificateChain.overload('[Ljava.lang.Long;', 'java.lang.String').implementation = function (arg1, arg2) {
console.log("[*] hooked OpenSSLEngineSocketImpl Conscrypt: " + arg2);
};
} catch (err) {
console.log("[×] OpenSSLEngineSocketImpl Conscrypt pinner not found");
}
// OpenSSLSocketImpl Apache Harmony
try {
var OpenSSLSocketImpl_Harmony = Java.use('org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl');
OpenSSLSocketImpl_Harmony.verifyCertificateChain.implementation = function (asn1DerEncodedCertificateChain, authMethod) {
console.log("[*] hooked OpenSSLSocketImpl Apache Harmony");
};
} catch (err) {
console.log("[×] OpenSSLSocketImpl Apache Harmony pinner not found");
}
// PhoneGap sslCertificateChecker (https://github.com/EddyVerbruggen/SSLCertificateChecker-PhoneGap-Plugin)
try {
var phonegap = Java.use('nl.xservices.plugins.sslCertificateChecker');
phonegap.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (arg1, arg2, arg3) {
console.log('[*] hooked PhoneGap sslCertificateChecker: ' + arg1);
return true;
};
} catch (err) {
console.log('[×] PhoneGap sslCertificateChecker pinner not found');
}
// IBM MobileFirst pinTrustedCertificatePublicKey
try {
var WLClient_1 = Java.use('com.worklight.wlclient.api.WLClient');
WLClient_1.getInstance().pinTrustedCertificatePublicKey.overload('java.lang.String').implementation = function (cert) {
console.log('[*] hooked IBM MobileFirst pinTrustedCertificatePublicKey {1}: ' + cert);
return;
};
} catch (err) {
console.log('[×] IBM MobileFirst pinTrustedCertificatePublicKey {1} pinner not found');
}
try {
var WLClient_2 = Java.use('com.worklight.wlclient.api.WLClient');
WLClient_2.getInstance().pinTrustedCertificatePublicKey.overload('[Ljava.lang.String;').implementation = function (cert) {
console.log('[*] hooked IBM MobileFirst pinTrustedCertificatePublicKey {2}: ' + cert);
return;
};
} catch (err) {
console.log('[×] IBM MobileFirst pinTrustedCertificatePublicKey {2} pinner not found');
}
// IBM WorkLight (ancestor of MobileFirst) HostNameVerifierWithCertificatePinning
try {
var worklight_1 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
worklight_1.verify.overload('java.lang.String', 'javax.net.ssl.SSLSocket').implementation = function (arg1, arg2) {
console.log('[*] hooked IBM WorkLight HostNameVerifierWithCertificatePinning {1}: ' + arg1);
return;
};
} catch (err) {
console.log('[×] IBM WorkLight HostNameVerifierWithCertificatePinning {1} pinner not found');
}
try {
var worklight_2 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
worklight_2.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (arg1, arg2) {
console.log('[*] hooked IBM WorkLight HostNameVerifierWithCertificatePinning {2}: ' +arg1);
return;
};
} catch (err) {
console.log('[×] IBM WorkLight HostNameVerifierWithCertificatePinning {2} pinner not found');
}
try {
var worklight_3 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
worklight_3.verify.overload('java.lang.String', '[Ljava.lang.String;', '[Ljava.lang.String;').implementation = function (arg1, arg2) {
console.log('[*] hooked IBM WorkLight HostNameVerifierWithCertificatePinning {3}: ' + arg1);
return;
};
} catch (err) {
console.log('[×] IBM WorkLight HostNameVerifierWithCertificatePinning {3} pinner not found');
}
try {
var worklight_4 = Java.use('com.worklight.wlclient.certificatepinning.HostNameVerifierWithCertificatePinning');
worklight_4.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (arg1, arg2) {
console.log('[*] hooked IBM WorkLight HostNameVerifierWithCertificatePinning {4}: ' + arg1);
return true;
};
} catch (err) {
console.log('[×] IBM WorkLight HostNameVerifierWithCertificatePinning {4} pinner not found');
}
// Conscrypt CertPinManager
try {
var conscrypt_CertPinManager = Java.use('com.android.org.conscrypt.CertPinManager');
conscrypt_CertPinManager.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (arg1, arg2) {
console.log('[*] hooked Conscrypt CertPinManager: ' +arg1);
return true;
};
} catch (err) {
console.log('[×] Conscrypt CertPinManager pinner not found');
}
// CWAC-Netsecurity (unofficial back-port pinner for Android<4.2) CertPinManager
try {
var cwac_CertPinManager_Activity = Java.use('com.commonsware.cwac.netsecurity.conscrypt.CertPinManager');
cwac_CertPinManager_Activity.isChainValid.overload('java.lang.String', 'java.util.List').implementation = function (arg1, arg2) {
console.log('[*] hooked CWAC-Netsecurity CertPinManager: ' + arg1);
return true;
};
} catch (err) {
console.log('[×] CWAC-Netsecurity CertPinManager pinner not found');
}
try{
var conscrypt_platform = Java.use("org.conscrypt.Platform")
conscrypt_platform.checkServerTrusted.overload('javax.net.ssl.X509TrustManager', '[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'org.conscrypt.ConscryptEngine').implementation = function (arg1,arg2,arg3,arg4) {
return true;
}
conscrypt_platform.checkServerTrusted.overload('javax.net.ssl.X509TrustManager', '[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'org.conscrypt.AbstractConscryptSocket').implementation = function(arg1,arg2,arg3,arg4){
return true;
}
}catch (err) {
console.log('[×] conscrypt_platform pinner not found');
}
try{
var android_conscrypt_platform = Java.use("com.android.org.conscrypt.Platform")
android_conscrypt_platform.checkServerTrusted.overload('javax.net.ssl.X509TrustManager', '[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'com.android.org.conscrypt.ConscryptEngine').implementation = function (arg1,arg2,arg3,arg4) {
return true;
}
android_conscrypt_platform.checkServerTrusted.overload('javax.net.ssl.X509TrustManager', '[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'com.android.org.conscrypt.AbstractConscryptSocket').implementation = function(arg1,arg2,arg3,arg4){
return true;
}
}catch (err) {
console.log('[×] android_conscrypt_platform pinner not found');
}
try{
var TrustManagerExtensions = Java.use("android.net.http.X509TrustManagerExtensions")
TrustManagerExtensions.checkServerTrusted.overload('[Ljava.security.cert.X509Certificate;', 'java.lang.String','java.lang.String').implementation = function(arg1,arg2,arg3){
return true;
}
}catch (err) {
console.log('[×] android_conscrypt_platform pinner not found');
}
// Worklight Androidgap WLCertificatePinningPlugin
try {
var androidgap_WLCertificatePinningPlugin_Activity = Java.use('com.worklight.androidgap.plugin.WLCertificatePinningPlugin');
androidgap_WLCertificatePinningPlugin_Activity.execute.overload('java.lang.String', 'org.json.JSONArray', 'org.apache.cordova.CallbackContext').implementation = function (arg1, arg2, arg3) {
console.log('[*] hooked Worklight Androidgap WLCertificatePinningPlugin: ' + arg1);
return true;
};
} catch (err) {
console.log('[×] Worklight Androidgap WLCertificatePinningPlugin pinner not found');
}
// Netty FingerprintTrustManagerFactory
try {
var netty_FingerprintTrustManagerFactory = Java.use('io.netty.handler.ssl.util.FingerprintTrustManagerFactory');
//NOTE: sometimes this below implementation could be useful
//var netty_FingerprintTrustManagerFactory = Java.use('org.jboss.netty.handler.ssl.util.FingerprintTrustManagerFactory');
netty_FingerprintTrustManagerFactory.checkTrusted.implementation = function (type, chain) {
console.log('[*] hooked Netty FingerprintTrustManagerFactory');
};
} catch (err) {
console.log('[×] Netty FingerprintTrustManagerFactory pinner not found');
}
// Squareup CertificatePinner [OkHTTP<v3] (double bypass)
try {
var Squareup_CertificatePinner_1 = Java.use('com.squareup.okhttp.CertificatePinner');
Squareup_CertificatePinner_1.check.overload('java.lang.String', 'java.security.cert.Certificate').implementation = function (arg1, arg2) {
console.log('[*] hooked Squareup CertificatePinner {1}: ' + arg1);
return;
};
} catch (err) {
console.log('[×] Squareup CertificatePinner {1} pinner not found');
}
try {
var Squareup_CertificatePinner_2 = Java.use('com.squareup.okhttp.CertificatePinner');
Squareup_CertificatePinner_2.check.overload('java.lang.String', 'java.util.List').implementation = function (arg1, arg2) {
console.log('[*] hooked Squareup CertificatePinner {2}: ' + arg1);
return;
};
} catch (err) {
console.log('[×] Squareup CertificatePinner {2} pinner not found');
}
// Squareup OkHostnameVerifier [OkHTTP v3] (double bypass) //
try {
var Squareup_OkHostnameVerifier_1 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier');
Squareup_OkHostnameVerifier_1.verify.overload('java.lang.String', 'java.security.cert.X509Certificate').implementation = function (arg1, arg2) {
console.log('[*] hooked Squareup OkHostnameVerifier {1}: ' + arg1);
return true;
};
} catch (err) {
console.log('[×] Squareup OkHostnameVerifier pinner not found');
}
try {
var Squareup_OkHostnameVerifier_2 = Java.use('com.squareup.okhttp.internal.tls.OkHostnameVerifier');
Squareup_OkHostnameVerifier_2.verify.overload('java.lang.String', 'javax.net.ssl.SSLSession').implementation = function (arg1, arg2) {
console.log('[*] hooked Squareup OkHostnameVerifier {2}: ' + arg1);
return true;
};
} catch (err) {
console.log('[×] Squareup OkHostnameVerifier pinner not found');
}
// Android WebViewClient (double bypass)
try {
// Bypass WebViewClient {1} (deprecated from Android 6)
var AndroidWebViewClient_1 = Java.use('android.webkit.WebViewClient');
AndroidWebViewClient_1.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (arg1, arg2, arg3) {
console.log('[*] hooked Android WebViewClient {1}');
};
} catch (err) {
console.log('[×] Android WebViewClient {1} pinner not found');
}
try {
// Bypass WebViewClient {2}
var AndroidWebViewClient_2 = Java.use('android.webkit.WebViewClient');
AndroidWebViewClient_2.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.WebResourceRequest', 'android.webkit.WebResourceError').implementation = function (arg1, arg2, arg3) {
console.log('[*] hooked Android WebViewClient {2}');
};
} catch (err) {
console.log('[×] Android WebViewClient {2} pinner not found');
}
// Apache Cordova WebViewClient
try {
var CordovaWebViewClient = Java.use('org.apache.cordova.CordovaWebViewClient');
CordovaWebViewClient.onReceivedSslError.overload('android.webkit.WebView', 'android.webkit.SslErrorHandler', 'android.net.http.SslError').implementation = function (arg1, arg2, arg3) {
console.log('[*] hooked Apache Cordova WebViewClient');
arg3.proceed();
};
} catch (err) {
console.log('[×] Apache Cordova WebViewClient pinner not found');
}
// Boye AbstractVerifier
try {
var boye_AbstractVerifier = Java.use('ch.boye.httpclientandroidlib.conn.ssl.AbstractVerifier');
boye_AbstractVerifier.verify.implementation = function (host, ssl) {
console.log('[*] hooked Boye AbstractVerifier: ' + host);
};
} catch (err) {
console.log('[×] Boye AbstractVerifier pinner not found');
}
try{
var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl")
TrustManagerImpl.verifyChain.implementation = function (arg1, arg2, host, arg3, arg4, arg5) {
console.log("[*] hooked TrustManagerImpl "+host)
return arg1;
}
}catch (err) {
console.log("[×] TrustManagerImpl pinner not found")
}
});
7)代码分析
我们先看一下日志:
# I/X509Util: Failed to validate the certificate chain, error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
根据Android官网给出的解释,CA证书校验未通过
https://developer.android.google.cn/training/articles/security-ssl?hl=zh_cn