我阅读了许多文章,发现如何使用套接字(AF_INET,SOCK_RAW,IPPROTO_RAW)基于IP发送自定义数据包。但是我想从以太网头开始发送完全自定义的数据包。如果无法形成以太网头,则导致ARP不基于IP,则无法发送ARP数据包。请帮忙! 附言我在Windows 7而非Linux上:(
答案 0 :(得分:0)
在python中,最简单的方法是使用跨平台的Scapy库。众所周知
您可以嗅探,发送...。很多数据包,添加自己的协议,使用现有的协议...并且它几乎可以在所有平台上工作。 (在Windows上,它使用Npcap / Winpcap)
然后您可以使用来构建ARP数据包
from scapy.all import *
pkt = ARP()
pkt.show()
sendp(Ether(dst=..., src=...)/pkt)
哪个会创建此类数据包
###[ ARP ]###
hwtype= 0x1
ptype= 0x800
hwlen= 6
plen= 4
op= who-has
hwsrc= 00:50:56:00:1e:3d
psrc= 212.83.148.19
hwdst= 00:00:00:00:00:00
pdst= 0.0.0.0
要构建数据包,请使用/运算符
ether = Ether()
ether.src = “00:00:00:00:00:00”
ether.dst = “ff:ff:ff:ff:ff:ff”
arp = ARP()
[edit arp.psrc, arp.pdst, arp.hwsrc, arp.hwdst]
packet = ether/arp
sendp(packet) # sens packet on layer 2
答案 1 :(得分:-1)
当然,没有跨平台的方法可以完成您想要的事情。
Python只是将这些值传递给基础C API。因此,在具有包括packet
接口的完整BSD套接字API的平台上,您可以仅使用AF_PACKET
和其他适当的标志。 (我认为您希望使用ETH_P_ALL
或ETH_P_802_2
而不是IPPROTO_RAW
,或者您可能想要SOCK_DGRAM
…,无论如何,请阅读平台的man packet
并弄清楚在Linux上,至少这些标志中的大多数应在SOCKET
模块上可用;具体取决于您的实际需要。在其他Unix上,它们通常不会被拾取,因此您必须在系统头文件中手动查找它们,并在代码中使用硬编码的常量整数。
不幸的是,如果您使用的是Windows,则此操作无济于事。尽管WinSock具有他们称为TCP/IP Raw Sockets的功能,可以通过SOCK_RAW
访问,并且最新版本的Python确实暴露了这一点,但这只是对实际BSD套接字实现可以做的一小部分的模仿,并且没有这样做。 t提供任何低于IP级别的方法(因此功能名称)。
Microsoft对此的解决方案是,您将使用DDK编写一个TDI提供程序,该提供程序将要公开的任何协议作为另一个WinSock协议来实现,然后您的应用程序级代码可以使用相同的协议它使用的方式,例如TCP。从上面的链接文档来看,这似乎已经过时了,但是替换似乎是相同的想法,但是使用不同的首字母缩写词(并且可能使用了不同的API)。
另一方面,我很确定Windows已经附带了ARP,ICMP协议以及用户模式工具所需的任何其他协议(因为它们显然不能围绕原始数据包编写)。我只是不确定如何访问它们。
据我所知,通常的替代方法是使用WinPcap。
虽然最初将其设计为数据包捕获库,但它还实现了完整的链接级套接字接口,可用于发送和接收原始帧。
并且有Python包装器,例如WinPcapy。
因此,只要您可以要求安装WinPcap驱动程序,就可以在Windows中使用Python编写ARP代码等。这与在Unix上做的只是不同。
实际上,WinPcapY主页上的示例之一“轻松发送数据包”应该可以帮助您入门:
from winpcapy import WinPcapUtils
# Build a packet buffer
# This example-code is built for tutorial purposes, for actual packet crafting use modules like dpkt
arp_request_hex_template = "%(dst_mac)s%(src_mac)s08060001080006040001" \
"%(sender_mac)s%(sender_ip)s%(target_mac)s%(target_ip)s" + "00" * 18
packet = arp_request_hex_template % {
"dst_mac": "aa"*6,
"src_mac": "bb"*6,
"sender_mac": "bb"*6,
"target_mac": "cc"*6,
# 192.168.0.1
"sender_ip": "c0a80001",
# 192.168.0.2
"target_ip": "c0a80002"
}
# Send the packet (ethernet frame with an arp request) on the interface
WinPcapUtils.send_packet("*Ethernet*", packet.decode("hex"))