TCP fields with SCAPY - python-3.x

i'm trying to extract some information from networking connections using SCAPY. I need to extract some fields from TCP packet header, in fact Receiver Windows Field (WIN), Retransmission Time Out field (RTO), Max Segment field (MSS) and the Options field (OPT).
I'm a bit lost. I'm using Python3 and SCAPY 2.4.3
Thank you

On a TCP packet you can access the following fields:
like print(packet.options) and so on

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: How to send a whole packet to a specific port on another host?

I have captured a TCP packet using libpcap, and I want to send this whole packet(without modifying it) to a specific port on another host(which has another sniffer listening to that port).
Is there any way I can do this?
Thanks a lot!
You didn't specify which programming language you're using and what you've tried so far.
Change the IP address field to the target IP and the TCP port field to the port you want. Don't forget to update both checksums.
If what you want is TCP forwarding, the Linux kernel already does this for you.
netcat may work in this case although I think you may have to reconstruct the header, have not tried.
How to escape hex values in netcat
The other option is to use iptables to tee the packet to the other sniffer while still catching it in you package analyzer
http://www.bjou.de/blog/2008/05/howto-copyteeclone-network-traffic-using-iptables/
Another option is using a port mirror, this goes by a few differnt names depending on the switch being used but it allows you to set a port on a a switch to be essentially a hub.
I think your best bet if you can't get netcat to work is to use iptables and you can add filters to that even.
I don't know whether you HAVE to use C or not, but even if you do, I would recommend building a prototype with Python/Scapy to begin with.
Using scapy, here are the steps:
Read the pcap file using rdpcap().
Grab the destination IP address and TCP destination port number (pkt.getlayer(IP).dst, pkt.getlayer(TCP).dport) and save it as a string in a format that you want (e.g. payload = "192.168.1.1:80").
Change the packet's destination IP address and the destination port number so that it can be received by the other host that is listening on the particular port.
Add the payload on top of the packet (pkt = pkt / payload)
Send the packet (sendp(pkt, iface='eth0'))
You will have to dissect the packet on the other host to grab the payload. Without knowing exactly what is on top of the TCP layer in the original packet, I can't give you an accurate code for this, but should be relatively straight forward.
This is all quite easy with Python/Scapy but I expect it to be much harder with C, having to manually calculate the correct offsets and checksums and things. Good luck, and I hope this helps.

where is skb_push for udp header in kernel?

I have been looking for the udp packet sending issue for a whole afternoon. It is said sendmsg system call would first comes to the inet_sendmsg, and then udp_sendmsg, then udp_push_pending_frames, in this function, UDP header is filled in before ip_push_pending_frames. However, according to http://vger.kernel.org/~davem/skb_data.html, UDP layer should have a pure user data as data in skb, and it skb_push to get room for UDP header. I just couldn't find it.
Anyone can offer some clue?
Thanks!
You will find skb_push in include/linux/skbuff.h in the kernel source - it's an inline function so it is in a header file rather than a normal source file.

Order Of Things

I have a sniffer in C++ where I'm getting the Source IP, Destination IP, Control Bit, and Sequence number. I am also getting the IP header and then the TCP info. I want to get the content type of the packets. Do I need to reassemble the packets to do that? Or can I use http request and respond to get the content type of the packets. Any help is appreciated, thank you!
There is no "content type". TCP will only provide an octet stream for the layer above TCP to interpret. If you are sniffing HTTP over TCP, you will have to assemble the packets, and parse the HTTP yourself.
Have you considered using Wireshark?
Update
By assembling the TCP packets into the octet stream, you basically append the payload of the TCP packets into one big byte array. Make sure you pay attention to the sequence number of the TCP packets, because the packets may arrive out of order.
Parsing the HTTP content is much trickier. The first headers are always in ASCII. They specify the content type and content length. It's the content type part that is tricky. Stuff may be encoded in a variety of encoding techniques, and they may be enveloped with yet another encoding technique (zip stream, SSL, etc).
TCP RFC: http://www.faqs.org/rfcs/rfc793.html
HTTP 1.1 RFC: http://www.faqs.org/rfcs/rfc2616.html
It might be a good idea to see how both Wireshark and WinPcap does it. I'm not sure if WinPcap contains filters and decoders for HTTP (basically bringing you the content of the HTTP) or not. At any rate, it might be worth checking out the code.

TCP handshake with SOCK_RAW socket

Ok, I realize this situation is somewhat unusual, but I need to establish a TCP connection (the 3-way handshake) using only raw sockets (in C, in linux) -- i.e. I need to construct the IP headers and TCP headers myself. I'm writing a server (so I have to first respond to the incoming SYN packet), and for whatever reason I can't seem to get it right. Yes, I realize that a SOCK_STREAM will handle this for me, but for reasons I don't want to go into that isn't an option.
The tutorials I've found online on using raw sockets all describe how to build a SYN flooder, but this is somewhat easier than actually establishing a TCP connection, since you don't have to construct a response based on the original packet. I've gotten the SYN flooder examples working, and I can read the incoming SYN packet just fine from the raw socket, but I'm still having trouble creating a valid SYN/ACK response to an incoming SYN from the client.
So, does anyone know a good tutorial on using raw sockets that goes beyond creating a SYN flooder, or does anyone have some code that could do this (using SOCK_RAW, and not SOCK_STREAM)? I would be very grateful.
MarkR is absolutely right -- the problem is that the kernel is sending reset packets in response to the initial packet because it thinks the port is closed. The kernel is beating me to the response and the connection dies. I was using tcpdump to monitor the connection already -- I should have been more observant and noticed that there were TWO replies one of which was a reset that was screwing things up, as well as the response my program created. D'OH!
The solution that seems to work best is to use an iptables rule, as suggested by MarkR, to block the outbound packets. However, there's an easier way to do it than using the mark option, as suggested. I just match whether the reset TCP flag is set. During the course of a normal connection this is unlikely to be needed, and it doesn't really matter to my application if I block all outbound reset packets from the port being used. This effectively blocks the kernel's unwanted response, but not my own packets. If the port my program is listening on is 9999 then the iptables rule looks like this:
iptables -t filter -I OUTPUT -p tcp --sport 9999 --tcp-flags RST RST -j DROP
You want to implement part of a TCP stack in userspace... this is ok, some other apps do this.
One problem you will come across is that the kernel will be sending out (generally negative, unhelpful) replies to incoming packets. This is going to screw up any communication you attempt to initiate.
One way to avoid this is to use an IP address and interface that the kernel does not have its own IP stack using- which is fine but you will need to deal with link-layer stuff (specifically, arp) yourself. That would require a socket lower than IPPROTO_IP, SOCK_RAW - you need a packet socket (I think).
It may also be possible to block the kernel's responses using an iptables rule- but I rather suspect that the rules will apply to your own packets as well somehow, unless you can manage to get them treated differently (perhaps applying a netfilter "mark" to your own packets?)
Read the man pages
socket(7)
ip(7)
packet(7)
Which explain about various options and ioctls which apply to types of sockets.
Of course you'll need a tool like Wireshark to inspect what's going on. You will need several machines to test this, I recommend using vmware (or similar) to reduce the amount of hardware required.
Sorry I can't recommend a specific tutorial.
Good luck.
I realise that this is an old thread, but here's a tutorial that goes beyond the normal SYN flooders: http://www.enderunix.org/docs/en/rawipspoof/
Hope it might be of help to someone.
I can't help you out on any tutorials.
But I can give you some advice on the tools that you could use to assist in debugging.
First off, as bmdhacks has suggested, get yourself a copy of wireshark (or tcpdump - but wireshark is easier to use). Capture a good handshake. Make sure that you save this.
Capture one of your handshakes that fails. Wireshark has quite good packet parsing and error checking, so if there's a straightforward error it will probably tell you.
Next, get yourself a copy of tcpreplay. This should also include a tool called "tcprewrite".
tcprewrite will allow you to split your previously saved capture files into two - one for each side of the handshake.
You can then use tcpreplay to play back one side of the handshake so you have a consistent set of packets to play with.
Then you use wireshark (again) to check your responses.
I don't have a tutorial, but I recently used Wireshark to good effect to debug some raw sockets programming I was doing. If you capture the packets you're sending, wireshark will do a good job of showing you if they're malformed or not. It's useful for comparing to a normal connection too.
There are structures for IP and TCP headers declared in netinet/ip.h & netinet/tcp.h respectively. You may want to look at the other headers in this directory for extra macros & stuff that may be of use.
You send a packet with the SYN flag set and a random sequence number (x). You should receive a SYN+ACK from the other side. This packet will have an acknowledgement number (y) that indicates the next sequence number the other side is expecting to receive as well as another sequence number (z). You send back an ACK packet that has sequence number x+1 and ack number z+1 to complete the connection.
You also need to make sure you calculate appropriate TCP/IP checksums & fill out the remainder of the header for the packets you send. Also, don't forget about things like host & network byte order.
TCP is defined in RFC 793, available here: http://www.faqs.org/rfcs/rfc793.html
Depending on what you're trying to do it may be easier to get existing software to handle the TCP handshaking for you.
One open source IP stack is lwIP (http://savannah.nongnu.org/projects/lwip/) which provides a full tcp/ip stack. It is very possible to get it running in user mode using either SOCK_RAW or pcap.
if you are using raw sockets, if you send using different source mac address to the actual one, linux will ignore the response packet and not send an rst.

Resources