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

📄 packet.cpp

📁 基于C++的网络端口扫描源代码
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////////////
//
//   PortScanner
//   Efficient TCP port scanner based on TCP half open scanning method.
//
//   Author  : Nagareshwar Y Talekar.
//	 Contact : nsry2002@yahoo.co.in
//	 Date    : 15-6-2004.
//
//   Name :  Packet.cpp
//   Description : It opens the device and captures the packet based on 
//				   the filter.
//				   For more information on Capture API , please refer
//				   Winpcap documentation.
//////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "Packet.h"
#include "PortScannerDlg.h"


#include <pcap.h>


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

IMPLEMENT_DYNCREATE(Packet, CWinThread)

Packet::Packet()
{
}



Packet::~Packet()
{
}



BOOL Packet::InitInstance()
{
	
	log.Open("log.txt",CFile::modeWrite | CFile::modeCreate | CFile::shareDenyWrite);
	return TRUE;
}

int Packet::ExitInstance()
{

	this->CloseDevice();
	
	// TODO:  perform any per-thread cleanup here
	return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(Packet, CWinThread)
ON_THREAD_MESSAGE(WM_PACKET_OPENDEVICE  , OpenDevice)
ON_THREAD_MESSAGE(WM_PACKET_STARTSCAN, StartScan)
ON_THREAD_MESSAGE(WM_PACKET_STOPSCAN , StopScan)
ON_THREAD_MESSAGE(WM_PACKET_CLOSEDEVICE , CloseDevice)
END_MESSAGE_MAP()



/**
*     Enumerate all available devices...
*
*/
int Packet::GetDeviceList()
{
int retvalue,i;
char err[PCAP_ERRBUF_SIZE];
pcap_if_t *d;

    devcount=0;


	retvalue=pcap_findalldevs(&devlist,err);
		
	if(retvalue==-1 || devlist==NULL)
	return FALSE;
 
	
	// Enumerate available devices...
	// Store the name and decription...
	for(d=devlist,i=0; d && i<10 ;d=d->next,i++)
    {
        devname[i]=d->name;
		description[i]=d->description;
			
	}

	devcount=i;


	// determine the local ip address
	GetLocalAddress();

	return devcount;

}




/**
*    Determine the ip address of local machine
*
*/

void Packet::GetLocalAddress()
{
char name[200];
HOSTENT *h;

	gethostname(name,200);

	h=::gethostbyname(name);

	memcpy(srcip,h->h_addr_list[0],4);

	sprintf(name,"%d.%d.%d.%d",srcip[0],srcip[1],srcip[2],srcip[3]);
	
}


/**
*	Open the device...based upon the device index ...
*	This index is obtained from GetDeviceList Function...
*
*/

BOOL Packet::OpenDevice(int index)
{
char err[PCAP_ERRBUF_SIZE];

    	
	// if the device is already open
	// close the device...
	if(isOpen==TRUE)
	{
	CloseDevice();	
	}	
	
	hdev=pcap_open_live( LPCTSTR(devname[index]), //name of the device
		                 65535,		 //Capture whole packet
	                     1,			 //promiscous mode  
						 1000,       //read timeout in ms
						 err 
						 );

	

	if(hdev==NULL)
	return FALSE;
	/*
	//check the link layer to support only ethernet
	if(pcap_datalink(hdev)!=DLT_EN10MB)
	{
	log.WriteString("\n Error : Only Ethernet Network is supported");
	return FALSE;
	}

	*/

	isOpen=TRUE;


return TRUE;

}


/**
*		Start the port scanning process
*       For protocol format , refer Packet.h file.
*/
LRESULT Packet::StartScan(WPARAM wp,LPARAM lp)
{
int retvalue;

eth_header eh;
ip_header ih,*rih;
tcp_header th,*rth;
pseudo_header psh;

CPortScannerDlg *scan;

char str[300],destaddr[100];
u_char frame[200];

int index=0;
u_short sport;
int i,repcount=0;




	
	//If capture device not opened then return ...
	if(isOpen==FALSE)
	return FALSE;


	// Obtains the pointer to main dialog
	scan=(CPortScannerDlg*)lp;
	
	
	// Check for destination address = 127.0.0.1
	// If so then assign proper address of the host to destination
	if(destip[0]==127 && destip[1]==0 && destip[2]==0 && destip[3]==1)
	{
	memcpy(destip,srcip,4);
	}

	
	
	// Don't use real host address as source address
	// Just change the last byte of source ip address
	// This is called IP Spoofing...
	memcpy(hostip,srcip,4);
	hostip[3]=::rand()%254+1;

	
		
		// Determine the MAC address of the destination machine
		if(GetDestMacAddress()==FALSE)
		{
		AfxMessageBox("Unable to determine the destination MAC address");
		scan->butstart->EnableWindow(TRUE);
		scan->butstop->EnableWindow(FALSE);
		return FALSE;
		}


	// ***** Now apply the filter *****
	// Receive only incoming packets from the target host
	// Filter details..
	// Protocol : TCP
	// Source Address  : Target Machine
	// Destination port : same as source machine port

	sprintf(destaddr,"%d.%d.%d.%d",destip[0],destip[1],destip[2],destip[3]);
	sprintf(str,"src net %s and tcp port 6000",destaddr);
	
	ApplyFilter(str);
	




	// Prepare Ethernet Header , IP Header and TCP Header in Advance

	
	/*******************  Ethernet Header ******************/

	memset(&eh,0,sizeof(eh));
	
	//Source MAC address
	memcpy(eh.shost,hostmac,6);
	
	//Destination MAC address
	memcpy(eh.dhost,destmac,6);
	
	eh.type=htons(0x0800); //IP Frames

	memcpy(&frame,&eh,ETHER_LENGTH);


	
	/*******************  IP Header ******************/
	
	memset(&ih,0,sizeof(ih));
	
	//source address
	memcpy(&ih.saddr,hostip,4);
		
	//destination address
	memcpy(&ih.daddr,destip,4);
	
	ih.proto=PROTO_TCP;         

	ih.flags_fo=htons(0x4000);			//For TCP Flag fixed
//	ih.flags_fo=htons(0x0000);			//For ICMP Flag fixed
	ih.identification=htons(0x0150);    //Any number
	
	
	ih.tlen=htons(IP_LENGTH+TCP_LENGTH);      //Depends upon data and tcp protocol
	ih.tos=0;
	ih.ttl=32;
	ih.ver_ihl=0x45;  //Version (v4) and  header length(5 nibbles)
	ih.crc=0;
	ih.crc=ComputeChecksum((u_short *)&ih,IP_LENGTH);

	memcpy(&frame[ETHER_LENGTH],&ih,IP_LENGTH);

	
	
	
	/***************  TCP Header ****************************/

	  
	memset(&th,0,sizeof(th));
	th.sport=htons(6000);   // source port
	th.dport=htons(139);    // dest port changes dynamically
	th.ackno=htonl(0);
	th.seqno=htonl(5555l);
	th.flag=TCP_SYN;        // SYN packet
	th.offset=0x50;         // data offset
	th.uptr=0;
	th.win=htons(512) ;
	th.checksum=0;
	
	//set up the pseudo header 
	memset(&psh,0,sizeof(psh));
	psh.saddr=ih.saddr;
	psh.daddr=ih.daddr;
	psh.proto=ih.proto;
	psh.zero=0;
	psh.tcp_len=htons(TCP_LENGTH);				//Length of Tcp header + Data in OCTATES
	memcpy(&psh.tcp,&th,TCP_LENGTH);
	
	th.checksum=ComputeChecksum((u_short*)&psh,TCP_LENGTH+PSEUDO_LENGTH);

	
	// Now start scanning  for all port numbers mentioned...

	for(i=startportno;i<=endportno;i++,index++)
	{
		//Check if stop scan button is pressed
		if(stopscanning==TRUE)
		{
		stopscanning=FALSE;
		return FALSE;
		}
		
		// Update ListCtrl in the Interface Window
		sprintf(str,"%d",i);
		scan->list->InsertItem(index,str,NULL);

		//Repeatcount of waiting for the proper packet
		repcount=0;

		//TCP Header
		th.dport=htons(i); 
		th.checksum=0;


		//copy new tcp header into pseudo header
		memcpy(&psh.tcp,&th,TCP_LENGTH);
		
		//Compute Checksum for TCP Header
		th.checksum=ComputeChecksum((u_short*)&psh,TCP_LENGTH+PSEUDO_LENGTH);

		//Copy TCP Header into the frame at the end of IP Packet
		memcpy(&frame[ETHER_LENGTH+IP_LENGTH],&th,TCP_LENGTH);
	
	
		//Send the packet
		pcap_sendpacket(hdev,frame,ETHER_LENGTH+IP_LENGTH+TCP_LENGTH);

	
		//Wait for the SYN - ACK or RST-ACK packet
		//If any other packet comes then ignore it....

		//If no packet comes after trying 5 times then stop the scan and exit
		//Since target machine might have shut down...or it may be sleeping..!!!
		
			int count=0;
	

			while(true)
			{
				
				//Check if stop scan button is pressed
				if(stopscanning==TRUE)
				{
				stopscanning=FALSE;
				return FALSE;
				}

				// Wait for next packet
				retvalue=pcap_next_ex(hdev,&header,&pkt_data);
			
				if(retvalue<0)
				{
				log.WriteString("Error in capturing the packet");
				scan->butstart->EnableWindow(TRUE);
				scan->butstop->EnableWindow(FALSE);
				return FALSE;
				}
				
				if(header->caplen==0)
				{
					count++;
					
					if(count>5)
					{
						AfxMessageBox("Target Machine is  not responding");
						scan->butstart->EnableWindow(TRUE);
						scan->butstop->EnableWindow(FALSE);
						return FALSE;
					}
				
					continue;
				}
			
				
				//Now check if this packet is proper or not	
			
				count=0;
				repcount++;
					//Check only for 3 times for the proper packet
					if(repcount>3)
					{
						AfxMessageBox("Target Machine is  not responding");
						scan->butstart->EnableWindow(TRUE);
						scan->butstop->EnableWindow(FALSE);
						return FALSE;
					}

				//Get the IP Header...
				rih=(ip_header*)(pkt_data+ETHER_LENGTH);
	
	 
				//Cross check the incoming packet

				if(rih->proto==PROTO_TCP)  //check for tcp protocol
				{
		
					//Get the TCP Header
					rth=(tcp_header*)((u_char*)rih+ (rih->ver_ihl & 0x0f)*4);

					//Convert network byte order to host byte order
					sport=ntohs(rth->sport);
					
					//Check if the response is for the current port number
					if(sport==i) 
					{
							
							// Check if it is SYN+ACK packet...
							if((rth->flag & TCP_SYN) && (rth->flag & TCP_ACK) )
							{
								sprintf(str,"*** Open ***");
								scan->list->SetItemText(index,1,str);
								break;
							}
							else // Check if it is RST+ACK packet
								if((rth->flag & TCP_RST) && (rth->flag & TCP_ACK) )
								{
								sprintf(str,"Closed");
								scan->list->SetItemText(index,1,str);
								break;
								}
					}
				
				}


			}    //End of Receiving while loop

	}		//End of port scanner for loop

	// Update the button status....
	scan->butstart->EnableWindow(TRUE);
	scan->butstop->EnableWindow(FALSE);
	
	AfxMessageBox("Scanning completed...");
	return TRUE;

}


//
//  Send ARP Request packet to determine the MAC address of
//  the destination machine.
//  ARP Reply message contains the MAC address of destination
//  machine...
//  This trick also prevents the target host from sending arp packet
//  to source host when source host sends the first SYN packet.
//  From the ARP request packet , target host will come to know
//  about the MAC address of the source host...
//

BOOL Packet::GetDestMacAddress()
{

eth_header eh,*peh;
arp_header arph,*parph;

int retvalue;
u_char frame[200];
char str[100],filter[200];


	// Apply filter to receive only ARP reply packet...
	sprintf(str,"%d.%d.%d.%d",destip[0],destip[1],destip[2],destip[3]);
	sprintf(filter,"arp src net %s",str);
	ApplyFilter(filter);
	

	// Prepare ARP request packet

	/*******************  Ethernet Header ******************/

	memset(&eh,0,sizeof(eh));
	
	// Source Mac address
	memcpy(eh.shost,hostmac,6);

	// Destination MAC address ; make it all 0xff
	memset(eh.dhost,0xff,6);
	
	eh.type=htons(0x0806); //IP Frames

	memcpy(&frame,&eh,ETHER_LENGTH);


	/*******************  ARP Header ******************/
	
	arph.eth_type=htons(0x0800);
	
	memcpy(arph.smac,eh.shost,6);
	memset(arph.dmac,0,6);

	memcpy(&arph.daddr,destip,4);
	memcpy(&arph.saddr,hostip,4);
	
	arph.hrd=htons(0x0001);
	
	arph.iplen=4;
	arph.maclen=6;

	arph.opcode=0x0100;  //Request ARP packet

	memcpy(&frame[ETHER_LENGTH],&arph,ARP_LENGTH);

		
	//Send the ARP request packet
	pcap_sendpacket(hdev,frame,ETHER_LENGTH+ARP_LENGTH);

	
	//Now wait ARP reply packet
			int count=0;

			while(true)
			{
				//Check if stop scan button is pressed
				if(stopscanning==TRUE)
				{
				stopscanning=FALSE;
				return FALSE;
				}

				retvalue=pcap_next_ex(hdev,&header,&pkt_data);
			
				if(retvalue<0)
				{
				log.WriteString("Error in capturing the packet");
				return FALSE;
				}
				
				if(header->caplen==0)
				{
					count++;
					
					if(count>5)
					{
						return FALSE;
					}
				
					continue;
				}
			
				//Now this packet is the required packet..
				//So take a break and check it out....
			
				//check for ARP packet IP address checking is better

		
				//Get the Ethernet Header...
				peh=(eth_header*)pkt_data;

				if(ntohs(peh->type)==0x0806)	
				{
					// Get the ARP Header
					parph=(arp_header*)(pkt_data+ETHER_LENGTH);
				
					//check if it is Reply
					if(parph->opcode==0x0200)
					{
						memcpy(destmac,parph->smac,6);
						return TRUE;
					}
				
				}


			}
	return FALSE;
}


/**
*    Standard checksum algorithm
*
*/
u_short Packet::ComputeChecksum(u_short *data,int size)
{
register int nleft=size;
register u_short *w=data;
register int sum=0;
u_short answer =0;



	while(nleft>1)
	{
	sum+=*w++;
	nleft-=2;
	}


	if(nleft==1)
	{

		*(u_char*) (&answer) = *(u_char*)w;
		sum+=answer;
	}


	sum= (sum>>16 )+ (sum & 0xffff);
	sum+=(sum>>16);
	answer=~sum;
	return (answer);

}



/**
*    Filter the incoming packets...
*	 For filter expression refer winpcap docs
*
*/

LRESULT Packet::ApplyFilter(char *filter)
{
u_int netmask;
int retvalue;

	//log.WriteString(strcat(mesg,filter));
	if(devlist->addresses!=NULL)
	netmask=((struct sockaddr_in *)(devlist->addresses->netmask))->sin_addr.S_un.S_addr;
	else
	netmask=0xffffffff;

	//compile the filter
	retvalue=pcap_compile(hdev,&fcode,filter,1,netmask);
	
	if(retvalue<0)
	{
	log.WriteString("\n Unable to compile the filter");
	return FALSE;
	}

	//Set the filter
	retvalue=pcap_setfilter(hdev,&fcode);
	
	if(retvalue<0)
	{
	log.WriteString("\n Unable to set the filter");
	return FALSE;
	}
	
	
	log.WriteString("\n Filter applied successfully");

return TRUE;

}






// presently not used....

LRESULT Packet::StopScan(WPARAM wp,LPARAM lp)
{
return TRUE;
}



/**
*   Before next scanning close the device...
*
*/  
BOOL  Packet::CloseDevice()
{

	if(isOpen==TRUE)
	{

	pcap_freealldevs(devlist);
	
	pcap_close(hdev);

	hdev=NULL;
	}
	
	isOpen=FALSE;


return TRUE;
}


⌨️ 快捷键说明

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