Crafting packets with Scapy inside Linux Craft a tiny fragme
Crafting packets with Scapy inside Linux. Craft a tiny fragment using Scapy. RFC 791 states that all hosts must accept packets with minimum 68 bytes. This implies that a legitimate fragment can be crafted with 60 bytes of IP header, and 8 bytes of payload resulting in the first 8 bytes of TCP header in the first fragment (aptly named \'tiny fragment\') with the remaining going to the next one. This technique can be implemented to evade firewall rules that checks for connection initation only in the first fragment. Write a python script using Scapy to craft and send an IP fragment with TCP as payload. Send the first 8 bytes of the fragment to the two receiving computers.
8 bytes Payload of fragment 2 8 bytes payload of ICMPv6 Payload of fragment 1 ICMPv6 Header IPv6 net packet payload per fragmentSolution
Write a python script using Scapy to craft and send an IP fragment with TCP as payload.
Scapy, which is a very powerful packet manipulation resource.
Scapy is able to forge and decode packets of several protocols, send and capture them, match requests and replies, and much more. It can be used to handle most network tasks such as scanning, tracerouting, probing, attacks, network discovery, to name a few.
Before we start, make sure you have Scapy in your machine:
$ pip install scapy
You can test the installation firing up Scapy iteratively. For example, these are some useful functions:
$ scapy
Welcome to Scapy (2.2.0)
>>> ls() ---> list protocols/layers
>>> lsc() ---> list commands
>>> conf ---> Display configurations
>>> help(sniff) --> Help for a specific command
A Simple Packet and its Headers
The basic unit in a network communication is the packet.
Scapy builds packets by the layersand then by the fieldsin each layer. Each layer is nested inside the parent layer, represented by the < and > brackets.
Specify the packet\'s source IP and then its destination IP.
This type of information goes in the IP header, which is a layer 3 protocolin the 0SI model:
>>> ip = IP(src=\"192.168.1.114\")
>>> ip = IP(src=\"192.168.1.114\")
>>> ip.dst=\"192.168.1.25\"
>>> pritnt ip
<IP src=192.168.1.114 dst=192.168.1.25 |>
Add a layer 4 protocol, such as TCP or UDP.
To attach this header to the previous, we use the operator / (which is used as a composition operator between layers):
>>> ip/TCP()
<IP frag=0 proto=tcp src=192.168.0.1 dst=192.168.0.2 |<TCP |>>
>>> tcp=TCP(sport=1025, dport=80)
>>> (tcp/ip).show()
###[ TCP ]###
sport= 1025
dport= www
seq= 0
ack= 0
dataofs= None
reserved= 0
flags= S
window= 8192
chksum= None
urgptr= 0
options= {}
###[ IP ]###
version= 4
ihl= None
tos= 0x0
len= None
id= 1
flags=
frag= 0
ttl= 64
(...)
We could even go further, adding layer 2 protocols such as Ethernet or IEEE 802.11:
>>> Ether()/Dot1Q()/IP()
<Ether type=0x8100 |<Dot1Q type=0x800 |<IP |>>>
>>> Dot11()/IP()
<Dot11 |<IP |>>
Sending a Packet: Layer 2 vs. Layer 3
we have a (very simple) packet, we can send it over the wire.
Scapy\'s method send is used to send a single packet to the IP destination. This is a layer 3 operation, so the route is based on the local table:
>>> send(ip/tcp)
.
Sent 1 packets.
In another hand, Scapy\'s method sendp works in the layer 2:
>>> sendp(Ether()/ip/tcp)
.
Sent 1 packets.
Sending an ICMP Packet
Create an ICMP packet with some message:
from scapy.all import *
packet = IP(dst=\"192.168.1.114\")/ICMP()/\"Helloooo!\"
send(packet)
packet.show()
The method show() displays details about the packet. Running the snippet above gives:
$ sudo python send_packet.py
.
Sent 1 packets.
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 192.168.1.114
dst = 192.168.1.114
\\options \\
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
###[ Raw ]###
load = \'Helloooo!\'
To send the same packet over again we can simply add the loop=1 argument within the send method:
send(packet, loop=1)
$ sudo python send_packet.py
Sending & Receiving a Packet
Scapy also has the ability to listen for responses to packets it sends (for example, ICMP ping requests).
As in the send method, Scapy has two types of packet sending & receiving, based on the network layer.
In the layer 3, the methods are sr and sr1. The former returns the answered and unanswered packets, while the last only returns answered and sent packets.
In the layer 2, the methods are srp and srp1. The former returns the answered and unanswered packets, while the last only returns answered and sent packets.
Sending & Receiving a ICMP Packet
For example, we can build an IP packet carrying an ICMP header, which has a default type of echo request, and use the sr() function to transmit the packet and record any response:
from scapy.all import *
output=sr(IP(dst=\'google.com\')/ICMP())
print \'\ Output is:\' + output
result, unanswered=output
print \'\ Result is:\' + result
A TCP Three-way Handshake
Scapy allows you to craft SYN request and match the corresponding returned SYN/ACK segment.
This is how it works:
1) we create an instance of an IP header:
ip = IP(src=\'192.168.1.114\', dst=\'192.168.1.25\')
2) we define a SYN instance of the TCP header:
SYN = TCP(sport=1024, dport=80, flags=\'S\', seq=12345)
3) we send this and capture the server\'s response with sr1:
packet = ip/SYN
SYNACK = sr1(packet)
4) we extract the server\'s TCP sequence number from the server, with SYNACK.seq, and increment it by 1:
ack = SYNACK.seq + 1
5) we create a new instance of the TCP header ACK, which now has the flag A (placing the acknowledgment value for the server there) and we send everything out:
ACK = TCP(sport=1024, dport=80, flags=\'A\', seq=12346, ack=ack)
send(ip/ACK)
6) Finally, we create the segment with no TCP flags and payload and send it:
PUSH = TCP(sport=1024, dport=80, flags=\'\', seq=12346, ack=ack)
data = \"HELLO!\"
send(ip/PUSH/data)




