大家也许用过网络嗅探器吧,确实网络嗅探器用在了很多方面。网络嗅探器是通过把网卡设置为混杂模式来捕获网络数据包的,简单介绍网络嗅探器的实现:
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协议结构
typedef struct _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;
}