云计算百科
云计算领域专业知识百科平台

从零实现一个 Windows 网络嗅探器(AI赋能)

做网络协议实验时,最直接的方案是打开 Wireshark,选择一个网卡,看着数据包滚过屏幕。工具很好用,但它不会解释一个数据包怎样从网卡进入程序,怎样被识别成 IPv4,又怎样变成协议树和十六进制视图。

我想把这个过程完整走一遍,于是用 C++17、Win32 和 Npcap 做了一个轻量网络分析器 NetObserver。

项目没有试图复刻 Wireshark。它的目标更具体:完成网卡枚举、实时捕获、BPF 过滤、协议解析、捕获后过滤、TCP 会话重组、pcapng 保存和读取,并提供一个可操作的图形界面。

基本是借助AI开发,所以除上述目的,还可以将之作为AI赋能的项目经验。

1. 安装 Windows 开发环境

下列都是一些比较简单的安装,就不一一提供下载链接和安装步骤了

安装:

  • Visual Studio 2022 Build Tools
  • 工作负载:使用 C++ 的桌面开发
  • CMake
  • Git
  • VS Code
  • Wireshark
  • Python,仅用于测试本地 HTTP 服务

验证:

cmake –version
git –version

在这里插入图片描述

VS Code 只是编辑器,编译由 MSVC 和 CMake 完成。

2. 安装 Npcap

安装 Npcap 运行库,建议选择:

Install Npcap in WinPcap API-compatible Mode

验证:

Get-Service Npcap

在这里插入图片描述

USB 抓包组件不是本实验必需项。

3. 准备 Npcap SDK

下载 Npcap SDK,并放到:

third_party\\npcap-sdk

验证:要均返回true

Test-Path "D:\\AI\\NetObserver\\third_party\\npcap-sdk\\Include\\pcap.h"
Test-Path "D:\\AI\\NetObserver\\third_party\\npcap-sdk\\Lib\\x64\\wpcap.lib"

在这里插入图片描述

目录应包含:

third_party\\npcap-sdk\\Include\\pcap.h
third_party\\npcap-sdk\\Lib\\x64\\wpcap.lib
third_party\\npcap-sdk\\Lib\\x64\\Packet.lib

不要把 SDK 二进制提交到 Git。

4. 建立空项目

例如:(命名自己想)

D:\\AI\\NetObserverLab

推荐结构:

NetObserverLab/
├── CMakeLists.txt
├── CMakePresets.json
├── src/
│ ├── core/
│ │ ├── CaptureEngine.h
│ │ ├── CaptureEngine.cpp
│ │ ├── PacketTypes.h
│ │ ├── PacketParser.h
│ │ └── PacketParser.cpp
│ ├── console_main.cpp
│ └── gui_main.cpp
├── tests/
├── scripts/
├── resources/
└── README.md

5. 创建基础 .gitignore

需要建立一个git仓库,可以让你开发的时候,回溯版本,很有用

至少忽略:

build/
.vs/
third_party/npcap-sdk/
captures/
*.pcap
*.pcapng

防止你的git仓库爆炸

下面就是具体步骤,可以将文章发给AI,辅助理解开发

6. 建立最小 CMake 工程

先只创建控制台目标,暂时不写 GUI。

CMake 需要找到 Npcap SDK:

find_path(PCAP_INCLUDE_DIR
NAMES pcap.h
HINTS "${CMAKE_SOURCE_DIR}/third_party/npcap-sdk"
PATH_SUFFIXES Include
)

find_library(WPCAP_LIBRARY
NAMES wpcap
HINTS "${CMAKE_SOURCE_DIR}/third_party/npcap-sdk"
PATH_SUFFIXES Lib/x64
)

链接:

target_include_directories(netobserver_core PUBLIC
"${CMAKE_SOURCE_DIR}/src"
"${PCAP_INCLUDE_DIR}"
)

target_link_libraries(netobserver_core PUBLIC
"${WPCAP_LIBRARY}"
ws2_32
)

在源文件中加入:

#define WPCAP
#define HAVE_REMOTE
#include <pcap.h>

使用 CMake 生成 Visual Studio 工程:

cmake -S . -B build -A x64
cmake –build build –config Debug

在这里插入图片描述

在这里插入图片描述

这个阶段不要先写界面。先保证 C++ 和 Npcap 能够链接成功。

7. 枚举网卡

第一项功能是列出所有抓包设备。

核心调用:

pcap_findalldevs
pcap_freealldevs

控制台输出网卡名称和描述。结果中一般可以看到:

Realtek Wireless LAN
Bluetooth Device
VMware Virtual Ethernet Adapter
Adapter for loopback traffic capture

运行:

.\\build\\Debug\\netobserver-cli.exe –list

在这里插入图片描述

如果能看到 \\Device\\NPF_…,说明 Npcap 和程序配置正常。

当前联网流量一般选择 Wi-Fi 或有线网卡。测试本地 HTTP 服务时选择回环网卡。

8. 打开网卡并抓包

选择网卡后调用:

pcap_open_live(
deviceName,
65535,
1,
1000,
errbuf
);

参数依次是网卡名称、捕获长度、混杂模式和读取超时。

循环调用:

pcap_next_ex

拿到数据后至少显示:

  • 数据包序号
  • 捕获长度
  • 原始长度

必须复制数据内容:

std::vector<std::uint8_t> bytes(
rawPacket,
rawPacket + packetHeader->caplen
);

pkt_data 指向的缓冲区会被下一次捕获复用,不能直接保存这个指针。

为了及时响应停止操作,可以开启非阻塞读取:

pcap_setnonblock(handle, 1, errbuf);

停止时:

pcap_breakloop(handle);
pcap_close(handle);

9. 设置 BPF 捕获过滤

使用:

pcap_lookupnet
pcap_compile
pcap_setfilter
pcap_freecode

可以先支持这些表达式:

tcp
udp
icmp
arp
udp port 53
tcp port 8080
host 10.122.60.186

捕获过滤在 Npcap 层生效,不匹配的数据包不会被程序读取。

10. 解析 Ethernet 和 IP

以太网帧开头包括:

目的 MAC:6 字节
源 MAC:6 字节
EtherType:2 字节

接着解析 IPv4:

  • 版本和首部长度
  • 总长度
  • TTL
  • 协议号
  • 源 IP
  • 目的 IP

IP 首部长度不能固定写成 20:

const std::size_t ipHeaderLength =
(ipHeader->verIhl & 0x0F) * 4;

传输层偏移:

const std::size_t l4Offset =
ethernetHeaderLength + ipHeaderLength;

端口和地址需要转换字节序:

ntohs
ntohl

协议解析前必须检查 caplen,不能让短包或畸形包造成越界读取。

11. 解析 TCP、UDP、ARP、ICMP 和 IGMP

建议按以下顺序实现:

UDP
→ TCP
→ ICMP
→ ARP
→ IGMP

TCP 至少解析:

  • 源端口、目的端口
  • 序列号、确认号
  • 首部长度
  • SYN、ACK、FIN、RST、PSH、URG
  • 应用层载荷偏移

UDP 解析端口、长度和载荷。ARP 解析请求、应答和发送方/目标 MAC、IP。ICMP 识别 Echo Request 和 Echo Reply。IGMP 可以先处理常见成员关系报文。

命令行输出示例:

[1] 10.0.0.1:50000 -> 10.0.0.2:80 TCP
[2] 10.0.0.1 -> 10.0.0.2 ICMP Echo Request
[3] Who has 10.0.0.20? Tell 10.0.0.10

12. 分析 HTTP 或 FTP

选择 HTTP 作为重点应用层协议。

在 TCP 载荷中检查:

GET /
POST /
HEAD /
HTTP/

可以提取:

  • 请求方法
  • URI
  • Host
  • Content-Type
  • HTTP 状态码

FTP 则可以先分析 21 端口的命令和响应首行。

这个阶段只分析单个数据包中的应用层文本,不要求立即实现完整 HTTP 流解析。

13. 加入多线程 GUI

GUI 建议先使用 Win32,避免引入 MFC 或 Qt 的额外配置。

界面大致分为:

顶部:网卡、捕获过滤、开始、停止
左侧:快捷过滤和实时统计
中间:数据包列表
右侧下方:协议详情、十六进制、会话统计

捕获线程只负责读取数据包。数据解析后通过消息交给主线程:

PostMessage(hWnd, WM_APP_PACKET, 0, (LPARAM)packet);

不要在捕获线程中直接操作窗口控件。

高流量下不要每个包发送一次消息,可以每 64 个包组成一批。否则消息队列会堆积,停止按钮可能很久才响应。

14. 实现捕获后显示过滤

捕获过滤和显示过滤要分成两个输入框。

例如:

BPF 捕获过滤:icmp
显示过滤:tcp and tcp.port == 80

显示过滤只改变已捕获的数据包列表,不影响 pcapng 文件。

可以先实现这些条件:

icmp
tcp
udp
arp
ip.addr == 192.168.1.10
tcp.port == 80
udp.port == 53
frame.len > 100

再增加 and、or、not 和括号。

“仅此会话”按钮可以根据当前数据包自动生成地址和端口条件。

15. 保存 pcap 或 pcapng

第一版可以直接使用 libpcap 保存经典 pcap:

pcap_dump_open
pcap_dump
pcap_dump_close

后续实现 pcapng 时,需要写入:

  • Section Header Block
  • Interface Description Block
  • Enhanced Packet Block

保存后先用 capinfos 检查文件:

capinfos capture.pcapng

然后直接用 Wireshark 打开。如果 Wireshark 能正常读取数据包数量和时间戳,说明文件结构基本正确。

16. 实现 TCP 会话和 Follow Stream

TCP Follow Stream 不是简单拼接载荷。

需要处理:

  • 双向 TCP 连接
  • 序列号
  • 乱序段
  • 重传段
  • 部分重叠
  • 序列号回绕

程序可以按两个端点建立会话,分别保存两个方向的数据。遇到重复段时跳过,遇到乱序段时进入待处理缓存。

流内容不能无限增长。可以限制每个方向最多保留 1 MB,同时设置全局内存上限。

明文文本直接显示。TLS、压缩数据和二进制内容显示十六进制预览,不要强行当作文本展示。

17. 测试和 Wireshark 对比

真实流量按以下顺序测试:

ICMP
→ ARP
→ DNS
→ TCP
→ HTTP
→ Follow Stream

保存 pcapng 后,用 Wireshark 打开同一个文件,对比:

  • 源、目的 MAC
  • 源、目的 IP
  • 协议
  • 源、目的端口
  • 数据包长度
  • TCP 标志位
  • ICMP 类型
  • 原始载荷

Wireshark 中选择:

Follow → TCP Stream → Hex Dump

就能对比同一个 TCP 流的十六进制内容。

理:

  • 双向 TCP 连接
  • 序列号
  • 乱序段
  • 重传段
  • 部分重叠
  • 序列号回绕

程序可以按两个端点建立会话,分别保存两个方向的数据。遇到重复段时跳过,遇到乱序段时进入待处理缓存。

流内容不能无限增长。可以限制每个方向最多保留 1 MB,同时设置全局内存上限。

明文文本直接显示。TLS、压缩数据和二进制内容显示十六进制预览,不要强行当作文本展示。

17. 测试和 Wireshark 对比

真实流量按以下顺序测试:

ICMP
→ ARP
→ DNS
→ TCP
→ HTTP
→ Follow Stream

保存 pcapng 后,用 Wireshark 打开同一个文件,对比:

  • 源、目的 MAC
  • 源、目的 IP
  • 协议
  • 源、目的端口
  • 数据包长度
  • TCP 标志位
  • ICMP 类型
  • 原始载荷

Wireshark 中选择:

Follow → TCP Stream → Hex Dump

就能对比同一个 TCP 流的十六进制内容。

在这里插入图片描述

赞(0)
未经允许不得转载:网硕互联帮助中心 » 从零实现一个 Windows 网络嗅探器(AI赋能)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!