How do I parse a captured packet in python?

James Mertz picture James Mertz · Dec 13, 2013 · Viewed 19.2k times · Source

I have a capture packet raw packet using python's sockets:

s = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))

while True:
    message = s.recv(4096)
    test = []
    print(len(message))
    print(repr(message))

I assumed that the packet returned would be in hex string format, however the printout of print(repr(message)) get me something like this:

b'\x00\x1b\xac\x00Gd\x00\x14\xd1+\x1f\x19\x05\n\x124VxC!UUUU\x00\x00\x00\x00\xcd\xcc\xcc=\xcd\xccL>\x9a\x99\x99>\xcd\xcc\xcc>\x00\x00\x00?\x9a\x......'

which has weird non hex characters like !UUUU or =. What encoding is this, and how do I decode the packet?


I know what the packet looks like ahead of time for now, since I'm the one generating the packets using winpcapy:

from ctypes import *
from winpcapy import *
import zlib
import binascii
import time


from ChanPackets import base, FrMessage, FrTodSync, FrChanConfig, FlChan, RlChan


while (1):

    now = time.time()

    errbuf = create_string_buffer(PCAP_ERRBUF_SIZE)
    fp = pcap_t
    deviceName = b'\\Device\\NPF_{8F5BD2E9-253F-4659-8256-B3BCD882AFBC}'
    fp = pcap_open_live(deviceName, 65536, 1, 1000, errbuf)

    if not bool(fp):
        print ("\nUnable to open the adapter.  %s is not supported by WinPcap\n" % deviceName)
        sys.exit(2)

    # FrMessage is a custom class that creates the packet
    test = FrMessage('00:1b:ac:00:47:64', '00:14:d1:2b:1f:19', 0x12345678, 0x4321, 0x55555555, list(i/10 for i in range(320)))

    # test.get_Raw_Packet() returns a c_bytes array needed for winpcap to send the packet
    if (pcap_sendpacket(fp, test.get_Raw_Packet(), test.packet_size) != 0):
        print ("\nError sending the packet: %s\n" % pcap_geterr(fp))
        sys.exit(3)


    elapsed = time.time() - now
    if elapsed < 0.02 and elapsed > 0:
        time.sleep(0.02 - elapsed)

    pcap_close(fp)

Note: I would like to get an array of hex values representing each byte

Answer

jfs picture jfs · Dec 13, 2013

What encoding is this, and how do I decode the packet?

What you see is the representation of bytes object in Python. As you might have guessed \xab represents byte 0xab (171).

which has weird non hex characters like !UUUU or =

Printable ASCII characters represent themselves i.e., instead of \x55 the representation contains just U.

What you have is a sequence of bytes. How to decode them depends on your application. For example, to decode a data packet that contains Ethernet frame, you could use scapy (Python 2):

>>> b = '\x00\x02\x157\xa2D\x00\xae\xf3R\xaa\xd1\x08\x00E\x00\x00C\x00\x01\x00\x00@\x06x<\xc0\xa8\x05\x15B#\xfa\x97\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\xbb9\x00\x00GET /index.html HTTP/1.0 \n\n'
>>> c = Ether(b)
>>> c.hide_defaults()
>>> c
<Ether  dst=00:02:15:37:a2:44 src=00:ae:f3:52:aa:d1 type=0x800 |
<IP  ihl=5L len=67 frag=0 proto=tcp chksum=0x783c src=192.168.5.21 dst=66.35.250.151 |
<TCP  dataofs=5L chksum=0xbb39 options=[] |
<Raw  load='GET /index.html HTTP/1.0 \n\n' |>>>>

I would like to get an array of hex values representing each byte

You could use binascii.hexlify():

>>> pkt = b'\x00\x1b\xac\x00Gd\x00'
>>> import binascii
>>> binascii.hexlify(pkt)
b'001bac00476400'

or If you want a list with string hex values:

>>> hexvalue = binascii.hexlify(pkt).decode()
>>> [hexvalue[i:i+2] for i in range(0, len(hexvalue), 2)]
['00', '1b', 'ac', '00', '47', '64', '00']