#include <winsock2.h> //#include <ws2tcpip.h> /* for IP_HDRINCL */ #include <mstcpip.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") /* WinSock使用的库函数 */ typedef struct _iphdr //定义IP首部 { unsigned char h_verlen; //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, UDP 或其他) 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; //32位序列号 unsigned int th_ack; //32位确认号 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; char* GetProtocolTxt(int Protocol) { switch (Protocol) { case IPPROTO_ICMP : //1 control message protocol return "ICMP"; case IPPROTO_TCP : //6 tcp */ return "TCP"; case IPPROTO_UDP : //17 user datagram protocol */ return "UDP"; default: return "UNKNOWN"; } } void printIP(IP_HEADER *ip) { printf("\nProtocol\t: %s(%u)\r\n",GetProtocolTxt(ip->proto),ip->proto);; printf( "ip version\t: %u\n",(ip->h_verlen&0xf0)>>4); printf( "ip header length\t: %u\n",(ip->h_verlen&0x0f)*4); printf( "ip inedtifier\t: %x\n",ip->ident); unsigned char* p = (unsigned char*)&ip->sourceIP; printf("Source IP\t: %u.%u.%u.%u\n",p[0],p[1],p[2],p[3]); p = (unsigned char*)&ip->destIP; printf("Destination IP\t: %u.%u.%u.%u\n",p[0],p[1],p[2],p[3]); printf("ip total length\t: %u\n", ntohs(ip->total_len)); } void printTCP(TCP_HEADER *tcp) { printf("\nTCP source Port\t: %u\r\n",ntohs(tcp->th_sport)); printf("TCP dest Port\t: %u\r\n",ntohs(tcp->th_dport) ); printf("seq number\t: %u\r\n",ntohl(tcp->th_seq)); printf("ack number\t: %u\r\n",ntohl(tcp->th_ack)); printf("TCP Header length\t: %u\r\n",((tcp->th_lenres&0xf0)>>4)*4); printf("FLAG\t: "); unsigned char it = 0x20; for(unsigned int i=0;i<6;i++) { if(tcp->th_flag&it) putchar('1'); else putchar('0'); it >>= 1 ; } printf("(Binary)\r\n"); printf("window size\t:%u\r\n",ntohs(tcp->th_win)); printf("urg ptr\t:%u\r\n",ntohs(tcp->th_urp)); // char *p = (char *)tcp; // printf("Data: \t%s\n\n", (char *)(p +((tcp->th_lenres&0xf0)>>4)*4 )); } int main(int argc, char **argv) { WSADATA wsa_data; WSAStartup(WINSOCK_VERSION, &wsa_data); /* 初始化 WinSock 资源 */ SOCKET raw_soc = 0; /* socket 句柄 */ int result; BOOL opt_val = TRUE; unsigned long local_addr; struct hostent *host_ent; char host[256]; /* 创建 raw socket */ raw_soc = socket( AF_INET, SOCK_RAW, IPPROTO_IP); if( raw_soc == INVALID_SOCKET ) { printf("socket() error: %d\n",WSAGetLastError()); return 0; } /* 得到本机的 IP 地址 */ if (gethostname(host, sizeof(host)) == SOCKET_ERROR) { printf("gethostname() error: %d\r\n", WSAGetLastError()); return -1; } host_ent = gethostbyname(host); if (host_ent == 0) { printf("gethostbyname() error: %d\r\n", WSAGetLastError()); return -1 ; } memcpy(&local_addr, host_ent->h_addr, sizeof(struct in_addr)); //绑定本地地址到SOCKET句柄 sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.S_un.S_addr = local_addr; //IP addr.sin_port = 0; //端口,IP层端口可随意填 if( SOCKET_ERROR == bind( raw_soc, (sockaddr *)&addr, sizeof(addr) ) ) { closesocket(raw_soc ); printf("bind error: %d\n",WSAGetLastError()); return 0; } //设置该SOCKET为接收所有流经绑定的IP的网卡的所有数据,包括接收和发送的数据包 //该函数在mstcpip.h里面,详见MSDN帮助 u_long sioarg = 1; DWORD wt=0; /*if( SOCKET_ERROR == WSAIoctl( raw_soc, SIO_RCVALL , &sioarg,sizeof(sioarg),NULL,0,&wt,NULL,NULL ) ) { closesocket( raw_soc); printf("WSAIoctl error: %d\n",WSAGetLastError()); return 0; }*/ // 设置SOCK_RAW为SIO_RCVALL(混合模式),以便接收所有的IP包. DWORD dwValue = 1; ioctlsocket(raw_soc, SIO_RCVALL, &dwValue); // dwValue为1时执行,0时取消 const int BUFFER_SIZE = 102400; char RecvBuf[BUFFER_SIZE]; IP_HEADER* ip; printf("Waiting for incopming IP packet..\n"); int len = 0; while (true) { // 接收原始数据包信息 int ret = recv(raw_soc, RecvBuf, BUFFER_SIZE, 0); if (ret > 0) { RecvBuf[ret] = 0; // 对数据包进行分析,并输出分析结果 ip = (IP_HEADER*)RecvBuf; if (ip->proto == IPPROTO_TCP) { //printf("TCP packet... \n"); printIP(ip); TCP_HEADER* tcp = (TCP_HEADER*)(RecvBuf + (ip->h_verlen&0x0f)*4); printTCP(tcp); printf("-----------------\n"); } else if (ip->proto == IPPROTO_UDP) { //printf("UDP packet...\n"); // printf("-----------------\n"); } else if (ip->proto == IPPROTO_ICMP) { //printf("ICMP packet...\n"); // printf("-----------------\n"); } } } return 0; }
在win7上,需要管理员身份运行。