簡易網絡嗅探器的實現
發表于:2007-06-23來源:作者:點擊數:
標簽:
本文介紹一個用C語言和 網絡 數據包分析 開發 工具實現的簡易網絡Sniffer。 目前,已經有不少的Sniff工具軟件,如Windows環境下,最富盛名的工具是Netxray和Sniffer pro,用它們在 Windows環境下抓包來分析,非常方便。在 UNIX 環境下如Sniffit,Snoop,Tcpd
本文介紹一個用C語言和網絡數據包分析開發工具實現的簡易網絡Sniffer。目前,已經有不少的Sniff工具軟件,如Windows環境下,最富盛名的工具是Netxray和Sniffer pro,用它們在 Windows環境下抓包來分析,非常方便。在UNIX環境下如Sniffit,Snoop,Tcpdump,Dsniff 等都是比較常見的。這里介紹一個用C語言和網絡數據包和分析開發工具libpcap及winpcap實現的簡易網絡Sniffer。
網絡嗅探器程序框圖
首先給出流程如圖1所示。

圖1 流程圖
網絡嗅探器程序實現
在c環境下編程,源碼如下:
clearcase/" target="_blank" >cc66 width="90%" align=center bgColor=#e6e4dd border=1>
/* June 2nd,2002
* Project for graduation qualification By Bby Team 19 */
#include <stdio.h>
#include <conio.h>
//必須加路徑,必須把頭文件packet32.h包含進去
#include "....Includepacket32.h"
#include "....Includentddndis.h"
#define Max_Num_Adapter 10
// Prototypes原形
//發包
void PrintPackets(LPPACKET lpPacket);
//設備列表
char AdapterList[Max_Num_Adapter][1024];
// 主程序開始
int main()
{
//define a pointer to an ADAPTER structure設備指針
LPADAPTER lpAdapter = 0;
//define a pointer to a PACKET structure包指針
LPPACKET lpPacket;
int i;
DWORD dwErrorCode;
DWORD dwVersion;
DWORD dwWindowsMajorVersion;
//Unicode strings (WinNT)
WCHAR AdapterName[8192]; //網絡適配器設備列表
WCHAR *temp,*temp1;
//ASCII strings (Win9x)
char AdapterNamea[8192]; //網絡適配器設備列表
char *tempa,*temp1a;
int AdapterNum=0,Open;
ULONG AdapterLength;
char buffer[256000]; // 容納來自驅動器的數據的緩沖區
struct bpf_stat stat;
// 獲得本機網卡名
AdapterLength=4096;
printf("Packet.dll test application. Library version:%sn", PacketGetVersion());
printf("Adapters installed:n");
i=0; |
下面這段代碼是用來在不同版本下得到網絡適配器名:
Win9x 和WinNT中的網卡名稱是分別用ASCII和UNICODE實現的,
所以首先要得到本地操作系統
的版本號:
dwVersion=GetVersion();
dwWindowsMajorVersion= (DWORD)(LOBYTE(LOWORD(dwVersion))); |
這里首先用到的Packet.dll函數是PacketGetAdapterNames(PTSTR pStr,
PULONG BufferSize,通常它是與驅動程序通信并被調用的第一個函數,
它將返回的用戶本地系統中安裝
的網絡適配器的名字放在
緩沖區pStr中;BufferSize是緩沖區的長度:
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4))
{
//是Windows NT
// 找不到設備列表
if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){
printf("Unable to retrieve the list of the adapters!n");
return -1;
}
// 找到設備列表
temp=AdapterName;
temp1=AdapterName;
while ((*temp!='')||(*(temp-1)!=''))
{
if (*temp=='')
{
memcpy(AdapterList[i],temp1,(temp-temp1)*2);
temp1=temp+1;
i++;
}
temp++;
}
// 顯示適配器列表
AdapterNum=i;
for (i=0;i<AdapterNum;i++)
wprintf(L"n%d- %sn",i+1,AdapterList[i]);
printf("n");
}
else //否則就是windows 9x,獲取適配器名的方法同WinNT下
{
if(PacketGetAdapterNames(AdapterNamea,&AdapterLength)==FALSE){
printf("Unable to retrieve the list of the adapters!n");
return -1;
}
tempa=AdapterNamea;
temp1a=AdapterNamea;
while ((*tempa!='')||(*(tempa-1)!=''))
{
if (*tempa=='')
{
memcpy(AdapterList[i],temp1a,tempa-temp1a);
temp1a=tempa+1;
i++;
}
tempa++;
}
AdapterNum=i;
for (i=0;i<AdapterNum;i++)
printf("n%d- %sn",i+1,AdapterList[i]);
printf("n");
} |
下面這段代碼就是讓用戶選擇監聽的網絡適配器號:
// 選擇設備
do
{
printf("Select the number of the adapter to open : ");
scanf("%d",&Open);
if (Open>AdapterNum)
printf("nThe number must be smaller than %d",AdapterNum);
} while (Open>AdapterNum);
|
然后,將所選擇的設備打開,這里可以設置為“混雜”模式打開,
也可以是“直接”模式打開。
代碼如下:
// 打開設備
lpAdapter = PacketOpenAdapter(AdapterList[Open-1]);
// 當設備無法打開時,出示錯誤信息:
if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
{
dwErrorCode=GetLastError();
printf("Unable to open the adapter, Error Code : %lxn",dwErrorCode);
return -1;
} |
將網卡設置為“混雜”模式,代碼如下:
這里用到函數PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter),
它在到來的包上設置了一個硬件過濾器,如操作成功,返回TRUE。
AdapterObject是過濾器所在的網卡
設備指針;過濾器的常量Filter定義在頭文件ntddndis.h 中,包括有:
·NDIS-PACKET-TYPE-PROMISCUOUS:設置混雜模式,每個到來的包都會被網卡接受;
·NDIS-PACKET-TYPE-DIRECTED:只有直接到主機網卡的包才會被接受;
·NDIS-PACKET-TYPE-BROADCAST:只接受廣播包;
·NDIS-PACKET-TYPE-MULTICAST:只接受到主機所在的組的多播包;
·NDIS-PACKET-TYPE-ALL-MULTICAS:接受每個多播的包。
// set the network adapter in promiscuous mode
// 如果混雜模式設置失敗,提示錯誤:
if(PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_PROMISCUOUS)==FALSE){
printf("Warning: unable to set promiscuous mode!n");
} |
然后在driver中置512K的緩沖:
這里用到函數PacketSetBuff(LPADAPTER AdapterObject,int dim),
它被用于設置AdapterObject指向的網卡的驅動程序的緩沖區,成功則返回TRUE。
Dim是新的緩沖區的大小,
當它被設定時,舊緩沖區中的數據將被丟棄,其中存儲的包也會失去。
需要注意的地方:驅動器緩沖區的大小設置是否恰當,將影響截包進程的性能,
設置應能保證運行快且不會丟包。這里設置的是512000Byte。
// set a 512K buffer in the driver
// 當無法設置緩沖區時,提示錯誤:
if(PacketSetBuff(lpAdapter,512000)==FALSE){
printf("Unable to set the kernel buffer!n");
return -1;
}
|
PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
函數的功能是,設置與AdapterObject指定網卡綁定的讀操作超時的值,timeout以毫秒為單位,
0表示沒有超時,
當沒有包到時,read就不返回。
// set a 1 second read timeout
// 設置1秒的讀取操作超時
if(PacketSetReadTimeout(lpAdapter,1000)==FALSE){
printf("Warning: unable to set the read tiemout!n");
} |
|
原文轉自:http://www.kjueaiud.com
老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月
|