This is a general introduction to pypacker and will cover the topics of creating, analyzing, sending and receiving packets. For a quick dive-into check out the examples in the respective directory.

Needed imports

In order to do anything with pypacker all relevant layers have to be imported. This will look like: from pypacker.layerX import PacketCLass. The following statement will import the ethernet layer:

from pypacker.layer12 import ethernet

Now the Ethernet class contained in the ethernet packet can be used:

ether = ethernet.Ethernet()

The following examples assume all relevant layers and classes have been imported.

Creating custom packets

There are two ways to create custom packets: Using keyword constructor or giving raw bytes:

# keyword consturctor
ether = Ethernet(src_s="aa:bb:cc:dd:ee:ff")
# init using raw bytes
ether = Ethernet(b"\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\x00\x00\xFF\xFF")

Note that only the src address was given using the keyword constructor. Generally all fields left out will be set to default values defined in the correspondig class (see API-documentation). Another handy feature is the auto-conversion seen in the keyword example: using the format “varname_s” generally all MAC and IP-address can be set using normal string representation. Setting values using raw bytes is supported after all e.g. via ‘src=b”\xAA\xBB\xCC\xDD\xEE\xFF’.

After instantiation all header fields can be further changed:

# change destination
ether.dst_s="aa:bb:cc:dd:ee:ff"
ether.bin()

Packets can contain static and dynamic fields. Dynamic ones don’t change in length or order. In contrast to this dynamic fields do have this feature. As static fields allready have been introduced the following examples will clear up handling dynamic ones:

# init packet having dynamic fields
# single value
ip = IP(src_s="127.0.0.1", opts=(IPOptMulti(type=IP_OPT_TS, len=3, body_bytes=b"\x00\x01"))
# multiple values
ip = IP(src_s="127.0.0.1", opts=[IPOptMulti(type=IP_OPT_TS, len=2, body_bytes=b"\x00\x01"), IPOptSingle(type=IP_OPT_EOOL)])
# change dynamic field after instantiation
ip.opts=IPOptSingle(type=IP_OPT_EOOL)

Dynamic fields expect tuples and/or Packets itself depending on the implementation. Most times tuples will be auto-converted to Packets based on the given values at tuple index 0. As dynamic fields are basically python lists itself, all list operations can be applied, too:

del ip.opts[0]
ip.opts.insert(1, IPOptMulti(type=IP_OPT_TS, len=2, body_bytes=b"\x00\x01"))
ip.opts.append(IPOptMulti(type=IP_OPT_TS, len=2, body_bytes=b"\x00\x01"))

Layers can be concatenated using “+”:

# create a new packet composed of concatenated ethernet, ip and tcp layer
packet = Ethernet() + IP() + TCP()
# dump raw bytes of all concatenated layers
packet.bin()

Analyzing packets

All header values can be retrieved like in the previous examples. To check if a packet matches other e.g. to find an answer packet using the direction() method can become in handy. This will return the constants DIR_SAME, DIR_REV or DIR_UNKNOWN:

# check direction
if ether1.is_direction(ether2, DIR_REV):
        print("found answer packet!")

All present layers can be accessed using the index notation:

tcp = ethernet[TCP]
# no TCP layer found
if tcp is None:
        print("no TCP layer found: %s" % tcp)
# this is equivalent to the previous example (assuming TCP is really present)
tcp = ethernet.ip.tcp

Read/write packets from/to file

Pypacker supports reading and writing pcap files (micro and nano second format). The ppcap module is responsible for this task:

from pypacker import ppcap
# open file to be read
pcap = ppcap.Reader(filename="my_packets.pcap")
# cycle through all packets
for ts, buf in pcap:
        eth = ethernet.Ethernet(buf)
        print("time (nanoseconds): %d, packet: %s:" % (ts, eth))
pcap.close()

Send and receive packets

Using the SocketHndl class one can send and receive packets at OSI layer 2 and 3. This supports simple receiving/sending, advanced receiving using filters and send/receiving auto-matching answers. The following examples will clear this up:

from pypacker import psocket

# open sockets using the socket handler
sock_l2 = psocket.SocketHndl(iface_name="eth0", mode=psocket.SocketHndl.MODE_LAYER_2)
sock_l3 = psocket.SocketHndl(iface_name="eth0", mode=psocket.SocketHndl.MODE_LAYER_3)
# send raw bytes
sock_l2.send(ether.bin())
sock_l3.send(ether.bin(), "127.0.0.1")
# receive arbitrary bytes
bts = sock_l2.recv()
# receive packets: raw bytes will be internally used to create packets
pkts = socket_l2.recvp(filter=lambda p: p[IP].src=="127.0.0.1", lowest_layer=Ethernet)
# send packets and auto-match answers: those will be returned
pkts = socket_l2.sr(Ethernet() + IP() + TCP(), lowest_layer=ethernet.Ethernet)
print("answer was: %s" % pkts[0])
# close sockets
sock_l2.close()
sock_l3.close()

Table Of Contents

Previous topic

General introduction

This Page