Scapy generating STP(Spanning Tree Protocol) packets - scapy

I am trying to generate STP packet and to capture it with wireshark.Basically what I do is >>> send(STP()) from Scapy and the result from wireshark is:
53918 2671.938356000 00.00.00 00.00.00 FC 49 [Malformed Packet]
My question is how to configure the STP packet, the result from wireshark to be STP packet not FC.Please help :)

You need to use the sendp() function instead of send(), and you also need to add the Ether() and LLC() layers before STP(). For instance:
sendp(Ether(dst="01:80:c2:00:00:00")/LLC()/STP(), iface=“eth0”)

The send function is used to send packets in layer 3, while STP is a layer 2 protocol:
In [1]: from scapy.all import STP
In [2]: STP
Out[2]: scapy.layers.l2.STP
Therefore, you should use the sendp function.
See scapy's docs for further information:
The send() function will send packets at layer 3. That is to say it will handle routing and layer 2 for you. The sendp() function will work at layer 2. It’s up to you to choose the right interface and the right link layer protocol.
The official API documentation states this as well:
send(pkts, inter=0, loop=0, verbose=None)
Send packets at layer 3, using the conf.L3socket supersocket.
sendp(pkts, inter=0, loop=0, iface=None, iface hint=None, verbose=None)
Send packets at layer 2 using the conf.L2socket supersocket.

Related

How do I decode whether a network packet is SSH or not using python and the library Scapy

I am using Python 3.7 and the Scapy library and I am unable to detect if a TCP packet is SSH or not.
I have tried to find an example, but have not found one that shows how to do this.
from scapy.all import *
self.__Pkts = rdpcap("sample.pcap")
pkt = self.__Pkts[i]
if pkt.haslayer('IP'):
self.__NumIpPkts += 1
has_ssh = self.__Pkts[i]['IP'].getlayer('TCP').getlayer('SSH')
if pkt.haslayer('TCP') or has_ssh:
self.__NumTcpPkts += 1
The code presented is able to detect IP and TCP packets, but it cannot detect SSH packets. I want to detect SSH packets.
It seems like Scapy does not come with a SSH layer implementation out of the box. What you can easily do is check whether the TCP packet is using port 22 and then in those cases assume it is an SSH packet and store the raw layer data.
If you want to do a more elaborate check you will have to implement your own scapy layer or find one on the internet: https://github.com/tintinweb/scapy-ssh/blob/master/src/scapy/layers/ssh.py
I have not tested the implementation provided in the link and I would suggest using it merely as a template for your own implementation while also following https://scapy.readthedocs.io/en/latest/build_dissect.html

Linux (uclinux 2.4.x)

I have one doubt.
Using uclinux 2.4.x. In this linux I have my own adapter code for reading the frames from ingress port.
Have added a debug log at exact place from where reading frames word by word and it is sure that I received all number of frames transmitted by peer.
( at Layer2 I am receiving all frames).
From here onward now invoking "netif_rx" to send all received framer to upper layer (i.e Network layer and Transport Layer).
Doubt : I observe that there are some drop of packets at (Transport Layer)UDP protocol.
How did I confirm: Added a count check at Layer 1 and Layer3(UDP Layer) and both counts are not equal.
that means even if we receiving all framer from layer 1 but when it reaching to UDP in between somewhere drop is happening.
So, Could any one suggest that where exactly the problem could be, How to check if memory is full or skb_alloc is not happening for more packets at UDP layer.
Kindly suggest your opinion, It will be of great help and support.
Please let me know if you need more information.
BR
Karn

How to send multiple packets in scapy

I am aware this has been asked before. However I am unclear on how to construct the command in order to accomplish my task and the previous question was never marked as answered. I need to send multiple packets with scapy and my use case is to send DNS queries to a remote server server using UDP. This is the command that I need to use:
sr1(IP(dst="192.168.155.128")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.oreilly.com")))
In the above example sr1 means send a packet at layer 3 but there are more function definitions to send packets. See Here. The remaining parts in between the braces is how to assemble a DNS query packet with scapy for an A record.
But what I want to do is send more than one packet in a single command. The previous question had a suggested answer of this:
sendp(p, iface=eth0, inter=1 , count=x )
Where p is your packet or a list of packets and count is the number of times to repeat the send operation.
This is where I am lost. If this is the correct answer, how would I integrate that into my command and what would it look like?
Thanks in advance!
Working solution: In the above example you will need to use a different function definition to send the packets.
Replace sendp with send, (sendp sends at layer2, send uses layer 3, and sr1 is designed to send only one packet) and place " , count=x" in between the last two closing braces. Where x = the number of packets you want to send. Running from the scapy prompt the command and output should look like this:
>>> send(IP(dst="192.168.155.128")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.oreilly.com")), count=100 )
....................................................................... .............................
Sent 100 packets.
>>>
A simple ICMP packet can also be sent can also be constructed. In this example we are sending 100 ICMP packets.
>>> send(IP(dst="192.168.155.128")/ICMP()/"testICMPpacket", count=100 )
....................................................................... .............................
Sent 100 packets.
>>>

Sending raw data in Scapy does not work correctly

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.
Edit: If I don't send that Raw payload I still get those 42 bytes for some reason.
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")

How to sent arp packets to queue from arptables

My aim was to find a way to process(drop,accept,forward and etc.) packets that are from Layer 2 ...
I know that "iptables" in *inux allow us to send packet to "NFQUEUE" for further packet processing ....
but it support layer 3 packets ... which means it does not detect packets that are from Layer 2..
although "arptables" detect packets that are destine for Layer 2, I couldn't find a way to send it to "NFQUEUE"
is there any way that can let us choose whether or not we should accept/drop/continue the layer packets?
Only ebtables has a target (-j arpreply) to generate ARP packets as of this date, though you can filter with either ebtables and arptables. NFQUEUE is also usable from ebtables, and in fact, can be quickly extended for arptables by just adding an entry to it, but so far, arptables has been pretty much a nice program, even more so than ebtables.

Resources