使用Scapy创建带自定义字段的ARP报文无法捕获,求解决方法
问题:Scapy自定义ARP字段无法被嗅探识别
我尝试使用Scapy为ARP报文添加名为is_good_packet的自定义字段,自定义了ARPGood类,但嗅探器无法识别该类型的报文。
自定义ARP报文代码:
class ARPGood(Packet): name = "ARPGood" fields_desc = [ ShortEnumField("hwtype", 1, {1: "Ethernet"}), ShortEnumField("ptype", 0x0800, {0x0800: "IPv4"}), ByteField("hwlen", 6), ByteField("plen", 4), ShortEnumField("op", 1, {1: "who-has", 2: "is-at"}), MACField("hwsrc", "00:00:00:00:00:00"), IPField("psrc", "0.0.0.0"), MACField("hwdst", "00:00:00:00:00:00"), IPField("pdst", "0.0.0.0"), BitField("is_good_packet", 0, 1) ]
嗅探器代码:
import scapy.all as sp from ARPSENDER import ARPGood def sniff(interface): sp.sniff(iface=interface, filter="inbound or outbound", store=False, prn=process_packet) def process_packet(packet): print(packet.summary(), packet.show()) if packet.haslayer(ARPGood): print(f"\n\n\n FOUND IT {packet.is_good_packet} \n\n\n") sniff("eth0")
原本以为嗅探器能捕获到该报文,但没有得到任何结果,想知道是否有其他方法可以为ARP报文添加自定义字段?
解决方案
核心原因
- 自定义的
ARPGood是独立的Packet类,Scapy默认会用原生ARP类解析以太网类型为0x0806的报文,不会自动映射到你的自定义类。 - 标准ARP报文结构中没有
is_good_packet字段,直接发送ARPGood报文时,额外字段会被视为ARP的负载而非头部,原生ARP解析会忽略这部分数据。
方法1:扩展Scapy原生ARP类
直接继承Scapy的ARP类添加自定义字段,既保留标准ARP的解析逻辑,又能包含自定义字段:
from scapy.layers.l2 import ARP from scapy.fields import BitField # 扩展原生ARP类,追加自定义字段 class ARPGood(ARP): fields_desc = ARP.fields_desc + [BitField("is_good_packet", 0, 1)]
发送报文示例:
from scapy.all import sendp, Ether # 构造带自定义字段的ARP报文 arp_pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARPGood(op=1, psrc="192.168.1.100", pdst="192.168.1.1", is_good_packet=1) sendp(arp_pkt, iface="eth0")
嗅探逻辑调整:
import scapy.all as sp from ARPSENDER import ARPGood def process_packet(packet): if packet.haslayer(ARP): # 将原生ARP数据重新解析为ARPGood类 arp_good = ARPGood(packet[ARP].build()) if hasattr(arp_good, "is_good_packet"): print(f"\n\n\n FOUND IT {arp_good.is_good_packet} \n\n\n") def sniff(interface): sp.sniff(iface=interface, filter="arp", store=False, prn=process_packet) sniff("eth0")
方法2:绑定自定义类到ARP以太网类型
通过bind_layers将自定义ARPGood类绑定到以太网类型0x0806(ARP的类型码),强制Scapy用你的类解析ARP报文:
from scapy.layers.l2 import Ether from scapy.packet import bind_layers # 绑定Ethernet(type=0x0806)到ARPGood bind_layers(Ether, ARPGood, type=0x0806)
注意:此方法会覆盖Scapy默认的ARP绑定,所有ARP报文都会用ARPGood解析,需确保你的类字段与标准ARP完全一致(即字段定义匹配原生ARP后再追加自定义字段)。
方法3:将自定义字段作为ARP负载
如果不需要把字段作为ARP头部的一部分,可以将自定义字段放在ARP报文的负载中:
发送示例:
arp_pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=1, psrc="192.168.1.100", pdst="192.168.1.1") / b"\x01" # 用1字节表示is_good_packet sendp(arp_pkt, iface="eth0")
嗅探逻辑:
def process_packet(packet): if packet.haslayer(ARP) and packet[ARP].payload: # 读取负载的第一个字节作为is_good_packet值 is_good = ord(packet[ARP].payload[:1]) & 0x01 print(f"\n\n\n FOUND IT {is_good} \n\n\n")
内容的提问来源于stack exchange,提问作者namnam
相关产品推荐
相关产品推荐

