Scapy TCP Handshake - Windows - python

While trying to perform a tcp TWH in scapy I encountered a problem.
When my host receives the syn/ack, the kernel ip/tcp stack aborts the handshake by sending rst.
It happens because the first packet sent (the syn) is transparent to the os due to the raw socket that scapy is using.
In some other questions regarding the same issue the solution was to set up iptables to drop packets with the rst flag.
Does anyone have a solution for windows?
(I prefer not to use the FW unless there is no choice)
Thanks!

That's a common problem, and it is not specific to Windows (or Scapy, for that matters - you can face similar issues with Masscan, for example).
You have totally understood and describe it: the problem lies in the IP address being "shared" between Scapy and your host's IP stack.
You have two options:
Use a firewall to prevent your host from getting the SYN/ACK packet (Scapy will get it anyway) or to prevent your host from sending a RST packet.
Use a different IP address with Scapy. This is a bit more difficult because it requires some kind of ARP proxy (or a Scapy script) to answer ARP request for the IP address you will use with Scapy.
Hope this helps, happy hacking!

Related

Scapy sniff() doesn't seem to capture TCP packets, only shows ethernet frames

I have tcpdump and scapy running sniff() on the same interface. There is a scp file transfer happening.
tcpdump: I see the tcp packets with the seq and acks going over.
scapy sniff() returned list: All I see in each packet summary() is (MAC addr1 ) > (Mac addr 2) (0x800) / Raw. Even in the packet .show(), all I see is a link layer stuff with "## [ Ethernet ] ##", src and dst.
I ran this with a timeout of 30 so I know I would capture the scp transfer of an empty text file so I know I timed it right.
There are definitely TCP packets going over, but none of them are being detected. Is there an issue with Scapy?
Thank you
There is probably a bug that prevents Scapy from processing the ethernet payload.
You can try to set conf.debug_dissector = True to debug the issue.
You can also get the current development version of Scapy (from the repository), since this may be an already fixed bug (we had a bug similar to what you are seeing with Python 3 until very recently).
If the bug still exists after updating to the current development version, please report it!

How to capture the packets that you send in Scapy?

I am sending packets using:
send(IP(dst="192.168.1.114")/fuzz(UDP()/NTP(version=4)), loop=1)
But I am not able to capture these packets in any other nearby machine (including the one with IP 192.168.1.114) which is on the same network. I am using wlan as my interface.
I also tried to sniff and then replay using scapy but I am still not able to capture those packets.
i would first try to capture the traffic on the sender machine with tcpdump while executing your program:
tcpdump -i any udp dst 192.168.1.114
if you can see the traffic leaving the source host it may be that it does not arrive on the target host. UDP packets are the first packets to be dropped by any network device and as it is the nature of UDP it wont get retransmitted. if you are sure the packet leaves the source verify if it arrives at the target:
tcpdump -i any upd dst 192.168.1.114
Another point to check is your firewall settings. It could be either on the source or target system that your firewall is blocking those requests.
I finally resolved this. Here is the checklist I made which might help others when dealing with replaying/fuzzing using scapy.
Check if all IP addresses you are dealing with are alive in the
network (use ping)
Understand the difference between send() (layer 3)and sendp() (layer 2)
If mutating existing packet make sure to
remove the checksum (using 'del') and recalculate the checksum
either using show2() or using str to convert packets to string
and then converting them back to packets
You should use Wireshark, or the sniff function in Scapy and make it pretty print the contents on the screen:
sniff(lambda x:x.show())

DHCP release using scapy

I want to send DHCP release packets to DHCP server on my lan.
I have MAC addresses of the machines for which i want to forge RELEASE packets.
I Googled it, didn't find anything useful. Can someone point me in the right direction?
I have tried sending a DHCP packet having options message-type:release. Basically i was trying to release my own IP. But it didn't work.
sendp(Ether(dst=server_mac)/IP(src=my_ip,dst=server_ip)/UDP(sport=68,dport=67)/BOOTP(chaddr=my_mac)/DHCP(options=[("message-type","release")]))
Thanks for taking a stab at it. There is one important thing to keep in mind with the DHCP release message. When you send the message to the server, it won't actually cause the IP address to be released on your local machine. If you are thinking of creating a demonstration of a DOS or some other attack by using RELEASE, you won't have much luck.
The release message simply tells that DHCP server that the client is relinquishing the network address and cancelling the remaining lease. It is up to the client to stop using the address after it has relinquished it.
In terms of why it might not be working for you, there are a couple of things that come to mind.
The mac address might be incorrect, you didn't include how you set my_mac... you can't simply use a string here. You can use the value obtained from the get_if_raw_hwaddr function.
You are missing the client address and transaction ID in the bootp part of the message.
You are missing the server identifier, and end in the DHCP options. If you used a client identifier to obtain the address, you must use this in the release. The standard dictates this, but not all DHCP servers mandate it.
Here is an example that works for me. You can find out more about DHCP by reading the RFC specification and/or using Wireshark to capture and observe real packets.
from scapy import *
fam,hw = get_if_raw_hwaddr('wlan0')
send(IP(src=my_ip,dst=server_ip) /
UDP(sport=68,dport=67) /
BOOTP(chaddr=hw, ciaddr='192.168.0.101', xid=random.randint(0, 0xFFFFFFFF)) /
DHCP(options=[("message-type","release"), ("server_id", "192.168.0.1"), 'end']))

Unwanted RST TCP packet with Scapy

In order to understand how TCP works, I tried to forge my own TCP SYN/SYN-ACK/ACK (based on the tutorial: http://www.thice.nl/creating-ack-get-packets-with-scapy/ ).
The problem is that whenever my computer recieve the SYN-ACK from the server, it generates a RST packet that stops the connection process.
I tried on a OS X Lion and on a Ubuntu 10.10 Maverick Meerkat, both reset the connection. I found this: http://lkml.indiana.edu/hypermail/linux/net/0404.2/0021.html, I don't know if it is the reason.
Does anyone could tell me what could be the reason? And how to avoid this problem?
Thank you.
The article you cited makes this pretty clear...
Since you are not completing the full TCP handshake your operating system might try to take control and can start sending RST (reset) packets, to avoid this we can use iptables:
iptables -A OUTPUT -p tcp --tcp-flags RST RST -s 192.168.1.20 -j DROP
Essentially, the problem is that scapy runs in user space, and the linux kernel will receive the SYN-ACK first. The kernel will send a RST because it won't have a socket open on the port number in question, before you have a chance to do anything with scapy.
The solution (as the blog mentions) is to firewall your kernel from sending a RST packet.
I don't have a non-iptables answer, but one can fix the reset issue. Instead of trying to filter the outgoing reset in the filter table, filter all of the incoming packets from the target in the raw table instead. This prevents the return packets from the target from even being processed by the kernel, though scapy still sees them. I used the following syntax:
iptables -t raw -A PREROUTING -p tcp --dport <source port I use for scapy traffic> -j DROP
This solution does force me to use the same source port for my traffic; feel free to use your own iptables-fu to identify your target's return packets.
The blog article cited in other answers is not entirely correct. It's not only that you aren't completing the three way handshake, it's that the kernel's IP stack has no idea that there's a connection happening. When it receives the SYN-ACK, it sends a RST-ACK because it's unexpected. Receiving first or last really doesn't enter into it. The stack receiving the SYN-ACK is the issue.
Using IPTables to drop outbound RST packets is a common and valid approach, but sometimes you need to send a RST from Scapy. A more involved but very workable approach is to go lower, generating and responding to ARP with a MAC that is different from the host's. This allows you to have the ability to send and receive anything without any interference from the host.
Clearly this is more effort. Personally, I only take this approach (as opposed to the RST dropping approach) when I actually need to send a RST myself.
I found a solution without IPTables in https://widu.tumblr.com/post/43624355124/suppressing-tcp-rst-on-raw-sockets .
To bypass this problem, simply create a standard TCP socket as a server socket and bind to the requested port. Don’t do accept().
Just socket(), bind() on the port and listen(). This relaxes the kernel and let you do the 3-way handshake.

Subsuming the Linux packet processing stack

We occasionally have to debug glitchy Cisco routers that don't handle the TCP Selective Acknowledgment (SACK) options correctly. This causes our TCP sessions to die when routed through an IPTABLES port redirection rule.
To help with the diagnosis, I've been constructing a python-based utility to construct a sequence of packets that can reproduce this error at will, the implementation uses raw sockets to perform this trick. I've got an ICMP ping working nicely but I've run into a snag on the UDP implementation, I can construct, send and receive the packet without problem, the issue that I'm seeing is that Linux doesn't like the UDP packets being sent back from the remote system and always sends an ICMP Destination unreachable packet, even though my python script is able to receive and process the packet without any apparent problems.
My question: Is it possible to subsume the Linux UDP stack to bypass these ICMP error messages when working with RAW sockets?.
Thanks
Are you receiving and processing the packet and only need to suppress the ICMP port-unreachable? If so, maybe just add an entry to the iptables OUTPUT chain to drop it?

Categories