wireshark 過濾表達式的比較運算符一覽 (類 C 形式和對應的英語形式)
enighish C-like 含義和實例
eq == 等于 ip.src == 10.0.0.5
ne != 不等于 ip.src != 10.0.0.5
gt > 大于 frame.len > 10
lt < 少于 frame.len < 128
ge >= 大于等于 frame.len ge 0x100
le <= 小于等于 frame.len <= 0x20
注意, ip.len le 1500 這里的 "ip.len" 含義是,從網絡層分組的 IP 頭部算起,加上傳輸層分段頭部,加上應用層數據,
總長度小于200字節,同理,"frame.len"需要從鏈路層乙太網幀頭開始計算;
默認情況下,wireshark 主界面最上方的數據包概況的 length 字段,計算的是從鏈路層乙太網幀頭開始計算的大小,我們可以
通過 ip.len , tcp.len , udp.len 等來指定從數據包的哪一層開始計算大小并顯示
一個簡單的捕獲實例分析如下:
【常用的捕捉過濾表達式】
僅捕獲來自或去往 192.168.1.0 網段中的數據包
net 192.168.0.0/24
注意,以 net 操作符開頭的過濾表達式不支持顯示過濾,僅支持捕獲時過濾,并且只要是用于捕捉過濾表達式的關鍵字,都不能用于顯示過濾表達式,反之亦然
僅捕獲來自或去往 192.168.0.1 主機的數據包
host 172.18.5.4
僅捕獲來自 192.168.0.0.1 主機的數據包
src host 192.168.0.1
僅捕獲與 www.evil.com 的通信中,非 HTTP 協議以及非 SMTP 協議的數據包
host www.evil.com and not (port 80 or port 25)
僅捕獲 TCP 協議,并且端口在 1501~1549 的數據包
tcp portrange 1501-1549
注意,關鍵字“portrange”僅支持 libpcap 0.9.1 以及更新版本,如果是 0.9.1 以前的版本,使用下面過濾表達式:
(tcp[0:2] > 1500 and tcp[0:2] < 1550) or (tcp[2:2] > 1500 and tcp[2:2] < 1550)
其中,
tcp[0:2] 表示從 TCP 分段頭部的第一個字節開始(0+1),總長度為2字節(2)的字節序列,而這就是源端口號
tcp[2:2] 表示從 TCP 分段頭部的第三個字節開始(2+1),總長度為2字節(2)的字節序列,而這就是目的端口號
上面這種語法:
一,支持捕捉過濾與顯示過濾
二,支持匹配 IP 分組頭部,TCP分段頭部,UDP 用戶數據報頭部,ICMP 網際控制消息協議數據包,以太網數據幀,以及其它多種格式的數據包頭部結構中特定的字段(字節序列),
考慮如下過濾表達式
ip[8:1]==1
僅顯示 IP 從分組頭部的第九個字節開始(8+1),總長度為1字節(1),其“值”為 10進制1 的數據包
查看相關 RFC 文檔對 IP 分組頭部結構的定義,其第九個字節為 TTL(Time To Live),這將會顯示所有 IP 分組頭部的 TTL=1 的數據包
為什么 TTL 的值如此重要?
我們知道,UNIX / Linux 平臺的 traceroute 工具,以及 windows 平臺的 tracert 工具,用來檢測并輸出與指定目標之間,經過的所有網絡設備或主機節點,
每經過一個節點,計算為一跳(hop),正常情況下,源主機發出的數據包,為了保證能順利到達目的主機,其 TTL 值應該在 40 以上,因為中間經過的每個節點會將收到的數據包 TTL 值減 1,然后判斷其值是否為 0,如果不為 0,則轉發該數據包給下一跳,如果為 0,直接丟棄這個數據包,然后給源主機回送一個 ICMP 類型為11(Time to live exceeded in transit,傳輸中 TTL 值耗盡)的數據包,
注意,
一,這個回送的 ICMP 包,其 IP 頭部的 TTL 值不可能為 1,至少也在40以上,否則當它被“前一跳”接收時,前一跳節點減去1后,判斷其為0,則直接丟棄,那么這個通知 TTL值耗盡的數據包就不可能正確的回傳給源主機
二,這個回送的 ICMP 包,其 IP 頭部的源地址字段,就是這個節點自身的 IP 地址
tracert / traceroute 工具正是利用了上述這兩個特性,向因特網上發出目標地址相同,但是每次 TTL 值 遞增1 的數據包,它首先發出的數據包 TTL=1,然后接收到的第一個節點將其減 1 后判斷,發現其為 0,于是丟棄這個數據包,向源主機返回 TTL 耗盡的 ICMP包,這個數據包的源地址字段,泄漏了第一個節點的 IP 地址給源主機上的 tracert / traceroute 進程,后者向屏幕輸出相關 IP信息,
同理,源主機發出的第二個數據包 TTL=2,第一個節點收到后減 1,判斷不為 0,于是轉發給“下一跳”,第二個節點收到后減 1,判斷為 0,丟棄,然后返回給源主機一個 TTL耗盡的 ICMP 包,其中帶有第二個節點的 IP 地址,于是源主機上的 tracert / traceroute 進程繼續向屏幕輸出相關信息。。。。
多數情況下,地球上實際距離再遠的兩個主機,中間的節點數也不會超過 40,因此利用上述原理,tracert / traceroute 進程只需發出 10 或 20 個 TTL 分別為1~10 或者 1~20 的“探測”包,就可以向用戶展示中間經過的所有設備列表
試想,我們運行 wireshark 的主機剛好位于第 5 個節點,那么源主機發來的 TTL=5 的探測包,將在經過前面 “4 跳”后,到達我們的主機上,其 TTL=1,于是 wireshark 的 ip[8:1]==1 表達式可以用來捕獲探測本機是否存在的數據包,并且我們可以從捕獲的這個探測包的源 IP 地址,查詢到發出探測包的源主機的物理地址
當我們運行 wireshark 的 Linux 主機是作為源主機想要探測的目標的前端網關防火墻時,這點尤其重要:我們可以將 wireshark 捕獲的 TTL=1 數據包的源 IP ,加入到 iptables 的入站鏈中并丟棄,或者設置成轉發給我們后臺的服務器,但是不向源主機回送 TTL 耗盡的數據包,避免泄漏我們的網關防火墻 IP 地址
回想一下你用使用 tracert / traceroute 的經驗,是不是曾經碰到過,中間“某一跳”的 IP 部分為 * * *
就是這個道理
下面的截圖驗證了上面一堆廢話:
*****僅捕獲“單播”流量,如果你只想捕獲進出本機的數據包,使用下面的表達式可以幫助你排除本地網絡中的“噪聲”———例如廣播和組播通告:
not broadcast and not multicast
*****不要被下面這個看起來很復雜的表達式嚇到,它的效果是僅捕捉使用 HTTP 的 GET 請求方法的數據包:
port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420
我們來分析一下這個表達式的語義,首先,port 80 指定 HTTP 協議,童鞋們應該都知道,
再來,HTTP 的請求方法是緊隨在 TCP 頭部后面的字段,其中,ASCII 字符的“G”,其16進制為 0x47,字符“E”的16進制為 0x45,字符“T”的16進制為
0x54,
在 HTTP 1.1 標準中,要求在方法名稱后接一個“空格”字符,這個不可打印的空格字符,其16進制為 0x20,
于是我們知道,捕獲 TCP 頭部后面為 0x47455420 的4字節序列(GET加上空格字符共4字節),就等于捕獲了 HTTP GET 請求數據包,
我們還需要知道 TCP 頭部的長度為多少字節,這樣才能定位16進制值的 “GET[space]” 字串的準確位置,
從每個數據包的 TCP 頭部的第十三個字節開始,長度為4位(bit,比特)的半個字節(1 byte = 8 bits),給出了該數據包的 TCP 頭部長度,因此,上面表達式中的 tcp[12:1] 部分,先獲取 TCP 頭部的第十三個字節(12+1=13),但是由于頭部長度信息只保存在該字節的前面4位中,因此 (tcp[12:1] & 0xf0) >> 2 的作用就是扣掉后面的4位(這4位屬于6位“保留位”中的前4位),計算出 TCP 頭部的“凈”長度,
得出 TCP 頭部長度后,例如典型的20字節,那么從第二十一個字節開始,長度為4字節的字節序列,就是 HTTP 的請求方法,對應上面表達式的 tcp[((tcp[12:1] & 0xf0) >> 2):4] 部分
綜上所述,
port 80 指定 HTTP 協議
tcp[((tcp[12:1] & 0xf0) >> 2):4] 定位 HTTP 請求方法 字段
0x47455420 指定 HTTP 請求方法為 GET[space]
對上面內容感覺頭暈的童鞋,請參考下面的 TCP 頭部結構示意圖,這樣就一目了然
*****下面這個表達式用來捕捉“沖擊波”蠕蟲病毒產生的網絡通信流量,它利用的是 RPC 協議的漏洞:
dst port 135 and tcp port 135 and ip[2:2]==48
Welchia 蠕蟲同樣利用 RPC 協議的漏洞,但是我們有更好的檢測這只蠕蟲的捕捉表達式:
icmp[icmptype]==icmp-echo and ip[2:2]==92 and icmp[8:4]==0xAAAAAAAA
我們來分析一下該表達式的語義,它搜索長度為92字節的 icmp echo request
(ICMP 回顯請求)數據包,而且該ICMP數據包的有效載荷起始部分為連續4字節長的16進制值0xAA,而這就是當Welchia 蠕蟲嘗試危害一個系統前的特征
*****許多蠕蟲嘗試通過與其它主機上的 135,445,1433 端口建立連接,來進行傳播,
下面這則捕捉過濾表達式,可以檢測絕大多數類型的蠕蟲,因為它可以捕捉那些來自本地局域網中的目標端口為 135,445,1433 的 TCP SYN 數據包(請求連接,SYN 標識位的值不為 0 )
dst port 135 or dst port 445 or dst port 1433 and tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) = 0 and src net 192.168.0.0/24
是系統管理員或運維工程師的童鞋,可以用上面介紹的三則捕捉過濾表達式,來檢測你的局域網中是否有機器感染了蠕蟲病毒,而且正在嘗試進行傳播,感染其它機器
還有一件事需要注意,如果你用 SSH 遠程連接到服務器(包括 Linux 下的 OpenSSH 以及 windows 下的 3389 終端),并且在服務器上運行 wireshark ,那么 wireshark 會通過檢測“環境變量”來智能的過濾掉你與服務器通信的流量,這里過濾的意思是不顯示或不捕捉,而非防火墻那樣阻擋數據包;
下面列出這些 wireshark 可能會探測的環境變量,并且給出相應的“默認過濾”表達式;如果你想要 wireshark 在服務器上捕捉或顯示你與服務器的遠程通信流量,只需要將這些表達式中的 not 關鍵字移除即可,
其中,
*****粗體關鍵字 srcport srchost dstport dsthost
需要分別替換成你的 SSH 通信的源端口,源主機 IP 地址,目標端口,目標主機 IP 地址,注意,由于 TCP 通信管道是雙向的,這意味著,srcport 可能是你托管機房中的 SSH 服務器的端口 22;也可能是你的 SSH 客戶端的臨時動態端口;需要根據具體情況賦值(取決于你要查看的是那個方向上的流量),其它三個關鍵字也是同理;
*****粗體關鍵字 addr_family 的取值只能有2種: “ip” 或 “ip6”,分別對應 IPv4 與 IPv6
Environment Variable
Resultant Filter
SSH_CONNECTION not (tcp port srcport and addr_family host srchost and tcp port dstport and addr_family host dsthost)
SSH_CLIENT
not (tcp port srcport and addr_family host srchost and tcp port dstport)
REMOTEHOST
not addr_family host host
DISPLAY not addr_family host host
CLIENTNAME
not tcp port 3389
上面內容援引自
http://wiki.wireshark.org/CaptureFilters#Further_Information
【常用的顯示過濾表達式】
僅顯示帶有目標IP層廣播地址的數據包
ip.dst==255.255.255.255
僅顯示帶有目標鏈路層廣播地址的數據包
arp
在顯示過濾表達式中,邏輯運算符 == 等同于 eq
但是需要注意,使用 eq 時,前后的比較值必須有空格,而 == 不需要與前后的比較值留空格
( and 與 && 也是同理)
例如
ip.src eq 192.168.10.0/24 and ip.dst eq 192.168.10.0/24
等同于
ip.src==192.168.10.0/24&&ip.dst==192.168.10.0/24
等同于
ip.src == 192.168.10.0/24 && ip.dst == 192.168.10.0/24
上面是僅顯示局域網中主機(工作站)與主機之間,或者主機與內網服務器(以及網關)之間的通信流量,不包含
從內網到外部網絡以及到Internet的通信流量,這對處在“混雜模式”工作狀態的網卡,用來檢測內網主機之間的掃描,攻擊流量(例如ARP欺騙),有一定的幫助
僅顯示“帶有特定的發送端建議接收端設置的接收窗口大小值的數據包”
tcp.window_size == 64239
這個表達式會匹配在數據包列表的 Info 字段的所有 Win=64239 的數據包
參考下面這張截圖:
僅顯示TCP頭部中標志字段中的SYN與ACK位被“置位”(設置為1)的數據包
tcp.flags.syn == 1 and tcp.flags.ack ==1
僅顯示TCP頭部中標志字段中的PSH與ACK位被“置位”(設置為1)的數據包
tcp.flags.push eq 1&&tcp.flags.ack eq 1
一種標識由 windows 主機發送和接收的數據包的辦法
smb || nbns || dcerpc || nbss || dns
檢測本地或者內網中是否存在沖擊波蠕蟲病毒(Sasser worm)的方法
ls_ads.opnum==0x09
僅顯示UDP(用戶數據報)的有效載荷起始處包含 0x81 0x60 0x03 這3個字節序列的任意數據包,(每字節,如0x81,占8位)
并且跳過占8個字節的UDP頭部,也就是說,從第9個字節開始計算,總長度為3字節的 81 60 03 字節序列,
注意這3個字節序列的值僅意味著16進制表示法。(用于匹配本地的,非開放式的分組協議)
udp[8:3]==81:60:03
類似的還有
eth.src[4:2]==78:e9
在上面這個例子中,將從以太網 MAC 源地址的第5位開始計算,總長度為2字節,并且匹配 78 e9 字節序列的數據包,
例如,源 MAC 地址為 00:00:29:4c:78:e9 的數據包將被顯示
也可以通過使用匹配操作符,來搜索出現在一個字段或協議的任何位置的特征字符,例如,
僅顯示在 udp 頭部,或者其有效載荷的任何位置處,包含3個特定的字符序列: 0x81,0x60,0x53 的數據包
udp contains 81:60:03
僅顯示 SMTP(端口25)與 ICMP 協議相關的流量(郵件交換,與收發電子郵件相關的流量)
tcp.port eq 25 or icmp
僅顯示“TCP 緩沖區已滿,發送方指示接收方停止發送數據”的數據包
tcp.window_size == 0 && tcp.flags.reset != 1
使用下面這個“分片“過濾表達式,可以僅顯示 MAC 地址的廠商標識符部分(OUI),你可以通過指定特定 OUI 來顯示來自相關設備制造商的數據包,例如只顯示和
DELL 機器相關的流量:
eth.addr[0:3]==00:06:5B
通過使用正則表達式,匹配操作符使得搜索數據包的應用層文本字符串和字節序列成為可能,這需要使用 Perl 語言的正則表達式語法,
注意,該功能依賴于 libpcre 庫,需要安裝
僅顯示 HTTP 請求的 URI 中(完整 URI = GET請求頭的值 + HOST 請求頭的值),其字符串以 "gl=se" 結尾的數據包
注意此處的美元符號,不屬于請求 URI 的一部分,它是 PCRE 匹配的字符串結束標記
http.request.uri matches "gl=se$"
常見的語法陷阱
要過濾掉(來自或去往 10.43.54.65 的數據包) ,你可能會使用
ip.addr != 10.43.54.65 ,但這個表達式不能達到你預期的效果
應該使用下面的過濾表達式:
! ( ip.addr == 10.43.54.65 )
或者
! (ip.src == 10.43.54.65 or ip.dst == 10.43.54.65)
注意,這個例子會“顯示”與 10.43.54.65 相關的 arp 廣播流量
其它 IP 同樣道理,例如
! ( ip.addr == 192.168.1.30 ) && !arp
將過濾掉與192.168.1.30相關的任何流量,并且過濾掉任何 IP 地址的 arp 廣播流量
*****假設你要找出任何網頁在線播放 flash 視頻的數據包,使用下面的表達式,注意,該表達式僅適用于那些 swf 視頻地址直接曝露在瀏覽器請求的 URI 中的數據包,
如果視頻地址通過 web 應用程序根據提交的查詢字符串“動態生成”,那么下面的表達式或許不能達到你預期的效果:
http.request.uri contains "flv" or http.request.uri contains "swf" or http.content_type contains "flash" or http.content_type contains "video"
對于那些在線播放的“流媒體”視頻,更常見的做法是服務器將視頻分成很多小“塊”傳送,每“塊”的大小不超過 1 MBytes,在一個前導的 HTTP 響應中首先給出當前要傳送的“視頻塊”大小信息,然后再將這個“視頻塊”劃分成多個長度為 1506 Bytes (這個大小已經達到當前鏈路層的 MTU 上限),的重新組裝的 TCP 分段,
通過每發2~3個這種分段,客戶端回送一個長度 50 Bytes 的 ACK 分段,如此重復數十次,才能將一個“視頻塊”完整的傳遞到客戶端,此時客戶端的瀏覽器插件,
例如 adobe shockwave flash 播放器,就可以播放(需要先解碼)這部分“已緩沖”的視頻塊,
在用戶觀看這段視頻內容的期間,瀏覽器繼續請求下一個視頻塊,
當然,對于總長度較小的視頻以及擁有較大出口帶寬的客戶端,也可能連續接收和緩存多個視頻塊,這就是我們看到播放器進度條的緩沖部分一次就走到幾乎最右側的原因;
由于視頻服務器上的 web server 會將這種“視頻塊”的 MIME 類型指定為 application/octet-stream 并包含在攜帶該視頻塊統計信息的前導 HTTP Content-Type 響應頭中發送,因此,我們只需在 wireshark 的顯示過濾表達式中添加這個關鍵字,就可以捕獲這種分塊傳輸的流媒體視頻的前導 HTTP 響應包:
http.content_type contains "application/octet-stream"
并且,由實際組成該視頻塊的后續 “8位字節流”(octet-stream)格式的 TCP 分段,每一個都填滿了當前鏈路層的 MTU 上限(1506 Bytes),因此,下面這個過濾表達式,可以捕捉到實際的流媒體數據包:
frame.len==1506
當然,并非只有流媒體能填滿鏈路層 MTU 上限,所以,你可以通過 邏輯 AND 操作符,在后面添加視頻服務器的 IP 或域名來限定
下面這些捕獲的數據包,就是“包含視頻塊大小信息的前導 HTTP 響應”與“組成視頻塊的 TCP 分段”:
僅顯示包含特定“緩存控制”風格的 HTTP 響應:
http.cache_control != "private, x-gzip-ok="""
上面這個例子將顯示服務器發送的所有“非 google 風格”緩存指示的 HTTP 響應,這個不太好理解,有興趣的童鞋可以自行測試,
下面這個表達式有相同的效果,但是更加復雜:
(((((http.cache_control != "private, x-gzip-ok=""") && !(http.cache_control == "no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, no-transform, private")) && !(http.cache_control == "max-age=0, no-store")) && !(http.cache_control == "private")) && !(http.cache_control == "no-cache")) && !(http.cache_control == "no-transform")
先不論你是否熟悉 HTTP 協議中,和文檔的緩存策略相關的內容,但至少通過這個例子可以看出,要通過 邏輯 AND(&&) 連接后續的否定表達式,則邏輯非(!)需要放在前面,且用括號將表達式括起來,不能使用類似 != 的錯誤語法
包括這個例子在內的后續表達式實例,都引用自
http://www.askapache.com/software/sniff-http-to-debug-apache-htaccess-and-httpdconf.html
有興趣的可以自行參考
*****根據 HTTP 響應的狀態碼來過濾某些特定類型的數據包:
1 #404: page not found
2 http.response.code == 404
3 #200: OK
4 http.response.code == 200
第一個過濾表達式僅顯示“404錯誤,找不到頁面”的 HTTP 響應包
第二個過濾表達式僅顯示“200,OK”的 HTTP 響應包
*****根據 HTTP 請求的方法類型來過濾某些特定類型的 HTTP 請求包
http.request.method == "POST" || http.request.method == "PUT"
上面這個例子中,僅顯示 HTTP POST 方法(用于提交用戶輸入的查詢字符串或者 HTML 表單數據)或者 HTTP PUT 方法(用于向服務器上傳文檔資源)的 HTTP 請求包
*****根據 HTTP 請求或者響應的“內容類型”(Content Type)頭部,來過濾 HTTP 請求包
http.content_type[0:4] == "text"
上面這個例子中,僅顯示 HTTP Content Type 頭部,以字符串“text”開頭的數據包,注意,這里的 [0:4] 代表,從第0個字節開始計算,總長度為4字節的字符串
http.content_type contains "javascript"
上面這個例子中,僅顯示內容類型為 javascript 的數據包,可以用來找出那些帶有 javascript 腳本,即將或者已經被瀏覽器本地渲染和加載的 HTML 頁面
*****僅顯示內容類型以 “image” 開頭的 HTTP 請求或響應包
http.content_type[0:5] == "image"
上面這個例子中,將會匹配 MIME 類型為 image/(gif|jepg|png|etc) 的數據包,實際上就是用來檢測瀏覽器是否收到包含這些圖片資源的 HTML 頁面。
文章來源:http://shayi1983.blog.51cto.com/4681835/1558161