双向认证处理流程
- 概述
- 获取证书
- [逆向app 获取证书的KeyStore的 key](#逆向app 获取证书的KeyStore的 key)
-
-
- [通过jadx 反编译 app 获取证书:](#通过jadx 反编译 app 获取证书:)
- [frida hook](#frida hook)
-
- 证书转换
-
-
- 命令行转换
- [portecle 工具使用](#portecle 工具使用)
-
- [charles 配置 p12 格式证书](#charles 配置 p12 格式证书)
概述
本篇只介绍怎么解决ssl pinning, 不讲ssl/tls 原理。
为了解决ssl pinning 服务端验证(又称 双向认证), 解决步骤如下:
获取证书
我们知道服务端证书绑定在客户端中, 那么直接解压apk就可以获取了
常见 akp 的证书一般放在assets
目录下面, 常见的证书格式: cer、pem、p12、pfx、bks
等
示例:
逆向app 获取证书的KeyStore的 key
通过ssl pinning 原理我们知道服务端证书被绑定在客户端中(apk里)
这里分为两步:第一步获取 证书passwrd代码位置; 第二步通过frida hook获取password
常见java代码模拟双向认证的请求的过程:
java
// 双向认证证书
KeyStore keyStore = KeyStore.getInstance("PKCS12");
KeyStore trustStore = KeyStore.getInstance("jks");
// keyStore是服务端验证客户端的证书,trustStore是客户端的信任证书
InputStream ksIn = new FileInputStream("E:/Java/jre8/lib/security/re/1.pfx");
InputStream tsIn = new FileInputStream(new File("E:/Java/jre8/lib/security/re/1"));
// 这里是客户端证书加载, 123456为keyStore的password
keyStore.load(ksIn, "123456".toCharArray());
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, "123456".toCharArray()).setSecureRandom(new SecureRandom()).useSSL().build();
ConnectionSocketFactory pSocketFactory = new PlainConnectionSocketFactory();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", pSocketFactory).register("https", sslConnectionSocketFactory).build();
PoolingHttpClientConnectionManager secureConnectionManager = new PoolingHttpClientConnectionManager(r);
HttpClientBuilder secureHttpBulder = HttpClients.custom().setConnectionManager(secureConnectionManager);
HttpClient client = secureHttpBulder.build();
HttpGet httpGet = new HttpGet("https://xxx.com");
HttpResponse httpResponse1 = client.execute(httpGet);
通过jadx 反编译 app 获取证书:
- 查找特征:
- keyStore.load
示例: ( 图二 )
frida hook
由于不同apk hook代码不同, 这里介绍两个hook点, 不提供hook 代码
- hook 密码解密函数
- hook keyStore 的load 函数
示例:(以图二为例)
js
// 这里使用hook 点一
function main(){
Java.perform(function(){
Java.enumerateClassLoaders({
onMatch : function(loader){
try {
// loadClass or findClass
if (loader.loadClass("o0O0000o.OooO0OO")){
Java.classFactory.loader = loader;
// something to do;
var OooO0OO = Java.use("o0O0000o.OooO0OO");
console.log("success hook it :", OooO0OO);
OooO0OO["OooO00o"].implementation = function (j) {
console.log(`OooO0OO.OooO00o is called: j=${j}`);
let result = this["OooO00o"](j);
console.log(`OooO0OO.OooO00o result= ${result}`);
return result;
};
}
} catch (error) {
// pass
}
},
onComplete: function () {
console.log("complete !!! ")
}
})
})
}
setImmediate(main);
结果:
bash
OooO0OO.OooO00o is called: j=-1973552697099
OooO0OO.OooO00o result= MZ4cozY8Qu32UzGe
OooO0OO.OooO00o is called: j=-2046567141131
OooO0OO.OooO00o result= MZ4cozY8Qu32UzGe
证书转换
如果如果证书是bks 的, 还需转换成p12(PKCS12) 或 pem(因为charles 只支持p12 和pem)
转换方式这里介绍两种: 第一种命令行; 第二种使用portecle工具
命令行转换
bash
keytool -importkeystore -srckeystore your_bks_cert.bks -srcstoretype BKS -destkeystore bks.p12 -deststoretype PKCS12
其中,your_bks_cert.bks 是你的 bks格式证书文件,bks.p12 是输出的p12格式证书文件名;之后,按照提示输入bks证书的密码(MZ4cozY8Qu32UzGe)和p12证书的密码(同bks证书)。
portecle 工具使用
网上有很多, 这里提供一个不错的blog 点击前往
charles 配置 p12 格式证书
网上有很多, 这里提供一个不错的blog 点击前往
借鉴:
- 问题解决过程:https://zhuanlan.zhihu.com/p/60392573
- charles 配置证书: https://blog.yii2.cc/mutual-tls-authentication/
- apk 获取证书:https://www.secpulse.com/archives/54027.html
- java 现SSL双向认证:https://blog.csdn.net/HD243608836/article/details/109105469
- bks证书转p12: https://tool.yimenapp.com/info@-bks-zheng-shu-zhuai-p12-159502.html
- 证书password hook点定位:https://xz.aliyun.com/t/12993?time__1311=mqmhqIhiGK0KDsD7GG7DyWrbDteXupuGD&alichlgref=https%3A%2F%2Fwww.google.com%2F
- Portecle工具 Portecle 使用:https://blog.csdn.net/jlcikai/article/details/124605175