黑客的攻击无外乎就是需要网络中有哪些主机开机,所以第一步当然是需要知道网络存活的主机ip地址,有了ip地址我们才能进行下一步操作,比如扫描端口等。
这篇文章将教您使用arp协议对局域网内主机进行扫描测试,知道有哪些主机存活。
首先,我们得知道arp协议的基本原理。
arp协议解析
ARP(Address Resolution Protocol),即是地址解析协议,其可以实现通过IP地址得知相应的物理地址。实现IP地址到物理地址的映射有两种方式:表格方式和非表格方式。地址解析协议具体说来就是把网络层(IP层,即相当于OSI的第三层)地址解析为数据连接层(MAC层,即相当于OSI的第二层)的MAC地址。
之所以存在ARP,是因为在现行寻址机制中,主机的以太网网卡仅且只能识别MAC地址,而不可以识别IP地址,假若数据帧中不指明主机的MAC 地址,则主机网卡不能识别出该帧是发送给自己的。因此两台主机如果想通信,仅知道对方主机的IP地址还不够,还必须知道对方主机的MAC地址,才能完成访问;网络之间是用IP进行地址寻址,网络之内是用MAC地址进行寻址。
ARP扫描原理
ARP扫描总体设计:ARP分为请求与响应数据包,正常情况下,主机发一个ARP请求包,就会收到一个ARP响应包。利用wincap发送ARP包进行扫描,当有主机存活的时候,会自动发送回应包让本主机知晓它是否存活。当接收到回应包,说明对方主机开机,接收不到对方主机回应包,则说明其处于关机状态。ARP扫描界面见图3.1。
ARP扫描是指利用winpcap冒充网关(又称做协议转换器、网间连接器,在采用不同协议或体系结构的网络之间进行互通的时候,用于提供路由选择、协议转换、数据交换等网络兼容功能设施。)发送ARP包,处于开机状态的电脑会回复一个ARP包,这样就能判断对方主机是否开机。ARP扫描主要是应用在局域网当中,要注意的是网关也会定时的给其他主机发送ARP包,这样可能会影响到扫描的质量。其示意图1.1所示。
在进行ARP扫描的时候,需要用到广播包来发送请求。所谓的广播包是数据包的一种,形象的理解就是在一个网段内所有PC都可以收到的数据包。广播通常是因为以下两个原因使用的:其一是一个应用程序期望在本地网络中找到某个资源,但是该应用程序对该资源的地址没有任何先验知识。其二是某些重要功能,比如路由要求把它们的信息发送到所有可以找到的邻机中。
ARP实现过程
以下为ARP扫描实现过程:
⑴初始化:填写界面信息:
获得主机名字、主机IP、主机MAC、子网掩码、网关IP。
用到的函数分别为:
①GetHostName()//获取主机名字。用gethostbyname(&name)函数获得,将获得的name直接填写在name文本框中;
②GetHostIP()//获取主机IP。用winpcap中的pcap_findalldevs_ex()函数来获得,将获得的IP填写在HostIP的文本框中;
③GetMAC()//获得主机MAC,利用netbios函数来获得,获得的MAC填写在MAC文本框中;
④GetNetMask()//获得子网掩码。用winpcap中的pcap_findalldevs_ex()函数来获得,将获得的NetMask填写在NetMask中文本框中;
⑤GetGateway()//获得网关IP。调用了自己写的DLL来获得,源函数是利用sendARP(::inet_addr(szDesIP),0,(ULONG*)arDestMac,&ulLen)函数向网关发送一个ARP包,然后网关就回应一个包,来解析这个包就可以知道网关的IP了.然后将获得的网关IP放到Gateway文本框中。
⑵ 开始扫描:
①设置一个全局变量来察看是否已启动扫描,如果已经开始扫描了则不做任何处理,如果没开始扫描或者扫描已经结束,则可以进行扫描。
②由于ARP扫描是利用winpcap扫描,所以必须先选择网卡,判断是否选择了网卡。如果选择了网卡就可以进行扫描,如果没选择网卡则弹出警告,告诉用户“没有选择网卡,请在主菜单中的选择网卡”。如果没选择网卡那么在后面所需要调用的监听,发送函数就会出现内存溢出的错误。
③创建一个线程进行输入监听ARP回应包数据,因为担心遗漏监听数据,所以就先进行监听,将数据进行监听,在发送ARP包之前就抓包,这样就不会遗漏数据了。将监听到的数据填写到主窗口中的列表控件中去。
首先、判断选择的网卡是否为合法的,如果合法就可以进行下面的操作,如果不合法就跳出不允许进行操作,并提示错误。
第二、对经过网卡的数据进行过滤设置,这样可以减轻判断的负担,只接收ARP包,利用的函数为pcap_compile() 和pcap_setfilter()。
第三、监听过滤以后的数据pcap_next_ex(),由于接收到的数据是一段字符串,所以还要对其进行分析,将其结构化为ARP报文,这样才能很好的输出和显示信息。
④填写ARP包函数为FillPackey(IP) (注:参数本来是用来传递参数IP的这样可以进行规整化,但是在发送ARP包时修改IP地址也可以做到,所以这里的设计还要修改)
ARP包结构的数据构建:
#pragma pack(push,1)
typedef struct Arp_Package
{ struct ehhdr
{
unsigned char eh_dst[6];
unsigned char eh_src[6];
unsigned short eh_type;
} ARPHEADER;
struct arphdr
{
unsigned short arp_hdr;
unsigned short arp_pro;
unsigned char arp_hln;
unsigned char arp_pln;
unsigned short arp_opt;
unsigned char arp_sha[6];
unsigned long arp_spa;
unsigned char arp_tha[6];
unsigned long arp_tpa;
} ARPHDR;
} ARP_PACKET;
#pragma pack(push)
填写ARP包,设置目的地址的MAC(eh_dst)为 FF-FF-FF-FF-FF-FF//设置为广播地址,让所有的人都能收到。
填写源地址的MAC为本机MAC(eh_src)//在前面的GetMAC函数中已经获得了,在这里可以直接填写进去。
填写帧代码(eh_type)为0x0806, 表示 ARP。
填写ARP数据包的硬件类型(arp_hdr)为:0x0001。
填写协议类型(arp_pro)为:0x0800,type:IP 指定下层协议。
填写硬件地址长度为(arp_hln):6。
填写协议地址长度为(arp_pln):4。
填写操作码(arp_opt)为:1, 表ARP请求包。
填写目的硬件地址(arp_tha),因为请求所以未知,填写全0。
填写发送的MAC, 填写源IP地址(arp_sha)为自己的。
填写目的IP地址(arp_tpa)为将要扫描的,这个是利用传递的参数还填写。
将填写的内容转为char*类型准备发送。利用函数memcpy();
⑤发送填写好的ARP包利用函数pcap_sendpacket(网卡号,要发送的数据),发送数据到网上。等到发送数据结束后等待超时,当超时后认为目的主机没回应,也就没开机。发送完成后提示“发送ARP完毕”。
⑥释放所有的资源,将所有的变量清空或者恢复成原来的初始时的值。这样可以为下一次开始做准备,也避免了由于没释放内存而造成的资源浪费。
⑦等待接收ARP数据报,将接受到的数据报进行分析,对比是否为我们需要的ARP数据报,如果为我们需要接收的回应数据报就把数据包接收,并把其数据报原IP地址记录下来保存在界面中。图3.3为ARP扫描流程图。
源码地址: https://download.csdn.net/download/arv002/12413239
开发软件VC++6.0
调测前记得安装winpcap。