首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C語言自製 PCAP 文件兼容 Wireshark:從 ETL 提取到 Libpcap 落地

     編輯:程式設計綜合問答

問題背景

使用 `netsh trace` 抓取網絡數據生成 `.etl` (ETW) 文件,需提取數據包與進程 ID,轉為 `.pcap` 供 Wireshark 分析。嘗試手工構造 PCAP 結構寫入,遭遇 UDP/TCP 校驗和錯誤、長度截斷、鏈路層類型不匹配等問題。

核心教訓:放棄手工拼接,擁抱 Libpcap

同 文章 32739,手工構造 PCAP 全局頭、包頭、校驗和極易出錯。Libpcap/WinPcap 提供標準 API,保證生成文件 100% 合規。

完整工程流程

  1. ETL 解析:使用 Microsoft TDH (Trace Data Helper) API 讀取 `.etl`,枚舉事件記錄。
    • 關鍵提供者:`Microsoft-Windows-TCPIP` (GUID: `{9A280AC0-C8E0-11D1-84E2-00C04FB998A2}`)。
    • 事件 ID:`Send` / `Receive` 等包含完整以太網幀負載、PID、時間戳。
  2. 數據提取:從事件 `EventRecord->UserData` 獲取原始幀數據指針與長度,提取 PID (`EventRecord->EventHeader.ProcessId`)。
  3. PCAP 寫入:對每個進程創建獨立 `.pcap` (如 `PID_1234.pcap`),使用 Libpcap API 寫入:

關鍵代碼框架

#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)

進程名稱獲取

  • ETL 事件頭僅含 PID。需調用 `OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid)` + `GetModuleBaseName` / `GetProcessImageFileName` 獲取進程名。
  • 或在 TDH 解析階段記錄 `ProcessId` 映射表,事後批量解析。

常見坑位與對策

參考資源

「經過不斷地測試,最終放棄按照 pcap 結構體,將數據賦值後寫入文件,因為總是存在一些大大小小的 bug,最後確定還是使用 libpcap」—— 親身踩坑總結,極具參考價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因對策
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