Search code examples
python-2.7layerscapypacket

wrong data type in packet layer (scapy)


I want to reconstruct a packet with scapy. If I compare the original packet with my constructed packet, I see that a few entries in a layer of my packet have the wrong values. I think it comes from unsuitable datatypes of some values like the following one:

If I print stream_id in one string like this

stream_id = "\x00\x22\x97\x04\x06\xba\x00\x00"

the output is unreadable (like wingding symbols).

But if I put stream_id together myself like this

alias = "CB"
stream_id = '\\x' + alias + '\\x' + alias + '\\x' + alias + '\\x' + alias

the printing output is \x9B\x9B\x9B\x9B.

What's the difference between those two notations?

Please help


Solution

  • \x<hex_byte> is a special escape sequence for Python strings denoting a literal byte as a hex digit.

    The first one is essentially writing bytes to your stream_id, e.g.:

    stream_id_1 = "\x00\x22\x97\x04\x06\xba\x00\x00"
    stream_id_2 = chr(0x00) + chr(0x22) + chr(0x97) + chr(0x04) \
                  + chr(0x06) + chr(0xba) + chr(0x00) + chr(0x00)
    
    assert stream_id_1 == stream_id_2  # passes
    

    and if you print out the bytes you get: 0022970406ba0000

    While the second one is writing a string, as if you wrote (using the same data as above):

    stream_id_1 = "\\x00\\x22\\x97\\x04\\x06\\xba\\x00\\x00"
    

    escaping the escape sequence so that the numbers don't get interpreted as bytes, resulting in the following printout: 5c7830305c7832325c7839375c7830345c7830365c7862615c7830305c783030 which is, as you can see, a vastly different structure.

    UPDATE - To build a stream of bytes you can construct them as in the 'manually' built string - by converting your alias to an integer and then using chr() to turn it into a byte char:

    alias = chr(int("CB", 16))
    stream_id = alias + alias + alias + alias  # etc.
    

    But judging by your comment, you just want to get a random byte so don't waste cycles by generating a hex string, then turning it into an integer to finally turn it into a byte char - get a random integer immediately and turn it into a byte char:

    alias = chr(random.randint(0, 255))
    stream_id = alias + alias + alias + alias  # etc.
    

    Or even better, forgo the random module and use os.urandom() instead:

    import os
    
    alias = os.urandom(1)
    stream_id = alias + alias + alias + alias  # etc.
    

    Of course, you can use the same technique to get as many different random bytes as you like.