大家也许用过网络嗅探器吧,确实网络嗅探器用在了很多方面。网络嗅探器是通过把网卡设置为混杂模式来捕获网络数据包的,简单介绍网络嗅探器的实现:
1定义IP协议结构
typedef struct _IP_HEADER { BYTE bVerAndHLen; //版本信息(前4位)和头长度(后4位) BYTE BTypeOfService; //服务类型 USHORT nToalLength; //数据包长度 USHORT nID; //数据包标识 USHORT nReserved; //保留字段 BYTE bTTL; //生成时间 BYTE bProtocol; //协议类型 USHORT nCheckSum; //校验和 UINT nSourIP; //源IP UINT nDestIp; //目的IP } IP_HEADER, *LPIP_HEADER;
2定义TCP协议结构
typedef struct _TCP_HEADER { USHORT nSourPort; //源端口号 USHORT nDestPort; //目的端口号 UINT nSeqNum; //序列号 UINT nAcknowledgeNum; //确认号 USHORT nHLenAndFlag; //前4位:TCP头长度 中6位:保留 后6位:标志位 USHORT nWindowSize; //窗口大小 USHORT nCheckSum; //校验和 USHORT nrgentPointer; //紧急数据偏移量 } TCP_HEADER, *LPTCP_HEADER;
3定义UDP协议结构
typedefstruct_UDP_HEADER
{
USHORT nSourPort; //源端口号
USHORT nDestPort; //目的端口号
USHORT nLength; //数据包长度
USHORT nCheckSum; //校验和
}UDP_HEADER,*LPUDP_HEADER;
4对于IP、TCP、UDP结构,我只抽取6个字段,当然可以自行添加所需要的字段
typedef struct _PACK_INFO { USHORT nLength; //数据包长度 USHORT nProtocol; //协议类型 UINT nSourIp; //源IP UINT nDestIp; //目的IP USHORT nSourPort; //源端口 USHORT nDestPort; //目的端口 } PACK_INFO, *LPPACK_INFO;
5点击“启动”按钮后启动一个独立的线程来捕获数据包
HANDLE hThread = ::CreateThread(NULL, 0, MonitorThread, this, 0, NULL);
6线程的实现如下
//监视线程 DWORD WINAPI MonitorThread(LPVOID lParam) { //取得窗体指针 CSnifferDlg *pDlg = (CSnifferDlg*)lParam; WSADATA wsaData; if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { TCHAR szErrorMessage[200]; ZeroMemory(szErrorMessage, sizeof(szErrorMessage)); wsprintf(szErrorMessage, "ERROR NO:%d", GetLastError()); AfxMessageBox(szErrorMessage); return 0; } //创建监听套接字 创建的是原始套接字 SOCKET MonSock; MonSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); if(MonSock == INVALID_SOCKET) { TCHAR szErrorMessage[200]; ZeroMemory(szErrorMessage, sizeof(szErrorMessage)); wsprintf(szErrorMessage, "ERROR NO:%d", GetLastError()); AfxMessageBox(szErrorMessage); return 0; } //获取本地地址信息 SOCKADDR_IN LocalAddr; TCHAR szLocalName[200]; ZeroMemory(szLocalName, sizeof(szLocalName)); gethostname(szLocalName, sizeof(szLocalName)); hostent *pHost = gethostbyname(szLocalName); if(pHost != NULL) { LocalAddr.sin_family = AF_INET; LocalAddr.sin_port = htons(0); memcpy (&(LocalAddr.sin_addr.s_addr), pHost->h_addr_list[0], pHost->h_length) ; } else { return 0; } //绑定 if(bind(MonSock, (SOCKADDR*)&LocalAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) { TCHAR szErrorMessage[200]; ZeroMemory(szErrorMessage, sizeof(szErrorMessage)); wsprintf(szErrorMessage, "ERROR NO:%d", GetLastError()); AfxMessageBox(szErrorMessage); return 0; } //设置为混杂模式 接收所有IP包 DWORD dwValue = 1; if(ioctlsocket(MonSock, SIO_RCVALL, &dwValue) != 0) { TCHAR szErrorMessage[200]; ZeroMemory(szErrorMessage, sizeof(szErrorMessage)); wsprintf(szErrorMessage, "ERROR NO:%d", GetLastError()); return 0; } //检测控制标志,是否继续监视 while(pDlg->isMonitor) { PACK_INFO PackInfo; ZeroMemory(&PackInfo, sizeof(PackInfo)); int nRecvSize = 0; TCHAR szPackBuff[1024]; ZeroMemory(szPackBuff, sizeof(szPackBuff)); nRecvSize = recv(MonSock, szPackBuff, sizeof(szPackBuff), 0); //如果接收到数据开始解析 if(nRecvSize > 0) { //解析IP包头 LPIP_HEADER pIpHeader = (LPIP_HEADER)szPackBuff; PackInfo.nLength = nRecvSize; PackInfo.nProtocol = (USHORT)pIpHeader->bProtocol; PackInfo.nSourIp = pIpHeader->nSourIP; PackInfo.nDestIp = pIpHeader->nDestIp; UINT nIpHeadLength = (pIpHeader->bVerAndHLen & 0x0F) * sizeof(UINT); //只检测TCP包和UDP包 switch(pIpHeader->bProtocol) { case IPPROTO_TCP: //取得TCP数据包端口号 LPTCP_HEADER pTcpHeader; pTcpHeader = (LPTCP_HEADER)&szPackBuff[nIpHeadLength]; PackInfo.nSourPort = pTcpHeader->nSourPort; PackInfo.nDestPort = pTcpHeader->nDestPort; pDlg->AddPackInfo(&PackInfo); break; case IPPROTO_UDP: //取得UDP数据包端口号 LPUDP_HEADER pUdpHeader; pUdpHeader = (LPUDP_HEADER)&szPackBuff[nIpHeadLength]; PackInfo.nSourPort = pTcpHeader->nSourPort; PackInfo.nDestPort = pTcpHeader->nDestPort; pDlg->AddPackInfo(&PackInfo); break; } } Sleep(100); } return 0; }