上篇文章我们成功发送了arp请求,这里我们就需要等待并看看能不能收到来自我们需探测ip的arp回复,如果收到,则该主机为活动的,因为这个等待arp返回需要等待一段时间,这里我之间写出来,实际用的时候,你们需要写成线程,并在发送arp请求之前调用。
定义需要的变量
pcap_if_t * alldevs;
pcap_if_t *d;
pcap_t * adhandle;//定义包捕捉句柄
char errbuf[PCAP_ERRBUF_SIZE];//错误缓冲最小为256
pcap_addr_t *pAddr;
struct bpf_program fcode;
char packet_filter[] = "ether proto \\arp";
int result;
struct pcap_pkthdr * header;
const u_char * pkt_data;
struct in_addr temp; <span style="white-space:pre"> </span>unsigned long netmask; //子网掩码
1.查找本机网卡,选择网卡,打开网卡,参考上一篇的解释,这里直接上代码
//
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
cout << "Error in pcap_findalldevs: " << errbuf << endl;;
exit(1);
}
d = alldevs;
if ((adhandle = pcap_open_live(d->name, 65536, 1, 1000, errbuf)) == NULL)
{
/*打开失败*/
cout << "打开失败." << d->name << "不被winpcap支持" << endl;
/* 释放设备列表 */
pcap_freealldevs(alldevs);
return -1;
}
2.获取子网掩码
pAddr = d->addresses;
netmask = ((struct sockaddr_in*)pAddr->next->netmask)->sin_addr.S_un.S_addr;
3.编译过滤器,只捕获arp包
if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask)<0)
{
printf("\nUnable to compile the packet filter.Check the syntax.\n");
pcap_freealldevs(alldevs);
return -1;
}
4.设置过滤器
if (pcap_setfilter(adhandle, &fcode)<0)
{
printf("\nError setting the filter.\n");
pcap_freealldevs(alldevs);
return -1;
}
5接收并解析收到的包,这里演示的是怎么接收和解析里面的信息,当我们需要实现arp扫描的时候,只需要将这些信息拿来和我们的源、目的、操作类型(arp应答的option为512,实际为2,因为option占2字节,网络字节序和本机是反的,即2在本机是0x0002,但网络上传过来是高字节和低字节是反的,这就解释了,为什么我们在构造数据包的时候,超过一字节(像short)就需要htons来转换,所以传过来的是0x0200,就是512)
while ((result = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0)
{
//循环解析ARP数据包
if (result == 0)//返回0表示超时
{
cout << "未接收到arp数据包,该IP可能不处于活动状态" << endl;
continue;
}
arp_packet* arph = (arp_packet *)pkt_data;
if (arph->arp.sour_ip==inet_addr("192.168.218.128")&&arph->arp.dest_ip==inet_addr("192.168.218.1"))
{
temp.S_un.S_addr = arph->arp.sour_ip;
cout << "源IP:" << inet_ntoa(temp) << endl;
temp.S_un.S_addr = arph->arp.dest_ip;
cout << "目的IP:" << inet_ntoa(temp) << endl;
printf_s("源MAC:%.2x-%.2x - %.2x -%.2x -%.2x -%.2x\n", arph->arp.sour_addr[0], arph->arp.sour_addr[1],
arph->arp.sour_addr[2], arph->arp.sour_addr[3], arph->arp.sour_addr[4], arph->arp.sour_addr[5]);
printf_s("目的MAC:%.2x-%.2x - %.2x -%.2x -%.2x -%.2x\n", arph->arp.dest_addr[0], arph->arp.dest_addr[1],
arph->arp.dest_addr[2], arph->arp.dest_addr[3], arph->arp.dest_addr[4], arph->arp.dest_addr[5]);
cout << "包类型:" << arph->arp.option << endl;
}
}
至此我们就可以实现arp扫描了