抓包
要想彻底解决抓包问题,必须先了解计算机网络的知识和抓包原理。
要讲计算机网络其实就不得不讲OSI七层模型。
这里就不重复赘述,详细介绍见:OSI七层模型与TCP/IP五层模型
如图,https和http在应用层,tcp和udp在传输层,socks在会话层,ip在网络层。
我们平时使用代理时,一般是通过给wifi设置http/https代理的方式进行抓包,这种抓包方式只是在应用层进行抓包。而很多包仅仅在应用层是抓不到的。此时我们要到更底层去抓,而从抓包方式来看,又分为两种。
-
基于中间人/流量转储的抓包:
优势:抓到的包全面、没有遗漏
劣势:遇到加密流量,得自己想办法解密,用wireshark在网络层抓包,遇到tls等只能看到密文
-
基于hook的抓包:
优势:抓的是加密前、解密后的数据,天生明文
劣势:不如前者全面,有些hook点难找
基于中间人/流量转储的抓包
大致方式如下:
协议层 | 抓包方法 |
---|---|
应用层 | Charles,Fiddler使用HTTP应用层代理抓包 |
传输层 | tcpdump工作在TCP传输层 ,Charlses socks5传输层 |
网络层 | Wireshark工作在网卡IP的网络层 |
应用层HTTP/HTTPS抓包
具体方法不赘述,说一些常见的检测和绕过。
两个API,查看当前系统是否挂了http代理:
System.getProperty(“http.proxyHost”)
System.getProperty(“http.proxyPort”);
网络层VPN抓包
Postern + Charles
搭建方法
vpn属于网络层,设置了vpn后,手机上会多一个接口,相当于加了一个虚拟网卡,所有的流量都会从这走。应用层和传输层的请求都可以拿到,还不会被上面提及的两个api所检测。
比如使用代理APP,postern
后,打开vpn服务,系统就会多一个tun0接口,如图:
路由表的第一条就指向了tun0
之后使用socks代理,将vpn连接到开启socks的抓包软件。将原本只能在应用层抓包的charles变为可以抓到网络层之上所有请求的工具。具体配置如下。
postern配置:
在配置规则中改为通过代理连接。
charles配置:
设置完之后,我们先在手机上安装charles证书,在charles界面点击Help--》SSL Proxying,里面有提示
在高版本的安卓上,用户安装的证书不会直接安装到系统根证书目录中,需要root手机后将证书移动到系统根证书目录中去。
当Charles的证书安装到系统根目录中去之后,系统就会信任来自Charles的流量包了,我们的抓包过程就会回归正常。完成后我们就可以通过中间人攻击的方式去抓取https的包了。
如果喜欢用burp,还可以加上burp
httpCanary
httpCanary是手机上的一个app抓包软件,采用vpn+中间人攻击的方法来抓包。
各种检验及绕过方法
api检测是否开启VPN以及绕过
两个api:
java.net.NetworkInterface.getName()
android.net.ConnectivityManager.getNetworkCapabilities()
第一个api会通过java.net.NetworkInterface.getName()是否等于“tun0”或“ppp0”来判断是否存在VPN。hook该api使其返回“rmnet_data1”,即可达到过vpn检测目的。
绕过:
第二个api,android.net.ConnectivityManager.getNetworkCapabilities()样例如下,这个是api23之后才加入的函数
双向证书(Https服务器校验客户端)
在许多业务非常聚焦并且当单一,比如行业应用、银行、公共交通、游戏等行业,C/S架构中服务器高度集中,对应用的版本控制非常严格,这时候就会在服务器上部署对app内置证书的校验代码。
中间人攻击中,单一通信已经分裂成两个互相独立的通信,这时候与服务器进行通信的已经不是app、而是Charles了,所以我们要将app中内置的证书导入到Charles中去。
这个操作要完成两项内容:
- 找到证书文件
- 找到证书密码
1.找证书文件:apk进行解包,直接过滤搜索后缀名为p12的文件即可,一般常用的命令为tree -NCfhl |grep -i p12。
2.找证书密码:
function hook_KeyStore_load() {
Java.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) {
printStack("KeyStore.load1");
console.log("KeyStore.load1:", arg0);
this.load(arg0);
};
KeyStore.load.overload('java.io.InputStream', '[C').implementation = function (arg0, arg1) {
printStack("KeyStore.load2");
console.log("KeyStore.load2:", arg0, arg1 ? StringClass.$new(arg1) : null);
this.load(arg0, arg1);
};
console.log("hook_KeyStore_load...");
});
}
有了证书和密码之后,就可以将其导入到抓包软件中,在Charles
中是位于Proxy
→SSL Proxy Settings
→Client Certificates
→Add
添加新的证书,输入指定的域名或IP使用指定的证书即可。
SSL Pinning Bypass(Https客户端代码校验服务器证书)
上文中我们还有一种情况没有分析,就是客户端并不会默认信任系统根证书目录中的证书,而是在代码里再加一层校验,这就是证书绑定机制——SSL pinning
,如果这段代码的校验过不了,那么客户端还是会报证书错误。
遇到这种情况的时候,我们一般有三种方式,当然目标是一样的,都是hook
住这段校验的代码,使这段判断的机制失效即可。
hook
住checkServerTrusted
,将其所有重载都置空;
function hook_ssl() {
Java.perform(function() {
var ClassName = "com.android.org.conscrypt.Platform";
var Platform = Java.use(ClassName);
var targetMethod = "checkServerTrusted";
var len = Platform[targetMethod].overloads.length;
console.log(len);
for(var i = 0; i < len; ++i) {
Platform[targetMethod].overloads[i].implementation = function () {
console.log("class:", ClassName, "target:", targetMethod, " i:", i, arguments);
//printStack(ClassName + "." + targetMethod);
}
}
});
}
- 使用
objection
,直接将SSL pinning
给disable
掉
# android sslpinning disable
图2-20 使用objection
的ssl pinning diable
功能
- 如果还有一些情况没有覆盖的话,可以来看看大佬的代码
-
目录ObjectionUnpinningPlus增加了ObjectionUnpinning没覆盖到的锁定场景.(objection)
- 使用方法1 attach : frida -U com.example.mennomorsink.webviewtest2 —no-pause -l hooks.js
-
使用方法2 spawn : python application.py com.example.mennomorsink.webviewtest2
- 更为详细使用方法:参考我的文章 Frida.Android.Practice(ssl unpinning) 实战ssl pinning bypass 章节 .
-
ObjectionUnpinningPlus hook list:
- SSLcontext(ART only)
- okhttp
- webview
- XUtils(ART only)
- httpclientandroidlib
- JSSE
- network_security_config (android 7.0+)
- Apache Http client (support partly)
- OpenSSLSocketImpl
- TrustKit
应该可以覆盖到目前已知的所有种类的证书绑定了。
网络层wireshark
- 手机上直接安装kali nethunter,直接在手机上跑kali运行wireshark来抓包。
- 制作路由器,手机连热点。
- 一般专门做协议这块的公司会有专门的抓包机。也就是连着网卡的虚拟机,其实和自己做路由器抓差不多
基于hook的抓包
SSL双向认证抓包
通用的解决办法可以用ssl_logger抓包:
https://github.com/google/ssl_logger
https://sec.mrfan.xyz/2019/12/16/安卓测试之Hook SSL_read和SSL_write/
https://curz0n.github.io/2020/08/15/android-ssl-and-intercept/
socket抓包
当使用Charles抓包的时候,会发现针对某些IP的数据传输一直显示CONNECT,无法Complete,显示Sending request body,并且数据包大小持续增长,这时候说明我们遇到了Socket端口通信。
Socket端口通信运行在会话层,并不是应用层,Socket抓包的原理与应用层Http(s)有着显著的区别。准确的说,Http(s)抓包是真正的“中间人”抓包,而Socket抓包是在接口上进行转储;Http(s)抓包是明显的将一套C/S架构通信分裂成两套完整的通信过程,而Socket抓包是在接口上将发送与接收的内容存储下来,并不干扰其原本的通信过程。
对于安卓应用来说,Socket通信天生又分为两种Java层Socket通信和Native层Socket通信。
java层Socket通信
使用的是java.net.InetAddress、java.net.Socket、java.net.ServerSocket等类,与证书绑定的情形类似,也可能存在着自定义框架的Socket通信,这时候就需要具体情况具体分析,比如谷歌的protobuf框架等;
native层socket通信
libc/send/recv,libssl/SSL_read/write,其中udp还可能用recvfrom()/sendto()
Frida $Okhttp : 系统库,ok(3), okhttp3logging, Retrofit
Frida $Java : Socket,XMPP, WEBSoket, Protobuf
抓包+逆向app分析protobuf:https://mp.weixin.qq.com/s/gMhztldG-0Xy_euX1wpZbw
Frida $Native: libc/send/recv,libssl/SSL_read/write
路由转储: WireShark,tcpdump,jnettop,nethogs,pcap
jnettop监听所选择网络接口的流量,并以表格的形式显示当前的使用量。像“为什么我的网速这么慢呢?!”这样的问题它可以直接回答。
NetHogs 打破了网络流量按协议或子网进行统计的惯例,它以进程来分组。所以,当网络流量猛增时,你可以使用 NetHogs 查看是由哪个进程造成的。