title: 抓包
categories: 逆向與協議分析
toc: true
mathjax: true
tags:
- 抓包
- 協議分析
- 逆向
widgets: - type: toc
position: left - type: profile
position: left
author: RunopeAuthor title
author_title: 不知不論,不做不論Author's current location
location: Nanjin,jiangsuURL or path to the avatar image
avatar: https://en.gravatar.com/userimage/194935117/7129e2095de79a9dd97e5cc344acaba2?size=200Whether show the rounded avatar image
avatar_rounded: falseEmail address for the Gravatar
gravatar: 275358499@qq.comURL or path for the follow button
follow_link: 'https://github.com/runope' - type: recent_posts
position: left
要想徹底解決抓包問題,必須先了解計算機網絡的知識和抓包原理。
要講計算機網絡其實就不得不講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 查看是由哪個進程造成的。