使用 `netsh trace` 抓取網絡數據生成 `.etl` (ETW) 文件,需提取數據包與進程 ID,轉為 `.pcap` 供 Wireshark 分析。嘗試手工構造 PCAP 結構寫入,遭遇 UDP/TCP 校驗和錯誤、長度截斷、鏈路層類型不匹配等問題。
同 文章 32739,手工構造 PCAP 全局頭、包頭、校驗和極易出錯。Libpcap/WinPcap 提供標準 API,保證生成文件 100% 合規。
#include
#include // Windows TDH API
// 為每個 PID 維護一個 dumper
typedef struct {
DWORD pid;
pcap_dumper_t *dumper;
pcap_t *pd;
} PcapWriter;
PcapWriter* get_writer(DWORD pid) {
// 查找或創建 PcapWriter
// pcap_open_dead(DLT_EN10MB, 65535)
// pcap_dump_open(pd, filename)
}
void write_packet(PcapWriter *w, const u_char *data, int len, ULONGLONG timestamp) {
struct pcap_pkthdr hdr;
hdr.ts.tv_sec = (long)(timestamp / 10000000); // FILETIME -> 秒
hdr.ts.tv_usec = (long)((timestamp % 10000000) / 10); // -> 微秒
hdr.caplen = len;
hdr.len = len;
pcap_dump((u_char*)w->dumper, &hdr, data);
}
// 主循環:遍歷 ETL 事件
// 1. TdhOpenTrace / TdhEnumerateProviders ...
// 2. 對每個網絡事件:
// PID = event.EventHeader.ProcessId
// payload = extract_payload(event)
// writer = get_writer(PID)
// write_packet(writer, payload, payload_len, event.EventHeader.TimeStamp.QuadPart)
| 問題 | 原因 | 對策 |
|---|---|---|
| Wireshark 提示 "Malformed Packet" | 鏈路層類型錯誤 (如用 DLT_NULL 寫以太網幀) | 確認數據鏈路層:本地回環用 DLT_NULL (101),乙太網用 DLT_EN10MB (1) |
| TCP 校驗和錯誤 | 捕獲數據包為經過 NIC 校驗和卸載後的數據,Wireshark 默認驗證 | Wireshark 中關閉 "Validate TCP checksum" 或使用 `pcap_dump` 寫入時不修改校驗和字段 |
| 大包截斷 | `pcap_open_dead` 的 snaplen 過小 | 設置 snaplen ≥ 65535 或實際 MTU+頭部開銷 |
| 時間戳跳躍 | ETL 事件時間戳為 100ns 間隔 FILETIME,換算錯誤 | 嚴格換算:秒 = ft/10000000, 微秒 = (ft%10000000)/10 |