ARP简介

本文详细介绍了ARP协议的工作原理及其在网络通信中的作用。通过实例说明了如何填充ARP数据包,并提供了发送ARP包的编程实现方法。

来源:http://blog.chinaunix.net/u/8780/showart.php?id=147506

 

一.    关于 ARP 协议的基础知识

 

1 ARP 的工作原理

以太网设备比如网卡都有全球唯一的 MAC 地址,MAC地址是网卡的物理地址,它由48位二进制数表示。其中前面24位表示网络厂商标识符,是由生产网卡的厂商向IEEE申请的厂商地址。后24位表示序号,由厂商自行分配。每个不同的网络厂商会有不同的厂商标识符,而每个厂商所生产出来的网卡都是依序号不断变化的。 网卡等是以 MAC 地址来传输以太网数据包的(它们识别不了 IP 包中的 IP 地址),所以在以太网中进行 IP 通信的时候就需要一个协议来建立 IP 地址与 MAC 地址的对应关系,以使 IP 数据包能发到一个确定的地方去。这就是 ARP(Address Resolution Protocol ,地址解析协议 )

 

arp命令 可以查询本地arp缓存:

     arp –a

 

可以发现类似于这样的条目

192.168.45.100    01-23-45-67-89-ab    dynamic

这就是存储的关于IP 地址与MAC 地址的对应关系,dynamic 表示是临时存储在ARP 缓存中的条目,过一段时间就会超时被删除(xp/2003 系统是2 分钟)

 

这样一来,某台电脑要和一台机器(比如192.168..45.1) 通信的时候,它会首先去检查arp 缓存,查找是否有对应的arp 条目,如果没有,它就会给这个以太网络发ARP 请求包 广播询问192.168.45.1 的对应MAC 地址,当然,网络中每台电脑都会收到这个请求包,但是它们发现192.168.45.1 并非自己,就不会做出相应,而192.168.45.1 就会回复一个ARP 应答包 ,告诉它的MAC 地址是xx-xx-xx-xx-xx-xx, 于是发出ARP请求的计算机中的ARP 缓存就会相应刷新, 多了这么一条:

192.168.45.1    xx-xx-xx-xx-xx-xx   dynamic

 

ARP 缓存是为了避免每发一个IP 包都要发个广播查询地址。

    

    网络设备是无法识别ARP 包的真伪的,如果按照ARP 的格式来发送数据包,只要信息有效计算机就会根据包中的内容做相应的反应.

 

 

 

2 ARP 包的格式

 

     从网络底层看来,一个ARP 包是分为两个部分的, 前面一个是物理帧头 ,后面一个才是 ARP

     首先,物理帧头,它将存在于任何一个协议数据包的前面,被称为 DLC Header ,因为这个帧头是在数据链路层构造的,并且其主要内容为收发双方的物理地址,以便硬件设备识别。  

DLC Header

字段

长度(Byte)

默认值

备注

接收方MAC

6

 

广播时, ff-ff-ff-ff-ff-ff

发送方MAC

6

 

 

Ethertype

2

0x0806

0x0806 ARP 帧的类型值

                           1 物理帧头格式

 

 

ARP 帧的格式.  

ARP Frame

字段

长度(Byte)

默认值

备注

硬件类型

2

0x1

以太网类型值

上层协议类型

2

0x0800

上层协议为IP 协议

MAC 地址长度

1

0x6

以太网MAC 地址长度为 6

IP 地址长度

1

0x4

IP 地址长度为 4

操作码

2

 

0x1 表示ARP 请求包,0x2 表示应答包

发送方MAC

6

 

 

发送方IP

4

 

 

接收方MAC

6

 

 

接收方IP

4

 

 

填充数据

18

 

因为物理帧最小长度为64 字节, 前面的42 字节再加上4CRC 校验字节, 还差18 个字节

                             2 ARP 帧格式

 

 

3.ARP 包的填充
 
1) 请求包的填充:
     例某计算机A的MAC地址为 aa-aa-aa-aa-aa-aa,IP为 192.168.0.1
 要查询 192.168.0.99的MAC地址:
 
     首先填充DLC Header;想要知道某个计算机对应的MAC地址是要给全网发送广播的,所以接收方MAC 是 ffffffffffff。 于是DLC Header就填充完成了,如图:

DLC Header
字段
长度(Byte)
填充值
接收方MAC
6
ffffffffffff
发送方MAC
6
aaaaaaaaaaaa
Ethertype
2
0x0806

图3 ARP请求包中 DLC Header内容
 
    接下来是ARP帧,请求包的操作码 是 1;发送 方的MAC 以及IP 应当填入A的相应数据;需要注意的是:这里的接收方IP 填入要查询的那个IP地址,就是192.168.0.99了,而接收方MAC 填入任意值就行,不起作用。于是,如图:
 

                            ARP Frame
字段
长度(Byte)
填充值
硬件类型
2
1
上层协议类型
2
0800
MAC地址长度
1
6
IP地址长度
1
4
操作码
2
1
发送方MAC
6
aaaaaaaaaaaa
发送方IP
4
192.168.0.1
接收方MAC
6
任意值 xxxxxxxxxxxx
接收方IP
4
192.168.0.99
填充数据
18
0

                 图4 ARP请求包中 ARP帧的内容
 
    构造一个这样的包发送出去,如果192.168.0.99存在且是活动的,就会收到一个192.168.0.99发来的一个响应包。可以查看一下ARP缓存列表,将出现类似这样的条 目:            
       192.168.0.99                  bb-bb-bb-bb-bb-bb
 
 
2) 响应包的填充
 
     例如:给192.168.0.99(MAC为 bb-bb-bb-bb-bb-bb)发一个ARP响应包,告诉它本机的MAC地址为 aa-aa-aa-aa-aa-aa,是如此来填充各个字段:
 

DLC Header
字段
长度(Byte)
填充值
接收方MAC
6
bbbbbbbbbbbb
发送方MAC
6
aaaaaaaaaaaa
Ethertype
2
0x0806

              图5 ARP响应包中 DLC Header内容
 

ARP Frame
字段
长度(Byte)
填充值
硬件类型
2
1
上层协议类型
2
0800
MAC地址长度
1
6
IP地址长度
1
4
操作码
2
2
发送方MAC
6
aaaaaaaaaaaa
发送方IP
4
192.168.0.1
接收方MAC
6
bbbbbbbbbbbb
接收方IP
4
192.168.0.99
填充数据
18
0

          图6 ARP响应包中 ARP帧的内容
 
    这样192.168.0.99的ARP缓存中就会多了一条关于192.168.0.1的地址映射。
 
 
 
二.   发送ARP数据包的编程实现
 

1.        填充数据包

 

相应的数据结构:

  // DLC Header

typedef struct tagDLCHeader   {

   unsigned char       DesMAC[6];       /* destination HW addrress */

   unsigned char       SrcMAC[6];       /* source HW addresss */

   unsigned short      Ethertype;       /* ethernet type */

} DLCHEADER, *PDLCHEADER;

 

// ARP Frame

typedef struct tagARPFrame  {

          unsigned short          HW_Type;      /* hardware address */

          unsigned short          Prot_Type;    /* protocol address */

          unsigned char       HW_Addr_Len;      /* length of hardware address */

          unsigned char       Prot_Addr_Len;    /* length of protocol address */

          unsigned short          Opcode;       /* ARP/RARP */

 

          unsigned char       Send_HW_Addr[6];  /* sender hardware address */

          unsigned long       Send_Prot_Addr;   /* sender protocol address */

          unsigned char       Targ_HW_Addr[6];  /* target hardware address */

          unsigned long       Targ_Prot_Addr;   /* target protocol address */

          unsigned char       padding[18];

} ARPFRAME, *PARPFRAME;

 

// ARP Packet = DLC header + ARP Frame

typedef struct tagARPPacket    {

     DLCHEADER     dlcHeader;

     ARPFRAME      arpFrame;

} ARPPACKET, *PARPPACKET;

 

 

2.发送ARP数据包
 
   发送ARP包需要用到winpcap的api。具体步骤及函数详见下面的代码(为了简单,错误处理的地方都被去掉了):
/*******************************************************************
*
*    功能:
*         发送ARP数据包
*
*******************************************************************/
 
void SendARPPacket()
{
     char *AdapterDeviceName =GetCurAdapterName();     // 首先获得获得网卡名字
 
     lpAdapter = PacketOpenAdapter(AdapterDeviceName);     // 根据网卡名字打开网卡
 
     lpPacket = PacketAllocatePacket();               // 给PACKET结构指针分配内存
 
     PacketInitPacket(lpPacket, &ARPPacket, sizeof(ARPPacket)); //初始化PACKET结构指针, 其中的ARPPacket是已经填充的ARP包
 
     PacketSetNumWrites(lpAdapter, 1);         // 每次只发送一个包
 
     PacketSendPacket(lpAdapter, lpPacket, true);
     PacketFreePacket(lpPacket);                 // 释放资源
     PacketCloseAdapter(lpAdapter);
}
 
 
使用ARP 包的tricks
 

在没有安全防护的网络里......

 

1)   如果   发一个请求包广播,其中的 ARP 帧里相关的信息填成这样:

 

发送方MAC

6

随便乱填一个错误的

发送方IP

4

  填上本机的IP

   本机将会显示一个 IP 地址冲突的提示。同样的道理,如果发送方 IP 填成别人的,然后,每隔x 秒发一次 ………

 

2)       假设A、B都靠一个网关 192.168.0.1 上网 ,如果A想让B( 192.168.0.77) 上不了网,就可以伪装成网关给 192.168.0.77 发一个错误的 ARP 响应包 ,如:

发送方MAC

6

随便乱填一个错误的

发送方IP

4

  网关IP 192.168.0.1

接收方就填 192.168.0.77 的相关信息,........

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值