利用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地址那,这样就没办法跟外部网络进行通信了。

posted on 2009-12-20 15:09  coolzgx  阅读(1300)  评论(0编辑  收藏  举报

导航