Exemple #1
0
    def readMessages(self, filePathList, delimitor=b"\n"):
        """Read all the messages found in the specified filePathList and given a delimitor.

        :param filePathList: paths of the file to parse
        :type filePathList: a list of :class:`str`
        :param delimitor: the delimitor used to find messages in the same file
        :type delimitor: :class:`str`
        :return: a sorted list of messages
        :rtype: a :class:`netzob.Common.Utils.SortedTypedList.SortedTypedList` of :class:`netzob.Model.Vocabulary.Messages.AbstractMessage`
        """
        # Verify the existence of input files
        errorMessageList = []
        for filePath in filePathList:
            try:
                fp = open(filePath)
                fp.close()
            except IOError as e:
                errorMessage = _("Error while trying to open the " +
                                 "file {0}.").format(filePath)
                if e.errno == errno.EACCES:
                    errorMessage = _(
                        "Error while trying to open the file " +
                        "{0}, more permissions are required for " +
                        "reading it.").format(filePath)
                errorMessageList.append(errorMessage)
                self._logger.warn(errorMessage)

        if errorMessageList != []:
            raise NetzobImportException("File", "\n".join(errorMessageList))

        self.messages = SortedTypedList(AbstractMessage)
        for filePath in filePathList:
            self.__readMessagesFromFile(filePath, delimitor)

        return self.messages
Exemple #2
0
    def __decodeLayer3(self, etherType, l2Payload):
        """Internal method that parses the specified header and extracts
        layer3 related proprieties."""

        if etherType == Packets.IP.ethertype:
            l3Proto = "IP"
            l3Decoder = Decoders.IPDecoder()
            layer3 = l3Decoder.decode(l2Payload)
            paddingSize = len(l2Payload) - layer3.get_ip_len()

            l3SrcAddr = layer3.get_ip_src()
            l3DstAddr = layer3.get_ip_dst()
            l3Payload = l2Payload[layer3.get_header_size():]
            if paddingSize > 0 and len(l3Payload) > paddingSize:
                l3Payload = l3Payload[:len(l3Payload) - paddingSize]
            ipProtocolNum = layer3.get_ip_p()
            return (l3Proto, l3SrcAddr, l3DstAddr, l3Payload, ipProtocolNum)
        else:
            warnMessage = _("Cannot import one of the provided packets since "
                            + "its layer 3 is unsupported (Only IP is " +
                            "currently supported, packet ethernet " +
                            "type = {0})").format(etherType)
            self._logger.warn(warnMessage)
            raise NetzobImportException("PCAP", warnMessage,
                                        self.INVALID_LAYER3)
Exemple #3
0
    def __decodeLayer4(self, ipProtocolNum, l3Payload):
        """Internal method that parses the specified header and extracts
        layer4 related proprieties."""

        if ipProtocolNum == Packets.UDP.protocol:
            l4Proto = "UDP"
            l4Decoder = Decoders.UDPDecoder()
            layer4 = l4Decoder.decode(l3Payload)
            l4SrcPort = layer4.get_uh_sport()
            l4DstPort = layer4.get_uh_dport()
            l4Payload = layer4.get_data_as_string()
            return (l4Proto, l4SrcPort, l4DstPort, l4Payload)
        elif ipProtocolNum == Packets.TCP.protocol:
            l4Proto = "TCP"
            l4Decoder = Decoders.TCPDecoder()
            layer4 = l4Decoder.decode(l3Payload)
            l4SrcPort = layer4.get_th_sport()
            l4DstPort = layer4.get_th_dport()
            l4Payload = layer4.get_data_as_string()
            return (l4Proto, l4SrcPort, l4DstPort, l4Payload)
        else:
            warnMessage = _("Cannot import one of the provided packets since " +
                            "its layer 4 is unsupported (Only UDP and TCP " +
                            "are currently supported, packet IP protocol " +
                            "number = {0})").format(ipProtocolNum)
            self._logger.warn(warnMessage)
            raise NetzobImportException("PCAP", warnMessage, self.INVALID_LAYER4)
Exemple #4
0
 def decodeLayer4(self, ipProtocolNum, l3Payload):
     if ipProtocolNum == Packets.UDP.protocol:
         l4Proto = "UDP"
         l4Decoder = Decoders.UDPDecoder()
         layer4 = l4Decoder.decode(l3Payload)
         l4SrcPort = layer4.get_uh_sport()
         l4DstPort = layer4.get_uh_dport()
         l4Payload = layer4.get_data_as_string()
         return (l4Proto, l4SrcPort, l4DstPort, l4Payload)
     elif ipProtocolNum == Packets.TCP.protocol:
         l4Proto = "TCP"
         l4Decoder = Decoders.TCPDecoder()
         layer4 = l4Decoder.decode(l3Payload)
         l4SrcPort = layer4.get_th_sport()
         l4DstPort = layer4.get_th_dport()
         l4Payload = layer4.get_data_as_string()
         return (l4Proto, l4SrcPort, l4DstPort, l4Payload)
     else:
         warnMessage = _(
             "Cannot import one of the provided packets since " +
             "its layer 4 is unsupported (Only UDP and TCP " +
             "are currently supported, packet IP protocol " +
             "number = {0})").format(ipProtocolNum)
         self.log.warn(warnMessage)
         raise NetzobImportException("PCAP", warnMessage, WARNING,
                                     self.INVALID_LAYER4)
    def saveMessagesInCurrentProject(self, messageIDList):
        """Retrieve messages from the provided list of IDs
        and add them to the current project"""
        addMessages = []
        # Compute the step
        step = float(100.0 / float(len(messageIDList)))
        status = 0.0
        old_status = 0.0
        for messageID in messageIDList:
            message = self.getMessageByID(str(messageID))
            if message is not None:
                addMessages.append(message)
            else:
                errorMessage = _(
                    "Message ID: {0} not found in importer message list"
                ).format(messageID)
                raise NetzobImportException("PCAP", errorMessage, ERROR)
            status += step

            if self.status_cb is not None:
                self.status_cb(status, None)
                old_status = status

        self.saveMessagesInProject(self.netzob.getCurrentWorkspace(),
                                   self.netzob.getCurrentProject(),
                                   addMessages)
Exemple #6
0
 def readMessages(self, filePathList, bpfFilter="", importLayer=5, nbPackets=0):
         warnMessage = _("Cannot import one of the provided packets since "
                         + "its layer 4 is unsupported (Only UDP and TCP " +
                         "are currently supported, packet IP protocol " +
                         "number = {0})").format(ipProtocolNum)
         self._logger.warn(warnMessage)
         raise NetzobImportException("PCAP", warnMessage,
                                     self.INVALID_LAYER4)
Exemple #7
0
 def getMessageDetails(self, messageID):
     if not messageID in self._payloadDict:
         errorMessage = "Message ID: {0} not found in importer message list".format(messageID)
         logging.error(errorMessage)
         raise NetzobImportException("PCAP", errorMessage, ERROR)
     decoder = Decoders.EthDecoder()
     payload = self._payloadDict[messageID]
     return decoder.decode(payload)
Exemple #8
0
    def readMessages(self,
                     filePathList,
                     bpfFilter="",
                     importLayer=5,
                     nbPackets=0):
        """Read all messages from a list of PCAP files. A BPF filter
        can be set to limit the captured packets. The layer of import
        can also be specified:
          - When layer={1, 2}, it means we want to capture a raw layer (such as Ethernet).
          - If layer=3, we capture at the network level (such as IP).
          - If layer=4, we capture at the transport layer (such as TCP or UDP).
          - If layer=5, we capture at the applicative layer (such as the TCP or UDP payload).
         Finally, the number of packets to capture can be specified.

        :param filePathList: the messages to cluster.
        :type filePathList: a list of :class:`str`
        :param bpfFilter: a string representing a BPF filter.
        :type bpfFilter: :class:`str`
        :param importLayer: an integer representing the protocol layer to start importing.
        :type importLayer: :class:`int`
        :param nbPackets: the number of packets to import
        :type nbPackets: :class:`int`
        :return: a list of captured messages
        :rtype: a list of :class:`netzob.Model.Vocabulary.Messages.AbstractMessage`
        """

        # Verify the existence of input files
        errorMessageList = []
        for filePath in filePathList:
            try:
                fp = open(filePath)
                fp.close()
            except IOError as e:
                errorMessage = _("Error while trying to open the " +
                                 "file {0}.").format(filePath)
                if e.errno == errno.EACCES:
                    errorMessage = _(
                        "Error while trying to open the file " +
                        "{0}, more permissions are required for " +
                        "reading it.").format(filePath)
                errorMessageList.append(errorMessage)
                self._logger.warn(errorMessage)

        if errorMessageList != []:
            raise NetzobImportException("PCAP", "\n".join(errorMessageList))

        # Verify the expected import layer
        availableLayers = [1, 2, 3, 4, 5]
        if not importLayer in availableLayers:
            raise Exception(
                "Only layers level {0} are available.".format(availableLayers))
        self.importLayer = importLayer

        # Call the method that does the import job for each PCAP file
        self.messages = SortedTypedList(AbstractMessage)
        for filePath in filePathList:
            self.__readMessagesFromFile(filePath, bpfFilter, nbPackets)
        return self.messages
Exemple #9
0
 def getMessageDetails(self, messageID):
     if not messageID in self._payloadDict:
         errorMessage = _("Message ID: {0} not found in importer " +
                          "message list").format(messageID)
         logging.error(errorMessage)
         raise NetzobImportException("IPC", errorMessage, ERROR)
     payload = self._payloadDict[messageID]
     return TypeConvertor.hexdump(
         TypeConvertor.netzobRawToPythonRaw(payload))
Exemple #10
0
 def __decodeLayer2(self, packet: Packet):
     """Internal method that parses the specified header and extracts
     layer2 related proprieties."""
     l2Proto = packet.name
     if isinstance(packet, Raw):
         print("Ignoring undecoded packet with values:", bytes(packet).hex())
         return l2Proto, None, None, ""
     if isinstance(packet, Dot11):
         l2DstAddr = packet.fields['addr1']  # receiver address, alt: packet.fields['addr3'] destination address
         l2SrcAddr = packet.fields['addr2']  # transmitter address, alt: packet.fields['addr4'] source address
     else:
         raise NetzobImportException("NEMERE_PCAP", "Unsupported layer 2 protocol " + l2Proto,
                                     PCAPImporter.INVALID_LAYER2)
     l2Payload = bytes(packet.payload)
     return l2Proto, l2SrcAddr, l2DstAddr, l2Payload
Exemple #11
0
    def __readMessagesFromFile(self, filePath, bpfFilter, nbPackets):
        """Internal methods to read all messages from a given PCAP file."""
        if (filePath is None):
            raise TypeError("filePath cannot be None")
        if (nbPackets < 0):
            raise ValueError(
                "A positive (or null) value is required for the number of packets to read."
            )

        # Check file can be opened (and read)
        try:
            fp = open(filePath, 'r')
            fp.close()
        except IOError as e:
            if e.errno == errno.EACCES:
                raise IOError(
                    "Error while trying to open the file {0}, more permissions are required to read it."
                ).format(filePath)
            else:
                raise e

        # Check (and configure) the bpf filter
        packetReader = pcapy.open_offline(filePath)
        try:
            packetReader.setfilter(bpfFilter)
        except:
            raise ValueError(
                "The provided BPF filter is not valid (it should follow the BPF format)"
            )

        # Check the datalink
        self.datalink = packetReader.datalink()
        if self.datalink not in list(PCAPImporter.SUPPORTED_DATALINKS.keys()):
            self._logger.debug("Unkown datalinks")

        if self.importLayer > 1 and self.datalink != pcapy.DLT_EN10MB and self.datalink != pcapy.DLT_LINUX_SLL \
                and self.datalink != pcapy.DLT_RAW and self.datalink != PCAPImporter.PROTOCOL201 and self.datalink != pcapy.DLT_NULL:
            self._logger.debug('Datalink: ' + str(self.datalink))
            errorMessage = _("This pcap cannot be imported since the " +
                             "layer 2 is not supported ({0})").format(
                                 str(self.datalink))
            raise NetzobImportException("PCAP", errorMessage,
                                        self.INVALID_LAYER2)
        else:
            packetReader.loop(nbPackets, self.__packetHandler)
Exemple #12
0
    def sniffingThread(self, device, count, time):
        logging.info("Launching sniff process on dev {0} with: count={1}, timeout={2}, filter=\"{3}\"".format(device, count, time, self.bpfFilter))
        sniffer = pcapy.open_live(device, 1024, False, int(time))
        try:
            sniffer.setfilter(self.bpfFilter)
        except:
            logging.warn("The provided filter is not valid (it should respects the BPF format")
            return

        self.datalink = sniffer.datalink()
        if self.datalink != pcapy.DLT_EN10MB and self.datalink != pcapy.DLT_LINUX_SLL:
            errorMessage = _("This device cannot be sniffed since the "
                             + "layer 2 is not supported ({0})").format(str(self.datalink))
            self.log.warn(errorMessage)
            raise NetzobImportException("PCAP", errorMessage, ERROR,
                                        self.INVALID_LAYER2)
        else:
            sniffer.loop(int(count), self._packetHandler)
Exemple #13
0
class PCAPImporter(AbstractImporter):
    """Model of PCAP importer plugin"""

    INVALID_BPF_FILTER = 0
    INVALID_LAYER2 = 1
    INVALID_LAYER3 = 2
    INVALID_LAYER4 = 3

    PROTOCOL201 = 201

    def __init__(self, netzob):
        super(PCAPImporter, self).__init__("PCAP IMPORT", netzob)
        # create logger with the given configuration
        self.log = logging.getLogger('netzob.Import.PcapImport.py')
        self.filesToBeImported = []
        self.bpfFilter = ""
        self.importLayer = 4
        self._payloadDict = {}

    @property
    def payloadDict(self):
        return self._payloadDict.copy()

    def setSourceFiles(self, filePathList):
        errorMessageList = []
        for filePath in filePathList:
            try:
                fp = open(filePath)
                fp.close()
            except IOError, e:
                errorMessage = _("Error while trying to open the " -
                                 + "file {0}.").format(filePath)
                if e.errno == errno.EACCES:
                    errorMessage = _(
                        "Error while trying to open the file " +
                        "{0}, more permissions are required for " +
                        "reading it.").format(filePath)
                errorMessageList.append(errorMessage)
                self.log.warn(errorMessage)

        if errorMessageList != []:
            raise NetzobImportException("PCAP", "\n".join(errorMessageList),
                                        ERROR)
        self.filesToBeImported = filePathList
Exemple #14
0
 def decodeLayer3(self, etherType, l2Payload):
     if etherType == Packets.IP.ethertype:
         l3Proto = "IP"
         l3Decoder = Decoders.IPDecoder()
         layer3 = l3Decoder.decode(l2Payload)
         l3SrcAddr = layer3.get_ip_src()
         l3DstAddr = layer3.get_ip_dst()
         l3Payload = l2Payload[layer3.get_header_size():]
         ipProtocolNum = layer3.get_ip_p()
         return (l3Proto, l3SrcAddr, l3DstAddr, l3Payload, ipProtocolNum)
     else:
         warnMessage = _(
             "Cannot import one of the provided packets since " +
             "its layer 3 is unsupported (Only IP is " +
             "currently supported, packet ethernet " +
             "type = {0})").format(etherType)
         self.log.warn(warnMessage)
         raise NetzobImportException("PCAP", warnMessage, WARNING,
                                     self.INVALID_LAYER3)
Exemple #15
0
    def packetHandler(self, packet: Packet):
        epoch = packet.time
        l1Payload = bytes(packet)
        if len(l1Payload) == 0:
            return
        # Build the RawMessage
        rawMessage = RawMessage(l1Payload, epoch, source=None, destination=None)

        if isinstance(packet, RadioTap):
            # lift layer to Dot11 if there is a RadioTap dummy frame
            packet = packet.payload
        if self.importLayer == 2:
            (l2Proto, l2SrcAddr, l2DstAddr, l2Payload) = self.__decodeLayer2(packet)
            if len(l2Payload) == 0:
                return
            # Build the L2NetworkMessage
            l2Message = L2NetworkMessage(l2Payload, epoch, l2Proto, l2SrcAddr, l2DstAddr)
            self._messages.add(l2Message)
            self._rawmessages.add(rawMessage)
        else:
            # Use Netzob's PCAPImporter if layer 2 is not WLAN
            raise NetzobImportException("PCAP", "Unsupported import layer. Currently only handles layer 2.",
                                        PCAPImporter.INVALID_LAYER2)
Exemple #16
0
    def readMessages(self,
                     filePathList,
                     bpfFilter="",
                     importLayer=5,
                     nbPackets=0,
                     mergePacketsInFlow=False,
                    ):
        """Read all messages from a list of PCAP files. A BPF filter
        can be set to limit the captured packets. The layer of import
        can also be specified:
          - When layer={1, 2}, it means we want to capture a raw layer (such as Ethernet).
          - If layer=3, we capture at the network level (such as IP).
          - If layer=4, we capture at the transport layer (such as TCP or UDP).
          - If layer=5, we capture at the applicative layer (such as the TCP or UDP payload).
         Finally, the number of packets to capture can be specified.

        :param filePathList: the messages to cluster.
        :type filePathList: a list of :class:`str`
        :param bpfFilter: a string representing a BPF filter.
        :type bpfFilter: :class:`str`
        :param importLayer: an integer representing the protocol layer to start importing.
        :type importLayer: :class:`int`
        :param nbPackets: the number of packets to import
        :type nbPackets: :class:`int`
        :param mergePacketsInFlow: if True, consecutive packets with same source and destination ar merged (i.e. to mimic a flow) 
        :type mergePacketsInFlow: :class:`bool`
        :return: a list of captured messages
        :rtype: a list of :class:`netzob.Model.Vocabulary.Messages.AbstractMessage`
        """

        # Verify the existence of input files
        errorMessageList = []
        for filePath in filePathList:
            try:
                fp = open(filePath)
                fp.close()
            except IOError as e:
                errorMessage = _("Error while trying to open the "
                                 + "file {0}.").format(filePath)
                if e.errno == errno.EACCES:
                    errorMessage = _("Error while trying to open the file " +
                                     "{0}, more permissions are required for "
                                     + "reading it.").format(filePath)
                errorMessageList.append(errorMessage)
                self._logger.warn(errorMessage)

        if errorMessageList != []:
            raise NetzobImportException("PCAP", "\n".join(errorMessageList))

        # Verify the expected import layer
        availableLayers = [1, 2, 3, 4, 5]
        if importLayer not in availableLayers:
            raise Exception(
                "Only layers level {0} are available.".format(availableLayers))
        self.importLayer = importLayer

        # Call the method that does the import job for each PCAP file
        self.messages = SortedTypedList(AbstractMessage)
        for filePath in filePathList:
            self.__readMessagesFromFile(filePath, bpfFilter, nbPackets)
            #Create a session and attribute it to messages:
            session = Session(list(self.messages.values()),name=filePath)
            for message in self.messages.values():
                message.session = session
        
        # if requested, we merge consecutive messages that share same source and destination
        if mergePacketsInFlow:
            mergedMessages = SortedTypedList(AbstractMessage)
            previousMessage = None
            for message in self.messages.values():
                if previousMessage is not None and message.source == previousMessage.source and message.destination == previousMessage.destination:
                    previousMessage.data += message.data
                else:
                    mergedMessages.add(message)
                    previousMessage = message
            self.messages = mergedMessages
            
        return self.messages