#include "stdafx.h" #include "stdio.h" #include "string.h" #include "mstcpip.h" #include "Winsock2.h" #pragma comment(lib,"WS2_32.lib") #define STATUS_FAILED 0xFFFF //定义异常出错代码 #define MAX_PACK_LEN 65535 //接收的最大 IP 报文 #define MAX_ADDR_LEN 16 //点分十进制 地址的最大长度 #define MAX_HOSTNAME_LAN 255 //最大主机名长度 typedef struct _iphdr //定义IP首部 { unsigned char h_lenver; //4 位首部长度+4 位IP 版本号 unsigned char tos; //8 位服务类型TOS unsigned short total_len; //16 位总长度(字节) unsigned short ident; //16 位标识 unsigned short frag_and_flags; //3 位标志位 unsigned char ttl; //8 位生存时间TTL unsigned char proto; //8 位协议(TCP 或其他) unsigned short checksum; //16 位IP 首部校验和 unsigned int sourceIP; //32 位源IP 地址 unsigned int destIP; //32 位目的IP 地址 }IP_HEADER; typedef struct _tcphdr //定义TCP 首
部 { USHORT th_sport; //16 位源端口 USHORT th_dport; //16 位目的端口 unsigned int th_seq; unsigned int th_ack; unsigned char th_lenres; //4 位首部长度/6 位保留字 unsigned char th_flag; //6 位标志位 USHORT th_win; //16 位窗口大小 USHORT th_sum; //16 位校验和 USHORT th_urp; //16 位紧急数据偏移量 }TCP_HEADER; SOCKET SockRaw; char* TcpFlag[6]={ //定
义TCP 标志位 "FIN ", //FIN: 表示发送端已经没有数据要求传输了,希望释放连接。 "SYN ", //SYN: 标志位用来建立连接,让连接双方同步序列号。如果SYN=1而ACK=0,则表示该数据包为连接请求,如果SYN=1而ACK=1则表示 接受连接。 "RST ", //RST: 用来复位一个连接。RST标志置位的数据包称为复位包。一般情况下,如果TCP收到的一个分段明显不是属于该主机上的任何一 个连接,则向远端发送一个复位包。 "PSH ", //PSH: 如果置位,接收端应尽快把数据传送给应用层。 "ACK ", //ACK: 为确认标志位。如果为1,表示包中的确认号时有效的。否则,包中的确认号无效。 "URG " //URG: 为紧急数据标志。如果它为1,表示本数据包中包含紧急数据。此时紧急数据指针有效。 }; bool ParamTcp =true; // -t 关注TCP 报文 char *strFromIpFilter=NULL; // 源IP 地址 过滤 char *strDestIpFilter=NULL; // 目的地址过 滤 //Referrence int DecodeIpPack(char *,int); int DecodeTcpPack(char *); void CheckSockError(int,char*); void usage(void); bool GetCmdLine(int, char **); // void main(int argc, char ** argv) { int iErrorCode; char RecvBuf[MAX_PACK_LEN] = { 0 }; usage(); if(GetCmdLine(argc, argv)==true) exit(0); //初始化SOCKET WSADATA wsaData; iErrorCode = WSAStartup(MAKEWORD(2,1),&wsaData); CheckSockError(iErrorCode, "WSAStartup"); SockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP); CheckSockError(SockRaw, "socket");
//获取本机IP 地址 char FAR name[MAX_HOSTNAME_LAN]; iErrorCode = gethostname(name, MAX_HOSTNAME_LAN); CheckSockError(iErrorCode, "gethostname"); struct hostent FAR * pHostent; pHostent = (struct hostent * )malloc(sizeof(struct hostent)); pHostent = gethostbyname(name); 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");
//设置SOCK_RAW 为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 报文 while(true) { memset(RecvBuf, 0, sizeof(RecvBuf)); iErrorCode = recv(SockRaw, RecvBuf, sizeof(RecvBuf), 0); CheckSockError(iErrorCode, "recv"); iErrorCode = DecodeIpPack(RecvBuf, iErrorCode); CheckSockError(iErrorCode, "Decode"); } }
//IP 解包程序 int DecodeIpPack(char *buf, int iBufSize) { IP_HEADER *pIpheader; int iProtocol, iTTL; char szProtocol[4]; char szSourceIP[MAX_ADDR_LEN], szDestIP[MAX_ADDR_LEN]; SOCKADDR_IN saSource, saDest; pIpheader = (IP_HEADER *)buf;
//Check Proto iProtocol = pIpheader->proto; strncpy(szProtocol, "TCP", 4); if(iProtocol==IPPROTO_TCP) { //Check Source IP saSource.sin_addr.s_addr = pIpheader->sourceIP; strncpy(szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN); if (strFromIpFilter) if (strcmp(strFromIpFilter,szSourceIP)) return true; //Check Dest IP saDest.sin_addr.s_addr = pIpheader->destIP; strncpy(szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN); if (strDestIpFilter) if (strcmp(strDestIpFilter,szDestIP)) return true; //TTL iTTL = pIpheader->ttl; //Output printf("%s ", szProtocol); printf("%s->%s ", szSourceIP, szDestIP); printf("bytes=%d TTL=%d ",iBufSize,iTTL); //Calculate IP Header Length int iIphLen = sizeof(unsigned long) * (pIpheader->h_lenver & 0xf); //Decode Sub Protocol:TCP DecodeTcpPack(buf+iIphLen); } return true; } //SOCK 错误处理程序 void CheckSockError(int iErrorCode, char *pErrorMsg) { if(iErrorCode==SOCKET_ERROR) { printf("%s Error:%d\n", pErrorMsg, GetLastError()); closesocket(SockRaw); exit(0); } }
//TCP 解包程序 int DecodeTcpPack(char * TcpBuf) { TCP_HEADER * pTcpHeader; pTcpHeader = (TCP_HEADER * )TcpBuf; printf("Port:%d->%d ", ntohs(pTcpHeader->th_sport),ntohs(pTcpHeader->th_dport)); unsigned char FlagMask = 1; int HdrLen = (pTcpHeader->th_lenres)>>2; printf("\n%s",((BYTE *)pTcpHeader)+HdrLen); for( int i=0; i<6; i++ ) { if((pTcpHeader->th_flag) & FlagMask) printf("%s",TcpFlag[i]); else printf(" "); FlagMask=FlagMask<<1; } printf("\n"); return true; }
//命令行参数处理 bool GetCmdLine(int argc, char ** argv) { for(int i=1;i<argc;i++) { if(argv[i][0]!='/') return true; else { switch (argv[i][1]) { case 'f': case 'F': { strFromIpFilter=(char*)malloc(16*sizeof(char)); memset(strFromIpFilter,0,16*sizeof(char)); strcpy(strFromIpFilter,argv[i]+3); break; } case 'd': case 'D': { strDestIpFilter=(char*)malloc(16*sizeof(char)); memset(strDestIpFilter,0,16*sizeof(char)); strcpy(strDestIpFilter,argv[i]+3); break; } case '?': return true; break; default: break; } } } printf("\nWill Sniffer"); printf(" TCP"); if(strFromIpFilter) printf(" FromIp:%s",strFromIpFilter); if(strDestIpFilter) printf(" DestIp:%s",strDestIpFilter); printf("\n\tCTRL+C to quit\nStart:\n"); return (false); }
void usage(void) { printf("\tSinffer for Win2K Console\n"); printf("USAGE:\n"); printf("\t/f: fromIP Output Packets FromIp=fromIP (default ALL)\n"); printf("\t/d: destIP Output Packets DestIp=destIP (default ALL)"); printf("\nExample:\n"); printf("\tsniffer.exe /d:192.168.15.233\n"); printf("\tsniffer.exe /f:192.168.15.231\n"); }

|