SnifferRawSocket/rawsocket.cpp

385 lines
8.5 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "rawsocket.h"
// 全局变量
SOCKET g_RawSocket = 0;
HOSTIP g_HostIp;
BOOL g_bStopRecv = FALSE;
// 函数定义
void ShowError(char *lpszText)
{
char szErr[MAX_PATH] = {0};
::wsprintf(szErr, "%s Error!\nError Code Is:%d\n", lpszText, ::GetLastError());
::MessageBox(NULL, szErr, "ERROR", MB_OK | MB_ICONERROR);
}
BOOL InitRawSocket()
{
// 设置版本
WSADATA wsaData = {0};
if(0 != WSAStartup(MAKEWORD(2, 2), &wsaData))
{
ShowError("WSAStartup");
return FALSE;
}
// 创建原始套接字
// Windows上没办法用Raw Socket抓MAC层的数据包只能抓到IP层及以上的数据包
g_RawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP); // 注意此处的设置!!!
// g_RawSocket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (INVALID_SOCKET == g_RawSocket)
{
WSACleanup();
ShowError("socket");
return FALSE;
}
// 绑定到接口
// 获取本机名
char szHostName[MAX_PATH] = {0};
if (SOCKET_ERROR == ::gethostname(szHostName, MAX_PATH))
{
closesocket(g_RawSocket);
WSACleanup();
ShowError("gethostname");
return FALSE;
}
// 根据本机名获取本机IP地址
hostent *lpHostent = ::gethostbyname(szHostName);
if(NULL == lpHostent)
{
closesocket(g_RawSocket);
WSACleanup();
ShowError("gethostbyname");
return FALSE;
}
// IP地址转换并保存IP地址
g_HostIp.iLen = 0;
::lstrcpy(g_HostIp.szIPArray[g_HostIp.iLen], "127.0.0.1");
g_HostIp.iLen++;
char *lpszHostIP = NULL;
while (NULL != (lpHostent->h_addr_list[(g_HostIp.iLen - 1)]))
{
lpszHostIP = inet_ntoa(*(in_addr *)lpHostent->h_addr_list[(g_HostIp.iLen - 1)]);
::lstrcpy(g_HostIp.szIPArray[g_HostIp.iLen], lpszHostIP);
g_HostIp.iLen++;
}
// 选择IP地址对应的网卡来嗅探
printf("Choose A IP Address To Sniff:\n");
for (int i = 0; i < g_HostIp.iLen; i++)
{
printf("\tIP %d:%s\n", i, g_HostIp.szIPArray[i]);
}
printf("Input A Number: ");
int iChoose = 0;
scanf("%d", &iChoose);
getchar();
if ((0 > iChoose) || (iChoose >= g_HostIp.iLen))
{
printf("Choose Error!\nExit Now!!!\n");
system("pause");
exit(0);
}
printf("Sniffing...\n");
if ((0 <= iChoose) && (iChoose < g_HostIp.iLen))
{
lpszHostIP = g_HostIp.szIPArray[iChoose];
}
// ::MessageBox(NULL, lpszHostIP, "HOST IP", MB_OK);
// 构造地址结构
sockaddr_in SockAddr = {0};
RtlZeroMemory(&SockAddr, sizeof(sockaddr_in));
SockAddr.sin_addr.S_un.S_addr = inet_addr(lpszHostIP);
SockAddr.sin_family = AF_INET;
SockAddr.sin_port = htons(0);
// 绑定
if (SOCKET_ERROR == ::bind(g_RawSocket, (sockaddr *)(&SockAddr), sizeof(sockaddr_in)))
{
closesocket(g_RawSocket);
WSACleanup();
ShowError("bind");
return FALSE;
}
// 设置混杂模式,这样才能捕获所有的数据包
DWORD dwSetVal = 1;
if (SOCKET_ERROR == ioctlsocket(g_RawSocket, SIO_RCVALL, &dwSetVal))
{
closesocket(g_RawSocket);
WSACleanup();
ShowError("ioctlsocket");
return FALSE;
}
return TRUE;
}
BOOL ReceivePacket()
{
sockaddr_in RecvAddr = { 0 };
int iRecvBytes = 0;
int iRecvAddrLen = sizeof(sockaddr_in);
DWORD dwBufSize = 12000;
BYTE *lpRecvBuf = new BYTE[dwBufSize];
int i = 0;
g_bStopRecv = TRUE;
// 接收
while (g_bStopRecv)
{
RtlZeroMemory(&RecvAddr, iRecvAddrLen);
iRecvBytes = recvfrom(g_RawSocket, (char *)lpRecvBuf, dwBufSize, 0, (sockaddr *)(&RecvAddr), &iRecvAddrLen);
if (0 < iRecvBytes)
{
// 接收到数据包
// 分析数据包
AnalyseRecvPacket(lpRecvBuf);
}
}
// 释放内存
delete[]lpRecvBuf;
lpRecvBuf = NULL;
return TRUE;
}
BOOL ReceivePacket_Print()
{
sockaddr_in RecvAddr = { 0 };
int iRecvBytes = 0;
int iRecvAddrLen = sizeof(sockaddr_in);
DWORD dwBufSize = 12000;
BYTE *lpRecvBuf = new BYTE[dwBufSize];
int i = 0;
g_bStopRecv = TRUE;
// 接收
char szTemp[10] = {0};
FILE *fp = fopen("RecvInfo.txt", "w+");
while (g_bStopRecv)
{
RtlZeroMemory(&RecvAddr, iRecvAddrLen);
iRecvBytes = recvfrom(g_RawSocket, (char *)lpRecvBuf, dwBufSize, 0, (sockaddr *)(&RecvAddr), &iRecvAddrLen);
if (0 < iRecvBytes)
{
// 接收到信息
printf("[RECV] %dbytes\n", iRecvBytes);
::wsprintf(szTemp, "[RECV] %dbytes\n", iRecvBytes);
fputs(szTemp, fp);
for (i = 0; i < iRecvBytes; i++)
{
if (!g_bStopRecv)
{
break;
}
if ((0 == (i % 8)) && (0 != i))
{
printf(" ");
::wsprintf(szTemp, "%s", " ");
fputs(szTemp, fp);
}
if ((0 == (i % 16)) && (0 != i))
{
printf("\n");
::wsprintf(szTemp, "%s", "\n");
fputs(szTemp, fp);
}
printf("%02x ", lpRecvBuf[i]);
::wsprintf(szTemp, "%02X ", lpRecvBuf[i]);
fputs(szTemp, fp);
}
printf("\n");
::wsprintf(szTemp, "%s", "\n");
fputs(szTemp, fp);
}
}
fclose(fp);
// 释放内存
delete[]lpRecvBuf;
lpRecvBuf = NULL;
return TRUE;
}
void MyPrintf(const char * _Format, ...)
{
char szTemp[MAX_PATH] = {0};
// 第1步定义这个指向参数列表的变量
va_list arg_ptr;
// 第2步把上面这个变量初始化让它指向参数列表
va_start(arg_ptr, _Format);
// 第3步获取arg_ptr指向的当前参数
vsprintf(szTemp, _Format, arg_ptr);
// 第4步清理工作
va_end(arg_ptr);
// 显示
printf("%s", szTemp);
// 保存到文件
SaveToFile("RecvInfo.txt", szTemp);
}
void SaveToFile(char *lpszFileName, char *lpBuf)
{
FILE *fp = fopen(lpszFileName, "a+");
if(NULL == fp)
{
return ;
}
fputs(lpBuf, fp);
fclose(fp);
}
BOOL ExitRawSocket()
{
g_bStopRecv = FALSE;
Sleep(500);
closesocket(g_RawSocket);
WSACleanup();
return TRUE;
}
void AnalyseRecvPacket(BYTE *lpBuf)
{
/*
Windows上没办法用Raw Socket抓MAC层的数据包只能抓到IP层及以上的数据包
注意:
数据包的字节顺序转换问题!!!
//这里要将网络字节序转换为本地字节序
*/
//分析IP协议
PIPV4HEADER ip = (PIPV4HEADER)lpBuf;
//分析IP包的协议类型
switch (ip->ipv4_pro)
{
case IPPROTO_ICMP:
{
MyPrintf("[ICMP]\n");
AnalyseRecvPacket_All(lpBuf);
break;
}
case IPPROTO_IGMP:
{
MyPrintf("[IGMP]\n");
AnalyseRecvPacket_All(lpBuf);
break;
}
case IPPROTO_TCP:
{
//分析tcp协议
MyPrintf("[TCP]\n");
AnalyseRecvPacket_TCP(lpBuf);
break;
}
case IPPROTO_UDP:
{
//分析udp协议
MyPrintf("[UDP]\n");
AnalyseRecvPacket_UDP(lpBuf);
break;
}
default:
{
MyPrintf("[OTHER IP]\n");
AnalyseRecvPacket_All(lpBuf);
break;
}
}
}
void AnalyseRecvPacket_All(BYTE *lpBuf)
{
struct sockaddr_in saddr, daddr;
PIPV4HEADER ip = (PIPV4HEADER)lpBuf;
saddr.sin_addr.s_addr = ip->ipv4_sourpa;
daddr.sin_addr.s_addr = ip->ipv4_destpa;
MyPrintf("From:%s --> ", inet_ntoa(saddr.sin_addr));
MyPrintf("To:%s\n", inet_ntoa(daddr.sin_addr));
}
void AnalyseRecvPacket_UDP(BYTE *lpBuf)
{
struct sockaddr_in saddr, daddr;
PIPV4HEADER ip = (PIPV4HEADER)lpBuf;
PUDPHEADER udp = (PUDPHEADER)(lpBuf + (ip->ipv4_ver_hl & 0x0F) * 4);
int hlen = (int)((ip->ipv4_ver_hl & 0x0F) * 4 + sizeof(UDPHEADER));
int dlen = (int)(ntohs(udp->udp_hlen) - 8);
// int dlen = (int)(udp->udp_hlen - 8);
saddr.sin_addr.s_addr = ip->ipv4_sourpa;
daddr.sin_addr.s_addr = ip->ipv4_destpa;
MyPrintf("Protocol:UDP ");
MyPrintf("From:%s:%d -->", inet_ntoa(saddr.sin_addr), ntohs(udp->udp_sourport));
MyPrintf("To:%s:%d\n", inet_ntoa(daddr.sin_addr), ntohs(udp->udp_destport));
PrintData((lpBuf + hlen), dlen, 0);
}
void AnalyseRecvPacket_TCP(BYTE *lpBuf)
{
struct sockaddr_in saddr, daddr;
PIPV4HEADER ip = (PIPV4HEADER)lpBuf;
PTCPHEADER tcp = (PTCPHEADER)(lpBuf + (ip->ipv4_ver_hl & 0x0F) * 4);
int hlen = (ip->ipv4_ver_hl & 0x0F) * 4 + tcp->tcp_hlen * 4;
int dlen = ntohs(ip->ipv4_plen) - hlen; //这里要将网络字节序转换为本地字节序
saddr.sin_addr.s_addr = ip->ipv4_sourpa;
daddr.sin_addr.s_addr = ip->ipv4_destpa;
MyPrintf("Protocol:TCP ");
MyPrintf("From:%s:%d --> ", inet_ntoa(saddr.sin_addr), ntohs(tcp->tcp_sourport));
MyPrintf("To:%s:%d ", inet_ntoa(daddr.sin_addr), ntohs(tcp->tcp_destport));
MyPrintf("ack:%u syn:%u length=%d\n", tcp->tcp_acknu, tcp->tcp_seqnu, dlen);
PrintData((lpBuf + hlen), dlen, 0);
}
void PrintData(BYTE *lpBuf, int iLen, int iPrintType)
{
if (0 == iPrintType) // 16进制
{
for (int i = 0; i < iLen; i++)
{
if ((0 == (i % 8)) && (0 != i))
{
MyPrintf(" ");
}
if ((0 == (i % 16)) && (0 != i))
{
MyPrintf("\n");
}
MyPrintf("%02x ", lpBuf[i]);
}
MyPrintf("\n");
}
else if (1 == iPrintType) // ASCII编码
{
for (int i = 0; i < iLen; i++)
{
MyPrintf("%c", lpBuf[i]);
}
MyPrintf("\n");
}
}