一个简易网络嗅探器的实现
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一个简易网络嗅探器的实现
摘要:本文介绍一个用C语言和网络数据包分析开发工具实现的简易网络Sniffer。
关键词:网络;数据包;Sniffer
1 引言
目前,已经有不少的Sniff工具软件,如Windows环境下,最富盛名的工具是Netxray 和Sniffer pro,用它们在 Windows环境下抓包来分析,非常方便。在UNIX环境下如Sniffit,Snoop,Tcpdump,Dsniff 等都是比较常见的。这里介绍一个用C语言和网络数据包和分析开发工具libpcap及winpcap 实现的简易网络Sniffer。
2网络嗅探器程序实现
在c环境下编程,源码
/* June 2nd,2002
* Project for graduation qualification By Bby Team 19 */
#include
#include
//必须加路径,必须把头文件包含进去
#include "..“..“Include“"
#include "..“..“Include“"
#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(" test application. Library version:%s“n", PacketGetVersion()); printf("Adapters installed:“n");
i=0;
下面这段代码是用来在不同版本下得到网
络适配器名:
Win9x 和WinNT中的网卡名称是分别用ASCII和UNICODE实现的,所以首先要得到本地操作系统的版本号.:
dwVersion=GetVersion();
dwWindowsMajorVersion=
(DWORD)(LOBYTE(LOWORD(dwVersion))); 这里首先用到的函数是PacketGetAdapterNames,它在到来的包上设置了一个硬件过滤器,如操作成功,返回TRUE。AdapterObject是过滤器所在的网卡设备指针;过滤器的常量Filter定义在头文件中,包括有:
•NDIS-PACKET-TYPE-PROMISCUOUS:设置混杂模式,每个到来的包都会被网卡接受;•ND IS-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_P ACKET_TYPE_PROMISCUOUS)==FALSE){
printf("Warning: unable to set promiscuous mode!“n");
}
然后在driver中置512K的缓冲:
这里用到函数PacketSetBuff,它被用于设置AdapterObject指向的网卡的驱动程序的缓冲区,成功则返回TRUE。Dim是新的缓冲区的大小,当它被设定时,旧缓冲区中的数据将被丢弃,其中存储的包也会失去。
需要注意的地方:驱动器缓冲区的大小设置是否恰当,将影响截包进程的性能,设置应能保证运行快且不会丢包。这里设置的是512000Byte。
// set a 512K buffer in the driver // 当无法设置缓冲区时,提示错误:
if(PacketSetBuff(lpAdapter,512000)==F ALSE){
printf("Unable to set the kernel buffer!“n");
return -1;
}
PacketSetReadTimeout函数的功能是,设置与AdapterObject指定网卡绑定的读操作超时的值,timeout以毫秒为单位,0表示没有超时,当没有包到时,read就不返回。// set a 1 second read timeout
// 设置1秒的读取操作超时
if(PacketSetReadTimeout(lpAdapter,100 0)==FALSE){
printf("Warning: unable to set the read tiemout!“n");
}
接下来,定位设备,代码
这里用到函数PacketAllocatePacket将在内存中分配一个PACKET结构并返回一个指