一个简易网络嗅探器的实现源代码
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
然后在 driver 中置 512K 的缓冲:
这里用到函数 PacketSetBuff(LPADAPTER AdapterObject,int dim),它被用于设置 AdapterObject 指向的网卡的驱动程序的缓冲区,成功则返回 TRUE。Dim 是新的缓冲区的大小,当它被设定时,旧缓冲区中的 数据将被丢弃,其中存储的包也会失去。
接下来,定位设备,Biblioteka Baidu码如下:
这里用到函数 PacketAllocatePacket(Void)将在内存中分配一个 PACKET 结构并返回一个指向它的指 针,但这个结构的 Buffer 字段还没有设定,所以应再调用 PacketInitPacket 函数来对其进行初始化。
//allocate and initialize a packet structure that will be used to //receive the packets. // 当定位失败时,提示错误: if((lpPacket = PacketAllocatePacket())==NULL){
需要注重的地方:驱动器缓冲区的大小设置是否恰当,将影响截包进程的性能,设置应能保证运行快且不会 丢包。这里设置的是 512000Byte。
// set a 512K buffer in the driver // 当无法设置缓冲区时,提示错误: if(PacketSetBuff(lpAdapter,512000)==FALSE){
·NDIS-PACKET-TYPE-PROMISCUOUS:设置混杂模式,每个到来的包都会被网卡接受;
·NDIS-PACKET-TYPE-DIRECTED:只有直接到主机网卡的包才会被接受;
·NDIS-PACKET-TYPE-BROADCAST:只接受广播包;
·NDIS-PACKET-TYPE-MULTICAST:只接受到主机所在的组的多播包;
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)) {
//是 Windows NT // 找不到设备列表 if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){
下面这段代码是用来在不同版本下得到网络适配器名:
Win9x 和 WinNT 中的网卡名称是分别用 ASCII 和 UNICODE 实现的,所以首先要得到本地操作系统的版 本号:
dwVersion=GetVersion(); dwWindowsMajorVersion= (DWORD)(LOBYTE(LOWORD(dwVersion)));
printf("Unable to set the kernel buffer!\n"); return -1; }
PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)函数的功能是,设置与 AdapterObject 指定网卡绑定的读操作超时的值,timeout 以毫秒为单位,0 表示没有超时,当没有包到时, read 就不返回。
·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"); }
需要注重的地方:PACKET 结构关联的缓冲区存储由 packet capture driver 截获的包,包的数量被缓冲 区大小所限制,最大缓冲区的大小就是应用程序从驱动器中一次能读到的数据的多少。所以设置大的缓冲区可减 少系统调用的次数,提高截获效率。这里设置的是 256K。
这里首先用到的 Packet.dll 函数是 PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize,通 常它是与驱动程序通信并被调用的第一个函数,它将返回的用户本地系统中安装的网络适配器的名字放在缓冲区 pStr 中;BufferSize 是缓冲区的长度:
摘要:本文介绍一个用 C 语言和网络数据包分析开发工具实现的简易网络 Sniffer。 要害词:网络;数据包;Sniffer
引言 目前,已经有不少的 Sniff 工具软件,如 Windows 环境下,最富盛名的工具是 Netxray 和 Sniffer pro, 用它们在 Windows 环境下抓包来分析,非常方便。在 UNIX 环境下如 Sniffit,Snoop,Tcpdump,Dsniff 等 都是比较常见的。这里介绍一个用 C 语言和网络数据包和分析开发工具 libpcap 及 winpcap 实现的简易网络 Sniffer。 网络嗅探器程序框图 首先给出流程如图 1 所示。
printf("\nError: failed to allocate the LPPACKET structure."); return (-1); }
然后,就可以初始化设备,开始接受网络包了:
用函数 PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)来初始化 PACKET 结构。lpPacket 是要被初始化的指针;Buffer 为指向用户分配的包含包的数据的缓冲区的指针;Length 为缓 冲区长度。
printf("Unable to retrieve the list of the adapters!\n"); return -1; } tempa=AdapterNamea; temp1a=AdapterNamea; while ((*tempa!='\0')(*(tempa-1)!='\0')) { if (*tempa=='\0') { memcpy(AdapterList[i],temp1a,tempa-temp1a); temp1a=tempa+1; i++; } tempa++; } AdapterNum=i; for (i=0;i<AdapterNum;i++) printf("\n%d- %s\n",i+1,AdapterList[i]); printf("\n"); } 下面这段代码就是让用户选择监听的网络适配器号:
memcpy(AdapterList[i],temp1,(temp-temp1)*2); temp1=temp+1; i++; }
temp++; } // 显示适配器列表 AdapterNum=i; for (i=0;i<AdapterNum;i++)
wprintf(L"\n%d- %s\n",i+1,AdapterList[i]); printf("\n"); } else //否则就是 windows 9x,获取适配器名的方法同 WinNT 下 { if(PacketGetAdapterNames(AdapterNamea,&AdapterLength)==FALSE){
// 选择设备 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);
printf("Unable to retrieve the list of the adapters!\n"); return -1; } // 找到设备列表 temp=AdapterName; temp1=AdapterName; while ((*temp!='\0')(*(temp-1)!='\0')) { if (*temp=='\0') {
图 1 流程图 网络嗅探器程序实现 在 c 环境下编程,源码如下:
/* June 2nd,2002 * Project for graduation qualification By Bby Team 19 */ #include <stdio.h>
#include <conio.h> //必须加路径,必须把头文件 packet32.h 包含进去 #include "..\..\Include\packet32.h" #include "..\..\Include\ntddndis.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:%s\n", PacketGetVersion()); printf("Adapters installed:\n"); i=0;
然后,将所选择的设备打开,这里可以设置为“混杂”模式打开,也可以是“直接”模式打开。代码如下:
// 打开设备 lpAdapter = PacketOpenAdapter(AdapterList[Open-1]); // 当设备无法打开时,出示错误信息: if (!lpAdapter (lpAdapter->hFile == INVALID_HANDLE_VALUE)) {
dwErrorCode=GetLastError(); printf("Unable to open the adapter, Error Code : %lx\n",dwErrorCode); return -1; }
将网卡设置为“混杂”模式,代码如下:
这里用到函数 PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter),它在到来的包上设 置了一个硬件过滤器,如操作成功,返回 TRUE。AdapterObject 是过滤器所在的网卡设备指针;过滤器的常 量 Filter 定义在头文件 ntddndis.h 中,包括有:
// set a 1 second read timeout // 设置 1 秒的读取操作超时 if(PacketSetReadTimeout(lpAdapter,1000)==FALSE){
printf("Warning: unable to set the read tiemout!\n"); }
这里用到函数 PacketSetBuff(LPADAPTER AdapterObject,int dim),它被用于设置 AdapterObject 指向的网卡的驱动程序的缓冲区,成功则返回 TRUE。Dim 是新的缓冲区的大小,当它被设定时,旧缓冲区中的 数据将被丢弃,其中存储的包也会失去。
接下来,定位设备,Biblioteka Baidu码如下:
这里用到函数 PacketAllocatePacket(Void)将在内存中分配一个 PACKET 结构并返回一个指向它的指 针,但这个结构的 Buffer 字段还没有设定,所以应再调用 PacketInitPacket 函数来对其进行初始化。
//allocate and initialize a packet structure that will be used to //receive the packets. // 当定位失败时,提示错误: if((lpPacket = PacketAllocatePacket())==NULL){
需要注重的地方:驱动器缓冲区的大小设置是否恰当,将影响截包进程的性能,设置应能保证运行快且不会 丢包。这里设置的是 512000Byte。
// set a 512K buffer in the driver // 当无法设置缓冲区时,提示错误: if(PacketSetBuff(lpAdapter,512000)==FALSE){
·NDIS-PACKET-TYPE-PROMISCUOUS:设置混杂模式,每个到来的包都会被网卡接受;
·NDIS-PACKET-TYPE-DIRECTED:只有直接到主机网卡的包才会被接受;
·NDIS-PACKET-TYPE-BROADCAST:只接受广播包;
·NDIS-PACKET-TYPE-MULTICAST:只接受到主机所在的组的多播包;
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)) {
//是 Windows NT // 找不到设备列表 if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){
下面这段代码是用来在不同版本下得到网络适配器名:
Win9x 和 WinNT 中的网卡名称是分别用 ASCII 和 UNICODE 实现的,所以首先要得到本地操作系统的版 本号:
dwVersion=GetVersion(); dwWindowsMajorVersion= (DWORD)(LOBYTE(LOWORD(dwVersion)));
printf("Unable to set the kernel buffer!\n"); return -1; }
PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)函数的功能是,设置与 AdapterObject 指定网卡绑定的读操作超时的值,timeout 以毫秒为单位,0 表示没有超时,当没有包到时, read 就不返回。
·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"); }
需要注重的地方:PACKET 结构关联的缓冲区存储由 packet capture driver 截获的包,包的数量被缓冲 区大小所限制,最大缓冲区的大小就是应用程序从驱动器中一次能读到的数据的多少。所以设置大的缓冲区可减 少系统调用的次数,提高截获效率。这里设置的是 256K。
这里首先用到的 Packet.dll 函数是 PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize,通 常它是与驱动程序通信并被调用的第一个函数,它将返回的用户本地系统中安装的网络适配器的名字放在缓冲区 pStr 中;BufferSize 是缓冲区的长度:
摘要:本文介绍一个用 C 语言和网络数据包分析开发工具实现的简易网络 Sniffer。 要害词:网络;数据包;Sniffer
引言 目前,已经有不少的 Sniff 工具软件,如 Windows 环境下,最富盛名的工具是 Netxray 和 Sniffer pro, 用它们在 Windows 环境下抓包来分析,非常方便。在 UNIX 环境下如 Sniffit,Snoop,Tcpdump,Dsniff 等 都是比较常见的。这里介绍一个用 C 语言和网络数据包和分析开发工具 libpcap 及 winpcap 实现的简易网络 Sniffer。 网络嗅探器程序框图 首先给出流程如图 1 所示。
printf("\nError: failed to allocate the LPPACKET structure."); return (-1); }
然后,就可以初始化设备,开始接受网络包了:
用函数 PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)来初始化 PACKET 结构。lpPacket 是要被初始化的指针;Buffer 为指向用户分配的包含包的数据的缓冲区的指针;Length 为缓 冲区长度。
printf("Unable to retrieve the list of the adapters!\n"); return -1; } tempa=AdapterNamea; temp1a=AdapterNamea; while ((*tempa!='\0')(*(tempa-1)!='\0')) { if (*tempa=='\0') { memcpy(AdapterList[i],temp1a,tempa-temp1a); temp1a=tempa+1; i++; } tempa++; } AdapterNum=i; for (i=0;i<AdapterNum;i++) printf("\n%d- %s\n",i+1,AdapterList[i]); printf("\n"); } 下面这段代码就是让用户选择监听的网络适配器号:
memcpy(AdapterList[i],temp1,(temp-temp1)*2); temp1=temp+1; i++; }
temp++; } // 显示适配器列表 AdapterNum=i; for (i=0;i<AdapterNum;i++)
wprintf(L"\n%d- %s\n",i+1,AdapterList[i]); printf("\n"); } else //否则就是 windows 9x,获取适配器名的方法同 WinNT 下 { if(PacketGetAdapterNames(AdapterNamea,&AdapterLength)==FALSE){
// 选择设备 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);
printf("Unable to retrieve the list of the adapters!\n"); return -1; } // 找到设备列表 temp=AdapterName; temp1=AdapterName; while ((*temp!='\0')(*(temp-1)!='\0')) { if (*temp=='\0') {
图 1 流程图 网络嗅探器程序实现 在 c 环境下编程,源码如下:
/* June 2nd,2002 * Project for graduation qualification By Bby Team 19 */ #include <stdio.h>
#include <conio.h> //必须加路径,必须把头文件 packet32.h 包含进去 #include "..\..\Include\packet32.h" #include "..\..\Include\ntddndis.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:%s\n", PacketGetVersion()); printf("Adapters installed:\n"); i=0;
然后,将所选择的设备打开,这里可以设置为“混杂”模式打开,也可以是“直接”模式打开。代码如下:
// 打开设备 lpAdapter = PacketOpenAdapter(AdapterList[Open-1]); // 当设备无法打开时,出示错误信息: if (!lpAdapter (lpAdapter->hFile == INVALID_HANDLE_VALUE)) {
dwErrorCode=GetLastError(); printf("Unable to open the adapter, Error Code : %lx\n",dwErrorCode); return -1; }
将网卡设置为“混杂”模式,代码如下:
这里用到函数 PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter),它在到来的包上设 置了一个硬件过滤器,如操作成功,返回 TRUE。AdapterObject 是过滤器所在的网卡设备指针;过滤器的常 量 Filter 定义在头文件 ntddndis.h 中,包括有:
// set a 1 second read timeout // 设置 1 秒的读取操作超时 if(PacketSetReadTimeout(lpAdapter,1000)==FALSE){
printf("Warning: unable to set the read tiemout!\n"); }