⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sniffer.cpp

📁 监听分析流量中的http流量
💻 CPP
字号:
// Sniffer.cpp: implementation of the CSniffer class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Sniffer.h"
#include <winsock2.h>
#include <WS2TCPIP.H>
#include <MSTcpIP.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSniffer::CSniffer()
{
	WSADATA wsaData;

	if(WSAStartup(0x202, &wsaData) == 0)
	{
		m_bWSAStartup = TRUE;
	}
	else
	{
		m_bWSAStartup = FALSE;
	}

	//初始化临界区对象
	InitializeCriticalSection(&m_ls);


	memset(m_szProto, 0, 16);
	memset(m_strAddr, 0, 64);

	memset(m_szDestPort, 0, 16);
	memset(m_szSourcePort, 0, 16);
	memset(m_szTTL, 0, 16);
	memset(m_szDestIP, 0, 16);
	memset(m_szSourceIP, 0, 16);
	memset(m_szProtocol, 0, 16);

	m_bIsRun = FALSE;
	m_IsAllPort = false;
	m_IsAllIp = TRUE;
	m_IsAllProto = TRUE;
}

CSniffer::~CSniffer()
{
	//销毁临界区对象
	DeleteCriticalSection(&m_ls);
	DelListBuf();
}

BOOL CSniffer::SnifferInit(LPSTR lpStrAddr, UINT uPort)
{
	DWORD	dwThreadID;
	strcpy(m_strAddr, lpStrAddr);
	m_uPort = uPort;
	m_HostIp = GetIp(); //得到本机IP
	//开始监听

	if(!CreateSock()) //建立
	{
		//"WinSock设置失败
		return false;
	}
	else
	{
		m_bIsRun = TRUE;
		m_hThread = CreateThread( NULL, NULL, RecvIpPro, (PVOID)this, NULL, &dwThreadID);
	}

	return true;
}

void CSniffer::StopSniffer()
{
	m_bIsRun = FALSE;
	if(m_hThread)
	{
		TerminateThread(m_hThread, 0);
		CloseHandle(m_hThread);
	}

	if(m_RawSock)
		closesocket(m_RawSock);
}

//建立原始套接字
BOOL CSniffer::CreateSock()
{
	char name[56] = {0};
	hostent *pHostent;
	int port = 8310;	//监听端口
	int err;
	SOCKADDR_IN sockaddr;
	
	m_RawSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
	if(m_RawSock == INVALID_SOCKET)
	{
		return WSAGetLastError(); //socket创建失败
	}
	
	err= ::gethostname(name, 56);
	if(err==SOCKET_ERROR)
	{
		return WSAGetLastError(); //取本机用户名失败
	}

	pHostent = gethostbyname (name);

	sockaddr.sin_family = AF_INET;
	sockaddr.sin_port = htons(port);
	memcpy(&sockaddr.sin_addr.s_addr, pHostent->h_addr_list[0],
		pHostent->h_length);

	//free(pHostent);
	
	err = bind(m_RawSock,(SOCKADDR *)&sockaddr, sizeof(sockaddr));//绑定
	if(err == SOCKET_ERROR)
	{
		return WSAGetLastError(); //取本机用户名失败
	}
	BOOL bOptval = TRUE;

	//设置套节字选项
	setsockopt(m_RawSock, SOL_SOCKET,SO_REUSEADDR, (char*)&bOptval, sizeof(bOptval));
	err = setsockopt(m_RawSock, IPPROTO_IP,IP_HDRINCL, (char*)&bOptval, //IP_HDRINCL该选项使之能操作IP头
		sizeof(bOptval));
	if(err == SOCKET_ERROR)
	{
		return WSAGetLastError(); //设置套节字选项失败
	}

	//把网卡置于混杂模式。获取IO操作的相关信息
	DWORD dwBufferLen[10] ;
	DWORD dwBufferInLen = 1 ;
	DWORD dwBytesReturned = 0 ;
	err=WSAIoctl (
		m_RawSock,                                               
		SIO_RCVALL,       //设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包                           
		&dwBufferInLen,                                     
		sizeof(dwBufferInLen),                                       
		&dwBufferLen,                                    
		sizeof(dwBufferLen),                                      
		&dwBytesReturned,                              
		NULL,                           
		NULL  
		);//最后两参数设置非阻塞


	if(err == SOCKET_ERROR)
	{
		return WSAGetLastError(); //设置套节字选项失败
	}

	return true;
}

//在线程中不断接受IP包
DWORD CALLBACK CSniffer::RecvIpPro(LPVOID lpParam)
{
	int err = 0;
	int recvLen;
	CSniffer* pSniffer = (CSniffer*)lpParam;
	char *recvBuf = new char[MAX_PACK_LEN];
	while(pSniffer->m_bIsRun)
	{
		memset(recvBuf, 0, MAX_PACK_LEN);
		recvLen = recv(pSniffer->m_RawSock,recvBuf, MAX_PACK_LEN, 0);//接受数据
		
		if(err==SOCKET_ERROR)
		{
			if(WSAGetLastError() == WSAEWOULDBLOCK) //如果错误为阻塞那么将继续接受
				continue;
			break;
		}
		//处理已经接受到的IP包
		EnterCriticalSection(&pSniffer->m_ls);
		pSniffer->SplitIpPack(recvBuf, recvLen); //分解IP包
		//pSniffer->ShowIpInfo(recvBuf,recvLen); //分析并处理IP数据包
		LeaveCriticalSection(&pSniffer->m_ls);
	}
	return 0;

}

//分解IP包
void CSniffer::SplitIpPack(char *pData, int len)
{
	IP_HEADER* pIpHead;

	memset(m_szDestPort, 0, 16);
	memset(m_szSourcePort, 0, 16);
	memset(m_szTTL, 0, 16);
	memset(m_szDestIP, 0, 16);
	memset(m_szSourceIP, 0, 16);
	memset(m_szProtocol, 0, 16);

	pIpHead = (IP_HEADER*)pData; //转为IP头结构
	SOCKADDR_IN saSource, saDest; //中间变量分别为源IP地址结构和目标IP地址结构 

	//得到包中协议
	int iProtocol;
	iProtocol = pIpHead->proto;
	//得到协议字符形式表示m_szProtocol
	strncpy(m_szProtocol,CheckProtocol(iProtocol), MAX_PROTO_TEXT_LEN);


	//得到源IP
	saSource.sin_addr.s_addr = pIpHead->sourceIP;
	strncpy(m_szSourceIP, inet_ntoa(saSource.sin_addr), MAX_ADDR_LEN);

	//得到目标IP
	saDest.sin_addr.s_addr=pIpHead->destIP;
	strncpy(m_szDestIP, inet_ntoa(saDest.sin_addr), MAX_ADDR_LEN);

	//得到TTL
	int ttl;
	ttl=pIpHead->ttl;
	wsprintf(m_szTTL, "%d", ttl);

	//得到头长度
	int ihLen = sizeof(unsigned long)*(pIpHead->h_lenver & 0xf);

	m_ihLen = ihLen;
	unsigned short srcPort = 0, destPort = 0;
	switch(iProtocol) 
	{
	case IPPROTO_TCP:
		{
		
		TCP_HEADER* pTcpHead;
		pTcpHead = (TCP_HEADER*)(pData+ihLen);
		srcPort = ntohs(pTcpHead->th_sport);
		destPort = ntohs(pTcpHead->th_dport);
		wsprintf(m_szSourcePort, "%d", srcPort);
		wsprintf(m_szDestPort, "%d", destPort);
		int nLen = ihLen + sizeof(TCP_HEADER);
		//基于TCP/IP协议之上的协议的解析
		TCPProtocolParse(pData + nLen, len - nLen);
		}
		break;
	case IPPROTO_UDP:
		UDP_HEADER* pUdpHead;
		pUdpHead = (UDP_HEADER*)(pData+ihLen);
		srcPort = ntohs(pUdpHead->uh_sport);
		destPort = ntohs(pUdpHead->uh_dport);	
		wsprintf(m_szSourcePort, "%d", srcPort);
		wsprintf(m_szDestPort, "%d",destPort);
		break;
	case IPPROTO_ICMP:
		ICMP_HEADER* pIcmpHead;
		pIcmpHead=(ICMP_HEADER*)(pData + ihLen);
		wsprintf(m_szSourcePort, "%s", "");
		wsprintf(m_szDestPort, "%s", "");
		break;
	default:
		wsprintf(m_szSourcePort, "%s", "");
		wsprintf(m_szDestPort, "%s", "");
	}
		
}

//将IP记录存放到链表中
void CSniffer::ShowIpInfo(char *pData, int len)
{
	if(len<0)
		return;
	char szSourceIP[32] = {0};
	char szDestIP[32] = {0};

	char szSourcePort[16] = {0}; //截取到的源端口
	char szDestPort[16] = {0}; //截取到的目标端口

	char szSourceIPt[32] = {0}; //截取到源IP
	char szDestIPt[32] = {0}; //截取到目标IP
	
	char szWprot[5] = {0}; //取得输入端口
	char szIP[32] = {0}; //取得输入IP
	char szProto[16] = {0}; //取得输入协议
	


	if(strcmp(m_HostIp, m_szSourceIP) == 0)
	{
		strcat(szSourceIP, "(本机)");
		strcat(szSourceIP, m_szSourceIP);
	}
	else
		strncpy(szSourceIP, m_szSourceIP, 16);

	if(strcmp(m_HostIp, m_szDestIP) == 0)
	{
		strcat(szDestIP, "(本机)");
		strcat(szDestIP, m_szDestIP);
	}
	else
		strncpy(szDestIP, m_szDestIP, 16);

	strncpy(szSourcePort, m_szSourcePort, 5);
	strncpy(szDestPort, m_szDestPort, 5);
	strncpy(szDestIPt, m_szSourceIP, 32);
	strncpy(szSourceIPt, m_szDestIP, 32);
	strncpy(szProto, m_szProtocol, 16);

	wsprintf(szWprot, "%d", m_uPort);
	//取得输入IP
	strcpy(szIP, m_strAddr);
	
	BOOL bProt = m_IsAllPort | (strcmp(szSourcePort, szWprot) == 0) |
		(strcmp(szDestPort, szWprot) == 0); //判断端口规则
	BOOL bIp = m_IsAllIp | (strcmp(szSourceIPt, szIP) == 0) |
		(strcmp(szDestIPt, szIP) == 0); //判断IP规则
	BOOL bProto = m_IsAllProto | (strcmp(szProto, m_szProto) == 0); //判断协议规则
	
	if(bProt && bIp && bProto)
	{
			char sNowTime[18] = {0};
			GetNowTime(sNowTime);

			char str[512] = {0};
			wsprintf(str, "[%s] %s:%s->%s:%s 包大小(头/总)%d/%d %s", m_szProtocol, szSourceIP,
				m_szSourcePort, szDestIP, m_szDestPort,
				m_ihLen, len, sNowTime);

			int nCount = m_strIPInfoList.size();
			if (nCount >= 1000)
				m_strIPInfoList.clear();
			//放入链表
			string strData(str);
			m_strIPInfoList.push_back(strData);
			//绑定数据
			IPDATA *pIpData = new IPDATA();
			pIpData->len = len;
			pIpData->buf = new char[len];
			memcpy(pIpData->buf, pData, len);
			m_strIPDataList.push_back((DWORD)pIpData);
	}
}

//清除和ListBox绑定的数据和列表
void CSniffer::DelListBuf()
{
}


//格式化显示IP包
void CSniffer::ShowIpData(char *pData, int len)
{


}

//协议分析统一在此处理
void CSniffer::TCPProtocolParse(char *pData, int nLen)
{
	for(int i=0; i<nLen; i++)
	{
		if(pData[i] == 0)
			pData[i] = '\n';
	}

		UINT nPort = GetPort();

	m_HttpParse.Perform(pData, nLen, nPort, m_szSourceIP, "",
				 m_szSourcePort, m_szDestIP, "", m_szDestPort);
	
}



void CSniffer::ConfigProtocolParsePack(vector<DWORD> &Parse_List)
{

	int nTelnetLen = Parse_List.size();
	int nLen = sizeof(TELNET_IAC_PACK) * nTelnetLen;
	char *config = new char[nLen];

	
	for (int i = 0; i < nTelnetLen; i++)
	{
		DWORD Node = Parse_List.at(i);

		if (Node != 0)
		{
			TELNET_IAC_PACK* pNode = (TELNET_IAC_PACK*)Node;
			memset(config, 0, nLen + 1);
			wsprintf(config, 
				"[时间]%s\r\n[源IP]%s\r\n[目的IP]%s\r\n[源MAC]%s\r\n[目的MAC]%s\r\n[命令]\r\n%s\r\n[数据域]\r\n%s%\r\n",
				pNode->date,
				pNode->src_ip,
				pNode->des_ip,
				pNode->src_mac,
				pNode->des_mac,
				pNode->cmd,
				pNode->data);
		}
	}
		
	

	//存放到文件中去
	char path[1024] ={0};
	//GetCurrentDirectory(1024, path);
	//strcat(path, "\\网络抓包日志(Telent).log");

	strcpy(path, "c:\\网络抓包日志(Telent).log");
	nLen = strlen(config);
	WriteLogFile(config, nLen, path);
}

//////////////////////////////////////////////////////////////////////////
//将协议int转为字符串
char* CSniffer::CheckProtocol(int iProtocol)
{
	for(int i=0; i < MAX_PROTO_NUM; i++)
	{
		if(ProtoMap[i].ProtoNum == iProtocol)
		{
			return ProtoMap[i].ProtoText;
		}
	}
		return "";
}

//得到本机IP
char* CSniffer::GetIp()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	char name[255];
	char *ip;
	PHOSTENT hostinfo;
	wVersionRequested = MAKEWORD( 2, 0 );
	if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
	{
		
		if( gethostname ( name, sizeof(name)) == 0)
		{
			if((hostinfo = gethostbyname(name)) != NULL)
			{
				ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
			}
		}
		
		WSACleanup();
	} 
	return ip;
}

//得到当前时间,格式:%Y-%m-%d %H:%M:%S
void CSniffer::GetNowTime(char *pCurTime)
{
	_SYSTEMTIME Curtime;
	GetSystemTime(&Curtime);
	wsprintf(pCurTime, "%4d-%2d-%2d %2d:%2d:%2d",
		Curtime.wYear,
		Curtime.wMonth,
		Curtime.wDay,
		Curtime.wHour,
		Curtime.wMinute,
		Curtime.wSecond);
}


//写入日志文件
bool CSniffer::WriteLogFile(char *strInfo, int nBuffer, char *strFileName)
{
	if (lstrlen(strInfo)<1)
		return FALSE;

	int nLen = sizeof(strInfo);
	FILE *lpfile;
	lpfile = fopen(strFileName, "aw+");
	//fseek(lpfile, 0, SEEK_END);

	char *temp =  new char[nBuffer];
	memset(temp, 0, nBuffer);
	strcpy(temp, strInfo);
	strcat(temp, "\r\n");
	fwrite(temp, nBuffer, 1, lpfile);
	fclose(lpfile);
	return true;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -