使用 `netsh trace start capture=yes tracefile=test.etl` 抓取網絡數據,生成 `.etl` (ETW) 文件。需離線解析 ETL,提取數據包與進程 ID,生成標準 `.pcap` 供 Wireshark 分析。
// 參考文章 32752 的 PcapWriter 結構與 write_packet 函數
void process_etl(const wchar_t* etl_path) {
TRACEHANDLE trace = 0;
EVENT_TRACE_LOGFILE log = {0};
log.LogFileName = (LPWSTR)etl_path;
log.ProcessTraceMode = PROCESS_TRACE_MODE_EVENT_RECORD;
log.EventRecordCallback = on_event_record;
trace = OpenTrace(&log);
if (trace == INVALID_PROCESSTRACE_HANDLE) return;
ProcessTrace(&trace, 1);
CloseTrace(trace);
}
void WINAPI on_event_record(PEVENT_RECORD record) {
// 1. 過濾 Provider
if (!IsEqualGUID(record->EventHeader.ProviderId, TCPIP_GUID)) return;
// 2. 提取 Payload (簡化:假設 UserData 直接是幀數據)
// 實際需用 TdhGetProperty 解析結構化負載
PBYTE payload = (PBYTE)record->UserData;
ULONG payload_len = record->UserDataLength;
if (payload_len == 0) return;
// 3. 獲取 PID 和時間戳
DWORD pid = record->EventHeader.ProcessId;
ULONGLONG timestamp = record->EventHeader.TimeStamp.QuadPart;
// 4. 寫入對應 PID 的 PCAP
PcapWriter* writer = get_writer(pid);
write_packet(writer, payload, payload_len, timestamp);
}
| 坑點 | 現象 | 對策 |
|---|---|---|
| ETL 事件結構複雜 | `UserData` 非直接幀數據,而是結構體嵌套 | 必須用 `TdhGetEventInformation` + `TdhGetProperty` 按名稱提取字段,不可硬編碼偏移 |
| TDH API 需 Manifest | 解析失敗,提示找不到事件結構 | 確保系統安裝了對應 Provider 的 Manifest (通常在 `C:\Windows\System32\winevt\Manifests\`),或動態加載 |
| 大量事件性能差 | 逐個 `TdhGetProperty` 極慢 | 批量處理、複用 `TRACE_EVENT_INFO`、考慮 C# `Microsoft.Diagnostics.Tracing.TraceEvent` 庫 (性能更好) |
| 權限不足 | `OpenProcess` 失敗 | 以管理員運行,或啟用 `SeDebugPrivilege` |