有个朋友说,某个车联网的 app 竟然抓不到包,让我帮忙看下,行吧,那就看下。
- 样本:byd海洋(v1.4.0)
小试牛刀
先用 Charles
软件试试,使用这个软件抓 App 的包,有几个前提:
- 手机端要配置好Charles的证书
- 电脑端安装好 Charles 的根证书,并信任
- 手机端证书要放到系统证书目录
(Android 系统 7.0 一下,这一步可以省略)
没配置好的话是抓不到 https 请求的,环境配置好后先抓个 https 的包测试一下
可以正常获取到数据,说明抓包环境配置成功。
现在对目标 app 抓包,看下是否成功,结果如下图
可以发现,并没有成功,为什么会这样呢🤔
为什么抓不到App包
目前App用到的网络请求库都是 OKHttp3
,这个库有一个 api:CertificatePinner
这个 API 的作用是
用于自定义证书验证策略,以增强网络安全性。在进行TLS/SSL连接时,服务器会提供一个SSL证书,客户端需要验证该证书的有效性以确保连接的安全性。CertificatePinner允许你指定哪些SSL证书是可接受的,从而有效地限制了哪些服务器可以与你的应用程序通信。
具体来说,CertificatePinner允许你指定一组预期的证书公钥或证书固定哈希值(SHA-256),以便与服务器提供的证书进行比较。如果服务器提供的证书与你指定的公钥或哈希值不匹配,则连接会被拒绝,从而防止中间人攻击和其他安全风险。
我们大胆的猜测一下,目标 App 就是用到了这个 API,添加了自定义的证书验证策略,我们既要大胆猜测,又要小心验证,怎么验证呢?这就要用到 Frida 了,用Frida Hook 这个 API,使其失效。Frida 代码如下
try {
var CertificatePinner = Java.use('okhttp3.CertificatePinner');
quiet_send('OkHTTP 3.x Found');
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function () {
quiet_send('OkHTTP 3.x check() called. Not throwing an exception.');
}
} catch (err) {
// If we dont have a ClassNotFoundException exception, raise the
// problem encountered.
if (err.message.indexOf('ClassNotFoundException') === 0) {
throw new Error(err);
}
}
验证了一下,发现还是抓不到包。
除了这个 API 可以用来防止中间人攻击,OKHttp3
还有其他防止中间人攻击的方法,如X509TrustManager
X509TrustManager 是Java安全架构中的一个接口,位于 javax.net.ssl 包中,主要用于处理 SSL(Secure Sockets Layer)和后续的 TLS(Transport Layer Security)协议中的证书信任管理功能。在基于SSL/TLS的网络通信中,特别是HTTPS连接,X509TrustManager扮演着至关重要的角色,它的主要职责是验证远程主机提供的X.509证书链的有效性。
同样,再用 Frida 验证一下,是不是X509TrustManager
导致的抓不到包,代码如下
var TrustManager;
try {
TrustManager = Java.registerClass({
name: 'org.wooyun.TrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function (chain, authType) {
},
checkServerTrusted: function (chain, authType) {
},
getAcceptedIssuers: function () {
return [];
}
}
});
} catch (e) {
quiet_send("registerClass from X509TrustManager >>>>>>>> " + e.message);
}
// Prepare the TrustManagers array to pass to SSLContext.init()
var TrustManagers = [TrustManager.$new()];
try {
// Prepare a Empty SSLFactory
var TLS_SSLContext = SSLContext.getInstance("TLS");
TLS_SSLContext.init(null, TrustManagers, null);
} catch (e) {
quiet_send(e.message);
}
send('Custom, Empty TrustManager ready');
// 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');
// Override the init method, specifying our new TrustManager
SSLContext_init.implementation = function (keyManager, trustManager, secureRandom) {
quiet_send('Overriding SSLContext.init() with the custom TrustManager');
SSLContext_init.call(this, null, TrustManagers, null);
};
Frida 执行上面的代码,再看下是否抓到包
这次就可以顺利的抓到数据了。
抓包工具推荐
虽然利用上面 Frida 的脚本可以成功抓包,但是上面的操作还是略显复杂,况且有的 App 还会有 Frida 检测,操作起来就难度骤升。
这里推荐一个抓包工具 httptoolkit,官网界面如下
使用起来也很简单
- 下载安装这个软件
- 连接手机
- 选择
Android Device Via ADB
选项卡 - 打开目标应用,开始抓包
看下这个软件的抓包效果
可以看到,数据都出来了并且不用额外的设置。
Xposed 方案
如果你手机刷了 Xposed,那就很简单了,只需要安装 JustTrustMe++
模块就可以了。安装之后,也可以通过 Charles
软件直接抓包了。
本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者没关系.
本文涉及到的代码项目可以去 爱码者说 知识星球自取,欢迎加入知识星球一起学习探讨技术。
关注公众号 爱码者说 及时获取最新推送文章。