过滤器表达式

Wireshark Version 3.4.7 (v3.4.7-0-ge42cbf6a415f)

Wireshark 提供了一种显示过滤语言,使您能够精确控制显示哪些数据包。 它们可用于检查协议或字段的存在、字段的值,甚至可以将两个字段相互比较。 这些比较可以与逻辑运算符(如“and”和“or”)以及括号组合成复杂的表达式。

以下部分将更详细地介绍显示过滤器功能。

更多操作提示 Wireshark Wiki 显示过滤器页面 上有许多显示过滤器示例: https://gitlab.com/wireshark/wireshark/wikis/DisplayFilters

过滤器字段

最简单的显示过滤器是单个协议的过滤器。要显示包含特定协议的数据包,请在 Wireshark 的显示过滤器工具栏中键入协议。 例如,要仅显示 TCP 数据包,请在 Wireshark 的显示过滤器工具栏中键入 tcp。 同样,要显示包含特定字段的数据包,请在 Wireshark 的显示过滤器工具栏中键入该字段。 例如,要仅显示 HTTP 请求,请在 Wireshark 的显示过滤器工具栏中键入 http.request

您可以过滤 Wireshark 支持的任何协议。 如果解析器为该字段添加了缩写,您还可以过滤解析器在树视图中的任何字段。 通过菜单项查看可用协议和字段的完整列表 → 内部 → 支持的协议获得。

值比较

您可以构建显示过滤器,使用许多不同的比较运算符来比较值。 例如,要仅显示发往或来自 IP 地址 192.168.0.1 的数据包,请使用 ip.addr==192.168.0.1

显示过滤器比较运算符

English C-like Description Example
eq == Equal ip.src==10.0.0.5
ne != Not equal ip.src!=10.0.0.5
gt > Greater than frame.len > 10
lt < Less than frame.len < 128
ge >= Greater than or equal to frame.len ge 0x100
le <= Less than or equal to frame.len <= 0x20
contains Protocol, field or slice contains a value sip.To contains "a1762"
matches ~ Protocol or text field matches a Perl-compatible regular expression `http.host matches "acme.(org
bitwise_and & Bitwise AND is non-zero tcp.flags & 0x02

所有协议字段都有一个类型。 [显示过滤器字段类型](mk:@MSITStore:C:\Program Files\Wireshark\user-guide.chm::/wsug_chm/ChWorkBuildDisplayFilterSection.html#ChWorkFieldTypes) 提供了类型列表以及如何使用它们的示例 显示过滤器。

显示过滤器字段类型

  • 无符号整数

    可以是 8、16、24、32 或 64 位。您可以用十进制、八进制或十六进制表示整数。以下显示过滤器是等效的:ip.len le 1500 ip.len le 02734 ip.len le 0x5dc

  • 有符号整数

    可以是 8、16、24、32 或 64 位。与无符号整数一样,您可以使用十进制、八进制或十六进制。

  • 布尔值

    可以是 1(表示真)或 0(表示假)。无论其值为真还是假,都存在布尔字段。例如,tcp.flags.syn 存在于所有包含该标志的 TCP 数据包中,无论 SYN 标志是 0 还是 1。要匹配设置了 SYN 标志的 TCP 数据包,您需要使用 tcp.flags.syn == 1

  • 以太网地址

    由冒号 (:)、点 (.) 或破折号 (-) 分隔的 6 个字节,分隔符之间有一到两个字节:eth.dst == ff:ff:ff:ff:ff:ff eth.dst == ff-ff-ff-ff-ff-ff eth.dst == ffff.ffff.ffff

  • IPv4 地址

    ip.addr == 192.168.0.1Classless InterDomain Routing (CIDR) 表示法可用于测试 IPv4 地址是否在某个子网中。例如,此过滤器将查找 129.111 B 类网络中的所有数据包:ip.addr == 129.111.0.0/16

  • IPv6 地址

    ipv6.addr == ::1与 IPv4 地址一样,IPv6 地址可以匹配子网。

  • 文本字符串

    http.request.uri == "https://www.wireshark.org/"

1
udp contains 81:60:03

上面的过滤器匹配包含 3 字节序列 0x81、0x60、0x03 在 UDP 标头或有效负载中任意位置的数据包。

1
sip.To contains "a1762"

上面的过滤器匹配 SIP To-header 在头中任何位置包含字符串“a1762”的数据包。

1
http.host matches "acme\.(org|com|net)"

上面的过滤器匹配 HOST 标头包含 acme.org、acme.com 或 acme.net 的 HTTP 数据包。 不区分大小写。

1
tcp.flags & 0x02

该过滤器将匹配所有包含“tcp.flags”字段且设置了 0x02 位(即 SYN 位)的数据包。

组合表达式

过滤器逻辑操作

English C-like Description Example
and && Logical AND ip.src==10.0.0.5 and tcp.flags.fin
or || Logical OR ip.scr==10.0.0.5 or ip.src==192.1.1.1
xor ^^ Logical XOR tr.dst[0:3] == 0.6.29 xor tr.src[0:3] == 0.6.29
not ! Logical NOT not llc
[…] Subsequence See “Slice Operator” below.
in Set Membership http.request.method in {"HEAD" "GET"}. See “Membership Operator” below.

切片运算符

Wireshark 允许您以相当复杂的方式选择序列的子序列。 在标签之后,您可以放置一对括号 [],其中包含逗号分隔的范围说明符列表。

1
eth.src[0:3] == 00:00:83

上面的示例使用 n:m 格式来指定单个范围。 在这种情况下,n 是起始偏移量,m 是指定范围的长度。

1
eth.src[1-2] == 00:83

上面的示例使用 n-m 格式来指定单个范围。 在这种情况下,n 是开始偏移量,m 是结束偏移量。

1
eth.src[:4] == 00:00:83:00

上面的示例使用 :m 格式,它采用从序列开头到偏移 m 的所有内容。 相当于 0:m

1
eth.src[4:] == 20:20

上面的示例使用 n: 格式,它采用从偏移量 n 到序列末尾的所有内容。

1
eth.src[2] == 83

上面的示例使用 n 格式来指定单个范围。 在这种情况下,选择序列中偏移量为 n 的元素。 这相当于 n:1。

1
2
eth.src[0:3,1-2,:4,4:,2] ==
00:00:83:00:83:00:00:83:00:20:20:83

Wireshark 允许您将逗号分隔列表中的单个范围串在一起,以形成如上所示的复合范围。

成员操作

Wireshark 允许您在一组值或字段中测试一个字段的成员资格。 在字段名称之后,使用 in 运算符,后跟用大括号 {} 括起来的集合项。 例如,要显示 TCP 源或目标端口为 80、443 或 8080 的数据包,您可以使用 tcp.port in {80 443 8080}。 这组值还可以包含范围:tcp.port in {443 4430..4434}

注意:

tcp.port in {80 443 8080}中的显示过滤器相当于tcp.port == 80 || tcp.port == 443 || tcp.port == 8080然而,tcp.port in {443 4430..4434}中的显示过滤器tcp.port并不等同于tcp.port == 443 || (tcp.port >= 4430 && tcp.port <= 4434)这是因为当 any 字段与过滤器匹配时满足比较运算符,因此源端口为 56789 和端口为 80 的目标端口的数据包也将匹配 自56789 >= 4430 && 80 <= 4434 以来的第二个过滤器为真。 相比之下,成员资格运算符根据范围条件测试单个字段。

集合不仅限于数字,还可以使用其他类型:

1
2
3
http.request.method in {"HEAD" "GET"}
ip.addr in {10.0.0.5 .. 10.0.0.9 192.168.1.1..192.168.1.9}
frame.time_delta in {10 .. 10.5}

函数

显示过滤函数

Function Description
upper Converts a string field to uppercase.
lower Converts a string field to lowercase.
len Returns the byte length of a string or bytes field.
count Returns the number of field occurrences in a frame.
string Converts a non-string field to a string.

upperlower 函数可用于强制不区分大小写匹配:lower(http.server) contains "apache"

要查找具有长请求 URI 的 HTTP 请求:len(http.request.uri) > 100。 请注意,len 函数以字节而不是(多字节)字符生成字符串长度。

通常一个 IP 帧只有两个地址(源和目标),但在 ICMP 错误或隧道的情况下,单个数据包可能包含更多地址。 这些数据包可以通过 count(ip.addr) > 2 找到。

string 函数将字段值转换为字符串,适用于“匹配”或“包含”等运算符。 整数字段被转换为其十进制表示。 它可以用于 IP/以太网地址(以及其他地址),但不能用于字符串或字节字段。

例如,匹配奇数帧数:

1
string(frame.number) matches "[13579]$"

要匹配子网块(172.16 到 172.31)中以 255 结尾的 IP 地址:

1
string(ip.dst) matches "^172\.(1[6-9]|2[0-9]|3[0-1])\..{1,3}\.255"

!= 的常见错误

在诸如eth.addrip.addrtcp.portudp.port 等组合表达式上使用!= 运算符可能不会按预期工作。 Wireshark 在使用的时候会显示警告“"!="可能有意外的结果”。

人们经常使用像ip.addr == 1.2.3.4这样的过滤字符串来显示所有包含IP地址1.2.3.4的数据包。

然后他们使用 ip.addr != 1.2.3.4 期望看到所有不包含 IP 地址 1.2.3.4 的数据包。不幸的是,这 没有 达到预期的效果。

相反,该表达式甚至适用于源或目标 IP 地址等于 1.2.3.4 的数据包。这样做的原因是因为表达式ip.addr != 1.2.3.4 被读作“数据包包含一个名为 ip.addr 的字段,其值不同于 1.2.3.4”。由于 IP 数据报同时包含源地址和目标地址,因此只要两个地址中的至少一个地址与 1.2.3.4 不同,则表达式的计算结果为真。

如果你想过滤掉所有包含发往或来自 IP 地址 1.2.3.4 的 IP 数据报的数据包,那么正确的过滤器是!(ip.addr == 1.2.3.4)名为 ip.addr 的字段存在值为 1.2.3.4 的情况是不正确的”,或者换句话说,“过滤掉所有没有出现名为 ip.addr 的值为 1.2.3.4 的字段的数据包”。

有时字段会更改名称

随着协议的发展,它们有时会更改名称或被更新的标准所取代。 例如,DHCP 扩展并在很大程度上取代了 BOOTP,TLS 取代了 SSL。 如果协议解析器最初为协议使用旧的名称和字段,Wireshark 开发团队可能会更新它以使用较新的名称和字段。 在这种情况下,他们会将旧协议名称的别名添加到新协议名称,以便更轻松地进行转换。

例如,DHCP 解析器最初是为 BOOTP 协议开发的,但从 Wireshark 3.0 开始,所有“bootp”显示过滤器字段都已重命名为它们的“dhcp”等效项。 您仍然可以暂时使用旧的过滤器名称,例如 “bootp.type”等价于“dhcp.type”,但Wireshark在使用时会显示警告““bootp”已弃用。 将来可能会删除对弃用字段的支持。

例子

1
!(http.request.uri matches "/v1/ddgx/dd/requirement/list" || http.response_for.uri matches "/v1/ddgx/dd/requirement/list") && ip.addr==39.108.227.45 && http
1
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
http.request.uri contains “/dll/test.htm?”
//过滤http请求的uri中含有/dll/test.htm?字段的请求信息

udp contains 81:60:03
//过滤包含81:60:03的udp数据包

http.request.uri matches “V4=..1″
//matches 匹配过滤条件中给定的正则表达式,支持与Perl兼容的正则表达式(PCRE)。

http.host==magentonotes.com
http.host contains magentonotes.com
//过滤经过指定域名的http数据包,这里的host值不一定是请求中的域名

http.response.code==302
//过滤http响应状态码为302的数据包

http.response==1
//过滤所有的http响应包

http.request==1
//过滤所有的http请求,貌似也可以使用http.request

http.request.method==POST
//wireshark过滤所有请求方式为POST的http请求包,注意POST为大写

http.cookie contains guid
//过滤含有指定cookie的http数据包

http.request.uri==”/online/setpoint”
//过滤请求的uri,取值是域名后的部分

http.request.full_uri==” http://task.browser.360.cn/online/setpoint”
//过滤含域名的整个url则需要使用http.request.full_uri

http.server contains “nginx”
//过滤http头中server字段含有nginx字符的数据包

http.content_type == “text/html”
//过滤content_type是text/html的http响应、post包,即根据文件类型过滤http数据包

http.content_encoding == “gzip”
//过滤content_encoding是gzip的http包

http.transfer_encoding == “chunked”
//根据transfer_encoding过滤

http.content_length == 279
http.content_length_header == “279″
//根据content_length的数值过滤

http.server
//过滤所有含有http头中含有server字段的数据包

http.request.version == “HTTP/1.1″
//过滤HTTP/1.1版本的http包,包括请求和响应

http.response.phrase == “OK”
//过滤http响应中的phrase

Wireshark捕获UDP数据包

UDP协议分析常用过滤条件
ip.addr==192.168.0.1 //过滤ip地址
data.len==8 //过滤data部分长度为8的数据包
data.data == 00:08:30:03:00:00:00:00 //过滤指定内容的数据包

udp.srcport == 10092 //过滤经过本机10092端口的udp数据包
udp.dstport == 80 //过滤目标机器10092端口的udp数据包
udp.port==10092 //过滤本机或目标机器10092端口的数据包
udp.length == 20 //过滤指定长度的UDP数据包

UDP校验和过滤条件
udp.checksum == 0x250f
udp.checksum_good == 0 //Boolean类型
udp.checksum_bad == 0

进程相关的过滤条件

以下过滤条件不支持Windows,因为需要特殊的驱动。

udp.proc.dstcmd //过滤目标进程名
udp.proc.dstpid //过滤目标进程PID
udp.proc.dstuid //过滤目标进程的用户ID
udp.proc.dstuname //过滤目标进程的用户名
udp.proc.srccmd //过滤源进程名
udp.proc.srcpid //过滤源进程PID
udp.proc.srcuid //过滤源进程的用户ID
udp.proc.srcuname //过滤源进程的用户名

Wireshark中根据MAC地址/物理地址过滤数据包

Wireshark捕获过滤中过滤MAC地址/物理地址
ether host 00:11:22:33:44:55 //过滤目标或源地址是00:11:22:33:44:55的数据包
ether dst host 00:11:22:33:44:55 //过滤目标地址是00:11:22:33:44:55的数据包
ether src host 00:11:22:33:44:55 //过滤源地址是00:11:22:33:44:55的数据包

Wireshark显示过滤中过滤MAC地址/物理地址
eth.addr== 00:11:22:33:44:55 //过滤目标或源地址是00:11:22:33:44:55的数据包
eth.src== 00:11:22:33:44:55 //过滤源地址是00:11:22:33:44:55的数据包
eth.dst== 00:11:22:33:44:55 //过滤目标地址是00:11:22:33:44:55的数据包

Wireshark捕获经过指定ip的数据包

捕捉过滤抓包前在capture option中设置,仅捕获符合条件的包,可以避免产生较大的捕获文件和内存占用,但不能完整的复现测试时的网络环境。

host 192.168.0.1 //抓取192.168.0.1 收到和发出的所有数据包
src host 192.168.0.1 //源地址,192.168.0.1发出的所有数据包
dst host 192.168.0.1 //目标地址,192.168.0.1收到的所有数据包

src host hostname //根据主机名过滤
ether host 80:05:09:03:E4:35 //根据MAC地址过滤

net 192.168.0 //网络过滤,过滤整个网段
src net 192.168
dst net 192

使用“非/且/或”建立组合过滤条件可以获得更精确的捕获
非: ! or “not” (去掉双引号)
且: && or “and”
或: || or “or”

wirershark过滤指定ip收发数据包示例:

抓取所有目的地址是192.168.0.2 或192.168.0.3 端口是80 的TCP 数据
(tcp port 80) and ((dst host 192.168.0.2) or (dst host 192.168.0.3)) //捕获过滤
tcp.port==80&&(ip.dst==192.168.0.2||ip.dst==192.168.0.3) //显示过滤

抓取所有目标MAC 地址是80:05:09:03:E4:35 的ICMP 数据
(icmp) and ((ether dst host 80:05:09:03:E4:35))
icmp && eth.dst==80:05:09:03:E4:35

抓取所有目的网络是192.168,但目的主机不是192.168.0.2 的TCP 数据
(tcp) and ((dst net 192.168) and (not dst host 192.168.0.2))
tcp&&ip.src==192.168.0.0/16&&!(ip.src==192.168.0.2)

捕获主机192.168.0.1 和主机192.168.0.2 或192.168.0.3的通信
host 192.168.0.1 and (192.168.0.2 or 192.168.0.3 )
ip.addr==192.168.0.1&&(ip.addr==192.168.0.2||ip.addr==192.168.0.3)

获取主机192.168.0.1除了和主机192.168.0.2之外所有主机通信的数据包
host 192.168.0.1 and ! 192.168.0.2
ip.addr==192.168.0.1&&!ip.addr==192.168.0.2

获取主机192.168.0.1接收或发出的telnet包,telnet使用tcp 23端口
tcp port 23 and host 192.168.0.1
tcp.port==23&&ip.addr==192.168.0.1

显示json数据