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

📄 frmmain.h

📁 应用ARP结构的知识与WinPcap的发送和捕获功能
💻 H
📖 第 1 页 / 共 4 页
字号:
				5、侦听并对收到的包处理
		 *******************************************************************************/

		System::Void buttStart_Click(System::Object^  sender, System::EventArgs^  e) 
		{
			array<int>^ iCount=gcnew array<int>(0);

			///判断开始条件是否满足
			if(strDevInfo[cboxDev->SelectedIndex,7]!="网络连通:  是")
			{
				if(System::Windows::Forms::MessageBox::Show("当前适配器处于未连网状态,将无法捕获到任何包\r\n确定继续么?",
					"注意",System::Windows::Forms::MessageBoxButtons::YesNo)==System::Windows::Forms::DialogResult::No)
					return;
			}
			for(int i=0;i<dgvOpt->Rows->Count;i++)
			{
				if(Convert::ToBoolean(dgvOpt->Rows[i]->Cells[0]->Value))
				{
					System::Array::Resize(iCount,iCount->Length+1);
					iCount[iCount->Length-1]=i;
				}
			}
			if(iCount->Length==0)
			{
				labStatus->ForeColor=System::Drawing::Color::DarkRed;
				labStatus->Text="提示: 请选择要捕获的网段再开始。";

				return;
			}
			buttStart->Enabled=false;
			labStatus->Text="准备开始……";
			System::Windows::Forms::Application::DoEvents();
			pcap_if_t *alldevs;
			pcap_if_t *d;
			pcap_t *adhandle;
			char errbuf[PCAP_ERRBUF_SIZE];
			ARPPacket *apPacket=new ARPPacket();
		    
			///获取本地机器设备列表
			if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
			{
				fnErrorMsg("Error in pcap_findalldevs_ex: " + gcnew String(errbuf));
				
				exit(1);
			}
			
			///找到设备
			for(d= alldevs; d != NULL; d= d->next)
			{
				String ^sTmp=gcnew String(d->name);
				if(sTmp->Contains(strDevInfo[cboxDev->SelectedIndex,0]->Replace("设 备 ID:","")->Trim()))
				{
					break;
				}
			}

			///打开设备
			if ( (adhandle= pcap_open(d->name,		// 设备名
								60,					// 只侦听ARP包,故60字节就足够了
								0,					// 正常模式,只接收发给自己的包
								1000,               // 读超时时间
								NULL,               // 远程机器验证
								errbuf              // 错误缓冲
								) ) == NULL)

			{
				fnErrorMsg("无法打开适配器,WinPcap不支持该设备。");
				///不再需要设备列表了,释放它
				pcap_freealldevs(alldevs);
				return;
			}

			
			///编译过滤器
			struct bpf_program fcode;
			char packet_filter[]="ether proto\\arp";


			if(pcap_compile(adhandle,&fcode,packet_filter,1,Convert::ToUInt32(0xffff0000))<0)
			{
				fnErrorMsg("Unable to compile the packet filter,please check the syntax!");
				///不再需要设备列表了,释放它 
				pcap_freealldevs(alldevs);
				return;
			}

			///设置过滤器
			if(pcap_setfilter(adhandle,&fcode)<0)
			{
				fnErrorMsg("Error setting the filter: "+gcnew String(pcap_geterr(adhandle)));
				///不再需要设备列表了,释放它 
				pcap_freealldevs(alldevs);
				return;
			}
			
			///
			/// 发送数据包
			///
			labStatus->Text="准备发送ARP包……";
			System::Windows::Forms::Application::DoEvents();
			array<unsigned char>^ cMacAddrs=gcnew array<unsigned char>(6);
			array<System::Net::NetworkInformation::NetworkInterface^> ^nwInterface=
				System::Net::NetworkInformation::NetworkInterface::GetAllNetworkInterfaces();
			for(int i=0;i<nwInterface->Length;i++)
			{
				if(strDevInfo[cboxDev->SelectedIndex,0]->Contains(nwInterface[i]->Id))
				{	
					//获得物理地址
					cMacAddrs=nwInterface[i]->GetPhysicalAddress()->GetAddressBytes();
					break;
				}
			}

			///for循环对每个已选网段操作一次
			for(int i=0;i<iCount->Length;i++)
			{
				String ^strIP_L=Convert::ToString(dgvOpt->Rows[iCount[i]]->Cells[3]->Value);
				String ^strIP_H=Convert::ToString(dgvOpt->Rows[iCount[i]]->Cells[4]->Value);
				///对当前网段设定的区间内单个IP地址进行发送
				while(true)
				{
					if(strIP_L!=Convert::ToString(dgvOpt->Rows[iCount[i]]->Cells[5]->Value) || true)
					{
								apPacket->InitAddr(cMacAddrs,Convert::ToString(dgvOpt->Rows[iCount[i]]->Cells[5]->Value),strIP_L);
								u_char * tmpee=apPacket->GetPack();
								u_char cctmp[60];
								for(int i=0;i<60;i++)
								{
									cctmp[i]=tmpee[i];
								}
								labStatus->Text="正在向" + strIP_L + "发送数据包……";
								System::Windows::Forms::Application::DoEvents();

								if (pcap_sendpacket(adhandle, apPacket->GetPack(), 60) != 0)
								{
									fnErrorMsg("发送包时发生错误:\n" + gcnew String(pcap_geterr(adhandle)));
									/// 不再需要设备列表了,释放它
									pcap_freealldevs(alldevs);
									return;
								}
					}
					if(strIP_L==strIP_H)			//当要发送的IP为自己的时跳过
						break;
					strIP_L=fnIncreIP(strIP_L);
				}
			}

			///发送完毕,侦听
			labStatus->Text="发送完毕,开始侦听……";
			System::Windows::Forms::Application::DoEvents();

			int res,iCounter=0,iCountPack=0;
			struct pcap_pkthdr *pHeader;
			const u_char *pData;
   
			while((res = pcap_next_ex( adhandle, &pHeader, &pData)) >= 0){
		        
				if(res == 0)							// 超时时间到 
				{
					if(++iCounter>3)break;
					labStatus->Text="继续侦听……超时 "+iCounter+" 次" ;
				}
				else
				{
					iCounter=0;
					labStatus->Text="侦听到第"+ ++iCountPack +"个包……";
					System::Windows::Forms::Application::DoEvents();

					fnPackect_Handler(pHeader,pData);	//调用fnPackect_Handler函数对侦听到的包处理

				}
				System::Windows::Forms::Application::DoEvents();
			}
			
		    
			if(res == -1){			//读包出错
				fnErrorMsg("读包出错: " + gcnew String( pcap_geterr(adhandle)));
				///不再需要设备列表了,释放它
				pcap_freealldevs(alldevs);
			}
			labStatus->Text="侦听完毕。共侦听到" + iCountPack+"个包,成功添加" +lvMain->Items->Count + "个表项";
			System::Windows::Forms::Application::DoEvents();
			///不再需要设备列表了,释放它
			pcap_freealldevs(alldevs);
			pcap_close(adhandle);
			buttStart->Enabled=true;
		}

		/****************************************
		 * 对详细设置栏编辑开始时调用的函数:
		 * 本函数功能:存放编辑之前的原始地址
		 ***************************************/
		System::Void dgvOpt_CellBeginEdit(System::Object^  sender, System::Windows::Forms::DataGridViewCellCancelEventArgs^  e) 
		{
			dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Tag=dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value;
		}


		/****************************************************************************
		 * 对详细设置栏编辑结束时调用的函数:
		 * 本函数功能:判断输入是否正确,不正确时写回之前存好的原始地址
		 ***************************************************************************/
		System::Void dgvOpt_CellEndEdit(System::Object^  sender, System::Windows::Forms::DataGridViewCellEventArgs^  e) 
		{
			if(e->ColumnIndex!=3 & e->ColumnIndex!=4)
				return;

			///格式不正确时
			if(!fnAnalyzeIP(Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value)))
			{
				fnErrorMsg("输入格式不正确。\r\n正确格式为“X.X.X.X”,X可以为0-255间的数值。");
				dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value=Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Tag);
				return;
			}


			///地址超出网段范围时
			if(!fnCompareNotLess(Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value),Convert::ToString(dsAll->Tables["Range"]->Rows[e->RowIndex]->ItemArray[6])) |
				!fnCompareNotLess(Convert::ToString(dsAll->Tables["Range"]->Rows[e->RowIndex]->ItemArray[7]),Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value)))
			{
				fnErrorMsg("地址超出网段范围。");
				dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value=Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Tag);
				return;
			}


			///上界小于下界时
			if(!fnCompareNotLess(Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[4]->Value),Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[3]->Value)))
			{
				fnErrorMsg("上界应大于下界。");
				dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Value=Convert::ToString(dgvOpt->Rows[e->RowIndex]->Cells[e->ColumnIndex]->Tag);
				return;
			}
		}
		

		/********************************
		 * 点下清除列表时调用的函数:
		 * 本函数功能:清除列表
		 *******************************/

		System::Void buttClear_Click(System::Object^  sender, System::EventArgs^  e) 
		{
			lvMain->Items->Clear();
			
		}


		/*******************************
		 * 点下保存列表时调用的函数:
		 * 本函数功能:保存列表
		 ******************************/
		System::Void buttSave_Click(System::Object^  sender, System::EventArgs^  e)
		{
			System::Windows::Forms::SaveFileDialog ^ fdDia=gcnew System::Windows::Forms::SaveFileDialog();
			fdDia->AddExtension=true;
			fdDia->CheckPathExists=true;
			fdDia->DefaultExt="*.txt";
			fdDia->Filter="文本文件(*.txt)|*.txt";
			fdDia->FileName="ArpList.txt";
			if(fdDia->ShowDialog()==System::Windows::Forms::DialogResult::OK)
			{
			array<System::String ^>^ strCon=gcnew array<System::String ^>(1);
			strCon[0]="响应时间\t所属网段\t子网掩码\tIP地址\t\tMAC地址";
				for(int i=0;i<lvMain->Items->Count;i++)
				{
					System::Array::Resize(strCon,strCon->Length+1);
					strCon[i+1]+=lvMain->Items[i]->SubItems[0]->Text + "   \t";
					for(int j=1;j<5;j++)
					{
						strCon[i+1]+=lvMain->Items[i]->SubItems[j]->Text + "\t";
					}
				}
				System::IO::File::WriteAllLines(fdDia->FileName,strCon);
			};
		}


		/******************************************************
		 * 侦听到包时调用的函数:
		 * 本函数功能:
				1、判断包是否有效
				2、有效时解析出IP对MAC关系并添加到列表
		 *****************************************************/
		System::Void fnPackect_Handler(const struct pcap_pkthdr *pHeader, const u_char *pData)
		{
			///判断包是否有效
			if(pData[20]==0 && pData[21]==1)		//是自己发的时丢弃
			{
				labStatus->Text+="发送方为自己,丢弃";
				System::Windows::Forms::Application::DoEvents();
				return;
			}
			array<String ^>^ strTmp=gcnew array<String ^>(5);
			strTmp[0]=String::Format("{0:T}",System::DateTime::Now);
			strTmp[3]=String::Format("{0}.{1}.{2}.{3}",pData[28],pData[29],pData[30],pData[31]);
			for(int i=0;i<lvMain->Items->Count;i++)	//已添加时丢弃
			{
				if(lvMain->Items[i]->SubItems[3]->Text==strTmp[3])	
				{
					labStatus->Text+="重复添加";
					System::Windows::Forms::Application::DoEvents();
					return;
				}
			}

			///有效时解析出IP对MAC关系并添加到列表
			labStatus->Text+="成功添加列表";
			System::Windows::Forms::Application::DoEvents();
			strTmp[4]=String::Format("{0:X2}-{1:X2}-{2:X2}-{3:X2}-{4:X2}-{5:X2}",pData[22],pData[23],pData[24],pData[25],pData[26],pData[27]);
			for(int i=0;i<dgvOpt->Rows->Count;i++)
			{
				if(Convert::ToBoolean(dgvOpt->Rows[i]->Cells[0]->Value)==true)
				{
					if(fnCompareNotLess(strTmp[3],Convert::ToString(dsAll->Tables["Range"]->Rows[i]->ItemArray[6])) && fnCompareNotLess(Convert::ToString(dsAll->Tables["Range"]->Rows[i]->ItemArray[7]),strTmp[3]) )
					{
						strTmp[1]=Convert::ToString(dgvOpt->Rows[i]->Cells[1]->Value);
						strTmp[2]=Convert::ToString(dgvOpt->Rows[i]->Cells[2]->Value);
						break;
					}
				}
			}
			lvMain->Items->Add(gcnew System::Windows::Forms::ListViewItem(strTmp));
			System::Windows::Forms::Application::DoEvents();

	
		}


		/******************************************************
		 * 本函数用来向对象控件打印字串:
		 *****************************************************/
		System::Void fnPrint(System::Windows::Forms::Control ^objCon,String ^strContext,bool bEndl)
		{
			objCon->Text+=strContext + (bEndl?"\r\n":"");
		}


	};
}

⌨️ 快捷键说明

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