• 嗅探器的实现 对协议的分析(转)


    #include <stdio.h>
    #include<conio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <winsock2.h>
    #include <ws2tcpip.h>
    #include <iostream>
    #include <string>
    using namespace std;
    #pragma  comment (lib, "ws2_32.lib")
    #define SIO_RCVALL      _WSAIOW(IOC_VENDOR,1)
    #define MAX_PACK_LEN 65535 // 最大包长度
    #define MAX_ADDR_LEN 16 // 最大地址长度
    #define MAX_PROTO_TEXT_LEN 16 // 子协议名称最大长度
    #define MAX_PROTO_NUM 12 // 子协议数量
    #define MAX_HOSTNAME_LEN 255 // 最大主机名长度
    
    // 定义IP首部格式
    typedef struct _IPHeader      
    { 
        unsigned char h_verlen;    // 版本和首部长度  
        unsigned char tos;         // 服务类型       
        unsigned short total_len;  // 总长度 
        unsigned short ident;      // 标识号     
        unsigned short frag_and_flags;  // 段偏移量
        unsigned char ttl;         // 生存时间       
        unsigned char proto;       // 协议   
        unsigned short checksum;   // 首部校验和
        unsigned int sourceIP;     // 源IP地址  
        unsigned int destIP;       // 目的地址   
    }IPHEADER;
    
    // 定义TCP首部格式
    typedef struct _TCPHeader 
    { 
        unsigned short th_sport;  // 源端口号        
        unsigned short th_dport;  // 目的端口号       
        unsigned int th_seq;  // SEQ序号    
        unsigned int th_ack;  // ACK序号
        unsigned char th_lenres;  //  首部长度    
        unsigned char th_flag;   // 控制位  
        unsigned short th_win;  // 窗口大小        
        unsigned short th_sum;  // 校验和        
        unsigned short th_urp;  // 紧急指针         
    }TCPHEADER;
    
    // 定义UDP首部格式
    typedef struct _UDPHeader
    {
    	unsigned short uh_sport; // 16位源端口
    	unsigned short uh_dport; // 16位目的端口
    	unsigned short uh_len; // 16位长度
    	unsigned short uh_sum; // 16位校验和
    }UDPHEADER;
    
    // 定义ICMP首部格式
    typedef struct _ICMPHeader
    {
    	BYTE i_type; // 8位类型
    	BYTE i_code; // 8位代码
    	unsigned short i_cksum; // 16位校验和
    	unsigned short i_id; // 识别号
    	unsigned short i_seq; // 报文序列号
    	unsigned long timestamp; // 时间戳
    }ICMPHEADER;
    //----------------------------------------------------------------------------------------------
    // 定义子协议映射表
    typedef struct _protomap 
    {
    	int ProtoNum;
    	char ProtoText[MAX_PROTO_TEXT_LEN];
    }PROTOMAP;
    
    // 为子协议映射表赋值
    PROTOMAP ProtoMap[MAX_PROTO_NUM]={
    	{IPPROTO_IP,"IP"},
    	{IPPROTO_ICMP,"ICMP"},
    	{IPPROTO_IGMP,"IGMP"},
    	{IPPROTO_GGP,"GGP"},
    	{IPPROTO_TCP,"TCP"},
    	{IPPROTO_PUP,"PUP"},
    	{IPPROTO_UDP,"UDP"},
    	{IPPROTO_IDP,"IDP"},
    	{IPPROTO_ND,"ND"},
    	{IPPROTO_RAW,"RAW"},
    	{IPPROTO_MAX,"MAX"},
    	{NULL,""}
    };
    
    SOCKET SockRaw; // 全局套接字
    char TcpFlag[6]={'F','S','R','P','A','U'}; // TCP标志位
    bool paramAll = false; // 嗅探所有的数据包
    bool paramTcp = false; // 嗅探TCP数据包
    bool paramUdp = false; // 嗅探UDP数据包
    bool paramIcmp = false; // 嗅探ICMP数据包
    
    int packet_totallen = 0; // 数据包总长度
    
    char paramHostAddr_A[20]; // 嗅探的主机A
    char paramHostAddr_B[20]; // 嗅探的主机B
    char keyword[100]; // 嗅探的关键信息
    
    // IP数据包解析函数
    int DecodeIpPack(char *);
    // TCP数据包解析函数
    int DecodeTcpPack(char *);
    // UDP数据包解析函数
    int DecodeUdpPack(char *);
    // ICMP数据包解析函数
    int DecodeIcmpPack(char *);
    // 显示数据包信息
    void ShowPackInfo(char *buf, int iProtocol, char *szSoueceIP, char *szDestIP, char *szProtocol);
    // 显示子协议数据包函数
    void ShowSubPackInfo(char *, int);
    // 错误检测函数
    void CheckSockError(int, char*);
    // 协议检测函数
    char *CheckProtocol(int);
    // 设置嗅探器参数函数
    bool SetSnifferParam();
    //-----------------------------------------------------------------------------------------------------
    // SOCK错误处理函数
    void CheckSockError(int iErrorCode, char *pErrorMsg)
    {
    	if(iErrorCode == SOCKET_ERROR)
    	{
    		printf("%s 出错了: %d",pErrorMsg,GetLastError());
    		closesocket(SockRaw);
    		exit(0);
    	}
    }
    //------------------------------------------------------------------------------------------------------
    // 协议识别函数
    char *CheckProtocol(int iProtocol)
    {
    	for(int i=0; i<MAX_PROTO_NUM;i++)
    	{
    		// 如果找到对应的子协议,则返回名称
    		if(ProtoMap[i].ProtoNum == iProtocol)
    		{
    			return ProtoMap[i].ProtoText;
    		}
    	}
    	return "";
    }
    //---------------------------------------------------------------------------------------------------------
    // TCP解包函数
    int DecodeTcpPack(char *TcpBuf)
    {
    	TCPHEADER *pTcpHeader;
    	char data[MAX_PACK_LEN];
    	int i;
    	// 转换成TCP首部格式
    	pTcpHeader = (TCPHEADER*)TcpBuf;
    	// 输出源端口和目的端口
    	printf("  端口 : %d-->%d  ",ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport));
    	unsigned char FlagMask = 1;
    	// 输出标志位
    	//printf("标志位:");
    	for(i=0;i<6;i++)
    	{
    		if((pTcpHeader->th_flag) & FlagMask)
    		{
    			printf("标志位:%c",TcpFlag[i]);
    		}
    		else
    		{
    			printf("-");
    		}
    		FlagMask = FlagMask<<1;
    	}
    	printf("
    ");
        // 求数据段长度
    	int totalheadlen = sizeof(IPHEADER)+sizeof(TCPHEADER);
    	int tcpheadlen = sizeof(TCPHEADER);
    	memcpy(data,TcpBuf+tcpheadlen,packet_totallen-totalheadlen);
    	return true;
    }
    //-------------------------------------------------------------------------------------------------------------
    // UDP 解包函数
    int DecodeUdpPack(char *UdpBuf)
    {
    	UDPHEADER *pUdpHeader;
    	char data[MAX_PACK_LEN];
    	pUdpHeader = (UDPHEADER *)UdpBuf;
    	// 输出端口和数据长度
    	printf(" 端口号: %d-->%d ",ntohs(pUdpHeader->uh_sport),ntohs(pUdpHeader->uh_dport));
    	printf(" 长度: %d
    ",ntohs(pUdpHeader->uh_len));
    	int totalheadlen = sizeof(IPHEADER)+sizeof(UDPHEADER);
    	int udpheadlen = sizeof(UDPHEADER);
    	memcpy(data,UdpBuf+udpheadlen,packet_totallen-totalheadlen);
    	return true;
    }
    //---------------------------------------------------------------------------------------------------------------------
    // ICMP 解包函数
    int DecodeIcmpPack(char *IcmpBuf)
    {
    	ICMPHEADER *pIcmpHeader;
    	pIcmpHeader = (ICMPHEADER *)IcmpBuf;
    	// 输出ICMP数据包类型、ID和SEQ
    	printf("  Type : %d,%d",pIcmpHeader->i_type,pIcmpHeader->i_code);
    	printf("  ID = %d SEQ = %d
    ",pIcmpHeader->i_id,pIcmpHeader->i_seq);
    	return true;
    }
    
    //-----------------------------------------------------------------------------------------------------------------------
    // 根据过滤条件显示数据包信息
    void ShowPackInfo(char *buf, int iProtocol, char *szSoueceIP, char *szDestIP, char *szProtocol)
    {
    	// 如果设置了主机B的IP,没有设置主机A的IP
    	if((!strcmp(paramHostAddr_A,"all")) && (strcmp(paramHostAddr_B,"all")))
    	{
    		if((!strcmp(paramHostAddr_B,szSoueceIP)) 
    			|| (!strcmp(paramHostAddr_B,szDestIP)))
    		{
    		printf(" -------------------------------------------------------------------------------
    ");
    		printf("| 协议|    源IP地址     |   目的IP地址   |  ");
    		printf("------------------------------------------------------------------------------
    ");
    		printf("
    | %s | ",szProtocol);
    		printf(" %s | %s  |",szSoueceIP,szDestIP);
    			// 显示子协议数据包相关信息
    			ShowSubPackInfo(buf,iProtocol);
    		}
    	}
    	// 如果设置主机A的IP,没有设置主机B的IP
    	else if((strcmp(paramHostAddr_A,"all")) && (!strcmp(paramHostAddr_B,"all")))
    	{
    		if((!strcmp(paramHostAddr_A,szSoueceIP)) 
    			|| (!strcmp(paramHostAddr_A,szDestIP)))
    		{
    		printf(" -------------------------------------------------------------------------------
    ");
    		printf("| 协议|    源IP地址     |   目的IP地址   |
      ");
    		printf("------------------------------------------------------------------------------");
    		printf("
    | %s | ",szProtocol);
    		printf(" %s | %s  |",szSoueceIP,szDestIP);
    			ShowSubPackInfo(buf,iProtocol);
    		}
    	}
    	// 如果主机A和B的IP都进行了设置
    	else if((strcmp(paramHostAddr_A,"all")) && (strcmp(paramHostAddr_B,"all")))
    	{
    		if((!strcmp(paramHostAddr_A,szSoueceIP) 
    			&& !strcmp(paramHostAddr_B,szDestIP))
    			|| (!strcmp(paramHostAddr_B,szSoueceIP) 
    			&& !strcmp(paramHostAddr_A,szDestIP)))
    		{
    			
    		printf(" -------------------------------------------------------------------------------
    ");
    		printf("| 协议|    源IP地址     |   目的IP地址   |
      ");
    		printf("------------------------------------------------------------------------------");
    		printf("
    | %s | ",szProtocol);
    		printf(" %s | %s  |",szSoueceIP,szDestIP);
    			ShowSubPackInfo(buf,iProtocol);
    		}
    	}
    	// 如果主机A和B的IP都没有进行设置
    	else
    	{
    		printf(" -------------------------------------------------------------------------------
    ");
    		printf("| 协议|    源IP地址     |   目的IP地址   |
      ");
    		printf("------------------------------------------------------------------------------");
    		printf("
    | %s | ",szProtocol);
    		printf(" %s | %s  |",szSoueceIP,szDestIP);
    		ShowSubPackInfo(buf,iProtocol);
    	}
    }
    //-----------------------------------------------------------------------------------------------------------------------
    
    // 显示子协议数据包信息
    void ShowSubPackInfo(char *buf, int iProtocol)
    {
    	switch(iProtocol)
    	{
    	case IPPROTO_TCP: // TCP数据包
    		DecodeTcpPack(buf);
    		break;
    	case IPPROTO_UDP: // UDP数据包
    		DecodeUdpPack(buf);
    		break;
    	case IPPROTO_ICMP: // ICMP数据包
    		DecodeIcmpPack(buf);
    		break;
    	default:
    		break;
    	}
    }
    // IP 解包函数
    int DecodeIpPack(char *buf)
    {
    
    	//cout<<"发送的buffer:"<<buf<<endl<<endl; 郁闷,这是个结构体,打印的时候都显示E
    	IPHEADER *pIpHeader;
    	int iProtocol;
    	// 定义协议
    	char szProtocol[MAX_PROTO_TEXT_LEN];
    	char szSourceIP[MAX_ADDR_LEN];
    	char szDestIP[MAX_ADDR_LEN];
    	SOCKADDR_IN saSource,saDest;
    	pIpHeader = (IPHEADER *)buf;
    	// 检测协议是哪种类型
    	iProtocol = pIpHeader->proto;
    	strncpy(szProtocol,CheckProtocol(iProtocol),MAX_PROTO_TEXT_LEN);
    	// 检测源地址
    	saSource.sin_addr.s_addr = pIpHeader->sourceIP;
    	strncpy(szSourceIP,inet_ntoa(saSource.sin_addr),MAX_ADDR_LEN);
    	// 检测目的地址
    	saDest.sin_addr.s_addr = pIpHeader->destIP;
    	strncpy(szDestIP,inet_ntoa(saDest.sin_addr),MAX_ADDR_LEN);
    
    	int iIpLen = sizeof(unsigned long)*(pIpHeader->h_verlen & 0xf);
    	packet_totallen = ntohs(pIpHeader->total_len);
    
    	// 下面显示过滤信息
    	if(paramAll) // 显示所有协议类型数据包
    	{
    		ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    	}
    	// 显示TCP类型数据包
    	else if(paramTcp && (iProtocol == IPPROTO_TCP))
    	{ 
    		ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    	}
    	// 显示UDP类型数据包
    	else if(paramUdp && (iProtocol == IPPROTO_UDP))
    	{
    		ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    	}
    	// 显示ICMP类型数据包
    	else if(paramIcmp && (iProtocol == IPPROTO_ICMP))
    	{
    		ShowPackInfo(buf+iIpLen,iProtocol,szSourceIP,szDestIP,szProtocol);
    	}
    	return true;
    }
    //------------------------------------------------------------------------------------------------------------
    // 设置嗅探器参数
    bool SetSnifferParam()
    {
    	int ret;
    	bool check_input = false;
    	while(!check_input)
    	{
                    printf("*************************基于原始套接字的网络嗅探器*****************************
    
    ");
    				printf("   学号:3109005953   姓名:卫海鹏   专业班级:2009级计算机科学与技术(2)班 
    
    ");
                    printf("==>>请选择要嗅探的数据包类型: 0. 全部  1. TCP  2. UDP  3. ICMP : ");
    		scanf("%d",&ret);
    		switch(ret)
    		{
    		case 0:
    			paramAll = true;
    			check_input = true;
    			break;
    		case 1:
    			paramTcp = true;
    			check_input = true;
    			break;
    		case 2:
    			paramUdp = true;
    			check_input = true;
    			break;
    		case 3:
    			paramIcmp = true;
    			check_input = true;
    			break;
    		default:
    			printf("==>>o(︶︿︶)o唉,输入错误!!!
    ");
    			check_input = false;
    			break;
    		}
    	}
    
    	printf("
    ==>>请输入嗅探的主机A的IP地址(输入all即为全部主机):");
    	scanf("%s",paramHostAddr_A);
    	printf("
    ==>>请输入嗅探的主机B的IP地址(输入all即为全部主机):");
        scanf("%s",paramHostAddr_B);
          
    	return true;
    }
    //----------------------------------------------------------------------------------------------------------------------
    void main(int argc, char **argv)
    {
    	int i,temp;
    	int iErrorCode;
    	char RecvBuf[MAX_PACK_LEN] = {0};
    	SetSnifferParam();
    	WSADATA wsaData;
    	// 初始化Winsock库
    	iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData);
    	CheckSockError(iErrorCode, "WSAStartup");
    	SockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
    	CheckSockError(SockRaw, "socket");
    	// 获取本机IP地址,并且判断Socket版本,建立原始套接字
    	char FAR name[MAX_HOSTNAME_LEN];
    	iErrorCode = gethostname(name, MAX_HOSTNAME_LEN);
    	CheckSockError(iErrorCode, "gethostname");
    
    	printf("%s
    ",name);
    
    	struct hostent FAR *pHostent;
    	pHostent = (struct hostent *)malloc(sizeof(struct hostent));
    
    	pHostent = gethostbyname(name);
    	
    	cout<<"pHostent->h_name:"<<pHostent->h_name<<endl;
    	cout<<"pHostent->h_aliases:"<<pHostent->h_aliases<<endl;
    	cout<<"pHostent->h_addrtype:"<<pHostent->h_addrtype<<endl;
        cout<<"pHostent->h_length:"<<pHostent->h_length<<endl;
    	cout<<"pHostent->h_addr_list:"<<pHostent->h_addr_list<<endl;
        
    
    
    
    	// 设置地址结构,端口为本地的6000
    	SOCKADDR_IN sa;
    	sa.sin_family = AF_INET;
    	sa.sin_port = htons(6000);
    
    	memcpy(&sa.sin_addr.S_un.S_addr,pHostent->h_addr_list[0],pHostent->h_length);
    
    	// 绑定地址结构
    	iErrorCode = bind(SockRaw, (PSOCKADDR)&sa, sizeof(sa));
    	CheckSockError(iErrorCode, "bind");
    	// 设置套接字为SIO_RCVALL,以便接收所有的IP包
    	DWORD dwBufferLen[10];
    	DWORD dwBufferInLen = 1;
    	DWORD dwBytesReturned = 0;
    
    	//为什么要有下面这一行,还不是很清楚
    	iErrorCode = WSAIoctl(SockRaw, SIO_RCVALL , &dwBufferInLen, sizeof(dwBufferInLen),
    		&dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL);
    
    	CheckSockError(iErrorCode, "Ioctl");
    	// 监听IP报文
       L1:  printf("
    ==>>请输入要嗅探数据包的个数:");
                    scanf("%d",&temp);
                    i=temp;
    
        	while(i)
    	{
    
    		// 每次将接收缓冲区清零
    		memset(RecvBuf, 0, sizeof(RecvBuf));
    		// 开始接收缓冲区的数据
    		iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf),0);
    		CheckSockError(iErrorCode, "recv");
    		// 对接收到的数据包进行解析
    		iErrorCode = DecodeIpPack(RecvBuf);
    		CheckSockError(iErrorCode, "Decode");
    		Sleep(100);
    		i--;
    	}
         if(i % 10 == 0) {
    	   system("pause");
           goto L1;
         } //等待输入一个字符(不回显)后继续输出.
    
    }
    

      

  • 相关阅读:
    五、Django之路由系统
    四、Django设置相关
    三、Django安装和流程
    二、Web框架实现
    Flask学习-Wsgiref库
    设计模式之设计模式六大原则(三大基本原则)【1】
    Linux之更改Nginx映射默认根目录
    顺序列表(栈/队列等)ADT[C++]
    [C++]数组与指针(纯代码-复习用)
    [C++]指针与多级指针(图解)
  • 原文地址:https://www.cnblogs.com/mynona/p/3485733.html
Copyright © 2020-2023  润新知