コード例 #1
0
    def mergeFields(self, field1, field2):
        """Merge specified fields.

        >>> import binascii
        >>> from netzob.all import *
        >>> samples = ["00ff2f000000", "000010000000",	"00fe1f000000"]
        >>> messages = [RawMessage(data=binascii.unhexlify(sample)) for sample in samples]
        >>> f1 = Field(Raw(nbBytes=1), name="f1")
        >>> f2 = Field(Raw(nbBytes=2), name="f2")
        >>> f3 = Field(Raw(nbBytes=2), name="f3")
        >>> f4 = Field(Raw(nbBytes=1), name="f4")
        >>> symbol = Symbol([f1, f2, f3, f4], messages=messages)
        >>> symbol.addEncodingFunction(TypeEncodingFunction(HexaString))

        >>> print(symbol)
        f1   | f2     | f3     | f4  
        ---- | ------ | ------ | ----
        '00' | 'ff2f' | '0000' | '00'
        '00' | '0010' | '0000' | '00'
        '00' | 'fe1f' | '0000' | '00'
        ---- | ------ | ------ | ----
        
        >>> fo = FieldOperations()
        >>> fo.mergeFields(f2, f3)
        >>> print(symbol)
        f1   | Merge      | f4  
        ---- | ---------- | ----
        '00' | 'ff2f0000' | '00'
        '00' | '00100000' | '00'
        '00' | 'fe1f0000' | '00'
        ---- | ---------- | ----

        >>> fo.mergeFields(symbol.fields[0], symbol.fields[1])
        >>> print(symbol)
        Merge        | f4  
        ------------ | ----
        '00ff2f0000' | '00'
        '0000100000' | '00'
        '00fe1f0000' | '00'
        ------------ | ----
        
        >>> fo.mergeFields(symbol.fields[0], symbol.fields[1])
        >>> print(symbol)
        Merge         
        --------------
        '00ff2f000000'
        '000010000000'
        '00fe1f000000'
        --------------
        
        :param field1: the left field to merge
        :type field1: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :param field2: the right field to merge
        :type field2: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`

        :raise Exception if something bad happens
        """

        if field1 is None or field2 is None:
            raise TypeError("Fields cannot be None")

        if field1 == field2:
            raise ValueError("Cannot merge a unique field (field1 == field2)")

        self._logger.debug("Merging field {0} with field {1}".format(field1.name, field2.name))

        if field1.parent is not field2.parent:
            raise ValueError("Specified fields don't have the same parent, only fields with same parents can be merged.")

        # retrieve indexes of specified fields
        iField1 = None
        iField2 = None
        for iField, field in enumerate(field1.parent.fields):
            if field == field1:
                iField1 = iField
            elif field == field2:
                iField2 = iField

        if iField1 is None:
            raise ValueError("Cannot retrieve position of field1 in its parent fields")
        if iField2 is None:
            raise ValueError("Cannot retrieve position of field2 in its parent fields")
        if iField2 != iField1 + 1:
            raise ValueError("Field1 must be directly on the left of field2 (iField1={0}, iField2={1})".format(iField1, iField2))

        # build a new field domain
        newDomain = Agg([field1.domain, field2.domain])
        newField = Field(domain=newDomain, name="Merge")
        newField.encodingFunctions = list(field1.encodingFunctions.values())
        parent = field1.parent
        before = parent.fields[:iField1]
        after = parent.fields[iField2 + 1:]
        parent.fields = before + [newField] + after
コード例 #2
0
    def _blendFields(field1, field2):
        """
        Completely blend two fields without using Agg.
        This requires that the two fields are of the same domain and its parameters.
        The returned new field still needs to be placed into the symbol.

        >>> from netzob.all import *
        >>> samples = [ b'\\x00\\xff/BPz', b'\\x00\\x00 CQ~', b'\\x00\\xff/Gf/' ]
        >>> messages = [RawMessage(data=sample) for sample in samples]
        >>> f1 = Field(Data(Integer(unitSize=AbstractType.UNITSIZE_8)))
        >>> f2 = Field(Raw(nbBytes=2))
        >>> f3 = Field(Raw(nbBytes=3))
        >>> symbol = Symbol([f1, f2, f3], messages=messages)
        >>> print(f2.domain.dataType.size)
        (16, 16)
        >>> print(f3.domain.dataType.size)
        (24, 24)
        >>> nf = FieldOperations._blendFields(f2,f3)
        >>> print(nf.domain.currentValue)
        None
        >>> print(nf.domain.dataType.endianness)
        big
        >>> print(nf.domain.dataType.size)
        (40, 40)
        >>> nf2 = FieldOperations._blendFields(f1,f2)
        Traceback (most recent call last):
        ...
        NotImplementedError: The datatype Integer is not yet supported.

        :param field1: the left field
        :param field2: the right field
        :return: a combination of field1 and field2
        :raises TypeError: if domains are not compatible
        :raises NotImplementedError: for datatypes which still need to be implemented
        """

        for d in [field1.domain, field2.domain]:
            if len(d._AbstractVariable__boundedVariables) > 0 \
                    or len(d._AbstractVariable__fathers) > 0 \
                    or len(d._AbstractVariable__tokenChoppedIndexes) > 0:
                raise TypeError(
                    "Blending does not support __boundedVariables, __fathers, or __tokenChoppedIndexes."
                )
            if not isinstance(d.dataType, Raw):
                raise NotImplementedError(
                    "The datatype {} is not yet supported.".format(
                        d.dataType.typeName))

        if not field1.domain.svas == field2.domain.svas:
            raise TypeError(
                "The SVAS-values of both fields to merge are not the same.")
        if not field1.domain.dataType.endianness == field2.domain.dataType.endianness:
            raise TypeError(
                "The endianness of both fields to merge are not the same.")
        if not field1.domain.dataType.sign == field2.domain.dataType.sign:
            raise TypeError(
                "The signedness of both fields to merge are not the same.")
        if not field1.domain.dataType.unitSize == field2.domain.dataType.unitSize:
            raise TypeError(
                "The unitSize of both fields to merge are not the same.")

        # '_ASCII__nbChars': (None, None)

        newDomain = field1.domain.__class__(field1.domain.dataType.__class__())
        newDomain.svas = field1.domain.svas
        newDomain.dataType.endianness = field1.domain.dataType.endianness
        newDomain.dataType.sign = field1.domain.dataType.sign
        newDomain.dataType.unitSize = field1.domain.dataType.unitSize
        newDomain.dataType.size = field1.domain.dataType.size

        minsizes = []
        maxsizes = []
        for f in [field1, field2]:
            if not f.domain.dataType.size is None:
                sizes = []
                for s in f.domain.dataType.size:
                    if s is not None:
                        sizes.append(s)
                minsizes.append(min(sizes))
                maxsizes.append(max(sizes))
        newDomain.dataType.size = (sum(minsizes), sum(maxsizes))

        newField = Field(domain=newDomain, name="Merge")
        newField.encodingFunctions = list(field1.encodingFunctions.values())

        # Position the new field in correct positions with correct dataType size
        if field1.domain.currentValue is None or field2.domain.currentValue is None:
            newField.domain.currentValue = None
        else:
            newField.domain.currentValue = (field1.domain.currentValue +
                                            field2.domain.currentValue)

        return newField
コード例 #3
0
    def split(field, delimiter):
        """Split a field (or symbol) with a specific delimiter. The
        delimiter can be passed either as an ASCII, a Raw, an
        HexaString, or any objects that inherit from AbstractType.


        >>> from netzob.all import *
        >>> samples = [b"aaaaff000000ff10", b"bbff110010ff00000011", b"ccccccccfffe1f000000ff12"]
        >>> messages = [RawMessage(data=sample) for sample in samples]
        >>> symbol = Symbol(messages=messages[:3])
        >>> Format.splitDelimiter(symbol, ASCII("ff"))
        >>> print(symbol)
        Field-0    | Field-sep-6666 | Field-2      | Field-sep-6666 | Field-4   
        ---------- | -------------- | ------------ | -------------- | ----------
        'aaaa'     | 'ff'           | '000000'     | 'ff'           | '10'      
        'bb'       | 'ff'           | '110010'     | 'ff'           | '00000011'
        'cccccccc' | 'ff'           | 'fe1f000000' | 'ff'           | '12'      
        ---------- | -------------- | ------------ | -------------- | ----------

        >>> samples = [b"434d446964656e74696679230400000066726564", b"5245536964656e74696679230000000000000000", b"434d44696e666f2300000000", b"524553696e666f230000000004000000696e666f", b"434d4473746174732300000000", b"52455373746174732300000000050000007374617473", b"434d4461757468656e7469667923090000006d7950617373776421", b"52455361757468656e74696679230000000000000000", b"434d44656e6372797074230a00000031323334353674657374", b"524553656e637279707423000000000a00000073707176777436273136", b"434d4464656372797074230a00000073707176777436273136", b"5245536465637279707423000000000a00000031323334353674657374", b"434d446279652300000000", b"524553627965230000000000000000", b"434d446964656e746966792307000000526f626572746f", b"5245536964656e74696679230000000000000000", b"434d44696e666f2300000000", b"524553696e666f230000000004000000696e666f", b"434d4473746174732300000000", b"52455373746174732300000000050000007374617473", b"434d4461757468656e74696679230a000000615374726f6e67507764", b"52455361757468656e74696679230000000000000000", b"434d44656e63727970742306000000616263646566", b"524553656e6372797074230000000006000000232021262724", b"434d44646563727970742306000000232021262724", b"52455364656372797074230000000006000000616263646566", b"434d446279652300000000", b"524553627965230000000000000000"]
        >>> messages = [RawMessage(data=TypeConverter.convert(sample, HexaString, Raw)) for sample in samples]
        >>> symbol = Symbol(messages=messages)
        >>> symbol.encodingFunctions.add(TypeEncodingFunction(ASCII))  # Change visualization to hexastring
        >>> Format.splitDelimiter(symbol, ASCII("#"))
        >>> print(symbol)
        Field-0         | Field-sep-23 | Field-2              | Field-sep-23 | Field-4
        --------------- | ------------ | -------------------- | ------------ | -------
        'CMDidentify'   | '#'          | '....fred'           | ''           | ''     
        'RESidentify'   | '#'          | '........'           | ''           | ''     
        'CMDinfo'       | '#'          | '....'               | ''           | ''     
        'RESinfo'       | '#'          | '........info'       | ''           | ''     
        'CMDstats'      | '#'          | '....'               | ''           | ''     
        'RESstats'      | '#'          | '........stats'      | ''           | ''     
        'CMDauthentify' | '#'          | '....myPasswd!'      | ''           | ''     
        'RESauthentify' | '#'          | '........'           | ''           | ''     
        'CMDencrypt'    | '#'          | '....123456test'     | ''           | ''     
        'RESencrypt'    | '#'          | "........spqvwt6'16" | ''           | ''     
        'CMDdecrypt'    | '#'          | "....spqvwt6'16"     | ''           | ''     
        'RESdecrypt'    | '#'          | '........123456test' | ''           | ''     
        'CMDbye'        | '#'          | '....'               | ''           | ''     
        'RESbye'        | '#'          | '........'           | ''           | ''     
        'CMDidentify'   | '#'          | '....Roberto'        | ''           | ''     
        'RESidentify'   | '#'          | '........'           | ''           | ''     
        'CMDinfo'       | '#'          | '....'               | ''           | ''     
        'RESinfo'       | '#'          | '........info'       | ''           | ''     
        'CMDstats'      | '#'          | '....'               | ''           | ''     
        'RESstats'      | '#'          | '........stats'      | ''           | ''     
        'CMDauthentify' | '#'          | '....aStrongPwd'     | ''           | ''     
        'RESauthentify' | '#'          | '........'           | ''           | ''     
        'CMDencrypt'    | '#'          | '....abcdef'         | ''           | ''     
        'RESencrypt'    | '#'          | '........'           | '#'          | " !&'$"
        'CMDdecrypt'    | '#'          | '....'               | '#'          | " !&'$"
        'RESdecrypt'    | '#'          | '........abcdef'     | ''           | ''     
        'CMDbye'        | '#'          | '....'               | ''           | ''     
        'RESbye'        | '#'          | '........'           | ''           | ''     
        --------------- | ------------ | -------------------- | ------------ | -------
        >>> print(symbol.fields[0]._str_debug())
        Field-0
        |--   Alt
              |--   Data (Raw=b'CMDidentify' ((0, 88)))
              |--   Data (Raw=b'RESidentify' ((0, 88)))
              |--   Data (Raw=b'CMDinfo' ((0, 56)))
              |--   Data (Raw=b'RESinfo' ((0, 56)))
              |--   Data (Raw=b'CMDstats' ((0, 64)))
              |--   Data (Raw=b'RESstats' ((0, 64)))
              |--   Data (Raw=b'CMDauthentify' ((0, 104)))
              |--   Data (Raw=b'RESauthentify' ((0, 104)))
              |--   Data (Raw=b'CMDencrypt' ((0, 80)))
              |--   Data (Raw=b'RESencrypt' ((0, 80)))
              |--   Data (Raw=b'CMDdecrypt' ((0, 80)))
              |--   Data (Raw=b'RESdecrypt' ((0, 80)))
              |--   Data (Raw=b'CMDbye' ((0, 48)))
              |--   Data (Raw=b'RESbye' ((0, 48)))

        Below is another example of the FieldSplitDelimiter usage: it splits fields based on a Raw string.


        >>> from netzob.all import *
        >>> samples = [b"\\x01\\x02\\x03\\xff\\x04\\x05\\xff\\x06\\x07", b"\\x01\\x02\\xff\\x03\\x04\\x05\\x06\\xff\\x07", b"\\x01\\xff\\x02\\x03\\x04\\x05\\x06"]
        >>> messages = [RawMessage(data=sample) for sample in samples]
        >>> symbol = Symbol(messages=messages)
        >>> Format.splitDelimiter(symbol, Raw(b"\\xff"))
        >>> print(symbol)
        Field-0        | Field-sep-ff | Field-2                | Field-sep-ff | Field-4   
        -------------- | ------------ | ---------------------- | ------------ | ----------
        '\\x01\\x02\\x03' | b'\\xff'      | '\\x04\\x05'             | b'\\xff'      | '\\x06\\x07'
        '\\x01\\x02'     | b'\\xff'      | '\\x03\\x04\\x05\\x06'     | b'\\xff'      | '\\x07'    
        '\\x01'         | b'\\xff'      | '\\x02\\x03\\x04\\x05\\x06' | ''           | ''        
        -------------- | ------------ | ---------------------- | ------------ | ----------


        :param field : the field to consider when spliting
        :type: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :param delimiter : the delimiter used to split messages of the field
        :type: :class:`netzob.Model.Vocabulary.Types.AbstractType.AbstractType`
        """

        if delimiter is None:
            raise TypeError("Delimiter cannot be None.")

        if field is None:
            raise TypeError("Field cannot be None.")

        if len(field.messages) < 1:
            raise ValueError(
                "The associated symbol does not contain any message.")

        # Find message substrings after applying delimiter
        splittedMessages = []

        for cell in field.getValues(encoded=False, styled=False):
            splittedMessage = cell.split(delimiter.value.tobytes())
            splittedMessages.append(splittedMessage)

        import itertools
        # Inverse the array, so that columns contains observed values for each field
        splittedMessages = list(itertools.zip_longest(*splittedMessages))

        # If the delimiter does not create splitted fields
        if len(splittedMessages) <= 1:
            return

        # Else, we add (2*len(splittedMessages)-1) fields
        newFields = []
        iField = -1
        for i in range(len(splittedMessages)):
            iField += 1

            fieldDomain = list()

            # temporary set that hosts all the observed values to prevent useless duplicate ones
            observedValues = set()
            has_inserted_empty_value = False

            isEmptyField = True  # To avoid adding an empty field            
            for v in splittedMessages[i]:
                if v != "" and v is not None:
                    isEmptyField = False

                    if v not in observedValues:
                        fieldDomain.append(Raw(v))
                        observedValues.add(v)
                else:
                    if not has_inserted_empty_value:
                        fieldDomain.append(Raw(nbBytes=0))
                        has_inserted_empty_value = True

            if not isEmptyField:
                newField = Field(
                    domain=DomainFactory.normalizeDomain(fieldDomain),
                    name="Field-" + str(iField))
                newField.encodingFunctions = list(
                    field.encodingFunctions.values())
                newFields.append(newField)
                iField += 1

            str_delimiter = TypeConverter.convert(delimiter.value, BitArray,
                                                  HexaString).decode('utf-8')
            fieldName = "Field-sep-{}".format(str_delimiter)

            newFields.append(
                Field(domain=Alt([delimiter, Raw(nbBytes=0)]), name=fieldName))

        newFields.pop()

        # Reset the field
        from netzob.Inference.Vocabulary.Format import Format
        Format.resetFormat(field)

        # Create a field for each entry
        field.fields = newFields
コード例 #4
0
    def split(field, delimiter):
        """Split a field (or symbol) with a specific delimiter. The
        delimiter can be passed either as an ASCII, a Raw, an
        HexaString, or any objects that inherit from AbstractType.


        >>> from netzob.all import *
        >>> samples = [b"aaaaff000000ff10", b"bbff110010ff00000011", b"ccccccccfffe1f000000ff12"]
        >>> messages = [RawMessage(data=sample) for sample in samples]
        >>> symbol = Symbol(messages=messages[:3])
        >>> Format.splitDelimiter(symbol, ASCII("ff"))
        >>> print(symbol)
        Field-0    | Field-sep-6666 | Field-2      | Field-sep-6666 | Field-4   
        ---------- | -------------- | ------------ | -------------- | ----------
        'aaaa'     | 'ff'           | '000000'     | 'ff'           | '10'      
        'bb'       | 'ff'           | '110010'     | 'ff'           | '00000011'
        'cccccccc' | 'ff'           | 'fe1f000000' | 'ff'           | '12'      
        ---------- | -------------- | ------------ | -------------- | ----------

        >>> samples = [b"434d446964656e74696679230400000066726564", b"5245536964656e74696679230000000000000000", b"434d44696e666f2300000000", b"524553696e666f230000000004000000696e666f", b"434d4473746174732300000000", b"52455373746174732300000000050000007374617473", b"434d4461757468656e7469667923090000006d7950617373776421", b"52455361757468656e74696679230000000000000000", b"434d44656e6372797074230a00000031323334353674657374", b"524553656e637279707423000000000a00000073707176777436273136", b"434d4464656372797074230a00000073707176777436273136", b"5245536465637279707423000000000a00000031323334353674657374", b"434d446279652300000000", b"524553627965230000000000000000", b"434d446964656e746966792307000000526f626572746f", b"5245536964656e74696679230000000000000000", b"434d44696e666f2300000000", b"524553696e666f230000000004000000696e666f", b"434d4473746174732300000000", b"52455373746174732300000000050000007374617473", b"434d4461757468656e74696679230a000000615374726f6e67507764", b"52455361757468656e74696679230000000000000000", b"434d44656e63727970742306000000616263646566", b"524553656e6372797074230000000006000000232021262724", b"434d44646563727970742306000000232021262724", b"52455364656372797074230000000006000000616263646566", b"434d446279652300000000", b"524553627965230000000000000000"]
        >>> messages = [RawMessage(data=TypeConverter.convert(sample, HexaString, Raw)) for sample in samples]
        >>> symbol = Symbol(messages=messages)
        >>> symbol.encodingFunctions.add(TypeEncodingFunction(ASCII))  # Change visualization to hexastring
        >>> Format.splitDelimiter(symbol, ASCII("#"))
        >>> print(symbol)
        Field-0         | Field-sep-23 | Field-2              | Field-sep-23 | Field-4
        --------------- | ------------ | -------------------- | ------------ | -------
        'CMDidentify'   | '#'          | '....fred'           | ''           | ''     
        'RESidentify'   | '#'          | '........'           | ''           | ''     
        'CMDinfo'       | '#'          | '....'               | ''           | ''     
        'RESinfo'       | '#'          | '........info'       | ''           | ''     
        'CMDstats'      | '#'          | '....'               | ''           | ''     
        'RESstats'      | '#'          | '........stats'      | ''           | ''     
        'CMDauthentify' | '#'          | '....myPasswd!'      | ''           | ''     
        'RESauthentify' | '#'          | '........'           | ''           | ''     
        'CMDencrypt'    | '#'          | '....123456test'     | ''           | ''     
        'RESencrypt'    | '#'          | "........spqvwt6'16" | ''           | ''     
        'CMDdecrypt'    | '#'          | "....spqvwt6'16"     | ''           | ''     
        'RESdecrypt'    | '#'          | '........123456test' | ''           | ''     
        'CMDbye'        | '#'          | '....'               | ''           | ''     
        'RESbye'        | '#'          | '........'           | ''           | ''     
        'CMDidentify'   | '#'          | '....Roberto'        | ''           | ''     
        'RESidentify'   | '#'          | '........'           | ''           | ''     
        'CMDinfo'       | '#'          | '....'               | ''           | ''     
        'RESinfo'       | '#'          | '........info'       | ''           | ''     
        'CMDstats'      | '#'          | '....'               | ''           | ''     
        'RESstats'      | '#'          | '........stats'      | ''           | ''     
        'CMDauthentify' | '#'          | '....aStrongPwd'     | ''           | ''     
        'RESauthentify' | '#'          | '........'           | ''           | ''     
        'CMDencrypt'    | '#'          | '....abcdef'         | ''           | ''     
        'RESencrypt'    | '#'          | '........'           | '#'          | " !&'$"
        'CMDdecrypt'    | '#'          | '....'               | '#'          | " !&'$"
        'RESdecrypt'    | '#'          | '........abcdef'     | ''           | ''     
        'CMDbye'        | '#'          | '....'               | ''           | ''     
        'RESbye'        | '#'          | '........'           | ''           | ''     
        --------------- | ------------ | -------------------- | ------------ | -------
        >>> print(symbol.fields[0]._str_debug())
        Field-0
        |--   Alt
              |--   Data (Raw=b'CMDidentify' ((0, 88)))
              |--   Data (Raw=b'RESidentify' ((0, 88)))
              |--   Data (Raw=b'CMDinfo' ((0, 56)))
              |--   Data (Raw=b'RESinfo' ((0, 56)))
              |--   Data (Raw=b'CMDstats' ((0, 64)))
              |--   Data (Raw=b'RESstats' ((0, 64)))
              |--   Data (Raw=b'CMDauthentify' ((0, 104)))
              |--   Data (Raw=b'RESauthentify' ((0, 104)))
              |--   Data (Raw=b'CMDencrypt' ((0, 80)))
              |--   Data (Raw=b'RESencrypt' ((0, 80)))
              |--   Data (Raw=b'CMDdecrypt' ((0, 80)))
              |--   Data (Raw=b'RESdecrypt' ((0, 80)))
              |--   Data (Raw=b'CMDbye' ((0, 48)))
              |--   Data (Raw=b'RESbye' ((0, 48)))

        Below is another example of the FieldSplitDelimiter usage: it splits fields based on a Raw string.


        >>> from netzob.all import *
        >>> samples = [b"\\x01\\x02\\x03\\xff\\x04\\x05\\xff\\x06\\x07", b"\\x01\\x02\\xff\\x03\\x04\\x05\\x06\\xff\\x07", b"\\x01\\xff\\x02\\x03\\x04\\x05\\x06"]
        >>> messages = [RawMessage(data=sample) for sample in samples]
        >>> symbol = Symbol(messages=messages)
        >>> Format.splitDelimiter(symbol, Raw(b"\\xff"))
        >>> print(symbol)
        Field-0        | Field-sep-ff | Field-2                | Field-sep-ff | Field-4   
        -------------- | ------------ | ---------------------- | ------------ | ----------
        '\\x01\\x02\\x03' | b'\\xff'      | '\\x04\\x05'             | b'\\xff'      | '\\x06\\x07'
        '\\x01\\x02'     | b'\\xff'      | '\\x03\\x04\\x05\\x06'     | b'\\xff'      | '\\x07'    
        '\\x01'         | b'\\xff'      | '\\x02\\x03\\x04\\x05\\x06' | ''           | ''        
        -------------- | ------------ | ---------------------- | ------------ | ----------


        :param field : the field to consider when spliting
        :type: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :param delimiter : the delimiter used to split messages of the field
        :type: :class:`netzob.Model.Types.AbstractType.AbstractType`
        """

        if delimiter is None:
            raise TypeError("Delimiter cannot be None.")

        if field is None:
            raise TypeError("Field cannot be None.")

        if len(field.messages) < 1:
            raise ValueError("The associated symbol does not contain any message.")

        # Find message substrings after applying delimiter
        splittedMessages = []

        for cell in field.getValues(encoded=False, styled=False):
            splittedMessage = cell.split(delimiter.value.tobytes())
            splittedMessages.append(splittedMessage)

        import itertools
        # Inverse the array, so that columns contains observed values for each field
        splittedMessages = list(itertools.zip_longest(*splittedMessages))
        
        # If the delimiter does not create splitted fields
        if len(splittedMessages) <= 1:
            return

        # Else, we add (2*len(splittedMessages)-1) fields
        newFields = []
        iField = -1
        for i in range(len(splittedMessages)):
            iField += 1
            
            fieldDomain = list()
            
            # temporary set that hosts all the observed values to prevent useless duplicate ones
            observedValues = set()
            has_inserted_empty_value = False
            
            isEmptyField = True  # To avoid adding an empty field            
            for v in splittedMessages[i]:
                if v != "" and v is not None:
                    isEmptyField = False
                
                    if v not in observedValues:                    
                        fieldDomain.append(Raw(v))
                        observedValues.add(v)
                else:
                    if not has_inserted_empty_value:
                        fieldDomain.append(Raw(nbBytes=0))
                        has_inserted_empty_value = True

            if not isEmptyField:
                newField = Field(domain=DomainFactory.normalizeDomain(fieldDomain), name="Field-"+str(iField))
                newField.encodingFunctions = list(field.encodingFunctions.values())
                newFields.append(newField)
                iField += 1

            str_delimiter = TypeConverter.convert(delimiter.value, BitArray, HexaString).decode('utf-8')
            fieldName = "Field-sep-{}".format(str_delimiter)

            newFields.append(Field(domain=Alt([delimiter, Raw(nbBytes=0)]), name=fieldName))

        newFields.pop()

        # Reset the field
        from netzob.Inference.Vocabulary.Format import Format
        Format.resetFormat(field)

        # Create a field for each entry
        field.fields = newFields
コード例 #5
0
ファイル: FieldOperations.py プロジェクト: gbossert/netzob
    def mergeFields(self, field1, field2):
        """Merge specified fields.

        >>> import binascii
        >>> from netzob.all import *
        >>> samples = ["00ff2f000000", "000010000000",	"00fe1f000000"]
        >>> messages = [RawMessage(data=binascii.unhexlify(sample)) for sample in samples]
        >>> f1 = Field(Raw(nbBytes=1), name="f1")
        >>> f2 = Field(Raw(nbBytes=2), name="f2")
        >>> f3 = Field(Raw(nbBytes=2), name="f3")
        >>> f4 = Field(Raw(nbBytes=1), name="f4")
        >>> symbol = Symbol([f1, f2, f3, f4], messages=messages)
        >>> symbol.addEncodingFunction(TypeEncodingFunction(HexaString))

        >>> print(symbol)
        f1   | f2     | f3     | f4  
        ---- | ------ | ------ | ----
        '00' | 'ff2f' | '0000' | '00'
        '00' | '0010' | '0000' | '00'
        '00' | 'fe1f' | '0000' | '00'
        ---- | ------ | ------ | ----
        
        >>> fo = FieldOperations()
        >>> fo.mergeFields(f2, f3)
        >>> print(symbol)
        f1   | Merge      | f4  
        ---- | ---------- | ----
        '00' | 'ff2f0000' | '00'
        '00' | '00100000' | '00'
        '00' | 'fe1f0000' | '00'
        ---- | ---------- | ----

        >>> fo.mergeFields(symbol.fields[0], symbol.fields[1])
        >>> print(symbol)
        Merge        | f4  
        ------------ | ----
        '00ff2f0000' | '00'
        '0000100000' | '00'
        '00fe1f0000' | '00'
        ------------ | ----
        
        >>> fo.mergeFields(symbol.fields[0], symbol.fields[1])
        >>> print(symbol)
        Merge         
        --------------
        '00ff2f000000'
        '000010000000'
        '00fe1f000000'
        --------------
        
        :param field1: the left field to merge
        :type field1: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :param field2: the right field to merge
        :type field2: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`

        :raise Exception if something bad happens
        """

        if field1 is None or field2 is None:
            raise TypeError("Fields cannot be None")

        if field1 == field2:
            raise ValueError("Cannot merge a unique field (field1 == field2)")

        self._logger.debug("Merging field {0} with field {1}".format(
            field1.name, field2.name))

        if field1.parent is not field2.parent:
            raise ValueError(
                "Specified fields don't have the same parent, only fields with same parents can be merged."
            )

        # retrieve indexes of specified fields
        iField1 = None
        iField2 = None
        for iField, field in enumerate(field1.parent.fields):
            if field == field1:
                iField1 = iField
            elif field == field2:
                iField2 = iField

        if iField1 is None:
            raise ValueError(
                "Cannot retrieve position of field1 in its parent fields")
        if iField2 is None:
            raise ValueError(
                "Cannot retrieve position of field2 in its parent fields")
        if iField2 != iField1 + 1:
            raise ValueError(
                "Field1 must be directly on the left of field2 (iField1={0}, iField2={1})".
                format(iField1, iField2))

        # build a new field domain
        newDomain = Agg([field1.domain, field2.domain])
        newField = Field(domain=newDomain, name="Merge")
        newField.encodingFunctions = list(field1.encodingFunctions.values())
        parent = field1.parent
        before = parent.fields[:iField1]
        after = parent.fields[iField2 + 1:]
        parent.fields = before + [newField] + after