Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
class InterfaceDescription(SectionMemberBlock):
    magic_number = 0x00000001
    schema = [
        ('link_type', IntField(16, False)),  # todo: enc/decode
        ('reserved', RawBytes(2)),
        ('snaplen', IntField(32, False)),
        (
            'options',
            OptionsField([
                (2, 'if_name', 'string'),
                (3, 'if_description', 'string'),
                (4, 'if_IPv4addr', 'ipv4+mask'),
                (5, 'if_IPv6addr', 'ipv6+prefix'),
                (6, 'if_MACaddr', 'macaddr'),
                (7, 'if_EUIaddr', 'euiaddr'),
                (8, 'if_speed', 'u64'),
                (9, 'if_tsresol'),  # Just keep the raw data
                (10, 'if_tzone', 'u32'),
                (11, 'if_filter', 'string'),
                (12, 'if_os', 'string'),
                (13, 'if_fcslen', 'u8'),
                (14, 'if_tsoffset', 'i64'),
            ]))
    ]

    @property  # todo: cache this property
    def timestamp_resolution(self):
        # ------------------------------------------------------------
        # Resolution of timestamps. If the Most Significant Bit is
        # equal to zero, the remaining bits indicates the resolution
        # of the timestamp as as a negative power of 10 (e.g. 6 means
        # microsecond resolution, timestamps are the number of
        # microseconds since 1/1/1970). If the Most Significant Bit is
        # equal to one, the remaining bits indicates the resolution as
        # as negative power of 2 (e.g. 10 means 1/1024 of second). If
        # this option is not present, a resolution of 10^-6 is assumed
        # (i.e. timestamps have the same resolution of the standard
        # 'libpcap' timestamps).
        # ------------------------------------------------------------

        if 'if_tsresol' in self.options:
            return unpack_timestamp_resolution(self.options['if_tsresol'])

        return 1e-6

    @property
    def statistics(self):
        # todo: ensure we always have an interface id -> how??
        return self.section.interface_stats.get(self.interface_id)

    @property
    def link_type_description(self):
        try:
            return link_types.LINKTYPE_DESCRIPTIONS[self.link_type]
        except KeyError:
            return 'Unknown link type: 0x{0:04x}'.format(self.link_type)
Exemplo n.º 3
0
 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
Exemplo n.º 4
0
 def _encode(self, outstream):
     fld_size = IntField(32, False)
     fld_data = RawBytes(0)
     if len(self.section.interfaces) > 1:
         # Spec is a bit ambiguous here. Section 4.4 says "it MUST
         # be assumed that all the Simple Packet Blocks have been captured
         # on the interface previously specified in the first Interface
         # Description Block." but later adds "A Simple Packet Block cannot
         # be present in a Section that has more than one interface because
         # of the impossibility to refer to the correct one (it does not
         # contain any Interface ID field)." Why would it say "the first"
         # IDB and not "the only" IDB if this was really forbidden?
         strictness.problem(
             "writing SimplePacket for section with multiple interfaces")
         if strictness.should_fix():
             # Can't fix this. The IDBs have already been written.
             pass
     snap_len = self.interface.snaplen
     if snap_len > 0 and snap_len < self.captured_len:
         # This isn't a strictness issue, it *will* break other readers
         # if we write more bytes than the snaplen says to expect.
         fld_size.encode(self.packet_len,
                         outstream,
                         endianness=self.section.endianness)
         fld_data.encode(self.packet_data[:snap_len], outstream)
     else:
         fld_size.encode(self.packet_len,
                         outstream,
                         endianness=self.section.endianness)
         fld_data.encode(self.packet_data, outstream)
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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'}]
Exemplo n.º 8
0
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"],
        },
    ]
Exemplo n.º 9
0
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']}]