在以太网中,所有的通信都是广播的,也就是说通常在同一个网段的所有网络接口都可以访问在物理媒体上传输的所有数据,而每一个网络接口对哦有一个唯一的硬件地址,这个硬件地址也就是网卡的MAC地址。在硬件地址和IP地址间使用ARP和RARP协议进行相互转换。
在正常情况下,一个网络接口只响应这样两种数据帧:与自己硬件地址相匹配的数据帧;向所有计算机的广播数据帧。
在一个系统中,数据的收发是由网卡来完成的,网卡接收到传输来的数据,网卡内的程序接收数据帧的目的MAC地址,根据计算机上的网卡驱动程序设置的接收模式判断该不该接收。
网卡一般有4种接收模式:
广播方式:该模式下的网卡能接收网络中的广播信息
组播方式:该模式下的网卡能够接收组播数据
直接方式: 该模式下,只有目的网卡才能接收数据
混杂谋杀:该模式下的网卡能够接收一切通过它的数据,而不管该数据是否是传给它的
Sniff的工作原理:让网卡接收一切所能接收的数据。
要实现一个Snaiff程序,需要把网卡设置为混杂模式;捕获数据包;分析数据包。
WinSniffer:
- #include<stdio.h>
- #include<winsock2.h>
- #include<mstcpip.h>
- #pragma comment(lib,"ws2_32.lib")
- typedef struct iphdr
- {
- unsigned char ver_hlen;//4位IPv4版本的4位头长度(用32位字表示)
- unsigned char tos;//服务的IP类型
- unsigned short total_len;//总长
- unsigned short ident;//唯一标识符
- unsigned short frag_and_flags;//片段偏移字段
- unsigned char ttl;//生存时间
- unsigned char proto;//协议
- unsigned short checksum;//IP校验和
- unsigned int sourceIP;//源地址
- unsigned int destIP;//目的地址
- }IPHeader;
- #define PACKAGE_SIZE sizeof(IPHeader)
- #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
- #define xfree(p) HeapFree(GetProcessHeap(),0,(p))
- BOOL WINAPI CtrlHandler(DWORD dwEvent);
- void HandleError(char *);
- BOOL g_bExit = FALSE;
- int main()
- {
- if(!SetConsoleCtrlHandler(CtrlHandler,TRUE))
- {
- printf("SetConsoleCtrlHandler:%d\n",GetLastError());
- return -1;
- }
- WSADATA wsaData;
- WSAStartup(MAKEWORD(2,2), &wsaData);
- SOCKET sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
- if(INVALID_SOCKET==sock)
- {
- HandleError("socket");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- SOCKADDR_IN addr;
- memset(&addr,0,sizeof(SOCKADDR_IN));
- addr.sin_family=AF_INET;
- addr.sin_addr.s_addr=inet_addr("192.168.1.222");
- if(SOCKET_ERROR==bind(sock,(SOCKADDR*)&addr,sizeof(addr)))
- {
- HandleError("bind");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- int on = RCVALL_ON;
- DWORD num;
- if(SOCKET_ERROR==WSAIoctl(sock,SIO_RCVALL,&on,sizeof(on),NULL,0,&num,NULL,NULL))
- {
- HandleError("WSAIoctl");
- closesocket(sock);
- WSACleanup();
- return -1;
- }
- char *buf = (char*)xmalloc(PACKAGE_SIZE);
- SOCKADDR_IN from;
- int fromlen;
- while(!g_bExit)
- {
- memset(buf,0,PACKAGE_SIZE);
- memset(&from,0,sizeof(from));
- fromlen=sizeof(from);
- if(SOCKET_ERROR==recvfrom(sock,buf,PACKAGE_SIZE,0,(SOCKADDR*)&from,&fromlen))
- {
- if(WSAEMSGSIZE!=WSAGetLastError())
- {
- HandleError("recvfrom");
- break;
- }
- }
- switch(((IPHeader*)buf)->proto)
- {
- case IPPROTO_ICMP:
- printf("ICMP From %s\n",inet_ntoa(from.sin_addr));
- break;
- case IPPROTO_IGMP:
- printf("IGMP From %s\n",inet_ntoa(from.sin_addr));
- break;
- case IPPROTO_TCP:
- printf("TCP From %s\n",inet_ntoa(from.sin_addr));
- break;
- case IPPROTO_UDP:
- printf("UPD From %s\n",inet_ntoa(from.sin_addr));
- break;
- default:
- printf("Unknown datagram From %s\n",inet_ntoa(from.sin_addr));
- }
- }
- xfree(buf);
- closesocket(sock);
- WSACleanup();
- printf("Stopped!\n");
- system("pause");
- return 0;
- }
- BOOL WINAPI CtrlHandler(DWORD dwEvent)
- {
- switch(dwEvent)
- {
- case CTRL_C_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- case CTRL_CLOSE_EVENT:
- printf("Stopping......\n");
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- void HandleError(char * func)
- {
- int error = WSAGetLastError();
- char info[65] = {0};
- _snprintf(info, 64, "%s: %d\n",func,error);
- printf(info);
- }