利用ARP协议来获取局域网内活动主机的IP跟MAC地址
我们都知道ARP协议可以用来获取已知IP主机的MAC地址,那是不是可以这样说,在同一个 局域网内,我们可以利用ARP回应包来判断局域网内的活动主机?其实是行的,只要局域网内的主机是处于开机状态,那就会对ARP请求包作出回应,通过分析ARP请求包就可以把局域网内所有活动主机的IP地址跟MAC地址提取出来。下面是ARP帧结构和以太网帧结构的定义:
//28字节ARP帧结构
struct arp_head
{
unsigned short hardware_type; //硬件类型
unsigned short protocol_type; //协议类型
unsigned char hardware_add_len; //硬件地址长度
unsigned char protocol_add_len; //协议地址长度
unsigned short operation_field; //操作字段
unsigned char source_mac_add[6]; //源mac地址
unsigned long source_ip_add; //源ip地址
unsigned char dest_mac_add[6]; //目的mac地址
unsigned long dest_ip_add; //目的ip地址
};
//14字节以太网帧结构
struct ethernet_head
{
unsigned char dest_mac_add[6]; //目的mac地址
unsigned char source_mac_add[6]; //源mac地址
unsigned short type; //帧类型
};
//arp最终包结构
struct arp_packet
{
ethernet_head ed;
arp_head ah;
};
这里我们是用winpcap开发包来构造相应的数据包的(利用pcap_sendpacket()函数可以发送构造后的数据包),具体内容可以自己去看下winpcap开发包的开发文档。下面是具体代码:
//获得自己主机的MAC地址
int GetSelfMac()
{
unsigned char sendbuf[42];//arp包结构大小
int i = -1;
int res;
ethernet_head eh;
arp_head ah;
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
memset(eh.dest_mac_add,0xff,6);
memset(eh.source_mac_add,0x0f,6);
memset(ah.source_mac_add,0x0f,6);
memset(ah.dest_mac_add,0x00,6);
eh.type = htons(ETH_ARP);
ah.hardware_type = htons(ARP_HARDWARE);
ah.protocol_type = htons(ETH_IP);
ah.hardware_add_len = 6;
ah.protocol_add_len = 4;
ah.source_ip_add = inet_addr("219.219.71.230"); //随便设的请求方ip
ah.operation_field = htons(ARP_REQUEST);
// unsigned long ip;
// ip = ntohl(inet_addr("192.168.1.101"));
// ah.dest_ip_add =htonl(ip + loop);
ah.dest_ip_add = localIP;//inet_addr("192.168.1.102");
memset(sendbuf,0,sizeof(sendbuf));
memcpy(sendbuf,&eh,sizeof(eh));
memcpy(sendbuf+sizeof(eh),&ah,sizeof(ah));
if(pcap_sendpacket(adhandle,sendbuf,42)==0)
{
// printf("\nPacketSend succeed\n");
}
else
{
printf("PacketSendPacket in getmine Error: %d\n",GetLastError());
return 0;
}
while((res = pcap_next_ex(adhandle,&pkt_header,&pkt_data)) >= 0)
{
if(*(unsigned short *)(pkt_data+12) == htons(ETH_ARP)&&
*(unsigned short*)(pkt_data+20) == htons(ARP_REPLY)&&
*(unsigned long*)(pkt_data+38) == inet_addr("219.219.71.230"))
{
for(i=0; i<6; i++)
{
selfMac[i] = *(unsigned char*)(pkt_data+22+i);
printf("%02x",selfMac[i]);
}
break;
}
}
if(i==6) return 1;
else return 0;
}
//向局域网内的所有可能的IP地址发送ARP请求包线程
void sendArpPacket()
{
unsigned char sendbuf[42];//arp包结构大小
unsigned long ip;
ethernet_head eh;
arp_head ah;
memset(eh.dest_mac_add,0xff,6);
memcpy(eh.source_mac_add,selfMac,6);
memcpy(ah.source_mac_add,selfMac,6);
memset(ah.dest_mac_add,0x00,6);
eh.type = htons(ETH_ARP);
ah.hardware_type = htons(ARP_HARDWARE);
ah.protocol_type = htons(ETH_IP);
ah.hardware_add_len = 6;
ah.protocol_add_len = 4;
ah.operation_field = htons(ARP_REQUEST);
ah.source_ip_add = inet_addr("192.168.1.101");
for (unsigned long i=0; i<HostNum; i++)
{
ip = iptosendh;
ah.dest_ip_add =htonl(ip + i);
memset(sendbuf,0,sizeof(sendbuf));
memcpy(sendbuf,&eh,sizeof(eh));
memcpy(sendbuf+sizeof(eh),&ah,sizeof(ah));
if(pcap_sendpacket(adhandle,sendbuf,42)==0)
{
// printf("\nRequest Packet succeed\n");
}
else
{
printf("Request Packet in getmine Error: %d\n",GetLastError());
}
Sleep(50);
}
Sleep(1000);
flag = TRUE;
}
//接收ARP响应线程,分析数据包后即可获得活动的主机IP地址等
void GetlivePc()
{
//pcap_t *p=(pcap_t *)lpParameter;
int res;
// arp_head ah;
struct pcap_pkthdr *pkt_header;
const u_char * pkt_data;
unsigned char tempMac[6];
while (true)
{
if(flag)
{
printf("扫描完毕,监听线程退出!\n");
//ExitThread(0);
break;
}
if ((res = pcap_next_ex(adhandle,&pkt_header,&pkt_data)) >= 0)
{
// printf("%x",ntohs(*(unsigned short *)(pkt_data+12)));
if(*(unsigned short *)(pkt_data+12) == htons(ETH_ARP))
{
arp_packet *recv = (arp_packet*)pkt_data;
if(*(unsigned short *)(pkt_data+20) == htons(ARP_REPLY))
{
printf("xx\n");
printf("IP地址:%d.%d.%d.%d---------->mac地址:",\
recv->ah.source_ip_add&255, recv->ah.source_ip_add>>8&255,\
recv->ah.source_ip_add>>16&255, recv->ah.source_ip_add>>24&255);
pcGroup[aliveNum].ip = *(unsigned long *)(pkt_data+28);
memcpy(pcGroup[aliveNum].mac,(pkt_data+22),6);
aliveNum++;
for(int i=0; i<6; i++)
{
tempMac[i] = *(unsigned char*)(pkt_data+22+i);
printf("%02x",tempMac[i]);
}
printf("\n");
}
}
}
Sleep(50);
}
}
其实这里可以利用对特定主机发送ARP欺骗包就可以进行ARP攻击,让对方上不了网。具体就是构造一个ARP请求包,包的源IP为所在局域网的网关,源MAC就随便设一个即可,这样被攻击的主机就会把原本到发到网关的数据包发到所设的MAC地址那,这样就没办法跟外部网络进行通信了。