Wireshark过滤器表达式
过滤器表达式
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.1
Classless 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 | eth.src[0:3,1-2,:4,4:,2] == |
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 | http.request.method in {"HEAD" "GET"} |
函数
显示过滤函数
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. |
upper
和 lower
函数可用于强制不区分大小写匹配: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.addr
、ip.addr
、tcp.port
和udp.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 | http.request.uri contains “/dll/test.htm?” |