Exemple #1
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        If Linux-Cooked (SLL) link-layer (i.e. the 'any' interface was used):
        6 bytes - Linux Cooked Protocol info
        6 bytes - source mac
        2 bytes - padding (00 00)
        2 bytes - type (should be 0x0800 for IP and 0x0806 for ARP)
        """
        # First, check length of packet to make sure it is at least long
        # enough for the header
        if len(packet_data) < 16:
            raise exceptions.PacketParsingException(
                "'Linux-cooked' layer data must at least be 16 bytes, "
                "but packet size is [" + str(len(packet_data)) + ']',
                fatal=True)

        self.dest_mac = PCAPPacket.char8_to_mac_address(*([0] * 6))
        self.source_mac = PCAPPacket.char8_to_mac_address(*packet_data[6:12])
        self.type = PCAPPacket.char8_to_int16(packet_data[14], packet_data[15])

        # Otherwise, judge based on the type from our built-ins
        if self.type == 0x0800:
            self.next_parse_recommendation = PCAPIP4
        elif self.type == 0x0806:
            self.next_parse_recommendation = PCAPARP
        else:
            raise exceptions.PacketParsingException(
                "Encapsulated type [" + str(self.type) + "] unknown",
                fatal=False)

        return packet_data[16:]
Exemple #2
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        Ethernet_II frame structure:
        6 bytes - dest_mac
        6 bytes - source mac
        2 bytes - type (should be 0x0800 for IP and 0x0806 for ARP)
        """
        # First, check length of packet to make sure it is at least long
        # enough for the header
        if len(packet_data) < 14:
            raise exceptions.PacketParsingException(
                'Ethernet layer data must at least be 14 bytes, '
                'but packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        self.dest_mac = PCAPPacket.char8_to_mac_address(*packet_data[0:6])
        self.source_mac = PCAPPacket.char8_to_mac_address(*packet_data[6:12])
        self.type = PCAPPacket.char8_to_int16(*packet_data[12:14])

        # Otherwise, judge based on the type from our built-ins
        if self.type == 0x0800:
            self.next_parse_recommendation = PCAPIP4
        elif self.type == 0x0806:
            self.next_parse_recommendation = PCAPARP
        else:
            raise exceptions.PacketParsingException(
                "No known handler for Ethernet type: " + str(self.type),
                fatal=False)

        return packet_data[14:]
Exemple #3
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        If UDP, the packet will look like this:
        word 1, 0: total 0: 1 byte  - Type
        word 1, 1: total 1: 1 byte  - Code
        word 1, 2: total 2: 2 bytes - Checksum
        word 2, 0: total 4: 4 bytes - Rest of header
        8 -> : Data
        """
        # First, check length of packet to make sure it is at least
        # long enough for the header
        if len(packet_data) < 8:
            raise exceptions.PacketParsingException(
                'ICMP layer data must at least be 8 bytes, '
                'but packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        self.type = packet_data[0]
        self.code = packet_data[1]
        self.header_data = packet_data[4:8]

        # ICMP is the last parsing step in the standard TCP/IP stack
        self.next_parse_recommendation = None

        # Remember, header length is in 4-octet words, so multiply by
        # 4 to get the data's starting byte
        return packet_data[8:]
Exemple #4
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        If UDP, the packet will look like this:
        word 1, 0: total 0:  2 bytes - Source port
        word 1, 2: total 2:  2 bytes - Destination port
        word 2, 0: total 4:  2 bytes - Length
        word 2, 2: total 6:  2 bytes - Checksum
        8 -> : Data
        """
        # First, check length of packet to make sure it is at least long
        # enough for the header
        if len(packet_data) < 8:
            raise exceptions.PacketParsingException(
                'UDP layer data must at least be 8 bytes, '
                'but packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        self.source_port = PCAPPacket.char8_to_int16(packet_data[0],
                                                     packet_data[1])
        self.dest_port = PCAPPacket.char8_to_int16(packet_data[2],
                                                   packet_data[3])
        self.length = PCAPPacket.char8_to_int16(packet_data[4], packet_data[5])

        # UDP is the last parsing step in the standard TCP/IP stack
        self.next_parse_recommendation = None

        # Remember, header length is in 4-octet words, so multiply by
        # 4 to get the data's starting byte
        return packet_data[8:]
Exemple #5
0
 def layer_name():
     """
     :return: str
     """
     raise exceptions.PacketParsingException(
         "Base layer class shouldn't be used directly.  "
         "Use a specific layer type instead.",
         fatal=False)
Exemple #6
0
 def parse_layer(self, packet_data):
     """
     :param packet_data: list[int] Array of int representing the bytes in
     the packet
     :return: list[int]
     """
     raise exceptions.PacketParsingException(
         "Base layer class shouldn't be used directly.  "
         "Use a specific layer type instead.",
         fatal=False)
Exemple #7
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        If TCP, the packet will look like this:
        word 1, 0: total 0:  2 bytes - Source port
        word 1, 2: total 2:  2 bytes - Destination port
        word 2, 0: total 4:  4 bytes - Sequence Number
        word 3, 0: total 8:  4 bytes - Acknoweldge Number
        word 4, 0: total 12: 1 byte  - Data Offset + 000 + NS Flag
        word 4, 1: total 13: 1 byte -  CWS, ECE, URG, ACK, PSH, RST, SYN,
                                       FIN Flags
        word 4, 2: total 14: 2 bytes - Window Size
        word 5, 0: total 16: 2 bytes - Checksum
        word 5, 2: total 18: 2 bytes - Urgent Pointer
        word 6-20: total 20-160: 0-40 bytes - Options
        20 - 60: Data
        """
        # First, check length of packet to make sure it is at least
        # long enough for the header
        if len(packet_data) < 20:
            raise exceptions.PacketParsingException(
                'TCP layer data must at least be 20 bytes, '
                'but packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        self.source_port = PCAPPacket.char8_to_int16(packet_data[0],
                                                     packet_data[1])
        self.dest_port = PCAPPacket.char8_to_int16(packet_data[2],
                                                   packet_data[3])
        self.seq = PCAPPacket.char8_to_int32(packet_data[4], packet_data[5],
                                             packet_data[6], packet_data[7])
        self.ack = PCAPPacket.char8_to_int32(packet_data[8], packet_data[9],
                                             packet_data[10], packet_data[11])
        self.data_offset = (packet_data[12] & 0xF0) >> 4

        # Sanity check on data offset
        if self.data_offset < 5:
            raise exceptions.PacketParsingException(
                'TCP data offset field must be at least 5, but it was [' +
                str(self.data_offset),
                fatal=True)

        if self.data_offset > len(packet_data):
            raise exceptions.PacketParsingException(
                'TCP data offset field specifies length [' +
                str(self.data_offset) + '] longer than the packet size [' +
                str(len(packet_data)) + ']!',
                fatal=True)

        self.flags = ((packet_data[12] & 0x1) * 0xFF) + packet_data[13]
        self.window_size = PCAPPacket.char8_to_int16(packet_data[14],
                                                     packet_data[15])

        # TCP is the last parsed packet in our stack.
        # Can add Layer 5-7 here (HTTP, SOAP, etc.)
        self.next_parse_recommendation = None

        # Remember, header length is in 4-octet words, so multiply
        # by 4 to get the data's starting byte
        return packet_data[(self.data_offset * 4):]
Exemple #8
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        If IP, the packet will look like this with word, word offset, and
        total offset followed by size of field):
        word 1, 0: total 0:  2 bytes - Hardware Type
        word 1, 2: total 2:  2 bytes - Protocol Type
        word 2, 0: total 4:  1 byte  - Hardware addr length
        word 2, 1: total 5:  1 byte  - Protocol addr length
        word 2, 2: total 6:  2 bytes -  Operation
        word 3, 0: total 8:  HW-ADDR-LENGTH bytes - Sender HW address
        word 4, 2: total (14):  PROTO-ADDR-LENGTH bytes - Sender Protocol
                                address
        word 5, 2: total (18):  HW-ADDR-LENGTH bytes - Target HW address
        word 7, 0: total (24):  PROTO-ADDR-LENGTH bytes - Target Protocol
                                address
        """
        # First, check length of packet to make sure it is at least long
        # enough for the header
        if len(packet_data) < 12:
            raise exceptions.PacketParsingException(
                'ARP layer data must at least be 12 bytes, '
                'but packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        self.hw_type = PCAPPacket.char8_to_int16(packet_data[0],
                                                 packet_data[1])
        self.proto_type = PCAPPacket.char8_to_int16(packet_data[2],
                                                    packet_data[3])
        self.hw_addr_length = packet_data[4]
        self.proto_addr_length = packet_data[5]
        self.operation = PCAPPacket.char8_to_int16(packet_data[6],
                                                   packet_data[7])

        # Sanity check on packet length now that we know the sizes of the
        # HW and Protocol addresses
        expected_size = (8 + (2 * self.hw_addr_length) +
                         (2 * self.proto_addr_length))
        if len(packet_data) < expected_size:
            raise exceptions.PacketParsingException(
                'ARP packet size is expected to be [' + str(expected_size) +
                '] based on set HW and Proto address lengths, '
                'but the real packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        sender_hw_addr_base = 8
        sender_proto_addr_base = sender_hw_addr_base + self.hw_addr_length
        target_hw_addr_base = sender_proto_addr_base + self.proto_addr_length
        target_proto_addr_base = target_hw_addr_base + self.hw_addr_length
        target_proto_addr_finish = \
            target_proto_addr_base + self.proto_addr_length

        self.sender_hw_addr_raw = \
            packet_data[sender_hw_addr_base:sender_proto_addr_base]
        self.sender_proto_addr_raw = \
            packet_data[sender_proto_addr_base:target_hw_addr_base]
        self.target_hw_addr_raw = \
            packet_data[target_hw_addr_base:target_proto_addr_base]
        self.target_proto_addr_raw = \
            packet_data[target_proto_addr_base:target_proto_addr_finish]

        if self.hw_type == ARP_PROTOCOL_HW_TYPE_EHTERNET:
            self.sender_hw_addr_ether = \
                PCAPPacket.char8_to_mac_address(*self.sender_hw_addr_raw)
            self.target_hw_addr_ether = \
                PCAPPacket.char8_to_mac_address(*self.target_hw_addr_raw)

        if self.proto_type == ETHERNET_PROTOCOL_TYPE_IP4:
            self.sender_ip_addr = \
                PCAPPacket.char8_to_ip4(*self.sender_proto_addr_raw)
            self.target_ip_addr = \
                PCAPPacket.char8_to_ip4(*self.target_proto_addr_raw)

        self.next_parse_recommendation = None

        if len(packet_data) > target_proto_addr_finish:
            raise exceptions.PacketParsingException(
                'ARP packet has junk data at end of packet [' + ', '.join([
                    '0x{0:02x}'.format(i)
                    for i in packet_data[target_proto_addr_finish:]
                ]),
                fatal=False)

        # Should be empty, but just in case...
        return []
Exemple #9
0
    def parse_layer(self, packet_data):
        """
        :type packet_data: list[int]
        :return: list[int]

        If IP, the packet will look like this with word, word offset, and
        total offset followed by size of field):
        word 1, 0: total 0:  1 byte -  Version + header length (length
                                       is in 4-byte words)
        word 1, 1: total 1:  1 byte -  DSCP + ECN
        word 1, 2: total 2:  2 bytes - Total Length
        word 2, 0: total 4:  2 bytes - ID
        word 2, 2: total 6:  2 bytes - Flags and Fragment Offset
        word 3, 0: total 8:  1 byte -  TTL
        word 3, 1: total 9:  1 byte -  Protocol
        word 3, 2: total 10: 2 bytes - Header Checksum
        word 4, 0: total 12: 4 bytes - Source IP
        word 5, 0: total 16: 4 bytes - Destination IP
        word 6-20: total 20-160: 0-40 bytes - Options
        20 - 60: Data
        """
        # First, check length of packet to make sure it is at least long
        # enough for the header
        if len(packet_data) < 20:
            raise exceptions.PacketParsingException(
                'IP layer data must at least be 20 bytes, '
                'but packet size is [' + str(len(packet_data)) + ']',
                fatal=True)

        self.version = (packet_data[0] & 0xf0) >> 4

        # Version must be either 4 or 6, no exceptions
        if self.version != 4 and self.version != 6:
            raise exceptions.PacketParsingException(
                'IP version must be either 4 or 6, but it was [' +
                str(self.version) + ']',
                fatal=True)

        self.header_length = packet_data[0] & 0x0f

        # Do a sanity check on header length vs. packet size
        if self.header_length < 5:
            raise exceptions.PacketParsingException(
                'IP header length field must be at least 5, but it was [' +
                str(self.header_length),
                fatal=True)

        if (self.header_length * 4) > len(packet_data):
            raise exceptions.PacketParsingException(
                'IP header length field specifies length [' +
                str(self.header_length) + '] longer than the packet size [' +
                str(len(packet_data)) + ']!',
                fatal=True)

        self.protocol = packet_data[9]

        # Otherwise, judge based on the type from our built-ins
        if self.protocol == IP4_PROTOCOL_TCP:
            self.next_parse_recommendation = PCAPTCP
        elif self.protocol == IP4_PROTOCOL_UDP:
            self.next_parse_recommendation = PCAPUDP
        elif self.protocol == IP4_PROTOCOL_ICMP:
            self.next_parse_recommendation = PCAPICMP
        else:
            raise exceptions.PacketParsingException(
                "IP protocol [" + str(self.protocol) + "] unknown",
                fatal=False)

        self.source_ip = PCAPPacket.char8_to_ip4(packet_data[12],
                                                 packet_data[13],
                                                 packet_data[14],
                                                 packet_data[15])
        self.dest_ip = PCAPPacket.char8_to_ip4(packet_data[16],
                                               packet_data[17],
                                               packet_data[18],
                                               packet_data[19])

        # Remember, header length is in 4-octet words, so multiply by 4 to
        # get the data's starting byte
        return packet_data[(self.header_length * 4):]