本文介紹一種在 Andorid 中實(shí)現(xiàn)單應(yīng)用、全局、優(yōu)雅的抓包方法。
本文于去年端午節(jié)編寫(xiě),由于種種原因,當(dāng)時(shí)藏拙并未發(fā)布。現(xiàn)刪除一些敏感信息后分享出來(lái),希望對(duì)各位有所幫助。
背景
昨天在測(cè)試一個(gè) Android APK 的時(shí)候發(fā)現(xiàn)使用 WiFi 的 HTTP 代理無(wú)法抓到包,在代理的日志中沒(méi)有發(fā)現(xiàn)任何 SSL Alert,因此可以判斷不是證書(shū)問(wèn)題;另外 APP 本身仍可以正常收發(fā)數(shù)據(jù),這說(shuō)明代理設(shè)置被應(yīng)用繞過(guò)了。
根據(jù)我們前一篇文章(終端應(yīng)用安全之網(wǎng)絡(luò)流量分析)中所介紹的,遇到這種情況時(shí)就可以使用路由抓包方法,確保接管所有流量。但是因?yàn)槎宋绶偶俦环庥≡诩遥矣糜谧グ?a href="http://www.asorrir.com/v/tag/481/" target="_blank">樹(shù)莓派放在了公司,因此只有另謀他路。
本來(lái)接著考慮裝個(gè) DroidProxy 去試一下,但突然間靈光一閃,為什么不直接用 iptables 去修改流量呢?于是,就有了這篇小記。
iptables 101
iptables
應(yīng)該大家都不會(huì)陌生,說(shuō)起來(lái)這也是我入門(mén) “黑客” 時(shí)就接觸的命令,因?yàn)槲业木W(wǎng)絡(luò)安全入門(mén)第一戰(zhàn)就是使用aircrack
去破解鄰居的 WiFi 密碼。多年以前還寫(xiě)過(guò)一篇Linux內(nèi)核轉(zhuǎn)發(fā)技術(shù),介紹 iptables 的常用操作,但當(dāng)時(shí)年幼無(wú)知,很多概念自己并沒(méi)有完全理解。其實(shí)介紹 iptables 最好的資料就是官方的man-pages,因此這里也就不做一個(gè)無(wú)情的翻譯機(jī)器人了,只簡(jiǎn)單介紹一些關(guān)鍵的概念。
basic
首先是我們作為系統(tǒng)管理員最為關(guān)心的命令行參數(shù),在坊間流傳的各類(lèi)防火墻、WiFi 熱點(diǎn)、流控 shell 腳本中,充斥著各種混亂而難以理解的 iptables 命令,但實(shí)際上其命令行參數(shù)非常優(yōu)雅,可以概況為以下表述:
iptables[-ttable]{-A|-C|-D}chainrule-specification
rule-specification=[matches...][target]
match=-mmatchname[per-match-options]
target=-jtargetname[per-target-options]
一個(gè) table 中有多個(gè) chain,除了內(nèi)置的 chain,用戶(hù)也可以自己新建(比如 DOCKER 鏈)。常用的 table 及其包含的 chain 有以下這些:
-
?filter
-
?INPUT
-
?FORWARD
-
?OUTPUT
-
-
?nat
-
?PREROUTING
-
?INPUT
-
?OUTPUT
-
?POSTROUTING
-
-
?mangle
-
?PREROUTING
-
?OUTPUT
-
?INPUT
-
?FORWARD
-
?POSTROUTING
-
-
?raw
-
?PREROUTING
-
?OUTPUT
-
其中有的表比其他表包含更多的 chain,這是其定位決定的。正如其名字而言,filter主要用于流量過(guò)濾,nat表主要用于網(wǎng)絡(luò)地址轉(zhuǎn)換,mangle表用于數(shù)據(jù)包修改,而raw表則用于網(wǎng)絡(luò)包更早期的配置。除此之外還有security表用于權(quán)限控制,不過(guò)用得不多。
雖然看起來(lái)各個(gè)表各司其職,但實(shí)際中也沒(méi)有強(qiáng)制的差異。比如 mangle 表雖然用來(lái)修改流量,但也可以用來(lái)做網(wǎng)絡(luò)地址轉(zhuǎn)換,filter 表也是同理。在日常中設(shè)置 iptables 規(guī)則的時(shí)候主要考慮的是數(shù)據(jù)包的時(shí)序,而這和 chain 的關(guān)系更大一些。
上面提到的這些常見(jiàn) chain,不管在哪個(gè)表中,其含義都是類(lèi)似的:
-
? INPUT: 表示數(shù)據(jù)包從遠(yuǎn)端發(fā)送到本地;
-
? OUTPUT: 表示數(shù)據(jù)包在本地生成,并準(zhǔn)備發(fā)送到遠(yuǎn)端;
-
? PREROUTING: 接收到數(shù)據(jù)包的第一時(shí)間,在內(nèi)核進(jìn)行路由之前;
-
? POSTROUTNG: 表示數(shù)據(jù)包準(zhǔn)備離開(kāi)的前一刻;
-
? FOWARD: 本機(jī)作為路由時(shí)正要準(zhǔn)備轉(zhuǎn)發(fā)的時(shí)刻;
table 結(jié)合對(duì)應(yīng)的 chain,網(wǎng)絡(luò)數(shù)據(jù)包在 iptables 中的移動(dòng)路徑如下圖所示:

extensions
對(duì)于iptables
而言重點(diǎn)無(wú)疑是其中的規(guī)則定義,上文提到的參數(shù)無(wú)非就是將自定義的規(guī)則加入到對(duì)應(yīng) CHAIN 之中,比如-A
是將規(guī)則插入到鏈的末尾(append),-I
是插入到鏈的頭部(insert),-D
是刪除對(duì)應(yīng)規(guī)則(delete),等等。
而規(guī)則又分為兩個(gè)部分,即數(shù)據(jù)包匹配以及匹配之后的操作,分別通過(guò)-m
和-j
來(lái)指定。這其中就引入了成百的命令行參數(shù),以至于社區(qū)還就此產(chǎn)生了不少段子:
Overheard:“Inanyteamyouneedatank,ahealer,adamagedealer,someonewithcrowdcontrolabilitiesandanotheronewhoknowsiptables”
—JéromePetazzoni(@jpetazzo)June27,2015
不過(guò)實(shí)際上社區(qū)對(duì) iptables 的抱怨更多是在多用戶(hù)系統(tǒng)中規(guī)則配置沖突以及由此引發(fā)的艱難調(diào)試之旅,在沒(méi)有沖突的情況下,配置規(guī)則也是比較簡(jiǎn)單的。定義 iptables 規(guī)則的參考主要是iptables-extensions(8),其中定義了一系列匹配拓展(MATCH EXTENSIONS)以及 **目標(biāo)拓展(TARGET EXTENSIONS)**。
match
先看匹配拓展,一般我們使用 iptables 都是根據(jù) ip 或者端口進(jìn)行匹配,比如-m tcp --dport 22
。但其中也有一些比較有趣的匹配規(guī)則,比如上一篇文章中介紹過(guò)的 Android 單應(yīng)用抓包方法:
$iptables-AOUTPUT-mowner--uid-owner1000-jCONNMARK--set-mark1
$iptables-AINPUT-mconnmark--mark1-jNFLOG--nflog-group30
$iptables-AOUTPUT-mconnmark--mark1-jNFLOG--nflog-group30
$dumpcap-inflog:30-wuid-1000.pcap
用到了兩個(gè)匹配拓展,一個(gè)是owner
拓展,使用--uid-owner
參數(shù)表示創(chuàng)建當(dāng)前數(shù)據(jù)包的應(yīng)用 UID。但是這樣只能抓到外發(fā)的包,而服務(wù)器返回的包由于并不是本地進(jìn)程創(chuàng)建的,因此沒(méi)有對(duì)應(yīng)的 UID 信息,因此 owner 拓展只能應(yīng)用于OUTPUT
或者POSTROUTING
鏈上。為了解決這個(gè)問(wèn)題,上面使用了另一個(gè)拓展connmark
,用來(lái)匹配 tcp 連接的標(biāo)志,這個(gè)標(biāo)志是在第一條命令中的外發(fā)數(shù)據(jù)中進(jìn)行設(shè)置的。
還有個(gè)值得一提的匹配拓展是bpf
,支持兩個(gè)參數(shù),可以使用--object-pinned
直接加載編譯后的 eBPF 代碼,也可以通過(guò)--bytecode
直接指定字節(jié)碼。直接指定的字節(jié)碼格式類(lèi)似于tcpdump -ddd
的輸出結(jié)果,第一條是總指令數(shù)目。
例如以下 bpf 指令 (ip proto 6):
4#numberofinstructions
48009#loadbyteip->proto
21016#jumpequalIPPROTO_TCP
6001#returnpass(non-zero)
6000#returnfail(zero)
實(shí)際調(diào)用時(shí)候需用用逗號(hào)分隔每條指令,且不支持注釋等其他符號(hào):
iptables-AOUTPUT-mbpf--bytecode'4,48009,21016,6001,6000'-jACCEPT
對(duì)于其他遇到的匹配拓展,可以在官方文檔中查看其詳細(xì)用法。
target
target 表示數(shù)據(jù)包匹配之后要執(zhí)行的操作,一般使用大寫(xiě)表示。標(biāo)準(zhǔn)操作有 ACCEPT/DROP/RETURN 這三個(gè),其他都定義在 target extensions 即目標(biāo)拓展中。
比如我們前面提到的CONNMARK
就是其中一個(gè)拓展,其作用是對(duì)當(dāng)前鏈接進(jìn)行打標(biāo),這樣 TCP 請(qǐng)求的返回?cái)?shù)據(jù)也會(huì)帶上我們的標(biāo)記。類(lèi)似的還有MARK
拓展,表示對(duì)當(dāng)前數(shù)據(jù)包設(shè)置標(biāo)志,主要用于后續(xù) table/chain 的識(shí)別。
前面用到的另一個(gè)拓展是NFLOG
,表示 netfilter logging,規(guī)則匹配后內(nèi)核會(huì)將其使用對(duì)應(yīng)的日志后端進(jìn)行保存,通常與nfnetlink_log
一起使用,通過(guò)多播的方式將獲取到的數(shù)據(jù)包發(fā)送到netlink
套接字中,從而可以讓用戶(hù)態(tài)的抓包程序獲取并進(jìn)行進(jìn)一步分析。
其他常用的拓展還有SNAT/DNAT
用于修改數(shù)據(jù)包的源地址和目的地址,LOG
可以使內(nèi)核 dmesg 打印匹配的數(shù)據(jù)包信息,TRACE
可以使內(nèi)核打印規(guī)則信息用于調(diào)試分析等。
Android Proxy
復(fù)習(xí)完 iptables 的基礎(chǔ)后,我們繼續(xù)回到文章開(kāi)頭的問(wèn)題,有什么辦法可以在不設(shè)置代理的基礎(chǔ)上代理所有流量呢?
這個(gè)問(wèn)題可以從兩方面去考慮,即:
-
1. 如何匹配目標(biāo)數(shù)據(jù)包;
-
2. 匹配之后如何轉(zhuǎn)發(fā)到代理地址;
第一個(gè)問(wèn)題比較簡(jiǎn)單,我們需要匹配從本地發(fā)出的,目的端口是 80/443 的 tcp 流量,因此匹配規(guī)則可以寫(xiě)為:
-ptcp-mtcp--dport443
在不確定目標(biāo) web 服務(wù)器端口的情況下,可以將 dport 指定為0:65535
,對(duì)所有端口都進(jìn)行劫持轉(zhuǎn)發(fā);當(dāng)然也可以直接不寫(xiě) match,默認(rèn)就是匹配所有 tcp 包。不過(guò)可以稍微過(guò)濾一下目的地址,比如! -d 127.0.0.1
,以免本地的 RPC 請(qǐng)求也被誤攔截。
或者,更優(yōu)雅的方案是使用multiport
來(lái)一次性指定多個(gè)端口:
-mmultiport--dports80,443
第二個(gè)問(wèn)題,既然我們需要將流量轉(zhuǎn)發(fā)到代理工具,那么可以選擇透明代理模式,上篇文章也有提到過(guò)。因此一個(gè)最簡(jiǎn)單的方法是使用 DNAT 修改目的地址。查閱文檔可知,DNAT 只能用在nat
表中的PREROUTING
和OUTPUT
鏈。再根據(jù)上文中的流程圖,如果代理地址在本地,那只能使用 OUTPUT、如果是遠(yuǎn)程地址,那么兩個(gè)鏈任選一個(gè)即可。
綜上所述,假設(shè) HTTP 透明代理監(jiān)聽(tīng)在127.0.0.1:8080
,那么可以直接用以下方法設(shè)置代理并進(jìn)行抓包:
iptables-tnat-AOUTPUT-ptcp!-d127.0.0.1-mmultiport--dports80,443-jDNAT--to-destination127.0.0.1:8080
更進(jìn)一步
通過(guò)這么一條 iptables 命令,配合上透明代理就可以實(shí)現(xiàn)全局的 HTTPS 抓包了。所以就這樣了嗎?回憶一下之前我們其實(shí)是可以通過(guò)owner
target 去進(jìn)行 UID 匹配的,只不過(guò)之前是使用 NFLOG 配合 tcpdump 進(jìn)行抓包。因此我們其實(shí)也可以通過(guò)類(lèi)似的方式實(shí)現(xiàn)基于 UID 的透明代理。
轉(zhuǎn)發(fā)規(guī)則并沒(méi)有太大變化,只需要在匹配規(guī)則上新增一個(gè)約束。
iptables-tnat-AOUTPUT-ptcp!-d127.0.0.1-mowner--uid-owner2000-mmultiport--dports80,443-jDNAT--to-destination127.0.0.1:8080
這樣,不需要額外的路由抓包設(shè)備,甚至不需要引入 VPN Service 等其他應(yīng)用,只需要一行命令即可實(shí)現(xiàn)針對(duì)單個(gè) Android 應(yīng)用的全局 HTTP/HTTPS 抓包。
elegant總結(jié)
本文主要介紹了 iptables 規(guī)則的配置方法,并且實(shí)現(xiàn)了一種在 Android 中全局 HTTP(S) 抓包的方案,同時(shí)借助owner
拓展實(shí)現(xiàn)應(yīng)用維度的進(jìn)一步過(guò)濾,從而避免手機(jī)中其他應(yīng)用的干擾。
相比于傳統(tǒng)的 HTTP 代理抓包方案,該方法的優(yōu)勢(shì)是可以實(shí)現(xiàn)全局抓包,應(yīng)用無(wú)法通過(guò)禁用代理等方法繞過(guò);而相比于 Wireshark 等抓包方案,該方法基于透明代理,因此可以使用 BurpSuite、MITMProxy 等成熟的 HTTP/HTTPS 網(wǎng)絡(luò)分析工具來(lái)對(duì)流量進(jìn)行快速的可視化、攔截/重放,以及腳本分析等操作,這些優(yōu)勢(shì)是傳統(tǒng)抓包方案所無(wú)法比擬的。
iptables-tnat-AOUTPUT-ptcp!-d127.0.0.1-mowner--uid-owner2000-mmultiport--dports80,443-jDNAT--to-destination<burp ip:port>
(1).-t nat -A OUTPUT 使用nat表,在OUTPUT鏈追加規(guī)則
(2).-p tcp 指定只過(guò)濾tcp協(xié)議
(3).!d 127.0.0.1 不誤傷回環(huán)包,很?chē)?yán)謹(jǐn)!
(4).-mowner--uid-owner2000 通過(guò)uid指定只看單個(gè)應(yīng)用的數(shù)據(jù)包
(5).-mmultiport--dports80,443 優(yōu)雅的一次性指定多個(gè)目標(biāo)端口,owsap wstg上分2條命令不夠優(yōu)雅!
(6).-jDNAT--to-destination<burp ip:port> 使用DNAT 即修改目標(biāo)地址到您的透明代理地址上,記得勾選 invisible proxy哦!
(7).iptables-tnat-F 搞事結(jié)束,清場(chǎng)恢復(fù)!
(8).驗(yàn)證查看轉(zhuǎn)發(fā)效果,可使用提供的debug版AOSP rom,開(kāi)啟adb root(高權(quán)限啟動(dòng)tcpdump),結(jié)合新版wireshark有線(xiàn)接口選擇捕獲android wlan0接口的數(shù)據(jù)包,完美驗(yàn)證!
(9).https如果有證書(shū)pin的 還是要hook搞定下,否則信任鏈不通數(shù)據(jù)包
審核編輯 :李倩
-
服務(wù)器
+關(guān)注
關(guān)注
13文章
9706瀏覽量
87327 -
數(shù)據(jù)包
+關(guān)注
關(guān)注
0文章
269瀏覽量
24895
原文標(biāo)題:參考鏈接
文章出處:【微信號(hào):哆啦安全,微信公眾號(hào):哆啦安全】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
一種基于IP包的單向文件廣播傳輸方法
以一種更優(yōu)雅的方式去實(shí)現(xiàn)一個(gè)Verilog版的狀態(tài)機(jī)
利用golang優(yōu)雅的實(shí)現(xiàn)單實(shí)例分享
一種丟包環(huán)境下的線(xiàn)性差錯(cuò)控制編碼方法
一種特殊陣列實(shí)現(xiàn)DOA估計(jì)的方法
一種基于包的邏輯內(nèi)置自測(cè)試電路設(shè)計(jì)方法
一種新的基于全局特征的極光圖像分類(lèi)方法

三種全局變量和全局函數(shù)的三種基本方法
一種分析繞組電氣參數(shù)對(duì)不同種類(lèi)變形的全局靈敏度方法
一種基于排序?qū)W習(xí)的軟件眾包任務(wù)推薦方法

一種AUTOSAR軟件架構(gòu)中RTE的實(shí)現(xiàn)方法
滲透測(cè)試過(guò)程中所使用的抓包方法
如何抓取app數(shù)據(jù)包 網(wǎng)絡(luò)抓包原理及實(shí)現(xiàn)

一種利用wireshark對(duì)遠(yuǎn)程服務(wù)器/路由器網(wǎng)絡(luò)抓包方法

評(píng)論