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