-
Notifications
You must be signed in to change notification settings - Fork 42
Home
code
- sub1
- sub2
- sub1
- sub2
blockquote
.. _intro:
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.
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.
There are two ways to create custom packets: Using keyword constructor or giving raw bytes:
`
ether = Ethernet(src_s="aa:bb:cc:dd:ee:ff")
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:
`
ether.dst_s="aa:bb:cc:dd:ee:ff"
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::
`
ip = IP(src_s="127.0.0.1", opts=[IPOptMulti(type=IP_OPT_TS, len=3, body_bytes=b"\x00\x01")])
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)])
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 "+"::
`
packet = Ethernet() + IP() + TCP()
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
packet.p = 123
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.
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::
`
direction = ether1.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]
if tcp is None: print("no TCP layer found: %s" % tcp)
tcp = ethernet.ip.tcp `
Pypacker supports reading and writing pcap files. The ppcap module is responsible for this task:
` from pypacker import ppcap
pcap = ppcap.Reader(filename="my_packets.pcap")
for ts, buf in pcap: eth = ethernet.Ethernet(buf) print("time (nanoseconds): %d, packet: %s:" % (ts, eth)) pcap.close() `
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
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)
sock_l2.send(ether.bin()) sock_l3.send(ether.bin(), "127.0.0.1")
bts = sock_l2.recv()
pkts = socket_l2.recvp(filter=lambda p: p[IP].src=="127.0.0.1", lowest_layer=Ethernet)
pkts = socket_l2.sr(Ethernet() + IP() + TCP(), lowest_layer=ethernet.Ethernet) print("answer was: %s" % pkts[0])
sock_l2.close() sock_l3.close() `