#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; } //等待输入一个字符(不回显)后继续输出. }