Introduction To Scapy | Networking in Python

by hash3liZer . 07 October 2018

Introduction To Scapy | Networking in Python

In few of the earlier tutorials, I've used a well-known packet manipulation tool scapy. It's an interactive layering tool that provides all famously known wired and wireless protocols. The protocols can easily be stacked up to form a packet/frame and can be sent at different layers. The best thing so far is you can craft your own protocols, even forged frames.

Power of Scapy?

You've been wondering why would you choose scapy? There are other libraries like dpkt as well. The thing is what you can build with scapy cannot be done with other libraries. It's a complete developing environment that could be used for more than just extracting and sniffing fields of layers. You can create, send, sniff, trace, ping, receive, loop, forge and much more.

Scapy represents raw data in packets in the binary hexadecimal representation which can be easily be decoded like using the binascii library. Well, in simple if I'd want to be good as much, scapy would be my first preference. Let's dig into scapy a bit.

Introduction

The project of scapy is available on GitHub. You can install it using pip:

$ pip install scapy
OR
$ apt install python-scapy

Scapy provides a bit of its own modified (IPython) interpreter where you can test various parts of your code. To launch scapy interpreter:

$ scapy
scapy

Scapy has its modules and layers scattered through submodules and reaching each of them at a sudden is somewhat time-consuming. For the purpose, the scapy has a submodule by the name of all from where all the scapy modules can be imported. Here I am on my normal Python Interpreter:

from scapy.all import *
scapy import

Reading and Writing PCAP/CAP Files:

To read from a captured file like from wireshark or airodump:

pkts = rdpcap( '/path/to/capturefile' )

This will return a list of packets which can be looped and further manipulated. To write a packet:

writer = PcapWriter("filename.pcap", append=False, sync=True)
writer.write( pkts )

The above will write the captured packets to the file named "filename.pcap".

Extracting and Manipulating Fields:

With scapy, most of the time you would be messing with layers upon layers and it's important to study what are the fields in a specific layer, what their current values are, and list of available scapy functions etc etc. Two functions: ls() and lsc() can be used for this purpose.

ls and lsc

In scapy, Packets are formed by loosely placing layer upon another layer like in OSI model. For example, a Deauthentication layer will be placed over a 802.11 layer to form a deauthentication packet. Consider the following example:

_pkt = RadioTap() / Dot11() / Dot11Deauth()
A simple packet

In the above example, a packet is created which have three layers stacked in a sequence. However, this packet is worthless for now because it doesn't now any better where to send the packet. To view complete information of a packet, use .show():

_pkt.show()
_pkt.show()

Values of fields can directly be specified while stacking the packet:

>>> add2, add1 = "34:23:FA:DF:02:12", "FF:FF:FF:FF:FF:FF"
>>> RadioTap() / Dot11(addr1=add1, addr2=add2, addr3=add2) / Dot11Deauth()

The other way around is while you are capturing packets. In that case, you can directly access or modify a field within layer. For the above case:

>>> _pkt[Dot11].addr2 = "34:23:FB:DA:02:12"
>>> _pkt[Dot11Deauth].reason = 7

Verifying and Accessing Layers:

One of important tasks while doing networking is to access a specific part of the packet to verify the packet type. An example would be to distinguish between ARP and 802.11 protocols. An ARP packet would've protocols related to only ARP while 802.11 will have protocols related to 802.11. Two powerful scapy functions hashlayer() and getlayer() are very helpful in this regard. To check whether a layer exists in a packet or not:

_pkt = RadioTap() / Dot11() / Dot11Deauth()
if _pkt.haslayer(Dot11Deauth):
    print "Deauthentication Packet Captured. "

Now, let's make it more precise by telling our user who is the sender and who was the receiver:

add2, add1 = "34:23:FA:DF:02:12", "FF:FF:FF:FF:FF:FF"
_pkt = RadioTap() / Dot11(addr1=add1, addr2=add2, addr3=add2) / Dot11Deauth()
if pkt.haslayer(Dot11Deauth):
    sender = pkt.getlayer( Dot11 ).addr2
    receiver = pkt.getlayer( Dot11 ).addr1
    print "Deauthentication %s > %s" % ( sender, receiver )

The above would print the fields as instructed.

Transmission

The most prominent function of scapy is sending and receiving packets at both layer 2 and layer 3. send() will dispatch packet at layer 3 whilst sendp() would send it at layer 2. Some other famous functions are sr(), srp(), srp1() etc. For example, consider we want to send an ARP frame:

_pkt = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=ip)
(ans, unans) = sr( _pkt, iface="wlan0")

The same could be applied to other receiving functions as well:

_pkt = RadioTap() / Dot11(addr1="ff:ff:ff:ff:ff:ff") / Dot11Deauth()
sendp(_pkt, iface="wlan0mon", count=64)

The above would dispatch 64 Deauthentication frame in air.

Conclusion

Scapy is a lot more functional than other traditional libraries. Further, the packets can be dissect, forged and can easily be sent with a variety of available functions. In scapy, you can't just manipulate layers or fields, you can also forge your own protocols. The stacking of layers, sending/receiving, sniffing makes it a lot more practical. Thus, scapy if properly learned can be very powerful tool in hands of a programmer.