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

来源:互联网 发布:淄博网络推广公司 编辑:程序博客网 时间:2024/05/19 02:03
#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]; // 嗅探的主机Achar paramHostAddr_B[20]; // 嗅探的主机Bchar 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("\n");    // 求数据段长度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\n",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和SEQprintf("  Type : %d,%d",pIcmpHeader->i_type,pIcmpHeader->i_code);printf("  ID = %d SEQ = %d\n",pIcmpHeader->i_id,pIcmpHeader->i_seq);return true;}//-----------------------------------------------------------------------------------------------------------------------// 根据过滤条件显示数据包信息void ShowPackInfo(char *buf, int iProtocol, char *szSoueceIP, char *szDestIP, char *szProtocol){// 如果设置了主机B的IP,没有设置主机A的IPif((!strcmp(paramHostAddr_A,"all")) && (strcmp(paramHostAddr_B,"all"))){if((!strcmp(paramHostAddr_B,szSoueceIP)) || (!strcmp(paramHostAddr_B,szDestIP))){printf(" -------------------------------------------------------------------------------\n");printf("| 协议|    源IP地址     |   目的IP地址   |  ");printf("------------------------------------------------------------------------------\n");printf("\n| %s | ",szProtocol);printf(" %s | %s  |",szSoueceIP,szDestIP);// 显示子协议数据包相关信息ShowSubPackInfo(buf,iProtocol);}}// 如果设置主机A的IP,没有设置主机B的IPelse if((strcmp(paramHostAddr_A,"all")) && (!strcmp(paramHostAddr_B,"all"))){if((!strcmp(paramHostAddr_A,szSoueceIP)) || (!strcmp(paramHostAddr_A,szDestIP))){printf(" -------------------------------------------------------------------------------\n");printf("| 协议|    源IP地址     |   目的IP地址   |\n  ");printf("------------------------------------------------------------------------------");printf("\n| %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(" -------------------------------------------------------------------------------\n");printf("| 协议|    源IP地址     |   目的IP地址   |\n  ");printf("------------------------------------------------------------------------------");printf("\n| %s | ",szProtocol);printf(" %s | %s  |",szSoueceIP,szDestIP);ShowSubPackInfo(buf,iProtocol);}}// 如果主机A和B的IP都没有进行设置else{printf(" -------------------------------------------------------------------------------\n");printf("| 协议|    源IP地址     |   目的IP地址   |\n  ");printf("------------------------------------------------------------------------------");printf("\n| %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; 郁闷,这是个结构体,打印的时候都显示EIPHEADER *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("*************************基于原始套接字的网络嗅探器*****************************\n\n");printf("   学号:3109005953   姓名:卫海鹏   专业班级:2009级计算机科学与技术(2)班 \n\n");                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唉,输入错误!!!\n");check_input = false;break;}}printf("\n==>>请输入嗅探的主机A的IP地址(输入all即为全部主机):");scanf("%s",paramHostAddr_A);printf("\n==>>请输入嗅探的主机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\n",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;    // 设置地址结构,端口为本地的6000SOCKADDR_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("\n==>>请输入要嗅探数据包的个数:");                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;     } //等待输入一个字符(不回显)后继续输出.}

  

0 0
原创粉丝点击