Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending raw data in Scapy does not work correctly

Tags:

scapy

I use Scapy to create an initial OpenVPN packet and send it to OpenVPN server (acting as a client). OpenVPN part of the packet I'm just reusing from old captured connection, but its irrelevant here.

Thing is, I add a payload of 42bytes but for some reason when I capture packet with Wireshark, I can see 84bytes of OpenVPN stuff. Last half of that is correct payload I sent, but I can't figure out what is the first half. All other layers (Ethernet, IP, UDP) have correct size.

#!/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)

I made an image. Here you can see green stuff is correct - first part is IP and UDP layers, and 2nd green part is my OpenVPN payload, but I don't understand what is the red part.

enter image description here

Edit: If I don't send that Raw payload I still get those 42 bytes for some reason.

like image 257
Tomas Avatar asked Oct 13 '25 10:10

Tomas


1 Answers

You've created an ordinary UDP datagram socket:

mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

This socket manages the ethernet, IP & UDP layers by itself, with guidance from the user through various auxiliary methods and arguments, such as the connect method you've in fact used in your code snippet:

mysocket.connect(('192.168.138.129', 1194))

Its various send methods, even when encapsulated as part of a scapy's StreamSocket object, are expecting to receive as their "data-to-send" argument just the application payload layered above the UDP layer.
However, you're passing on to it the entire protocol stack payload, i.e. the ethernet, IP & UDP headers, which is misinterpreted to be part of the payload data that you wish to send to the other side:

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")

Thus, the data you've marked in red is actually the payload data you've yourself set, before it is followed by the OpenVPN part:

Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)

The first part marked in green, which you've mistakenly identified as created by yourself, is actually generated by the socket object (the kernel, the appropriate driver and the underlying hardware, to be more accurate).


Depending on your needs, you should either instantiate your socket as a raw one:

mysocket = socket(socket.AF_PACKET, socket.SOCK_RAW)

or set the payload accordingly as just the OpenVPN data:

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")
like image 181
Yoel Avatar answered Oct 16 '25 11:10

Yoel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!