ARP协议获得局域网内活动主机物理地址程序doc.docx
《ARP协议获得局域网内活动主机物理地址程序doc.docx》由会员分享,可在线阅读,更多相关《ARP协议获得局域网内活动主机物理地址程序doc.docx(25页珍藏版)》请在冰点文库上搜索。
![ARP协议获得局域网内活动主机物理地址程序doc.docx](https://file1.bingdoc.com/fileroot1/2023-5/5/e6283098-c2c6-48cd-9361-3fceccf9dab2/e6283098-c2c6-48cd-9361-3fceccf9dab21.gif)
ARP协议获得局域网内活动主机物理地址程序doc
<ARP协议获得局域网内活动主机物理地址程序>
项目设计报告
1.需求分析
实验目的:
使用ARP发现局域网内活动主机,自行构造、发送ARP请求数据帧,加深对ARP协议的了解。
实验任务:
(1)掌握ARP协议分组结构与协议运作过程;
(2)了解ARP协议获取活动主机MAC地址的方法与软件实现;
(3)在windows/linux平台上构造自定义数据帧,并通过指定网络适配器(网卡)发送的基本方法。
实验环境:
1~2台PC机
操作系统:
WindowsXP
开发环境:
MicrosoftVisualC++6.0,winpcap;可以使用MFC类库
1.1问题重述
(1)梳洗arp数据帧格式和字段含义以及arp协议运作过程
(2)了解Winpcap开发包的使用方法,
(3)掌握windows平台构造自定义数据帧,并通过指定的网络适配器发送的基本过程。
应用现状综述:
Ethernet是目前使用最为广泛的局域网,它基于802.3协议,主机间通过网卡的MAC(MediaAccessControl)地址(即物理地址)进行通信。
Arp协议工作在TCP/IP协议的第二层(数据链路层)。
用于将IP地址转换为网卡物理地址(NIC的MAC地址,媒体访问控制地址)。
无论是任何高层协议的通信,最终都将转换为数据链路层的MAC地址来通信。
所以说,ARP协议是保证网络通信的基础协议。
ARP攻击就是通过伪造IP地址和MAC地址实现ARP欺骗,能够在网络中产生大量的ARP通信量使网络阻塞,攻击者只要持续不断的发出伪造的ARP响应包就能更改目标主机ARP缓存中的IP-MAC条目,造成网络中断或中间人攻击。
2概要设计
2.1原理概述
1课程设计中涉及的网络基本理论简介:
(1)在网际协议中定义的是因特网的IP地址,但在实际进行通信时,物理层不能识别IP地址只能识别物理地址。
因此,需在IP地址与物理地址之间建立映射关系,地址之间的这种映射称为地址解析。
(2)以太网网络中的物理地址即网卡的序列号。
IEEE规定网卡序列号为6个字节(48位),前三个字节为厂商代号,由于厂商向IEEE注册登记申请,后3个字节为网卡的流水号。
(3)地址解析包括从IP地址到物理地址的映射和从物理地址到IP地址的映射。
TCP/IP协议组提供了两个映射协议:
地址解析协议ARP和逆向地址解析协议RARP。
ARP用于从IP地址到物理地址的映射,RARP用于从物理地址到IP地址的映射。
(4)地址解析协议的ARP的工作原理:
假定在一个物理网络上,A(源主机)要与D(目的主机)进行通信,但是不知道D的物理地址。
A利用ARP协议工作的过程如下:
A广播一个ARP请求报文,请求IP地址为IPD的主机回答其物理地址。
网上所有主机都能收到该ARP请求,并将本机IP地址与请求的IP地址比较,D主机识别出自己的地址IPD,并作出回应,通报自己的物理地址。
A收到这个ARP回应包后,就可以与D进行通信。
为了提高效率,ARP协议使用了高速缓存技术。
在每台使用ARP的主机中,都保留了一个专用的内存区,一收到ARP应答,主机就将获得的IP地址和物理地址存入缓存。
以后每次要发送报文时,首先到缓存中查找有无相应的项,若找不到,再利用ARP进行地址解析。
由于多数网络通信都要连续发送多个报文,所以高速缓存大大提高ARP的效率。
在ARP请求报文中还放入源主机的“IP地址——物理地址”的地址对,源主机在广播ARP请求时,网络上所有主机都可以知道该源主机的“IP地址——物理地址”的地址对并将其存入自己的缓存。
在新主机入网时,令其主动广播其地址映射,以减少其他主机进行ARP请求。
(5)网卡具有如下的几种工作模式:
广播模式(BroadCastModel):
它的物理地址(MAC)地址是0Xffffff的帧为广播帧,工作在广播模式的网卡接收广播帧。
多播传送(MultiCastModel):
多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。
但是,如果将网卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员。
直接模式(DirectModel):
工作在直接模式下的网卡只接收目地址是自己Mac地址的帧。
混杂模式(PromiscuousModel):
工作在混杂模式下的网卡接收所有的流过网卡的帧,信包捕获程序就是在这种模式下运行的。
(6)ARP帧的数据结构表达方式:
以太网帧头中的前两个字段是以太网的目的地址和源地址。
目的地址为全1时为广播地址。
两个字节长的以太网帧类型表示后面数据的类型。
对于ARP请求或应答来说,该字段的值为0X0806.
硬件类型字段:
指明了发送方想知道的硬件地址的类型,以太网的值为1;
协议类型字段:
表示要映射的协议地址类型,IP为0X0800;
硬件地址长度和协议地址长度:
指明了硬件地址和高层协议地址的长度,这样ARP帧就可以在任意硬件和任意协议的网络中使用。
对于以太网上IP地址的ARP请求或应答来说,它们的值分别为6和4;
操作字段:
用来表示这个报文的类型,ARP请求为1,ARP响应为2,RARP请求为3,RARP响应为4;
发送端的以太网地址:
源主机硬件地址,6个字节;
发送端IP地址:
发送端的协议地址(IP地址),4个字节;
目的以太网地址:
目的端硬件地址,6个字节;
目的IP地址:
目的端的协议地址(IP地址),4个字节。
2.2主要问题
1.ARP相关数据帧结构
2.ARP协议工作原理
3.程序的流程
4.Winpcap开发包的使用方法
5.Windows平台构造自定义数据帧,并通过指定网络适配器发送的方法。
解决思路:
(1).先查找资料,深入掌握ARP的相关数据帧结构,工作原理。
并且对要编程的ARP程序的流程进行熟悉。
(2).查阅资料,掌握Winpcap开发包的使用方法。
(3).查阅资料,掌握通过指定网络适配器发送数据帧的方法。
实现预期目标的可行性分析:
ARP协议工作在TCP/IP的第二层,用于将IP地址转换为网卡的物理地址。
通过一定时间的学习,熟悉ARP协议和Winpcap开发包使用方法,并且在老师的细心指导下,本课题中遇见的问题可以迎刃而解。
顺利完成程序的开发。
本论文主要通过对ARP协议的帧结构,ARP原理,工作流程等的分析来完成获取局域网内活动主机的物理地址的程序的开发。
第一章主要介绍当前计算机网络,协议的发展。
第二章主要描述网络基础知识和ARP协议的原理,帧结构等相关知识。
第三章主要介绍ARP软件开发时使用的工具,包括VisualC++和Winpcap开发包。
第四章为ARP软件的详细设计,主要包括ARP软件的工作程序的编写,和ARP软件界面的设计。
第五章为总结,对本文进行最终的归纳。
2.3数据结构
structethernet_head
{
unsignedchardest_mac[6];//目标主机MAC地址
unsignedcharsource_mac[6];/源端MAC地址
unsignedshorteh_type;//以太网类型
};
structarp_head
{
unsignedshorthardware_type;//硬件类型:
以太网接口类型为1
unsignedshortprotocol_type;//协议类型:
IP协议类型为0X0800
unsignedcharadd_len;//硬件地址长度:
MAC地址长度为6B
unsignedcharpro_len;//协议地址长度:
IP地址长度为4B
unsignedshortoption;//操作:
ARP请求为1,ARP应答为2
unsignedcharsour_addr[6];/源MAC地址:
发送方的MAC地址
unsignedlongsour_ip;//源IP地址:
发送方的IP地址
unsignedchardest_addr[6];//目的MAC地址:
ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
unsignedlongdest_ip;//目的IP地址:
ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
unsignedcharpadding[18];
};
structarp_packet//最终arp包结构
{
ethernet_headeth;//以太网头部
arp_headarp;//arp数据包头部
};
3详细设计
3.1主要函数说明
/****************
*物理帧头部结构
*****************/
typedefstructethernet_head
{
unsignedchareh_dest_mac[6];//目标主机mac
unsignedchareh_source_mac[6];//本地主机mac
unsignedshorteh_type;//类型
}ethernet_head,*pEthernetHead;
/************
*ARP帧结构
*************/
typedefstructarpHead
{
unsignedshortarp_hardwaretype;//硬件类型(2bit)
unsignedshortarp_protocoltype;//协议类型(2bit)
unsignedchararp_har_len;//硬件地址长度(1bit)
unsignedchararp_pro_len;//协议地址长度(1bit)
unsignedshortarp_option;//操作号(2bit)
unsignedchararp_sour_addr[6];//源硬件地址(6bit)
unsignedlongarp_sour_ip;//源协议地址(4bit)
unsignedchararp_dest_addr[6];//目的硬件地址(6bit)
unsignedlongarp_dest_ip;//目的协议地址(4bit)
unsignedcharpadding[18];//填充数据(18bit)
}arpHead,*pArpHead;
/****************
*IP数据报头结构
*****************/
typedefstructipHead
{
unsignedcharh_lenver;//版本(4bits)+首部长度(4bits)
unsignedchartos;//服务类型(Typeofservice)
unsignedshorttotal_len;//总长(Totallength)
unsignedshortident;//标识(Identification)
unsignedshortfrag_and_flags;//标志位(Flags)(3bits)+段偏移量(Fragmentoffset)(13bits)
unsignedcharttl;//存活时间(Timetolive)
unsignedcharproto;//协议(Protocol)
unsignedshortchecksum;//首部校验和(Headerchecksum)
unsignedintsourceip;//源地址(Sourceaddress)
unsignedintdestip;//目的地址(Destinationaddress)
}ipHead,*PipHead;
#pragmapack(push)
LPADAPTERlpadapter=0;//defineapointertoanADAPTERstructure设备指针
LPPACKETlppacketr,lppackets;//defineapointertoaPACKETstructure包指针
unsignedlongmyip;//本地主机IP
unsignedcharmymac[6]={0};//本地主机mac初始化
charadapterlist[MAX_NUM_ADAPTER][1024];//本地主机网卡列表
intnum=0;//用于发送ARP包时候递增
voidstart()
{
printf("************************************\n");
printf("**\n");
printf("*局域网内活动主机检测*\n");
printf("*07微电子董巍2120070223*\n");
printf("**\n");
printf("************************************\n");
return;
}
/**********************
*获得本地主机的mac地址
***********************/
intgetmine()
{
charsendbuf[1024];
intk;
ethernet_headeth;
arpHeadarp;
for(k=0;k<6;k++)
{
eth.eh_dest_mac[k]=0xff;
eth.eh_source_mac[k]=0x82;
arp.arp_sour_addr[k]=0x82;
arp.arp_dest_addr[k]=0x00;
}
eth.eh_type=htons(ETH_ARP);
arp.arp_hardwaretype=htons(ARP_HARDWARE);
arp.arp_protocoltype=htons(ETH_IP);
arp.arp_har_len=6;
arp.arp_pro_len=4;
arp.arp_option=htons(ARP_REQUEST);
arp.arp_dest_ip=htonl(myip);
arp.arp_sour_ip=inet_addr("112.112.112.112");
memset(sendbuf,0,sizeof(sendbuf));
memcpy(sendbuf,e,sizeof(eth));
memcpy(sendbuf+sizeof(eth),&arp,sizeof(arp));
PacketInitPacket(lppackets,sendbuf,sizeof(eth)+sizeof(arp));
if(PacketSendPacket(lpadapter,lppackets,TRUE)==FALSE)
{
printf("PacketSendPacketingetmineError:
%d\n",GetLastError());
return-1;
}
return0;
}
/****************
*解析数据报
*****************/
voidreceivedata(LPPACKETlppktr)
{
unsignedlongulbytesreceived,off;
unsignedlongj;
char*buf,*pChar,*base;
PipHeadip;
structbpf_hdr*hdr;//数据报头部
structsockaddr_insin;
ethernet_head*eth;
arpHead*arp;
ulbytesreceived=lppktr->ulBytesReceived;
buf=(char*)lppktr->Buffer;
off=0;
//解析数据报
while(off{
if(kbhit())
{
return;
}
hdr=(structbpf_hdr*)(buf+off);
off+=hdr->bh_hdrlen;//数据报头部长度
pChar=(char*)(buf+off);
base=pChar;
off=Packet_WORDALIGN(off+hdr->bh_caplen);
eth=(pEthernetHead)pChar;
arp=(pArpHead)(pChar+sizeof(ethernet_head));
if(eth->eh_type==htons(ETH_IP))
{
ip=(PipHead)(pChar+sizeof(ethernet_head));
}
elseif((eth->eh_type==htons(ETH_ARP))&&(arp->arp_option==htons(ARP_REPLY)))
{
sin.sin_addr.s_addr=arp->arp_sour_ip;
if(sin.sin_addr.s_addr==htonl(myip))
{
memcpy(mymac,eth->eh_source_mac,6);
}
//输出ip地址
printf("\n[IP:
]%.16s[MAC:
]",inet_ntoa(sin.sin_addr));
//输出mac地址
for(j=0;j<5;j++)
{
printf("%.2x-",eth->eh_source_mac[j]);
}
printf("%.2x\n",eth->eh_source_mac[5]);
}
}
return;
}
/************************************************
*将网卡设置为混杂模式,接收所有流过的数据报
************************************************/
DWORDWINAPIsniff(LPVOIDno)
{
charrecvbuf[1024*250];
//设置网卡为混杂模式失败
if(PacketSetHwFilter(lpadapter,NDIS_PACKET_TYPE_PROMISCUOUS)==FALSE)
{
printf("Warning:
Unabletosettheadaptertopromiscuousmode\n");
}
//设置网卡内核缓冲的大小为500*1024失败,返回错误代码
if(PacketSetBuff(lpadapter,500*1024)==FALSE)
{
printf("PacketSetBuffError:
%d\n",GetLastError());
return-1;
}
//设置接收一个数据报后等待的时间为1毫秒失败
if(PacketSetReadTimeout(lpadapter,1)==FALSE)
{
printf("Warning:
Unabletosetthetimeout\n");
}
//接收PACKET指针失败
if((lppacketr=PacketAllocatePacket())==FALSE)
{
printf("PacketAllocatePacketreceiveError!
");
return-1;
}
//初始化一个_PACKET结构
PacketInitPacket(lppacketr,(char*)recvbuf,sizeof(recvbuf));
//当没有按键按下时,从NPF驱动程序读取网络数据报,不成功则退出,读取成功调用解析函数
while(!
kbhit())
{
if(PacketReceivePacket(lpadapter,lppacketr,TRUE)==FALSE)
{
if(GetLastError()==6)
return0;
printf("PacketReceivePacketError:
%d\n",GetLastError());
return-1;
}
receivedata(lppacketr);
}
return0;
}
/**********************************************
*发送ARPRequest数据报,请求获得目的ip的mac地址
***********************************************/
DWORDWINAPItransmit(LPVOIDno)
{
inti;
charsendbuf[1024];//发送缓存
ethernet_headeth;
arpHeadarp;
/***************************************************
*初始化mac地址和ip地址,以本地主机mac地址作为源地址,
*以物理广播地址作为物理帧目的地址,
*ARP帧目的地址置0
****************************************************/
for(i=0;i<6;i++)
{
eth.eh_dest_mac[i]=0xff;
arp.arp_dest_addr[i]=0x00;
}
memcpy(eth.eh_source_mac,mymac,6);
eth.eh_type=htons(ETH_ARP);
arp.arp_hardwaretype=htons(ARP_HARDWARE);//硬件类型0x0001,并将16位的主机字节顺序转化为1