简单网络嗅探c++实现

一、原理

    用一些比喻,集线器网络中所有主机都连接在一条网线上,也就是说每台主机发送的数据都将经过其他主机的门前(网卡),只是说一般网卡一看数据包报头,这不是发给自己的,就不理这个包了,而我们现在要做的,就是敞开大门,不管这个包是发给谁的,都将其纳入囊中。那么如何做呢?只需将网卡设置为混杂模式。

    要用到C语言网络编程中的Socket,一般的Socket只能获取到传输数据包,所以我们要用的是Raw SOCKET(原始Socket),它可以工作在链路层或者IP层(取决于创建时的参数设置)。


二、实现

    原始套接字的创建方法跟TCP/IP创建方法几乎一模一样:

    int sockfd;

    sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);

     这两句程序你就可以创建一个原始套接字。这种类型套接字的功能与TCP或者UDP类型套接字的功能有很大的

  不同:TCP/UDP类型的套接字只能够访问传输层以及传输层以上的数据,因为当IP层把数据传递给传输层时,下的

  数据包头已经被丢掉了。而原始套接字却可以访问传输层以下的数据,所以使用raw套接字你可以实现上至应用层

  的数据操作,也可以实现下至链路层的数据操作。

 

三、代码

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#pragma comment(lib,"WS2_32.lib")

#define BUFFER_MAX 2048
#define IP_HDRINCL 2
#define     SIO_RCVALL     _WSAIOW(IOC_VENDOR,1)


using namespace std;
int main(){
	SOCKET sock;
	int n_read,proto;
	int flag = 1;
	char buffer[BUFFER_MAX];
	char LocalName[256];
	char *ethhead,*iphead,*tcphead,*udphead,*icmphead,*p;
	WSADATA WSAData;

	if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)
	{                                        
		printf("WSAStartup ERROR.\\n");  //如果初始化WSADATA结构得到错误码,则显示出错信息
		return -1;
	}

//	if(sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)<0){
//		cout<<"Socket创建失败"<<endl;
//		exit(0);
//	}
//	 setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)); //设置 IP 头操作选项 
	创建并设置原始套接字
  sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);//启用winsock创建原始套接字,SOCK_RAW 类型表示原始套接字类型混杂模式,也就是接收所有包
  setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));//设置原始套接字,设置 IP 头操作选项 

 把原始套接字绑定到本地主机网卡上,实现将本地网卡置于混杂模式
	if(gethostname((char*)LocalName,   sizeof(LocalName)-1)!=0) //获取本地主机IP
	{
		printf("获取主机名失败   Error:%d.\\n",WSAGetLastError());    
              return   -1;  
	}
	gethostname((char*)LocalName, 256);//把本地主机名存放入指定的缓冲区中
	hostent   *pHost   =   gethostbyname((char*)LocalName);

	SOCKADDR_IN   addr_in;   //获取本地 IP 地址 
    addr_in.sin_addr   =   *(in_addr   *)pHost->h_addr_list[0];  
    addr_in.sin_family   =   AF_INET;    
    addr_in.sin_port   =   htons(40000); 
	
	if(bind(sock,   (PSOCKADDR)&addr_in,   sizeof(addr_in))!=0) //把原始套接字绑定在本地主机网卡上
    {    
        printf("绑定失败:%d.\\n",WSAGetLastError());    //绑定失败时显示提示信息
        return   -1;    
    }   
//设置原始套接字能够接受所有的数据
	DWORD   dwValue   =   1;   
	if(ioctlsocket(sock,   SIO_RCVALL,   &dwValue)!=0)  
    {    
         printf("ioctlsocket   Error:%d.\\n",WSAGetLastError());  //设置失败时显示提示信息  
         return   -1;    
    }   
	
	while(true){
		int ret = recv(sock,buffer,BUFFER_MAX,0);
		if(ret>0){
			ethhead = buffer;
			p = ethhead;
			int n = 0XFF;

			//链路层前6+6+2个字节为目的MAC 源MAC type
//			printf("MAC:	%.2X:%-02X-%.02X-%.02X-%.02X-%.02X	 ==>	  %.2X-%.2X-%.2X-%.2X-%.2X-%.2X-\n",p[6]&n,p[7]&n,p[8]&n,p[9]&n,p[10]&n,p[11]&n,
//				p[0]&n,p[1]&n,p[2]&n,p[3]&n,p[4]&n,p[5]&n);

			iphead = ethhead;// + 14;
			p = iphead + 12;
			//数据包前14个字节后为20字节的第九个字节为协议,第12-16,17-20个字节为源IP,目的IP
			printf("IP:	%d.%d.%d.%d	   ==>	   %d.%d.%d.%d\n",p[0]&0XFF,p[1]&0XFF,p[2]&0XFF,p[3]&0XFF,p[4]&0XFF,p[5]&0XFF,p[6]&0XFF,p[7]&0XFF);
			short length = (short)(iphead+2)[0];
			printf("总长度:%d\n",length);

			proto = (iphead+9)[0];
			p = iphead + 20;
			printf("Protocol:");
			switch(proto){
			case 1:		printf("ICMP\n");break;
			case 2:		printf("IGMP\n");break;
			case 4:		printf("IP\n");break;
			case 6:		printf("TCP\n");break;
			case 8:		printf("EGP\n");break;
			case 9:		printf("IGP\n");break;
			case 17:	printf("UDP\n");break;
			case 41:	printf("IPv6\n");break;
			case 50:	printf("ESP\n");break;
			case 89:	printf("OSPF\n");break;
			default:	printf("不知道,协议编号是%d,请自己查文档\n",proto);break;
			}
		}
		cout<<endl;                         
		Sleep(200);
	}

}


  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
网络器是一种用于监视和分析网络流量的工具,它能够捕获经过网络的数据包,并对这些数据包进行分析和处理。基于C语言的网络器的设计与实现需要考虑以下几个方面: 首先,需要使用C语言编写网络器的核心功能,包括数据包捕获和分析。可以使用像libpcap这样的库来实现数据包捕获功能,该库可以在网络接口上进行数据包捕获,并将捕获的数据包传递给应用程序进行分析。 其次,网络器需要实现数据包的解析和分析功能,包括提取数据包中的源地址、目的地址、协议类型等信息,并能够对数据包进行过滤和分类。这需要对网络协议进行深入的了解和分析,以便能够正确地解析和处理每一种类型的数据包。 另外,网络器还需要实现数据的存储和展示功能,可以将捕获到的数据包保存到本地存储或数据库中,并能够以图形界面或命令行界面的形式展示分析结果。 最后,在设计和实现网络器时,需要考虑到安全和性能等方面的问题,确保网络器能够稳定可靠地运行,并能够有效地监视和分析网络流量。 总的来说,基于C语言的网络器的设计与实现需要对网络协议有较深入的了解,并需要充分考虑到安全和性能等方面的问题,以确保网络器能够准确、稳定地监视和分析网络流量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值