抓包总结
背景
对于App的 逆向分析
,抓包
是一个绕不开的话题,同时 被抓包
我看来也算是一个App的命门吧。首先声明下,网上已经有很多大佬写了很详细的文章来介绍各种抓包场景,为什么我还要写,主要为自己能更好地理解,毕竟也是刚入门,嘿嘿。
关于抓包
前言
对于我们来说,所有数据都是通过标准协议的网络线路传输,所以关于抓包的一切都是以此为基础。从物理层开始,所有的数据就开始通过某种方式开始传输;不过幸运的是,对于我们来说一般只需要关心 网络层
or 传输层
or 它们的上层协议。常用的抓包分为 中间人攻击(mitm)
和 VPN抓包
两种方式。
中间人攻击
中间人攻击,是从英文 Man-in-the-middle attack
翻译过来的,缩写为 mitm
。
VPN抓包
通过自建VPN服务,对流量重定向。
多场景对抗
0x01 抓不到https包,APP可联网
这种情况,大概率是没有成功配置抓包环境,需要正确安装证书。网上有很多教程,就不展开讲了,我也讲不好。这里有一篇关于 Charles捕获HTTPS 原理的文章,感兴趣的可以看看。
0x02 抓不到包,APP可联网
首先确定app是可以上网的,但是抓不到包。那么可能会有以下情况:
- 流量没有走到代理抓包软件上
- 流量走的协议比较低,代理抓包软件没法代理
- 流量走的自己自建协议,代理抓包软件没法代理
第一种情况,是由于app在代码中设置了不走代理(okhttp如下)。1
OkHttpClient client = new OkHttpClient().newBuilder().proxy(Proxy.NO_PROXY).build();
针对这种情况,可以使用VPN将流量导向抓包工具,常见的有Postern
配合 Charles
使用Socks5
代理。
第二种情况,常见于某团系、某里系产品。但是在代码中一般有开关,可以通过hook
强行走http。1
2
3
4
5
6
7
8Java.perform(function () {
send("Inside java perform");
// disable socket connect
var tunnel2 = Java.use("com.guess.nvnetwork.tunnel2.a");
tunnel2.isSocketConnected.implementation = function () {
return false;
}
}
第三种情况,这种情况只能具体问题具体分析了,分析具体的组包、序列化的过程;最后通过逆向还原出来。
0x03 抓不到https包,APP不可联网
这种情况基本上就是APP开启SSL Pinning
。SSL Pinning
简单来说,就是应用程序中只信任固定证书或是公钥。而我们是使用的是抓包软件的证书,当然校验不过去,所以就断网了。针对SSL Pinning
,可以从两个角度去破解:
让客户端不校验证书
- 使用现成的
trust
模块,如JustTrustMe
- 逆向app,找校验的位置,bypass掉
Frida example for bypass okhttp1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42Java.perform(function () {
//okttp3.x unpinning
try {
var CertificatePinner = Java.use("okhttp3.CertificatePinner");
CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1){
// do nothing
console.log("Called! [Certificate]");
return;
};
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1){
// do nothing
console.log("Called! [List]");
return;
};
} catch (e) {
console.log("okhttp3 not found");
}
//okhttp unpinning
try {
var OkHttpClient = Java.use("com.squareup.okhttp.OkHttpClient");
OkHttpClient.setCertificatePinner.implementation = function(certificatePinner){
// do nothing
console.log("Called!");
return this;
};
// Invalidate the certificate pinnet checks (if "setCertificatePinner" was called before the previous invalidation)
var CertificatePinner = Java.use("com.squareup.okhttp.CertificatePinner");
CertificatePinner.check.overload('java.lang.String', '[Ljava.security.cert.Certificate;').implementation = function(p0, p1){
// do nothing
console.log("Called! [Certificate]");
return;
};
CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(p0, p1){
// do nothing
console.log("Called! [List]");
return;
};
} catch (e) {
console.log("okhttp not found");
}
}
- 使用现成的
让客户端信任抓包证书(硬编码校验服务器证书的情况并不适用)
- 换一个低安卓版本的(低于7.0)手机
- 将抓包工具的证书安装到系统根证书目录中
0x04 抓得到包,APP不可联网
这种情况很有可能是服务端校验了客户端证书,在这里我们不能控制服务端,所以只能拿到客户端证书导入抓包工具。拿到客户端的方法:
- 可以在assets、raw目录中找找看
- 逆向app,对证书进行提取
1
2
3
4
5
6
7
8
9
10
11
12
13Java.perform(function () {
var StringClass = Java.use("java.lang.String");
var KeyStore = Java.use("java.security.KeyStore");
KeyStore.load.overload('java.security.KeyStore$LoadStoreParameter').implementation = function (arg0) {
console.log("KeyStore.load1:", arg0);
this.load(arg0);
};
KeyStore.load.overload('java.io.InputStream', '[C').implementation = function (arg0, arg1) {
send(arg0)
console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1) : null);
this.load(arg0, arg1);
};
});