📄 frmmain.h
字号:
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 + -