Skip to content
Michael Stahn edited this page Mar 11, 2018 · 22 revisions

Welcome to the pypacker wiki!

test1

test2

test3

code

  • sub1
  • sub2
  1. sub1
  2. sub2

blockquote


.. _intro:

Pypacker: general introduction

This is a general user-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/examples 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. Another handy feature is the auto-conversion seen in the keyword example: using the format "varname_s" generally all MAC-, IP-address or DNS-names 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 like this..

ether.dst_s="aa:bb:cc:dd:ee:ff"

..this is the same as that

ether.dst= b"\xAA\xBB\xCC\xDD\xEE\xFF" ether.bin() `

Packets can contain simple (static and dynamic) and list style fields (aka TriggerList). Simple ones are like python integers or byte strings. Byte fields have a fixed length except some rare cases (see dns.DNS.Query -> name). Those can be identified via their header format "None". All simple fields can be deactivated by setting the value to "None" and re-activated by setting an appropriate value.

In contrast to this, list style headers can contain Packets, tuples as key/value pairs and bytes. The kind of content for this header depends on the class itself. List style headers can be identified via format "None" and a TriggerList-like value. As static fields already 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 generally expect raw bytes, tuples or Packets itself depending on the implementation. 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() `

Note: Changes to a packet will also change the original packet instances used to build "packet" and vise versa:

` ip1 = IP() tcp1 = TCP() packet = ip1 + tcp1

this will also change "p" in ip1

packet.p = 123

this will also change packet.tcp1.sport

tcp1.sport = 123 `

Note: Auto-update fields like checksums, lengths etc. (eg "sum" in IP) will not be updated until calling bin(). This can be disabled by calling bin(update_auto_fields=False) to set custom values eg for fuzzing purposes.

Analyzing packets

All header values can be retrieved like in the previous examples. To check if a packet matches an 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 or an "OR"-concatination of some::

`

DIR_SAME, DIR_REV, DIR_UNKNOWN or combination of any of them

direction = ether1.direction

check direction explicitly

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. 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() `

Clone this wiki locally