processpacket.cpp

来自「The C++ Client Edition contains a full s」· C++ 代码 · 共 742 行

CPP
742
字号
#include "StdAfx.h"
#include ".\processPacket.h"




CProcessPacket::CProcessPacket(CFilterLog* in_pFilterLog):
m_szSourceDevice(NULL),
m_hSniffThread(NULL),
m_pUrlFilterObj(NULL),
m_pFilterLog(in_pFilterLog),
m_cbBlockBuffer(-1),
m_hThrdReadyEvent(NULL)
{
	RetrieveAllAdaptersInfo();

	WSADATA wsock;
	WSAStartup(MAKEWORD(2,2), &wsock);

	ZeroMemory(m_pBlockBuffer, 512);
	

	CString strBufferHdr;
	CString strBufferHTML;

	
	strBufferHTML =		"<html>";
	strBufferHTML +=	"<head>";
	strBufferHTML +=	"<title>HTTPFilter block page</title></head><body><TABLE height=\"100%\" width=\"100%\">";
	strBufferHTML +=	"<TR>";
	strBufferHTML +=	"<TD align=\"center\"><h1>This page is restricted by HTTPFilter!</h1>";
	strBufferHTML +=	"</TD>";
	strBufferHTML +=	"</TR>";
	strBufferHTML +=	"</TABLE>";
	strBufferHTML +=	"</body>";
	strBufferHTML +=	"</html>\n\n\n";	


	char len[10];
	_itoa (strBufferHTML.GetLength(), len, 10);

	strBufferHdr +=	"HTTP/1.1 200 OK\r\n";
	strBufferHdr +=	"Content-Type: Text/HTML\r\n";
	strBufferHdr +=	"Connection: close\r\n";
	strBufferHdr +=	"Content-Lenght: ";
	strBufferHdr += len;
	strBufferHdr +=	"\r\n\r\n";


	strBufferHdr += strBufferHTML;

	// First 40 bytes reserved for TCP and IP header placement
	_mbscpy (m_pBlockBuffer + 40,(u_int8_t*) strBufferHdr.GetBuffer());	
	m_cbBlockBuffer = strBufferHdr.GetLength(); // size of HTTP payload only
	
}

CProcessPacket::~CProcessPacket(void)
{	
	WSACleanup();		
}


int CProcessPacket::StartEngine(const char* in_szSourceDevice)
{	
	int optval;

	m_szSourceDevice = strdup(in_szSourceDevice);

	/* prepare URL list */
	m_pUrlFilterObj = new CURIFilter();
	if (m_pUrlFilterObj->Init(g_ProgVar) <= 0)
	{
		return 0;
	}
		

	if (m_szSourceDevice != NULL)
	{		





		if((m_helperSocket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==SOCKET_ERROR)
		{		
			return 0;
		}

		if(setsockopt(m_helperSocket, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))==SOCKET_ERROR)
		{		
			return 0;
		}

		


		if((m_sniffSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP))==SOCKET_ERROR)
		{		
			return 0;
		}




		PIP_ADAPTER_INFO pAdapterInfo = m_AdapterInfo;		
		u_long in = 0;
		do {
			if (strcmp (in_szSourceDevice, pAdapterInfo->AdapterName ) == 0)
			{
				break;
			}
			in++;
			pAdapterInfo = pAdapterInfo->Next;    // Progress through
		}
		while(pAdapterInfo);  
		

		struct sockaddr_in src;
		memset(&src, 0, sizeof(src));
		src.sin_addr.S_un.S_addr = inet_addr (pAdapterInfo->IpAddressList.IpAddress.String);		
		src.sin_family      = AF_INET;
		src.sin_port        = 0;
		if (bind(m_sniffSocket,(struct sockaddr *)&src,sizeof(src)) == SOCKET_ERROR)
		{			
			return 0;
		}

		int j=1;

		if (WSAIoctl(m_sniffSocket, SIO_RCVALL, &j, sizeof(j), 0, 0, &in,0, 0) == SOCKET_ERROR)
		{			
			return 0;
		}		

		m_hThrdReadyEvent = CreateEvent( 
			NULL,         // no security attributes
			TRUE,         // manual-reset event
			FALSE,         // initial state is signaled
			"HttpFilter_ThreadReadyEvent"  // object name
			); 

		DWORD dwThreadID = 0;
		m_hSniffThread = CreateThread(NULL, 
							NULL,
							CProcessPacket::ThreadHandler,
							this,
							NULL,
							&dwThreadID);
		
		// wait until the thready started completely
		WaitForSingleObject(m_hThrdReadyEvent, INFINITE);
		
	}
	else
	{
		return 0;
	}


	// if successful
	return 1;
}

int CProcessPacket::StopEngine()
{

	closesocket(m_sniffSocket);
	//closesocket(m_helperSocket);

	if (m_hThrdReadyEvent)
		CloseHandle(m_hThrdReadyEvent); // Close thread ready event
	m_hThrdReadyEvent = NULL;
	
	if (m_hSniffThread)
		CloseHandle(m_hSniffThread);	
	m_hSniffThread = NULL;


	if (m_pUrlFilterObj)
	{
		delete m_pUrlFilterObj;
		m_pUrlFilterObj = NULL;
	}	

	
	

	// if successful
	return 1;
}

DWORD CProcessPacket::ThreadHandler(LPVOID in_pParam)
{
		

	CProcessPacket* _this = (CProcessPacket*)in_pParam;	

	int  res = 0;
	char *pkt_data = (char *)malloc(65536); //Its Big!	
	char					m_pLogString[256];		
	Packet					p;
	
	if (pkt_data == NULL)
	{		
		return 0;
	}

	SetEvent(_this->m_hThrdReadyEvent);
	
	// Capture packet
	do
	{
		res = recvfrom(_this->m_sniffSocket,pkt_data,65536,0,0,0); //Eat as much as u can
		if(res > 0)	
		{			
			ZeroMemory(&p, sizeof (Packet));
			
			_this->DecodeIP((u_int8_t*)pkt_data, res, &p);

			if (p.banned == 1)
			{
				_this->FilterHttpRequest(&p);

				char ip_string_src[17];
				char ip_string_dst[17];

				memcpy (ip_string_src, inet_ntoa(p.iph->ip_src), 17);
				memcpy (ip_string_dst, inet_ntoa(p.iph->ip_dst), 17);

				sprintf (m_pLogString,
					"Keyword \'%s\' is detected in a request from %s to %s. Session Droped!", 
					p.matched, ip_string_src, ip_string_dst);

				_this->m_pFilterLog->AddLog(m_pLogString);
				
			}

		}
	} 
	while (res > 0);



	free(pkt_data);
	return 1;
}



void CProcessPacket::DecodeIP(u_int8_t * pkt, const u_int32_t len, Packet * p){	u_int32_t ip_len;			/* length from the start of the ip hdr to the								* pkt end */	u_int32_t hlen;             /* ip header length */			/* lay the IP struct over the raw data */	p->iph = (IPHdr *) pkt;	/* do a little validation */	if(len < IP_HEADER_LEN)	{				p->iph = NULL;		return;	}	if(IP_VER(p->iph) != 4)	{		p->iph = NULL;		return;	}	/* set the IP datagram length */	ip_len = ntohs(p->iph->ip_len);	/* set the IP header length */	hlen = IP_HLEN(p->iph) << 2;	/* header length sanity check */	if(hlen < IP_HEADER_LEN)	{		p->iph = NULL;		return;	}	if (ip_len > len) 	{		 ip_len = len;	}	if(ip_len < hlen)	{		 p->iph = NULL;		 return;	}	/* test for IP options */	p->ip_options_len = hlen - IP_HEADER_LEN;	if(p->ip_options_len > 0)	{		p->ip_options_data = pkt + IP_HEADER_LEN;			}	/* set the remaining packet length */	ip_len -= hlen;	/* check for fragmented packets */	p->frag_offset = ntohs(p->iph->ip_off);	/* 	* get the values of the reserved, more 	* fragments and don't fragment flags 	*/	p->rf = (u_int8_t)((p->frag_offset & 0x8000) >> 15);	p->df = (u_int8_t)((p->frag_offset & 0x4000) >> 14);	p->mf = (u_int8_t)((p->frag_offset & 0x2000) >> 13);	/* mask off the high bits in the fragment offset field */	p->frag_offset &= 0x1FFF;	if(p->frag_offset || p->mf)	{		/* set the packet fragment flag */		p->frag_flag = 1;		}	/* if this packet isn't a fragment */	if(!(p->frag_flag))	{		/* Decode only TCP headers */		if (p->iph->ip_proto == IPPROTO_TCP)		{
			DecodeTCP(pkt + hlen, ip_len, p);
		}	}	else	{		/* set the payload pointer and payload size */		p->data = pkt + hlen;		p->dsize = (u_short) ip_len;	}	return;}void CProcessPacket::DecodeTCP(u_int8_t * pkt, const u_int32_t len, Packet * p){
	u_int32_t hlen;            /* TCP header length */
		if(len < 20)	{
		  p->tcph = NULL;
		  return;
	}

	/* lay TCP on top of the data cause there is enough of it! */	p->tcph = (TCPHdr *) pkt;	/* multiply the payload offset value by 4 */	hlen = TCP_OFFSET(p->tcph) << 2;

	if(hlen < 20)	{
		p->tcph = NULL;
		return;
	}

	if(hlen > len)	{
		p->tcph = NULL;
		return;
	}

	/* if options are present, decode them */	p->tcp_options_len = hlen - 20;

	if(p->tcp_options_len > 0)	{			p->tcp_options_data = pkt + 20;		}


	/* set the data pointer and size */	p->data = (u_int8_t *) (pkt + hlen);

	if(hlen < len)	{		p->dsize = (u_short)(len - hlen);	}	else	{		p->dsize = 0;	}
	
	if (p->tcph->th_flags & TH_ACK
		&& p->tcph->th_flags & TH_PSH)
	{
		if(p->tcph->th_dport != htons(80) &&
			p->tcph->th_dport != htons(8080) )
			return ;


		DecodeHTTP(p->data, p->dsize, p);

	}

	
		
	
	
	
	
	return;
}

void CProcessPacket::DecodeHTTP(u_int8_t * pkt, const u_int32_t len, Packet * p)
{
	if (CheckHttpState(pkt, len) == CLIENT_REQUEST)
	{	int matched_idx = 0;
		if (m_pUrlFilterObj->CheckPattern(pkt, len, &matched_idx))
		{
			/* packet caught, Filter it */ 
			p->banned = 1;
			_mbscpy(p->matched, m_pUrlFilterObj->GetPattern(matched_idx));
		}

	}
}
int CProcessPacket::CheckHttpState(u_int8_t* buffer,u_int32_t len)
{
	if(!len)
		return NOT_HTTP;

	if( buffer[0] == 'G' &&
		buffer[1] == 'E' &&
		buffer[2] == 'T' &&
		buffer[3] == ' ' &&
		buffer[4] == '/' 
		)
		return CLIENT_REQUEST;

	if( buffer[0] == 'H' &&
		buffer[1] == 'T' &&
		buffer[2] == 'T' &&
		buffer[3] == 'P')
		return SERVER_RESPONSE;
	
	//else anyway
	return NOT_HTTP;
}


unsigned short CProcessPacket::CalcIPSum(unsigned short * w, int blen){	unsigned int cksum;	/* IP must be >= 20 bytes */	cksum  = w[0];	cksum += w[1];	cksum += w[2];	cksum += w[3];	cksum += w[4];	cksum += w[5];	cksum += w[6];	cksum += w[7];	cksum += w[8];	cksum += w[9];	blen  -= 20;	w     += 10;	while( blen ) /* IP-hdr must be an integral number of 4 byte words */	{		cksum += w[0];		cksum += w[1];		w     += 2;		blen  -= 4;	}	cksum  = (cksum >> 16) + (cksum & 0x0000ffff);	cksum += (cksum >> 16);	return (unsigned short) (~cksum);}unsigned short CProcessPacket::CalcTCPSum(unsigned short *h, unsigned short * d, int dlen){	unsigned int cksum;	unsigned short answer=0;	/* PseudoHeader must have 12 bytes */	cksum  = h[0];	cksum += h[1];	cksum += h[2];	cksum += h[3];	cksum += h[4];	cksum += h[5];	/* TCP hdr must have 20 hdr bytes */	cksum += d[0];	cksum += d[1];	cksum += d[2];	cksum += d[3];	cksum += d[4];	cksum += d[5];	cksum += d[6];	cksum += d[7];	cksum += d[8];	cksum += d[9];	dlen  -= 20; /* bytes   */	d     += 10; /* short's */ 	while(dlen >=32)	{		cksum += d[0];		cksum += d[1];		cksum += d[2];		cksum += d[3];		cksum += d[4];		cksum += d[5];		cksum += d[6];		cksum += d[7];		cksum += d[8];		cksum += d[9];		cksum += d[10];		cksum += d[11];		cksum += d[12];		cksum += d[13];		cksum += d[14];		cksum += d[15];		d     += 16;		dlen  -= 32;	}	while(dlen >=8)  	{		cksum += d[0];		cksum += d[1];		cksum += d[2];		cksum += d[3];		d     += 4;   		dlen  -= 8;	}	while(dlen > 1)	{		cksum += *d++;		dlen  -= 2;	}	if( dlen == 1 ) 	{ 		/* printf("new checksum odd byte-packet\n"); */		*(unsigned char*)(&answer) = (*(unsigned char*)d);		/* cksum += (u_int16_t) (*(u_int8_t*)d); */		cksum += answer;	}	cksum  = (cksum >> 16) + (cksum & 0x0000ffff);	cksum += (cksum >> 16);	return (unsigned short)(~cksum);}

int CProcessPacket::FilterHttpRequest(Packet *p)
{
	DWORD err = 0;
	SOCKADDR_IN dest;
	dest.sin_family = AF_INET;

	struct pseudoheader       /* pseudo header for TCP checksum calculations */
	{
		u_int32_t sip, dip;   /* IP addr */
		u_int8_t  zero;       /* checksum placeholder */
		u_int8_t  protocol;   /* protocol number */
		u_int16_t tcplen;     /* TCP packet length */
	};
	struct pseudoheader ph;    /* pseudo header declaration */


	//////////////////////////SENDING BLOCK PAGE TO CLIENT//////////////////////////

	// Use the first 40 bytes of m_pBlockBuffer for future TCP control packet transmission.
	ZeroMemory(m_pBlockBuffer, 40); // only zero first 40 bytes
	IPHdr*	respIpHdr	= ((IPHdr*)(m_pBlockBuffer ));
	TCPHdr*	respTcpHdr	= ((TCPHdr*)(m_pBlockBuffer + sizeof (IPHdr)));


	respIpHdr->ip_csum = 0;
	respIpHdr->ip_dst = p->iph->ip_src;
	respIpHdr->ip_src = p->iph->ip_dst;
	respIpHdr->ip_len = htons(sizeof (IPHdr) + sizeof (TCPHdr) + m_cbBlockBuffer);
	SET_IP_VER(respIpHdr, 0x4);
	SET_IP_HLEN(respIpHdr, 0x5);
	respIpHdr->ip_tos = p->iph->ip_tos;
	respIpHdr->ip_ttl = p->iph->ip_ttl;
	respIpHdr->ip_id = htons(2);	
	respIpHdr->ip_off = 0;
	respIpHdr->ip_proto = 0x06;
	respIpHdr->ip_csum = 
		CalcIPSum((u_short*) respIpHdr, IP_HLEN(respIpHdr) << 2);



	respTcpHdr->th_ack = htonl (ntohl (p->tcph->th_seq) + p->dsize);
	respTcpHdr->th_seq = p->tcph->th_ack;
	respTcpHdr->th_sport = p->tcph->th_dport;
	respTcpHdr->th_dport = p->tcph->th_sport;
	respTcpHdr->th_flags = TH_ACK | TH_FIN;

	SET_TCP_OFFSET(respTcpHdr, 0x5);
	SET_TCP_X2(respTcpHdr, 0x0);
	respTcpHdr->th_win = p->tcph->th_win;
	respTcpHdr->th_urp = 0;

	

	ph.sip = (u_int32_t)(p->iph->ip_dst.s_addr);
	ph.dip = (u_int32_t)(p->iph->ip_src.s_addr);
	ph.zero = 0;
	ph.protocol = 0x06;
	ph.tcplen = htons((u_short)(sizeof (TCPHdr) + m_cbBlockBuffer));
	respTcpHdr->th_sum = 0;
	respTcpHdr->th_sum		 = 
		CalcTCPSum((u_int16_t *)&ph, 
		(u_int16_t *)respTcpHdr,
		sizeof(TCPHdr) + m_cbBlockBuffer);


	dest.sin_port   = p->tcph->th_sport;
	dest.sin_addr = p->iph->ip_src;
	
	
	if((sendto(m_helperSocket ,(const char*)( m_pBlockBuffer ), sizeof(IPHdr) + sizeof(TCPHdr) + m_cbBlockBuffer, 0,
		(SOCKADDR *)&dest, sizeof(dest))) == SOCKET_ERROR)
	{		
		m_pFilterLog->AddLog("sendto failed!");
		return 0;
	}	


	///////////////////////SENDING TCP RESET TO SERVER////////////////////////////

	ZeroMemory(reset_buf, 40);	
	IPHdr*	rstIpHdr = ((IPHdr*)(reset_buf ));
	TCPHdr*	rstTcpHdr = ((TCPHdr*)(reset_buf + sizeof (IPHdr) ));



	rstIpHdr->ip_dst = p->iph->ip_dst;
	rstIpHdr->ip_id = htons(2);
	rstIpHdr->ip_len = htons(sizeof (IPHdr) + sizeof (TCPHdr));
	rstIpHdr->ip_off = 0;
	rstIpHdr->ip_proto = 0x06;
	rstIpHdr->ip_src = p->iph->ip_src;
	rstIpHdr->ip_tos = p->iph->ip_tos;
	rstIpHdr->ip_ttl = p->iph->ip_ttl;
	SET_IP_VER(rstIpHdr, 0x4); 
	SET_IP_HLEN(rstIpHdr, 0x5);
	rstIpHdr->ip_csum = 
		CalcIPSum((u_short*) rstIpHdr, IP_HLEN(rstIpHdr) << 2);

	rstTcpHdr->th_ack = p->tcph->th_ack;	
	rstTcpHdr->th_seq = p->tcph->th_seq;
	rstTcpHdr->th_sport = p->tcph->th_sport;
	rstTcpHdr->th_dport = p->tcph->th_dport;
	rstTcpHdr->th_flags = TH_RST;

	SET_TCP_OFFSET(rstTcpHdr, 0x5);
	SET_TCP_X2(rstTcpHdr, 0x0);
	rstTcpHdr->th_win = p->tcph->th_win;
	rstTcpHdr->th_urp = 0;

	ph.sip = (u_int32_t)(p->iph->ip_src.s_addr);
	ph.dip = (u_int32_t)(p->iph->ip_dst.s_addr);
	ph.zero = 0;
	ph.protocol = 0x06;
	ph.tcplen = htons((u_short)sizeof (TCPHdr));

	rstTcpHdr->th_sum		 = 
		CalcTCPSum((u_int16_t *)&ph, 
		(u_int16_t *)rstTcpHdr,
		sizeof(TCPHdr));






	dest.sin_port   = p->tcph->th_dport;
	dest.sin_addr = p->iph->ip_dst;



	if((sendto(m_helperSocket ,(const char*)( reset_buf ), sizeof(IPHdr) + sizeof(TCPHdr), 0,
		(SOCKADDR *)&dest, sizeof(dest))) == SOCKET_ERROR)
	{
		m_pFilterLog->AddLog("sendto failed!");
		return 0;
	}


	
	return 1;
}


int CProcessPacket::RetrieveAllAdaptersInfo()
{
	
	DWORD dwBufLen = sizeof(m_AdapterInfo);
	if (GetAdaptersInfo(      // Call GetAdapterInfo
		m_AdapterInfo,                 // [out] buffer to receive data
		&dwBufLen) != ERROR_SUCCESS)
	{
		return 0;
	}	

	return 1;

}

⌨️ 快捷键说明

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