在 Scapy 中发送原始数据不能正常工作
Sending raw data in Scapy does not work correctly
我使用 Scapy 创建一个初始 OpenVPN 数据包并将其发送到 OpenVPN 服务器(作为客户端)。数据包的 OpenVPN 部分我只是从旧的捕获连接中重用,但它在这里无关紧要。
事实是,我添加了 42 字节的有效负载,但出于某种原因,当我使用 Wireshark 捕获数据包时,我可以看到 84 字节的 OpenVPN 内容。后半部分是我发送的正确负载,但我不知道前半部分是什么。所有其他层(以太网、IP、UDP)的大小都正确。
#!/usr/bin/env python
import socket
from scapy.all import *
mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
mysocket.connect(('192.168.138.129', 1194))
mystream=StreamSocket(mysocket)
ascapypacket=Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)/Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
etherLoad = len(ascapypacket.getlayer(Ether)) # display size
print etherLoad
ipLoad = len(ascapypacket.getlayer(IP)) # display size
print ipLoad
udpLoad = len(ascapypacket.getlayer(UDP)) # display size
print udpLoad
rawLoad = len(ascapypacket.getlayer(Raw)) # display size
print rawLoad
mystream.send(ascapypacket)
我做了一个图像。在这里你可以看到绿色的东西是正确的 - 第一部分是 IP 和 UDP 层,第二个绿色部分是我的 OpenVPN 有效负载,但我不明白红色部分是什么。
编辑:如果我不发送原始负载,出于某种原因我仍然会收到这 42 个字节。
您已经创建了一个普通的 UDP 数据报套接字:
mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
此套接字自行管理 ethernet、IP 和 UDP 层,有指导来自用户的各种辅助方法和参数,例如您在代码片段中实际使用的 connect
方法:
mysocket.connect(('192.168.138.129', 1194))
它的各种 send
方法,即使封装为 scapy 的 StreamSocket
object 的一部分,也期望收到他们的 "data-to-send" 参数只是位于 UDP 层之上的应用程序负载。
但是,您将整个协议栈有效负载传递给它,即 ethernet、IP & UDP headers,它被误解为您希望发送到另一端的有效负载数据的一部分:
ascapypacket=Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)/Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
因此,您用红色标记的数据实际上是您自己设置的负载数据,然后是OpenVPN部分:
Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)
绿色标记的第一部分,你误认为是自己创建的,实际上是由socket
object(内核,相应的driver和底层硬件,更准确地说)。
根据您的需要,您应该将套接字实例化为原始套接字:
mysocket = socket(socket.AF_PACKET, socket.SOCK_RAW)
或相应地设置负载为 OpenVPN 数据:
ascapypacket=Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
我使用 Scapy 创建一个初始 OpenVPN 数据包并将其发送到 OpenVPN 服务器(作为客户端)。数据包的 OpenVPN 部分我只是从旧的捕获连接中重用,但它在这里无关紧要。
事实是,我添加了 42 字节的有效负载,但出于某种原因,当我使用 Wireshark 捕获数据包时,我可以看到 84 字节的 OpenVPN 内容。后半部分是我发送的正确负载,但我不知道前半部分是什么。所有其他层(以太网、IP、UDP)的大小都正确。
#!/usr/bin/env python
import socket
from scapy.all import *
mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
mysocket.connect(('192.168.138.129', 1194))
mystream=StreamSocket(mysocket)
ascapypacket=Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)/Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
etherLoad = len(ascapypacket.getlayer(Ether)) # display size
print etherLoad
ipLoad = len(ascapypacket.getlayer(IP)) # display size
print ipLoad
udpLoad = len(ascapypacket.getlayer(UDP)) # display size
print udpLoad
rawLoad = len(ascapypacket.getlayer(Raw)) # display size
print rawLoad
mystream.send(ascapypacket)
我做了一个图像。在这里你可以看到绿色的东西是正确的 - 第一部分是 IP 和 UDP 层,第二个绿色部分是我的 OpenVPN 有效负载,但我不明白红色部分是什么。
编辑:如果我不发送原始负载,出于某种原因我仍然会收到这 42 个字节。
您已经创建了一个普通的 UDP 数据报套接字:
mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
此套接字自行管理 ethernet、IP 和 UDP 层,有指导来自用户的各种辅助方法和参数,例如您在代码片段中实际使用的 connect
方法:
mysocket.connect(('192.168.138.129', 1194))
它的各种 send
方法,即使封装为 scapy 的 StreamSocket
object 的一部分,也期望收到他们的 "data-to-send" 参数只是位于 UDP 层之上的应用程序负载。
但是,您将整个协议栈有效负载传递给它,即 ethernet、IP & UDP headers,它被误解为您希望发送到另一端的有效负载数据的一部分:
ascapypacket=Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)/Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
因此,您用红色标记的数据实际上是您自己设置的负载数据,然后是OpenVPN部分:
Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)
绿色标记的第一部分,你误认为是自己创建的,实际上是由socket
object(内核,相应的driver和底层硬件,更准确地说)。
根据您的需要,您应该将套接字实例化为原始套接字:
mysocket = socket(socket.AF_PACKET, socket.SOCK_RAW)
或相应地设置负载为 OpenVPN 数据:
ascapypacket=Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")