wireshark

WireShark是非常流行的网络封包分析工具,可以截取各种网络数据包,并显示数据包详细信息。常用于开发测试过程中各种问题定位。

TCP三次握手

过滤规则

显示过滤器的核心逻辑是基于协议栈对象,配合各类运算符、正则表达式、底层位运算以及字节切片,实现对流量特征的极度精细化提取。以下是全套语法与实战规则的结构化整理。

1. 核心过滤对象

所有的运算符和切片操作,本质上都是在对 OSI 模型各层的基础对象及其派生字段进行研判。

  • 数据链路层
    • eth.src / eth.dst: 源 / 目的 MAC 地址(例如 eth.src == 00:11:22:33:44:55)。
    • eth.type: 以太网类型(0x0806 为 ARP,0x0800 为 IPv4)。
    • arp.opcode: ARP 操作码(1 为 Request,2 为 Reply。大量异常 Reply 常伴随内网 ARP 投毒)。
  • 网络层
    • ip.addr: 匹配源或目的 IPv4 地址(支持 CIDR,如 ip.addr == 192.168.1.0/24)。
    • ip.proto: 内部封装的协议号(1 为 ICMP,6 为 TCP,17 为 UDP)。
    • ip.ttl: 生存时间。异常的 TTL 值常作为操作系统指纹特征或用于识别逃逸技术。
    • icmp.type: ICMP 类型(8 为 Echo Request,0 为 Reply)。
  • 传输层
    • tcp.port / tcp.srcport / tcp.dstport: 端口号过滤(如 tcp.dstport == 3389)。
    • tcp.flags: 标志位对象(tcp.flags.syn, tcp.flags.reset 等),精准提取握手或阻断包。
    • tcp.stream: TCP 流索引。tcp.stream == 0 可快速提取第 0 号完整会话数据。
    • tcp.payload: TCP 原始应用层载荷。
  • 应用层
    • HTTP: http.request.method == "POST" (请求方法);http.request.uri (请求路径);http.response.code (状态码);http.user_agent (UA 头);http contains(内容过滤)
    • DNS: dns.qry.name (查询的域名,常用于排查 DNS 隧道);dns.flags.response (0 为查询,1 为响应)。
    • TLS/SSL: tls.handshake.type == 1 (Client Hello);tls.handshake.extensions_server_name (提取加密流量中的 SNI 明文域名)。
    • SMB/SMB2: smb2.cmd == 5 (Create/打开文件,内网横向移动分析重点);smb.file (传输文件名)。

2. 比较与逻辑运算符 (Comparison & Logical Operators)

用于组合多个条件或对比特定字段。在复杂组合中,建议始终使用括号 () 明确优先级(NOT > AND > OR > XOR)。

比较运算符

符号 英文缩写 功能说明 典型安全场景示例
== eq 等于 ip.src == 192.168.1.100 (精准定位攻击源 IP)
!= ne 不等于 tcp.port != 443 (排除标准 HTTPS 流量,寻找异常端口)
> gt 大于 http.content_length > 50000 (寻找可能的大文件数据外发/泄露)
< lt 小于 frame.len < 64 (筛选以太网帧长度小于 64 字节的异常截断包)
>= ge 大于等于 http.response.code >= 400 (筛选所有 HTTP 客户端与服务端错误)
<= le 小于等于 ip.ttl <= 5 (筛选 TTL 值极低的包,可能用于路由探测或逃逸)

逻辑运算符

符号 英文缩写 功能说明 规则与示例
&& and 逻辑与 两个条件必须同时满足。
tcp.port == 80 && ip.src == 10.0.0.1
|| or 逻辑或 满足任意一个条件即可。
http.request.method == “GET” || http.request.method == “POST”
! not 逻辑非 对后续条件取反。
!arp (过滤掉所有 ARP 广播噪音)
^^ xor 逻辑异或 仅当两个条件中有且只有一个为真时才匹配。
tcp.port == 80 ^^ tcp.port == 443

⚠️ 核心避坑指南:多值字段的 !=!(==) 陷阱

ip.addr 这样的字段在一个数据包中包含两个值(源 IP 和目的 IP)。

  • ip.addr != 1.1.1.1 的底层逻辑是:只要源或目的中有一个不是 1.1.1.1,该包就会被放行

  • 正确过滤方案:使用逻辑非包装全等。!(ip.addr == 1.1.1.1) 表示:彻底排除任何包含 1.1.1.1 的数据包。


3. 搜索与匹配运算符 (Search & Pattern Matching)

在进行 Payload 分析、WebShell 查杀或漏洞利用特征(如 SQLi、RCE)提取时,这是最核心的工具集。

操作符 功能说明 语法规范与实战示例
contains 精确子串匹配 在协议字段或负载中搜索精确的字节序列或字符串,默认区分大小写。



• 搜字符串:http.request.uri contains ".php?cmd="



• 搜十六进制:tcp.payload contains 4d:5a (寻找 PE 文件的 MZ 头)
matches 正则表达式 使用 PCRE (Perl 兼容正则) 进行复杂模式匹配。



• 匹配目录穿越:http.request.uri matches "(?i)\.\./\.\./" ((?i)为忽略大小写)



• 匹配多种后缀:`smb.file matches “.(exe\
bat\ vbs\ ps1)$”`
in 集合成员关系 检查某字段的值是否属于指定的集合,极大简化连续的 `\ 操作。<br><br> <br><br>• 离散值:tcp.port in {80 443 8080}<br><br> <br><br>• 范围值:http.response.code in {500..599}` (匹配所有 5xx 错误)

4. 底层按位运算符 (Bitwise Operators)

按位运算符允许深入协议头部的标志位(Flags)寄存器进行比特级别的检验。

  • 符号: & (bitwise_and) / 按位与

  • 功能说明: 用于掩码测试,判断某个特定的 Bit 位是否被置为 1。

  • 实战场景示例: tcp.flags & 0x02

  • 解析: TCP 标志位寄存器中,SYN 位对应 0x02 (二进制 00000010)。这个表达式的意思是:无论 ACK、PSH 等其他位是什么状态,只要 SYN 位是 1,就匹配成功。这比 tcp.flags == 0x02 (严格要求只有 SYN 是 1,其他必须全为 0) 容错率更高,更具实战价值。


5. 字节切片运算符 (Slice Operator)

切片允许绕过现有的协议解析树,直接对二进制流进行精准的偏移量截取。在分析未公开协议或提取特定结构体时非常强大。

语法结构: [偏移量:长度][起始偏移量-结束偏移量] (_注:偏移量从 0 开始计算_)

  • 截取连续字节: tcp.payload[0:4] == 47:45:54:20 (提取 TCP 载荷前 4 个字节,硬匹配 “GET “)

  • 提取单个字节: ip.hdr_len[0] == 0x05 (仅提取 IP 头长度字段的第一个字节)

  • 截取到末尾: udp.payload[4:] (跳过 UDP 载荷的前 4 个字节,匹配后续所有内容)

  • 范围切片: eth.src[0-2] == 00:11:22 (匹配 MAC 地址的前三个字节,通常用于识别网卡设备厂商 OUI)


6. 显示过滤器内置函数 (Functions)

Wireshark 内置了数据处理函数,可将字段值转换后再进行比较,在处理数据混淆或长度检测时极为高效。

  • len() - 计算字节长度

    • 用于检测超长负载(如缓冲区溢出攻击)或异常短包。

    • 示例:len(http.request.uri) > 255 (筛选 URI 长度超过 255 字节的请求)

  • lower() / upper() - 大小写转换

    • 将字符串字段转换为全小写或全大写后匹配,实现免疫大小写混淆。

    • 示例:lower(http.server) contains "nginx" (无论服务器返回 Nginx, NGINX 还是 nginx 都能匹配)

  • string() - 强制转为字符串

    • 将非字符串字段(如十六进制序列)强转为 ASCII 字符串进行匹配。

    • 示例:string(tcp.payload) matches "cmd\.exe"

tcpdump

tcpdump 是一款强大的网络抓包工具,它使用 libpcap 库来抓取网络数据包,这个库在几乎在所有的 Linux/Unix 中都有。熟悉 tcpdump 的使用能够帮助你分析调试网络数据。

tcpdump 是 Linux 环境下最底层、最强大的网络数据采集分析工具。它直接挂载在内核的 BPF(Berkeley Packet Filter)虚拟机上,在网卡接收到数据包且尚未交由网络协议栈处理之前,对其进行拷贝和过滤。

需要特别注意:tcpdump 使用的是 BPF 语法(即 Wireshark 中的“捕获过滤器”),而不是此前讨论的 Wireshark “显示过滤器”语法。 它的匹配逻辑发生在底层,效率极高,但不支持对应用层协议(如 HTTP 请求方法或 URI)的结构化解析。

以下是 tcpdump 的核心参数与高阶过滤语法详解。


一、 核心控制参数 (Options)

控制参数主要用于决定 tcpdump 的抓包行为、输出格式以及文件读写。

1. 抓包行为控制

  • -i <interface>: 指定监听的网络接口(如 -i eth0)。使用 -i any 可以监听所有接口(注意:any 模式下抓到的包在 Wireshark 中可能会显示 Linux Cooked Capture 伪协议头)。
  • -c <count>: 抓取指定数量的数据包后自动停止。
  • -s <snaplen>: 定义抓取的字节数(Snap Length)。默认情况下,较新的 tcpdump 版本会抓取完整数据包(262144 字节)。如果在旧版本或对性能要求极高的情况下,只关心包头,可以设置为 -s 96
  • -p: 关闭混杂模式(Promiscuous Mode)。默认情况下 tcpdump 会将网卡置于混杂模式以抓取同一冲突域的所有流量。

2. 输出解析控制(极度重要)

在安全分析或高并发场景下,禁用反向域名解析可以极大提升抓包性能并防止暴露分析机的 DNS 请求轨迹。

  • -n: 不将 IP 地址解析为主机名。
  • -nn: 不将 IP 地址解析为主机名,且不将端口号解析为服务名(例如显示 80 而不是 http)。(实战标配)
  • -v, -vv, -vvv: 增加输出的详细程度,显示如 TTL、TOS、ID、TCP 序列号等信息。
  • -e: 在输出行中额外打印链路层(L2)的 MAC 地址信息。

3. Payload 检查(常用于 CTF / 快速研判)

  • -X: 同时以十六进制和 ASCII 码打印数据包头部和载荷。
  • -XX: 类似于 -X,但额外包含以太网(L2)链路层头部。
  • -A: 仅以 ASCII 码打印数据包载荷。用于在终端快速窥探明文协议(如 HTTP、FTP、Telnet)的交互内容。

4. 文件读写(与 Wireshark 联动)

  • -w <file.pcap>: 将原始数据包写入 PCAP 文件,不进行终端格式化输出
  • -r <file.pcap>: 读取已保存的 PCAP 文件进行二次过滤和分析。

二、 BPF 过滤表达式语法 (Filter Expressions)

过滤表达式用于在内核层直接丢弃不需要的流量。BPF 语法由三种修饰符(Type, Dir, Proto)和逻辑运算符组成。

1. 基础原语组合

  • Type(类型): host (主机), net (网段), port (端口), portrange (端口范围)。
  • Dir(方向): src (源), dst (目的), src or dst (默认)。
  • Proto(协议): ether, ip, ip6, arp, tcp, udp, icmp

实战组合示例:

  • tcpdump -nn -i eth0 host 192.168.1.100 (双向抓取特定主机的流量)
  • tcpdump -nn -i eth0 src net 10.0.0.0/8 and dst port 22 (抓取源自 10 网段且目的端口为 22 的 SSH 流量)
  • tcpdump -nn -i eth0 portrange 10000-20000 (抓取特定范围的动态端口流量)

2. 逻辑运算符

支持文本与符号两种形式,建议使用括号进行优先级控制(在 Bash 环境中,由于括号具有特殊含义,包含括号和逻辑符的表达式必须用单引号 '' 闭合)。

  • and&&
  • or||
  • not!

复杂逻辑示例:

1
2
tcpdump -nn -i eth0 'src 192.168.1.100 and (tcp port 80 or tcp port 443)'
tcpdump -nn -i eth0 'net 192.168.1.0/24 and not host 192.168.1.1'

三、 高阶数据切片与标志位提取 (Byte-Slicing)

由于 tcpdump 在内核层运行,它没有 Wireshark 那样丰富的应用层解析器。如果需要提取特定特征的流量,必须通过 BPF 字节切片语法进行位运算。

语法结构: proto[expr:size]

1. TCP 标志位硬核过滤

由于网络环境复杂,直接匹配整个 TCP 标志位寄存器往往会因为 PSH 或 URG 位被意外置位而漏报。必须使用按位与(&)操作符。

  • 只抓取 SYN 握手请求包 (探测扫描行为):

    1
    tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-syn != 0'
  • 只抓取 RST 连接重置包 (排查阻断或端口屏蔽):

    1
    tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-rst != 0'
  • 抓取 SYN-ACK (二次握手响应):

    1
    tcpdump -nn -i eth0 'tcp[tcpflags] == (tcp-syn|tcp-ack)'

2. ICMP 类型提取

  • 只抓取 Ping (Echo Request) 数据包:
    1
    tcpdump -nn -i eth0 'icmp[icmptype] == icmp-echo'

3. 应用层特征硬匹配 (Hex 提取)

不依赖应用层解析,直接读取 TCP 载荷前几个字节来判断协议。由于 TCP 头部长度可变(通常为 20 字节,但含有选项时会变长),严格写法需要计算 Header Length。

  • 粗略匹配 HTTP GET 请求 (假设 TCP 头为默认 20 字节):
    提取 TCP 载荷的第 0-3 字节,判断是否等于 GET 的十六进制 0x47455420

    1
    tcpdump -nn -i eth0 'tcp[20:4] = 0x47455420'
  • 严格匹配 HTTP POST 请求 (动态计算 IP 和 TCP 头长度):
    这段 BPF 字节码会动态读取 IP 头长度和 TCP 头长度,定位到 Payload 的绝对偏移量,匹配 POST (0x504f5354)。在底层的 WebShell 流量清洗中非常实用。

    1
    tcpdump -nn -i eth0 'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'

四、 典型安全研判场景速查

  1. 脱机保存特定主机的全流量以备后续 Wireshark 分析:

    1
    tcpdump -i eth0 host 10.0.0.5 -w target_traffic.pcap
  2. 监听本地环回网卡,排查内网服务反向代理或本地提权漏洞交互:

    1
    tcpdump -nn -i lo port 3306 or port 6379
  3. 提取明文凭证(终端快速溯源):

    结合 -A 参数和 egrep 正则管道,直接在终端抓取并过滤包含密码字段的明文流量。

    1
    tcpdump -nn -A -i eth0 tcp port 80 or tcp port 21 | egrep -i 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|passwd='