使用Python发送自定义帧/数据包

时间:2018-06-19 18:08:37

标签: python networking

我阅读了许多文章,发现如何使用套接字(AF_INET,SOCK_RAW,IPPROTO_RAW)基于IP发送自定义数据包。但是我想从以太网头开始发送完全自定义的数据包。如果无法形成以太网头,则导致ARP不基于IP,则无法发送ARP数据包。请帮忙! 附言我在Windows 7而非Linux上:(

2 个答案:

答案 0 :(得分:0)

在python中,最简单的方法是使用跨平台的Scapy库。众所周知

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

看看它的Scapy documentation

答案 1 :(得分:-1)

当然,没有跨平台的方法可以完成您想要的事情。

Python只是将这些值传递给基础C API。因此,在具有包括packet接口的完整BSD套接字API的平台上,您可以仅使用AF_PACKET和其他适当的标志。 (我认为您希望使用ETH_P_ALLETH_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"))