def _decode(self): """Decodes the raw data of this block into its fields""" stream = six.BytesIO(self._raw) self._decoded = struct_decode(self.schema[:1], stream, self.section.endianness) # Now we can get our ``captured_len`` property which is required # to really know how much data we can load self._decoded['packet_data'] = RawBytes(self.captured_len).load( stream, self.section.endianness) del self._raw
def __init__(self, section, **kwargs): self.section = section if "raw" in kwargs: # Since we can't be sure of the packet length without the snap length, # we have to do a bit of work here stream = io.BytesIO(kwargs["raw"]) self._decoded = struct_decode(self.schema[:1], stream, kwargs["endianness"]) # Now we can get our ``captured_len`` property which is required # to really know how much data we can load rb = RawBytes(self.captured_len) self._decoded["packet_data"] = rb.load(stream) else: super(SimplePacket, self).__init__(section, **kwargs)
def __init__(self, **kwargs): if "raw" in kwargs: self._decoded = struct_decode( self.schema, io.BytesIO(kwargs["raw"]), kwargs["endianness"] ) else: self._decoded = {} for key, packed_type, default in self.schema: if key == "options": self._decoded[key] = Options( schema=packed_type.options_schema, data={}, endianness="=" ) if "options" in kwargs: for oky, ovl in kwargs["options"].items(): self.options[oky] = ovl else: try: self._decoded[key] = kwargs[key] except KeyError: self._decoded[key] = default
def test_decode_simple_struct(): schema = [ ('rawbytes', RawBytes(12)), ('int32s', IntField(32, True)), ('int32u', IntField(32, False)), ('int16s', IntField(16, True)), ('int16u', IntField(16, False)), ] stream = io.BytesIO() stream.write('Hello world!') stream.write(struct.pack('>i', -1234)) stream.write(struct.pack('>I', 1234)) stream.write(struct.pack('>h', -789)) stream.write(struct.pack('>H', 789)) stream.seek(0) decoded = struct_decode(schema, stream, '>') assert decoded['rawbytes'] == 'Hello world!' assert decoded['int32s'] == -1234 assert decoded['int32u'] == 1234 assert decoded['int16s'] == -789 assert decoded['int16u'] == 789
def test_decode_simple_struct(): schema = [ ("rawbytes", RawBytes(12), b""), ("int32s", IntField(32, True), 0), ("int32u", IntField(32, False), 0), ("int16s", IntField(16, True), 0), ("int16u", IntField(16, False), 0), ] stream = io.BytesIO() stream.write(b"Hello world!") stream.write(struct.pack(">i", -1234)) stream.write(struct.pack(">I", 1234)) stream.write(struct.pack(">h", -789)) stream.write(struct.pack(">H", 789)) stream.seek(0) decoded = struct_decode(schema, stream, ">") assert decoded["rawbytes"] == b"Hello world!" assert decoded["int32s"] == -1234 assert decoded["int32u"] == 1234 assert decoded["int16s"] == -789 assert decoded["int16u"] == 789
def test_decode_simple_struct(): schema = [ ('rawbytes', RawBytes(12)), ('int32s', IntField(32, True)), ('int32u', IntField(32, False)), ('int16s', IntField(16, True)), ('int16u', IntField(16, False)), ] stream = io.BytesIO() stream.write(b'Hello world!') stream.write(struct.pack('>i', -1234)) stream.write(struct.pack('>I', 1234)) stream.write(struct.pack('>h', -789)) stream.write(struct.pack('>H', 789)) stream.seek(0) decoded = struct_decode(schema, stream, '>') assert decoded['rawbytes'] == b'Hello world!' assert decoded['int32s'] == -1234 assert decoded['int32u'] == 1234 assert decoded['int16s'] == -789 assert decoded['int16u'] == 789
def _decode(self): return struct_decode(self.schema, io.BytesIO(self._raw), endianness=self.section.endianness)
def test_unpack_dummy_packet(): schema = [ ('a_string', RawBytes(8)), ('a_number', IntField(32, False)), ('options', OptionsField([])), ('packet_data', PacketDataField()), ('simple_packet_data', SimplePacketDataField()), ('name_res', ListField(NameResolutionRecordField())), ('another_number', IntField(32, False)), ] # Note: NULLs are for padding! data = io.BytesIO( '\x01\x23\x45\x67\x89\xab\xcd\xef' '\x00\x00\x01\x00' # Options '\x00\x01\x00\x0cHello world!' '\x00\x01\x00\x0fSpam eggs bacon\x00' '\x00\x02\x00\x0fSome other text\x00' '\x00\x00\x00\x00' # Enhanced Packet data '\x00\x00\x00\x12' '\x00\x01\x00\x00' 'These are 18 bytes\x00\x00' # Simple packet data '\x00\x00\x00\x0d' 'Simple packet\x00\x00\x00' # List of name resolution items '\x00\x01' # IPv4 '\x00\x13' # Length: 19bytes '\x0a\x22\x33\x44www.example.com\x00' # 19 bytes (10.34.51.68) '\x00\x01' # IPv4 '\x00\x13' # Length: 19bytes '\xc0\xa8\x14\x01www.example.org\x00' # 19 bytes (192.168.20.1) '\x00\x02' # IPv6 '\x00\x1e' # 30 bytes '\x00\x11\x22\x33\x44\x55\x66\x77' '\x88\x99\xaa\xbb\xcc\xdd\xee\xff' 'v6.example.net\x00\x00' '\x00\x00\x00\x00' # End marker # Another number, to check end '\xaa\xbb\xcc\xdd' ) unpacked = struct_decode(schema, data, endianness='>') assert unpacked['a_string'] == '\x01\x23\x45\x67\x89\xab\xcd\xef' assert unpacked['a_number'] == 0x100 assert isinstance(unpacked['options'], Options) assert len(unpacked['options']) == 2 assert unpacked['options']['opt_comment'] == 'Hello world!' assert unpacked['options'][2] == 'Some other text' assert unpacked['packet_data'] == (0x12, 0x10000, 'These are 18 bytes') assert unpacked['simple_packet_data'] == (13, 'Simple packet') assert unpacked['name_res'] == [ {'address': '\x0a\x22\x33\x44', 'name': 'www.example.com', 'type': 1}, {'address': '\xc0\xa8\x14\x01', 'name': 'www.example.org', 'type': 1}, {'type': 2, 'address': '\x00\x11\x22\x33\x44\x55\x66\x77' '\x88\x99\xaa\xbb\xcc\xdd\xee\xff', 'name': 'v6.example.net'}]
def test_unpack_dummy_packet(): schema = [ ("a_string", RawBytes(8), ""), ("a_number", IntField(32, False), 0), ("options", OptionsField([]), None), ("pb_captured_len", IntField(32, False), 0), ("pb_orig_len", IntField(32, False), 0), ("packet_data", PacketBytes("pb_captured_len"), b""), ("spb_orig_len", IntField(32, False), 0), ("simple_packet_data", PacketBytes("spb_orig_len"), b""), ("name_res", ListField(NameResolutionRecordField()), []), ("another_number", IntField(32, False), 0), ] # Note: NULLs are for padding! data = io.BytesIO( b"\x01\x23\x45\x67\x89\xab\xcd\xef" b"\x00\x00\x01\x00" # Options b"\x00\x01\x00\x0cHello world!" b"\x00\x01\x00\x0fSpam eggs bacon\x00" b"\x00\x02\x00\x0fSome other text\x00" b"\x00\x00\x00\x00" # Enhanced Packet data b"\x00\x00\x00\x12" b"\x00\x01\x00\x00" b"These are 18 bytes\x00\x00" # Simple packet data b"\x00\x00\x00\x0d" b"Simple packet\x00\x00\x00" # List of name resolution items b"\x00\x01" # IPv4 b"\x00\x13" # Length: 19bytes b"\x0a\x22\x33\x44www.example.com\x00" # 19 bytes (10.34.51.68) b"\x00\x01" # IPv4 b"\x00\x13" # Length: 19bytes b"\xc0\xa8\x14\x01www.example.org\x00" # 19 bytes (192.168.20.1) b"\x00\x02" # IPv6 b"\x00\x1e" # 30 bytes b"\x00\x11\x22\x33\x44\x55\x66\x77" b"\x88\x99\xaa\xbb\xcc\xdd\xee\xff" b"v6.example.net\x00\x00" b"\x00\x00\x00\x00" # End marker # Another number, to check end b"\xaa\xbb\xcc\xdd" ) unpacked = struct_decode(schema, data, endianness=">") assert unpacked["a_string"] == b"\x01\x23\x45\x67\x89\xab\xcd\xef" assert unpacked["a_number"] == 0x100 assert isinstance(unpacked["options"], Options) assert len(unpacked["options"]) == 2 assert unpacked["options"]["opt_comment"] == "Hello world!" assert unpacked["options"][2] == b"Some other text" assert unpacked["pb_captured_len"] == 0x12 assert unpacked["pb_orig_len"] == 0x10000 assert unpacked["packet_data"] == b"These are 18 bytes" assert unpacked["spb_orig_len"] == 13 assert unpacked["simple_packet_data"] == b"Simple packet" assert unpacked["name_res"] == [ {"address": "10.34.51.68", "names": ["www.example.com"], "type": 1}, {"address": "192.168.20.1", "names": ["www.example.org"], "type": 1}, { "type": 2, "address": "11:2233:4455:6677:8899:aabb:ccdd:eeff", "names": ["v6.example.net"], }, ]
def test_unpack_dummy_packet(): schema = [ ('a_string', RawBytes(8)), ('a_number', IntField(32, False)), ('options', OptionsField([])), ('packet_data', PacketDataField()), ('simple_packet_data', SimplePacketDataField()), ('name_res', ListField(NameResolutionRecordField())), ('another_number', IntField(32, False)), ] # Note: NULLs are for padding! data = io.BytesIO( b'\x01\x23\x45\x67\x89\xab\xcd\xef' b'\x00\x00\x01\x00' # Options b'\x00\x01\x00\x0cHello world!' b'\x00\x01\x00\x0fSpam eggs bacon\x00' b'\x00\x02\x00\x0fSome other text\x00' b'\x00\x00\x00\x00' # Enhanced Packet data b'\x00\x00\x00\x12' b'\x00\x01\x00\x00' b'These are 18 bytes\x00\x00' # Simple packet data b'\x00\x00\x00\x0d' b'Simple packet\x00\x00\x00' # List of name resolution items b'\x00\x01' # IPv4 b'\x00\x13' # Length: 19bytes b'\x0a\x22\x33\x44www.example.com\x00' # 19 bytes (10.34.51.68) b'\x00\x01' # IPv4 b'\x00\x13' # Length: 19bytes b'\xc0\xa8\x14\x01www.example.org\x00' # 19 bytes (192.168.20.1) b'\x00\x02' # IPv6 b'\x00\x1e' # 30 bytes b'\x00\x11\x22\x33\x44\x55\x66\x77' b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff' b'v6.example.net\x00\x00' b'\x00\x00\x00\x00' # End marker # Another number, to check end b'\xaa\xbb\xcc\xdd' ) unpacked = struct_decode(schema, data, endianness='>') assert unpacked['a_string'] == b'\x01\x23\x45\x67\x89\xab\xcd\xef' assert unpacked['a_number'] == 0x100 assert isinstance(unpacked['options'], Options) assert len(unpacked['options']) == 2 assert unpacked['options']['opt_comment'] == 'Hello world!' assert unpacked['options'][2] == b'Some other text' assert unpacked['packet_data'] == (0x12, 0x10000, b'These are 18 bytes') assert unpacked['simple_packet_data'] == (13, b'Simple packet') assert unpacked['name_res'] == [ {'address': b'\x0a\x22\x33\x44', 'name': b'www.example.com', 'type': 1}, {'address': b'\xc0\xa8\x14\x01', 'name': b'www.example.org', 'type': 1}, {'type': 2, 'address': b'\x00\x11\x22\x33\x44\x55\x66\x77' b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff', 'name': b'v6.example.net'}]
def test_unpack_dummy_packet(): schema = [ ('a_string', RawBytes(8), ''), ('a_number', IntField(32, False), 0), ('options', OptionsField([]), None), ('pb_captured_len', IntField(32, False), 0), ('pb_orig_len', IntField(32, False), 0), ('packet_data', PacketBytes('pb_captured_len'), b''), ('spb_orig_len', IntField(32, False), 0), ('simple_packet_data', PacketBytes('spb_orig_len'), b''), ('name_res', ListField(NameResolutionRecordField()), []), ('another_number', IntField(32, False), 0), ] # Note: NULLs are for padding! data = io.BytesIO( b'\x01\x23\x45\x67\x89\xab\xcd\xef' b'\x00\x00\x01\x00' # Options b'\x00\x01\x00\x0cHello world!' b'\x00\x01\x00\x0fSpam eggs bacon\x00' b'\x00\x02\x00\x0fSome other text\x00' b'\x00\x00\x00\x00' # Enhanced Packet data b'\x00\x00\x00\x12' b'\x00\x01\x00\x00' b'These are 18 bytes\x00\x00' # Simple packet data b'\x00\x00\x00\x0d' b'Simple packet\x00\x00\x00' # List of name resolution items b'\x00\x01' # IPv4 b'\x00\x13' # Length: 19bytes b'\x0a\x22\x33\x44www.example.com\x00' # 19 bytes (10.34.51.68) b'\x00\x01' # IPv4 b'\x00\x13' # Length: 19bytes b'\xc0\xa8\x14\x01www.example.org\x00' # 19 bytes (192.168.20.1) b'\x00\x02' # IPv6 b'\x00\x1e' # 30 bytes b'\x00\x11\x22\x33\x44\x55\x66\x77' b'\x88\x99\xaa\xbb\xcc\xdd\xee\xff' b'v6.example.net\x00\x00' b'\x00\x00\x00\x00' # End marker # Another number, to check end b'\xaa\xbb\xcc\xdd' ) unpacked = struct_decode(schema, data, endianness='>') assert unpacked['a_string'] == b'\x01\x23\x45\x67\x89\xab\xcd\xef' assert unpacked['a_number'] == 0x100 assert isinstance(unpacked['options'], Options) assert len(unpacked['options']) == 2 assert unpacked['options']['opt_comment'] == 'Hello world!' assert unpacked['options'][2] == b'Some other text' assert unpacked['pb_captured_len'] == 0x12 assert unpacked['pb_orig_len'] == 0x10000 assert unpacked['packet_data'] == b'These are 18 bytes' assert unpacked['spb_orig_len'] == 13 assert unpacked['simple_packet_data'] == b'Simple packet' assert unpacked['name_res'] == [ {'address': '10.34.51.68', 'names': ['www.example.com'], 'type': 1}, {'address': '192.168.20.1', 'names': ['www.example.org'], 'type': 1}, {'type': 2, 'address': '11:2233:4455:6677:8899:aabb:ccdd:eeff', 'names': ['v6.example.net']}]