簡介
WinPcap 是由伯克利分組捕獲庫派生而來的分組捕獲庫,它是在Windows 操作平台上來實現對底層包的截取過濾。WinPcap 為用戶級的數據包提供了Windows 下的一個平台。WinPcap 是 BPF 模型和 Libpcap 函式館在 Windows 平台下網路數據包捕獲和網路狀態分析的一種體系結構,這個體系結構是由一個核心的包過濾驅動程式,一個底層的動態連線庫 Packet.dll 和一個高層的獨立於系統的函式館 Libpcap 組成。底層的包捕獲驅動程式
實際為一個協定網路驅動程式,通過對 NDIS 中函式的調用為 Win95、Win98、WinNT、和 Win2000 提供一類似於 UNIX 系統下 Berkeley Packet Filter 的捕獲和傳送原始數據包的能力。Packet.dll 是對這個 BPF 驅動程式進行訪問的 API 接口,同時它有一套符合 Libpcap 接口(UNIX 下的捕獲函式館)的函式館。WinPcap的結構圖如圖1。
WinPcap 包括三個部分:第一個模組NPF(Netgroup Packet Filter),是一個虛擬設備驅動程式檔案。它的功能是過濾數據包,並把這些數據包原封不動地傳給用戶態模組,這個過程中包括了一些作業系統特有的代碼。第二個模組packet.dll為win32平台提供了一個公共的接口。不同版本的Windows系統都有自己的核心模組和用戶層模組。Packet.dll用於解決這些不同。調用Packet.dll的程式可以運行在不同版本的Windows平台上,而無需重新編譯。
第三個
模組 Wpcap.dll是不依賴於作業系統的。它提供了更加高層、抽象的函式。
packet.dll和Wpcap.dll:packet.dll直接映射了核心的調用。 Wpcap.dll提供了更加友好、功能更加強大的函式調用。WinPcap的優勢提供了一套標準的抓包接口,與libpcap兼容,可使得原來許多UNIX平台下的網路分析工具快速移植過來便於開發各種網路分析工具,充分考慮了各種性能和效率的最佳化,包括對於NPF核心層次上的過濾器支持,支持核心態的統計模式,提供了傳送數據包的能力。
2網路數據包捕獲的原理
3在windows情況下捕獲數據包的結構
4利用winpcap進行網路數據包的捕獲和過濾的設計步驟
5主要原始碼
根據用 Windows 分組捕獲庫 WinPcap 提供功能首先要初始化兩個結構體,一個是適配器的結構體 LpAdapter, 一個是存放接收到的數據包的結構體 RecvPacket。
使用 Packet.dll 動態連線庫編寫原始碼:
#define MAX__LINK__NAME__LENGTH 64
適配器結構
typedef struct__ADAPTER
{
HANDLE hFile;
TCHAR Symboliclink[MAX__LINK__NAME__LENGTH];
Int NumWrites;
} ADAPTER , *LPADAPTER;
說明:hFile 是一個指向該網路適配器 Handle 的指針,通過它可以對網路適配器進行操作。symboliclink 包含當前打開的網路適配器的名字。
數據包結構:
typedef struct _PACKET
{
HANDLE hEvent;
OVERLAPPED OverLapped;
PVOID Buffer;
UINT Length;
PVOID Next;
UINT ulBytesReceived;
BOOLEAN bloComplete; //控制接受包的開始和結束
實現的步驟
的主要原始碼:
1)
要獲得
適配器列表。
#define Max__Num__Adapter 10 //獲得適配器列表
char Adapterlist [Max__Num__Adapter[512]]
int i=0
char AdapterNames[512], *tempa,*templa;
ULONG AdapterLength=1024; } PACKET, *LPPACKET:
2)獲得系統中網路適配器的名字。
PacketGetAdapterNames(AdapterNamea,&AdapterLength);
tempa=AdapterNamea;
templa=
Adapternamea;
while ((*tempa!=’\0’)∣∣(*tempa-1!=’\0))
{
if (*tempa= =’\0’)
{
memcpy(AdapterList,temla,tempa-templa); //記憶體數據拷貝
templa=tempa+1;
i++
}
tempa++
}
3)從適配器列表中選擇一個默認的 0 號適配器。
LPADAPTER lpAdapter
lpAdapter = PacketOpenAdapter (AdapterList[0]);
if (!lpAdapter∣∣(lpAdapter->hFile==INVALID__HANDLE__VALUE))
{
dwErrorCode=GetLastError();
return FALSE;
}
4)將所選擇的適配器 lpAdapter 設定為混雜模式。
PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS)
5)設定 BPF 核心中包過濾的過濾器的代參政。利用這個函式右以完成對於原始數據包的初始的過濾處理,如根據其中連線埠號、IP 地址等。
PacketSetBpf(LpAdapter AdapterObject,structbpf_program*fp)
6)設定緩衝池為512K位元組。
PacketSetBuff(lpAdapter,512000);
7)分配一個數據包對象,並連線已分配的緩衝。
PacketInitPacket(lpPacket,(char*)bufferReceive,512000);
8)捕獲多個數據包。從網卡 lpAdapter 接收數據包,並將數據包放入 lpPacket所指向的數據包結構體中,若接收成功返回 TRUE,否則返回 FALSE。
PacketReceivePacket(lpAdapter,lpPacket,TRUE);
9)通過觸發回調函式,把捕獲符合過濾器規則的數據包轉發給網路協定分析模組進行分析處理。
10) 結束接收數據包,釋放數據包對象。
if(lpPacket!=NULL
{
PacketFreePacket(lpPacket);
lpPacket=NULL;
}
11)關閉網卡設備,將網卡恢復到正常接收狀態。
if(lpAdapter!=NULL
{
PacketCloseAdapter(lpAdapter);
lpAdapter=NULL;
}
6結束語
數據包捕獲技術是網路管理系統的關鍵技術,已經按照標題4中的流程進行了簡單的實現。如果在一個繁忙的網路上進行截獲,而不設定任何過濾,那得到的數據包是非常多的,可能在一秒鐘內得到上千的數據包。如果應用程式不進行必要的性能最佳化,那么將會大量的丟失數據包。對捕包性能的最佳化必不可少,考慮採用多執行緒來處理數據包。若在程式中建立一個公共的數據包緩衝池,這個緩衝池是一個LILO的佇列。於是在程式中使用三個執行緒進行操作:一個執行緒只進行捕獲操作,它將從驅動程式獲得的數據包添加到數據包佇列的頭部;另一個執行緒只進行過濾操作,它檢查新到的隊尾的數據包,檢查其是否滿足過濾條件,如果不滿足則將其刪除出佇列;最後一個執行緒進行數據包處理操作,象根據接收的數據包傳送新數據包這樣的工作都由它來進行。考慮儘可能少丟失數據包的條件,應該是進行捕獲操作的執行緒的優先權最高,這樣就可以得到更高的捕包性能。