前段時間接到一個公司關於解析pacp文件的培訓(我是被培訓的),在完成了一部分的功能后決定把一些關於pcap文件的了解記錄到博客中。
初識Pcap文件
在開始讀取pcap文件之前,先讓我們來看看Pcap文件的大概結構。

如上圖所示在一個Pcap文件中存在1個Pcap文件頭和多個數據包,其中每個數據包都有自己的頭和包內容。
下面我們先看看PCAP文件頭每個字段是什么意思:
magic為文件識別頭,pcap固定為:0xA1B2C3D4。(4個字節)
magor version為主版本號(2個字節)
minor version為次要版本號(2個字節)
timezone為當地的標准時間(4個字節)
sigflags為時間戳的精度(4個字節)
snaplen為最大的存儲長度(4個字節)
linktype為鏈路類型(4個字節)
常用類型:
0 BSD loopback devices, except for later OpenBSD
1 Ethernet, and Linux loopback devices
6 802.5 Token Ring
7 ARCnet
8 SLIP
9 PPP
10 FDDI
100 LLC/SNAP-encapsulated ATM
101 “raw IP”, with no link
102 BSD/OS SLIP
103 BSD/OS PPP
104 Cisco HDLC
105 802.11
108 later OpenBSD loopback devices (with the AF_value in network byte order)
113 special Linux “cooked” capture
114 LocalTalk
1 Ethernet, and Linux loopback devices
6 802.5 Token Ring
7 ARCnet
8 SLIP
9 PPP
10 FDDI
100 LLC/SNAP-encapsulated ATM
101 “raw IP”, with no link
102 BSD/OS SLIP
103 BSD/OS PPP
104 Cisco HDLC
105 802.11
108 later OpenBSD loopback devices (with the AF_value in network byte order)
113 special Linux “cooked” capture
114 LocalTalk
數據包頭則依次為:時間戳(秒)、時間戳(微妙)、抓包長度和實際長度,依次各占4個字節。
讀取各個數據包到單個pcap文件
c代碼:
pcap_header.h
#pragma pack( push, 1) // 為了保證在windows和linux下都能正常編譯,放棄使用INT64或者_int_64 typedef short _Int16; typedef long _Int32; typedef char Byte; // Pcap文件頭 struct __file_header { _Int32 iMagic; _Int16 iMaVersion; _Int16 iMiVersion; _Int32 iTimezone; _Int32 iSigFlags; _Int32 iSnapLen; _Int32 iLinkType; }; // 數據包頭 struct __pkthdr { _Int32 iTimeSecond; _Int32 iTimeSS; _Int32 iPLength; _Int32 iLength; }; #pragma pack( pop)
main.c
#include<stdio.h> #include"pcap_header.h" #include<memory.h> #include<stdlib.h> #include<math.h> int main() { struct __pkthdr data; struct __file_header header; FILE* pFile = fopen( "iupsc.pcap", "rb"); if( pFile == 0) { printf( "打開pcap文件失敗"); return 0; } fseek( pFile, 0, SEEK_END); long iFileLen = ftell( pFile); fseek( pFile, 0, SEEK_SET); Byte* pBuffer = (Byte*)malloc( iFileLen); fread( (void*)pBuffer, 1, iFileLen, pFile); fclose( pFile); memcpy( (void*)&header, (void*)(pBuffer) , sizeof(struct __file_header)); int iIndex = sizeof(struct __file_header); int iNo = 1; while(iIndex <= iFileLen) { memcpy( (void*)&data, (void*)(pBuffer + iIndex) , sizeof(struct __pkthdr)); char strPath[51]; sprintf( strPath, "export/%d-%d.pcap", iNo++, (int)data.iTimeSecond); strPath[50] = '\0'; FILE* pwFile = fopen( strPath, "wb"); fwrite((void*)&header, 1, sizeof(struct __file_header), pwFile); fwrite( (void*)(pBuffer + iIndex), 1, sizeof(struct __pkthdr) + data.iPLength, pwFile); fclose( pwFile); iIndex += sizeof(struct __pkthdr) + data.iPLength; } free( pBuffer); printf( "成功導出%d個文件", iNo - 1); return 1; }