日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用Packet.dll和npf.sys实现原始数据包的发送和接收

發布時間:2024/4/11 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用Packet.dll和npf.sys实现原始数据包的发送和接收 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
相應源碼下載地址: http://download.csdn.net/source/3521479 ?

有人可能問我為什么不直接用wpcap.dll,那個不但功能更強大還穩定。那是因為我這個功能很簡單,使用packet.dll有點“殺雞用牛刀”的味道了,而packet.dll足夠我使用。

Packet.dll簡介

Packet.dll 是一個動態鏈接庫,并提供了一些低層的函數,用來:

1> 安裝,啟動和停止NPF設備驅動

2> 從NPF驅動接收數據包

3> 通過NPF驅動發送數據包

4> 獲取可用的網絡適配器列表

5> 獲取適配器的不同信息,比如設備描述,地址列表和掩碼

6> 查詢并設置一個低層的適配器參數

用到的Packet.dll相關數據結構及函數

首先介紹一些相關的數據結構:

1>???? ?typedef struct _ADAPTER ADAPTER //描述一個網絡適配器;

typedef struct _ADAPTER {HANDLE hFile; // 一個打開的NPF driver實例的句柄:CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; // 當前打開的網卡的名字:int NumWrites; // 在這塊Adapter上,一個數據包被寫的次數:HANDLE ReadEvent; /* 這塊Adapter上的read操作的通知事件。它可以被傳遞給標準Win32函數(如WaitForSingleObject或者WaitForMultipleObjects),這樣可以等待到driver的緩沖區內有數據到來。在同時等待幾個事件的GUI程序中,它特別有用。在Windows2000/XP中,函數PacketSetMinToCopy()可以用來設置內核緩沖區中激發本事件的最小數據大小:*/UINT ReadTimeOut; // 設置一個時間,到時候,即使沒有捕獲任何包,read操作也會被釋放,ReadEvent也會被觸發:} ADAPTER, *LPADAPTER;

2>???? ?typedef struct _PACKET PACKET //描述一組網絡數據報的結構;

typedef struct _<strong style="color:black;background-color:#A0FFFF">PACKET</strong>{ HANDLE hEvent; // 向后兼容用的:OVERLAPPED OverLapped; // 向后兼容用的:PVOID Buffer; // 存放Packets的緩沖區:UINT Length; // 緩沖區的大小:DWORD ulBytesReceived; // 當前緩沖區中有效的字節數,如,上一次調用PacketReceivePacket()函數接收到的字節數:BOOLEAN bIoComplete // 向后兼容用的:} <strong style="color:black;background-color:#A0FFFF">PACKET</strong>, *LPPACKET;

?

下面,將介紹用到的各個函數,他們都是在packet.dll中定義的:

?????? 1>?? PacketGetAdapterNames(從注冊表中讀取網卡名)

得到現有的網絡適配器的列表和它們的描述。 BOOLEAN PacketGetAdapterNames( PTSTR pStr, PULONG BufferSize );

參數:

pStr: [in , out] 一塊用戶負責分配的緩沖區,將把適配器的名字填充進去。 BufferSize: [in] pStr這塊緩沖區的大小。

返回值:

如果查詢成功,返回一個非零值。

Usage:

[C/C++] C/C++ Usage Sample

?

char AdapterNamea[8192];ULONG AdapterLength;PacketGetAdapterNames(AdapterName,&AdapterLength);


?????? 2>?? PacketOpenAdapter (打開網卡) 根據傳入的設備名,打開它。

LPADAPTER PacketOpenAdapter(LPTSTR AdapterName);

參數:

AdapterName:

[in] 要打開的設備的名字。

返回值:

如果打開成功,返回一個指針,它指向一個正確初始化了的ADAPTER Object。否則,返回NULL。

Usage:

[C/C++]C/C++ Usage Sample

LPADAPTER adapter;adapter = PacketOpenAdapter(pStr+rewind);


?????? 3>?? LPPACKET PacketAllocatePacket(void);

參數:無

返回值:如果執行成功,返回指向_PACKET結構的指針。否則,返回NULL。

Usage:

C/C++ Usage SampleLPPACKET lpPacket; lpPacket = PacketAllocatePacket() ;


4>?? PacketInitPacket初始化一個_PACKET結構,即將packet結構中的buffer設置為傳遞的buffer指針。

VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);

參數:lpPacket[in] 指向一個_PACKET結構的指針。

Buffer[in] 一個指向一塊用戶分配的緩沖區的指針。捕獲的數據將放置于此。

Length[in] 緩沖區的大小。這是一個讀操作從driver傳遞到應用的最大數據量。

返回值:無。

Usage:

C/C++ Usage Sample

?

char buffer[256000]; LPPACKET lpPacket; PacketInitPacket(lpPacket,(char*)buffer,256000);


5>?? PacketSendPacket發送一個或多個數據報的副本。

BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket, BOOLEAN Sync)

?????? 6>?? PacketFreePacket釋放參數提供的_PACKET結構。

VOID PacketFreePacket(LPPACKET lpPacket)

?????? 7>?? PacketCloseAdapter關閉網卡。

VOID PacketCloseAdapter(LPADAPTER lpAdapter);

參數:

lpAdapter:[in] 指向一個_ADAPTER結構的指針。

8>?? PacketSetHwFilter ???? 設置一個hardware filter。比如,Filter參數傳遞NDIS_PACKET_TYPE_PROMISCUOUS ,就可以設置網卡為混雜模式。

BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);

參數:

AdapterObject:[in] 指向一個_ADAPTER結構的指針。Filter:[in] 過濾器的id。

返回值:如果執行成功,返回一個非零值。

Usage:

C/C++ Usage Sample

lpAdapter=PacketOpenAdapter(AdapterList[Open-1]); PacketSetHwFilter(lpAdapter,NDIS_<strong style="color:black;background-color:#A0FFFF">PACKET</strong>_TYPE_PROMISCUOUS);


?????? 9>?? PacketSetBuff ??? 設置捕獲的內核級緩沖區的大小。

BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);

參數:

AdapterObject:[in] 指向一個_ADAPTER結構的指針。dim: [in] 緩沖區的大小(單位:字節)。

返回值:

如果執行成功,返回一個TRUE。如果沒有足夠的內存分配,返回FALSE。

Usage:

C/C++ Usage Sample

lpAdapter=PacketOpenAdapter(AdapterList[Open-1]); PacketSetBuff(lpAdapter,512000) ; // 設置 driver 有 512KB 字節的緩沖區


?????? 10>? PacketSetReadTimeout ?設置一次讀操作返回的超時時間。

?

BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);

參數:

AdapterObject:[in] 指向一個_ADAPTER結構的指針。timeout:[in] 超時時間(單位:毫秒)。

返回值:

如果執行成功,返回非零值。

Usage:

C/C++ Usage Sample

lpAdapter=PacketOpenAdapter(AdapterList[Open-1]); PacketSetReadTimeout(lpAdapter,1000) ; // 設置讀操作超時時間 1 秒


?????? 11>? PacketReceivePacket? 從NPF driver上讀取數據(Packets或者統計信息)。

?

BOOLEAN ??PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);

參數:

AdapterObject:[in] 指向一個_ADAPTER結構的指針。

lpPacket:[in , out] 放數據的_PACKET結構緩沖區。

Sync:[in] 一個可以忽略的參數,保留它是為了向后兼容。

返回值:如果執行成功,返回一個非零值。

Usage:

C/C++ Usage Sample

LPADAPTER lpAdapter = 0; LPPACKET lpPacket; lpAdapter = PacketOpenAdapter(AdapterList[Open-1]); lpPacket = PacketAllocatePacket(); PacketInitPacket(lpPacket,(char*)buffer,256000); PacketReceivePacket(lpAdapter,lpPacket,TRUE);


發送原始數據包 SendData

大概流程:

1>?????? 打開指定的網絡適配器,調用PacketOpenAdapter。

2>?????? 調用PacketAllocatePacket分配一個packet。如果運行成功,返回一個_PACKET結構的指針,否則返回NULL。成功返回的結果將會傳送到PacketSendPacket()函數,用來將數據發送出去。

3>?????? 調用PacketInitPacket初始化一個_PACKET結構,即將packet結構中的buffer設置為傳遞的buffer指針

4>?????? 調用PacketSendPacket發送一個或多個數據報的副本。

接受原始數據包 RevData

大概流程:

1>???? 打開指定的網絡適配器,調用PacketOpenAdapter。

2>???? 調用PacketSetHwFilter將網絡適配器設置為混雜模式,這樣才可以監聽流過本地主機的數據報

3>???? 調用PacketSetBuff自定義網絡適配器的內核緩存的大小。

4>???? 調用PacketAllocatePacket分配一個packet。如果運行成功,返回一個_PACKET結構的指針,否則返回NULL。成功返回的結果將會傳送到PacketReceivePacket()函數,接收來自驅動的網絡數據報。

5>???? 調用PacketInitPacket初始化一個_PACKET結構,即將packet結構中的buffer設置為傳遞的buffer指針

6>???? 在設置網絡適配器為混雜模式后,調用PacketReceivePacket接收數據包。

安裝packet.dll和npf.sys

在一篇文章中看到(http://douvip.blog.51cto.com/75074/41228)說:

安裝程序需要做兩件事:

1>?????? 拷貝packet.dll到Windows\system32目錄下;

2>?????? 拷貝驅動文件npf.sys到windows/systems/drivers/目錄下,并向系統注冊一下抓包驅動的服務。

經過我實踐,僅僅需要第一步就可以了;也在“www.winpcap.org/”找到這樣一句話:“It's installed by directly interacting with the service control manager。”

詳情請進http://www.winpcap.org/pipermail/winpcap-users/2008-March/002326.html

并且,那篇文章僅僅能夠在32bit系統下成功,64位系統還要在Windows\SysWOW64拷入相應packet.dll,64位的packet.dll和32bit的是不一樣的。

不管多少位系統得到packet.dll和npf.sys的方法都很簡單,只要安裝winpcap包然后在Windows搜索即可。

以下我的批處理:

@echo offcd /d %~dp0 ;轉到當前目錄Is64.exe ;判斷系統是不是64位系統,自己寫的一個win32程序if %errorlevel% == 64 (goto 64bit) else (goto 32bit) :64bit (if /i "%CD%" == "%SYSTEMROOT%\system32" goto COPYDRV_64 copy 64bit\32\<strong style="color:black;background-color:#A0FFFF">packet</strong>.dll %SYSTEMROOT%\system32\ if /i "%CD%" == "%SYSTEMROOT%\SysWOW64" goto COPYDRV_64 copy 64bit\64\<strong style="color:black;background-color:#A0FFFF">packet</strong>.dll %SYSTEMROOT%\SysWOW64\ :COPYDRV_64 if /i "%CD%" == "%SYSTEMROOT%\system32\drivers" goto END copy 64bit\npf.sys %SYSTEMROOT%\system32\drivers\ goto END ) :32bit (if /i "%CD%" == "%SYSTEMROOT%\system32" goto COPYDRV_32 copy 32bit\<strong style="color:black;background-color:#A0FFFF">packet</strong>.dll %SYSTEMROOT%\system32\ :COPYDRV_32 if /i "%CD%" == "%SYSTEMROOT%\system32\drivers" goto END copy 32bit\npf.sys %SYSTEMROOT%\system32\drivers\ ):ENDdel Is64.exerd /s /q "64bit" rd /s /q "32bit" del %0

以上在win7 32bit和647bit ,xp32bit和64bit測試過,沒問題的。


相應源碼下載地址:http://download.csdn.net/source/3521479?

總結

以上是生活随笔為你收集整理的使用Packet.dll和npf.sys实现原始数据包的发送和接收的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。