WinPcap权威指南(三):ARP协议
ARP协议在局域网内使用的非常广泛,它的数据包类型分为请求包和答复包。Windows系统内部有一个缓冲区,保存了最近的ARP信息,可以在cmd下使用命令arp -a来显示目前的缓存,或者使用命令arp -d来清除该缓存(Win7下需要以管理员权限运行cmd)。
在局域网内,两台机器之间通信,实际上靠的是网卡的物理地址。比如说,本机的IP是192.168.1.80,现在想往另外一台IP为192.168.1.138的机器发送一个ICMP包,或者发起一个TCP连接,操作系统第一步会先获取目标机器的网卡物理地址,获取的步骤是先在ARP缓存里面查找,如果没有找到,则发送ARP请求包(一般是广播方式,询问这个IP的网卡物理地址是多少,目标机器收到请求包,发现请求的目标IP是自己,则反馈一个ARP回复包)。如果目标IP的网卡物理地址获取失败,则无法通信—因为不管TCP、UDP还是ICMP,这些基于以太网的数据包,都有一个以太网帧头。如果没有目标的网卡物理地址,底层就无法填充目的地结构,也不知道发送给哪个网卡了。
下面我们结合程序来做个实验。先说说如何调用WinPcap发送数据包。WinPcap的发包函数是PacketSendPacket,这里我们封装一个函数来调用它:
| 
 1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
 | 
function  SendPackets(pBuffer: PAnsiChar; dwSize: Cardinal; bFree: Boolean): Boolean;var  pSendPacket: LPPACKET;begin  Result := False;  pSendPacket := PacketAllocatePacket;  if  pSendPacket = nil  then  Exit;  //初始化一个_PACKET结构。  PacketInitPacket(pSendPacket, pBuffer, dwSize);  //发送一个或多个数据报的副本。  if  (PacketSendPacket(g_pAdapter, pSendPacket, 1) = 0) then  begin    PacketFreePacket(pSendPacket);    Exit;  end;  if  bFree then  FreeMem(pBuffer);  PacketFreePacket(pSendPacket);  Result := True;end; | 
我们先把程序里面TAnalysePacketsThread的ProcessUDPPacket(LPUDPPacket(pBuffer));注释掉,只留下ProcessARPPacket函数,用意其实是我们只处理ARP包,暂时不理会其它类型的。然后打开cmd,执行命令arp -d清除缓冲区。然后输入命令”ping 192.168.1.138″,这时候,可以看到我们的程序捕获到两个ARP包:一个是本机发送的ARP请求包,这是一个目标物理地址为FF:FF:FF:FF:FF的广播包,类型是请求包,内容是询问192.168.1.138的物理地址;另外一个就是对方的回复包了。我们再arp -a显示,发现这个IP对应的物理地址已经在缓冲区里面的(不过ICMP包被对方的防火墙拦截了,所以ping没返回)。


然后我们再连接这个IP,这时候,机器不再发送请求包了(因为缓冲区内还有这个记录)。 另外,我们在目标机器用arp -a命令,可以看到该机器也有发送端的物理地址记录了:

回到我们程序的主界面,细心的朋友可能发现网关物理地址是空的。实际上,我们的电脑如果和外网通信,比如说连接微软的站点,操作系统发送数据包的时候,是如何获取微软主机的网卡物理地址呢?答案是获取不到,也无须获取。操作系统组包的时候,目标物理地址会填写网关的物理地址,然后将数据包发送出去。网关路由器收到数据包后,发现目的IP地址不是自己,就将源物理地址改成自己的,目标物理地址改成下一级的路由的物理地址,然后发送出去。下一级路由则同样重复这个过程,直到数据到底最终目的地。
我们先来解决这个界面问题—获取网关的物理地址。方法1是从本机的ARP缓存获取(一般地说,只要连接过外网,缓存肯定有对应的记录),类似cmd下的arp -a命令:
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
 | 
functionBoolean;var  dwSize:Cardinal;  dwRet:Cardinal;  pIpNetTable:  i:Cardinal;begin  ResultFalse;  //从本机ARP表中来查询得到  dwSize0;  dwRetnil,False);  ifthen  GetMem(pIpNetTable,  ifnil   dwRetFalse);  ifthen  begin    FreeMem(pIpNetTable);    Exit;  end;  for0 1  begin    //pIpNetTable^.table[i].dwIndex;         //pIpNetTable^.table[i].dwPhysAddrLen;//物理接口长度    //pIpNetTable^.table[i].bPhysAddr;       //pIpNetTable^.table[i].dwAddr;          //pIpNetTable^.table[i].dwType;          //MIB_IPNET_TYPE_STATIC;    ifthen    begin      CopyMemory(pMAC,6);      FreeMem(pIpNetTable);      ResultTrue;      Exit;    end;  end;  ifnil  begin    FreeMem(pIpNetTable);    //pIpNetTable  end;end; | 
方法2就是发送请求包,调用了iphlpapi.dll里面的SendARP函数:
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
 | 
functionBoolean;var  dwSize:Cardinal;  dwRet:Cardinal;begin  ResultFalse;  dwSize6;  dwRet0,  ifand0)then  begin    ResultTrue;    Exit;  end;end; | 
界面的处理过程:
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
 | 
procedure.ComboBox_GatewayIPsChange(Sender:var  IP:Cardinal;  Mac:begin  Edit_GatewayMac.Clear;  if.Text''   IPPAnsiChar(ComboBox_GatewayIPs.Text));  if then    if then  Edit_GatewayMac.Textend; | 
我们前面已经介绍了WinPcap的发包函数,那么我们还可以使用第三种方法,自己构造arp请求包,函数如下:
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
 | 
functionconstconstAnsiString;Boolean):Boolean;var  ARPPacket:begin  //1、填充TEthernetHeader  CopyMemory(@ARPPacket.EthernetHeader.DestMac,  CopyMemory(@ARPPacket.EthernetHeader.SourceMac,  ARPPacket.EthernetHeader.EthernetType  //2、填充TARPHeader  ARPPacket.ARPHeader.HardwareType  ARPPacket.ARPHeader.ProtocolType  ARPPacket.ARPHeader.HrdAddrlen6;  ARPPacket.ARPHeader.ProAddrLen4;  ifthen.ARPHeader.Operation  else.ARPHeader.Operation  CopyMemory(@ARPPacket.ARPHeader.SenderMAC,  ARPPacket.ARPHeader.SenderIPPAnsiChar(strSourceIP));  CopyMemory(@ARPPacket.ARPHeader.TargetMAC,  ARPPacket.ARPHeader.TargetIPPAnsiChar(strDestIP));  ResultFalse);end; | 
例如,我们需要获取192.168.1.138的物理地址,则这样调用:
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 | 
procedure.Button1Click(Sender:var  DestMac,  strDestIP,AnsiString;begin  FillChar(DestMac,$FF);//广播包  SourceMac.Text));  strSourceIP.Text);  strDestIP'192.168.1.138';  SendARPPacket(DestMac,True);end; | 
然后从程序主界面,或本机的arp -a命令,或目标机器的arp -a命令都可以验证这个过程。现在我们来看看电脑里面这个ARP缓存表是什么时候更新的。实际上,除了上面说的主动请求获取外,只要机器收到ARP包,不管是请求包还是反馈包,它都会添加或更新自己的缓存。修改一下上面的代码,我们广播一条ARP请求包,但是将源IP地址改成一个不存在的IP“192.168.1.111”:
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 | 
procedure.Button1Click(Sender:var  DestMac,  strDestIP,AnsiString;begin  FillChar(DestMac,$FF);//广播包  SourceMac.Text));  strSourceIP'192.168.1.111';//Trim(ComboBox_OwnIPs.Text);  strDestIP'192.168.1.138';  SendARPPacket(DestMac,True);end; | 
在目标机器输入arp -a,发现的确出现了一条对应的记录。也就是说,如果现在在目标机器连接“192.168.1.111”,那么实际上会连接我们的机器。

如果我们把源IP改成跟目标IP一样呢?
| 
 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
 | 
procedure.Button1Click(Sender:var  DestMac,  strDestIP,AnsiString;begin  FillChar(DestMac,$FF);//广播包  SourceMac.Text));  strSourceIP'192.168.1.138';//Trim(ComboBox_OwnIPs.Text);  strDestIP'192.168.1.138';  SendARPPacket(DestMac,True);end; | 
目标机器会出现如下提示框:

        
如果开一个线程重复这个过程,那台机器就无法上网了。
最后我们讲述一下ARP欺骗和路由器。因为局域网内通信是依靠物理地址,而只要机器收到请求或反馈包,都会更新自己的缓存,所以可以利用这个特性,进行ARP欺骗。具体做法就是:欺骗目标电脑,告诉它网关的IP对应的物理地址是自己;欺骗网关,告诉它目标IP的物理地址是自己。也就是开一个线程不断的发送ARP请求或反馈包给这两个苦主,然后目标电脑发往外网的数据,都会发送到你的电脑,你的电脑收到数据包后,检查如果目标IP不是自己,说明应该转发,你就把该数据包的源物理地址改成自己的,目标物理地址改成网关的,然后发送出去(注意:源IP地址不要改变);外网返回数据后,将数据发给你的电脑,你的电脑收到数据包后,检查如果目标IP(这时候,明白为什么前面说源IP地址不要改变了吧?)不是自己,说明应该转发,你就把该数据包的源物理地址改成自己的,目标物理地址改成目标电脑的,然后发送出去。
实际上,这个就是路由器的实现,只不过它是把这个代码写进了芯片里面。另外它不用ARP欺骗,而是你自己将网络连接的网关IP设置成它的。你也可以按照上面的流程,去掉ARP欺骗的过程,仅保留数据转发,然后将局域网另外一台机器的网关设置为你的机器,那么它就需要通过你来上网了。因为现在ARP欺骗不像2003年,到处都是代码,这里就不给出具体的实现,留作大家的课后作业吧。
下一节我们将讲述UDP协议部分,进入初步的数据修改阶段。我们先实现一个应用层的DNS客户端和服务端,再来在驱动层玩玩。
附件下载:
本节代码
WinPcap权威指南(三):ARP协议的更多相关文章
- WinPcap权威指南(一)
		
WinPcap是一个开源的网络抓包模块,顾名思义,它只能工作在Windows下,但本文介绍的知识并不局限于任何操作系统和开发语言,因为网络协议本身是没有这些区别的.阅读本指南之前,请先下载WinPca ...
 - arp协议简单介绍
		
1. 什么是ARP? ARP (Address Resolution Protocol) 是个地址解析协议.最直白的说法是:在IP以太网中,当一个上层协议要发包时,有了该节点的IP地址,ARP就能提供 ...
 - Winpcap网络编程九之Winpcap实战,ARP协议获得MAC表及主机通信
		
大家好,本次我们须要完毕的任务是: 完毕两台主机之间的数据通信(数据链路层) 仿真ARP协议获得网段内主机的MAC表 使用帧完毕两台主机的通信(Hello! I'm -) 声明:本文章的目的是为大家的 ...
 - Android编程权威指南第三版 第32章
		
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/qq_35564145/article/de ...
 - PADSPCB权威指南-第三章 预处理(部分)(原创)
		
PADSPCB权威指南-第三章(部分)豆丁地址:http://www.docin.com/p-707132066.html
 - 图解ARP协议(三)ARP防御篇-如何揪出“内鬼”并“优雅的还手”
		
一.ARP防御概述 通过之前的文章,我们已经了解了ARP攻击的危害,黑客采用ARP软件进行扫描并发送欺骗应答,同处一个局域网的普通用户就可能遭受断网攻击.流量被限.账号被窃的危险.由于攻击门槛非常低, ...
 - 通信原理之IP协议,ARP协议 (三)
		
把这三个协议放到一起学习是因为这三个协议处于同一层,ARP协议用来找到目标主机的Ethernet网卡Mac地址,IP则承载要发送的消息.数据链路层可以从ARP得到数据的传送信息,而从IP得到要传输的数 ...
 - 【笔记】javascript权威指南-第三章-类型,值和变量
		
javascript中的原始类型和对象类型(基本类型和引用类型) //本书是指:javascript权威指南 //以下内容摘记时间为:2013.7.27 计算机程序运行时需要对值(value ...
 - ARP协议(3)ARP编程--winpcap&vs2012配置
		
好.之前说了那么多.最终到了,我们能够操刀的时候了. 在对ARP协议编程前.我们必需要能控制网络适配器(网卡).这个部分就是驱动! "我们要编写网卡驱动?",对,可是,至少我们现阶 ...
 
随机推荐
- SCTF2018-Event easiest web - phpmyadmin
			
6月19日的SCTF的web送分题. 打开链接是一个phpmyadmin的登陆界面,尝试用默认账号:root 密码:root登陆 于是直接进去了,首先看下数据库,除了些初始化的库以外,abc这个库比 ...
 - Nutch源码阅读进程5
			
看nutch的源码仿佛就是一场谍战片,而构成这精彩绝伦的谍战剧情的就是nutch的每一个从inject->generate->fetch->parse->update的环节,首 ...
 - 1038 一元三次方程求解  2001年NOIP全国联赛提高组
			
题目描述 Description 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100 ...
 - Bzoj3677:树形DP
			
首先我们知道这棵树的形态,一眼DP.考虑蓝线的性质,显然蓝线在树上是连接连续三个节点的.这样就有三种情况:连接 一个节点 的 某个孩子->本身->父亲 或者 一个孩子->本身-> ...
 - Bzoj4558:分类讨论 计算几何 组合数学
			
国际惯例的题面: 这题让我爆肝啦......这种计数显然容斥,正好不含任何坏点的我们不会算,但是我们能算至少含零个坏点的,至少含一个坏点的,至少含两个坏点的......所以最终的答案就是(至少含零个坏 ...
 - python基础-UDP、进程、进程池、paramike模块
			
1 基于UDP套接字1.1 介绍 udp是无连接的,是数据报协议,先启动哪端都不会报错 udp服务端 import socket sk = socket() #创建一个服务器的套接字 sk.bind( ...
 - Tesseract ocr 3.02学习记录一
			
光学字符识别(OCR,Optical Character Recognition)是指对文本资料进行扫描,然后对图像文件进行分析处理,获取文字及版面信息的过程.OCR技术非常专业,一般多是印刷.打印行 ...
 - 硬盘img镜像备份工具
			
linux下使用dd,Windows下使用WinImage,不过dd使用的比较多.
 - MikroTik RouterOS网址资源收集
			
routeros|mikrotik|ros|软路由论坛|中国路由网|软件路由|软件路由器|routeros技术论坛|路由论坛 - Powered by Discuz! Mikrotik RB450 ...
 - web压力测试工具(小而精)
			
实际的测试过程中,我们一般都是采用A.B两台机器,一台跑Web服务,另外一台跑ab测试.也有的情况是单机对单机可能测不出结果,那就要采用很多台机器同是跑AB去请求一台机器进行测试,根据多台机器反馈的结 ...