Exemple #1
0
    def merge_nontest_fields(self, fields_origin, fid):
        logging.debug("[+] Merge Fields")
        fields_merged = list()
        fields = copy.deepcopy(fields_origin)
        fsize_total = 0
        for i in range(len(fields)):
            typename = fields[i].domain.dataType.typeName
            if typename != "Raw":
                logging.error("Field type is not Raw")
            typesize = fields[i].domain.dataType.size[1]
            # print(i, fid, typesize, type(typesize))

            if i == fid:
                if fsize_total > 0:
                    field = Field(Raw(nbBytes=fsize_total // 8))
                    fields_merged.append(field)
                    fsize_total = 0
                if fid != (len(fields) - 1):
                    field = Field(Raw(nbBytes=typesize // 8))
                    fields_merged.append(field)
                    field = Field()
                    fields_merged.append(field)
                else:
                    if type(typesize).__name__ == 'NoneType':
                        field = Field()
                    else:
                        field = Field(Raw(nbBytes=typesize // 8))
                    fields_merged.append(field)
                break
            else:
                fsize_total += typesize

        return fields_merged
Exemple #2
0
    def __define_field(self,val_set,field):
        """

        :param val_set: A set of values in the field
        :param field: The field containing the CRC
        :return: new_field: A new field (Alt or Raw)
        """
        if len(val_set) > 1:
            # More than one value, create Alt Fields
            domain_list = []
            for value in val_set:
                domain_list.append(Raw(value))
            new_field = Field(name=field.name, domain=Alt(domain_list))
        else:
            # Only one value, create static Fields
            new_field = Field(name=field.name, domain=Raw(val_set.pop()))
        return new_field
Exemple #3
0
    def generate_fields(self, fields_result):
        fields = list()
        for typeinfo in fields_result:
            if typeinfo[0] == "Raw":
                field = Field(Raw(nbBytes=(typeinfo[1] // 8,
                                           typeinfo[2] // 8)))
                fields.append(field)
            else:
                logging.error("Field type is not Raw")

        return fields
Exemple #4
0
    def _splitFieldFollowingAlignment(self, field, align):
        """Update the field definition with new fields following the
        specified align."""

        # STEP 1 : Create a field separation based on static and dynamic fields
        leftAlign, rightAlign = self._splitAlignment(align)
        splited = self._mergeAlign(leftAlign, rightAlign)
        step1Fields = []

        for (entryVal, entryDyn) in splited:
            if entryDyn:
                newField = Field(Raw(nbBytes=(0, int(len(entryVal) / 2))))
            else:
                newField = Field(
                    Raw(TypeConverter.convert(entryVal, HexaString, Raw)))
            step1Fields.append(newField)

        for f in step1Fields:
            f.encodingFunctions = list(field.encodingFunctions.values())

        field.fields = step1Fields
Exemple #5
0
 def __init__(self, fields=None, messages=None, name="Symbol", meta=False):
     """
     :keyword fields: the fields which participate in symbol definition
     :type fields: a :class:`list` of :class:`netzob.Model.Vocabulary.Field`
     :keyword messages: the message that represent the symbol
     :type messages: a :class:`list` of :class:`netzob.Model.Vocabulary.Messages.AbstractMessage.AbstractMessage`
     :keyword name: the name of the symbol
     :type name: :class:`str`
     """
     super(Symbol, self).__init__(name, meta)
     self.__messages = TypedList(AbstractMessage)
     if messages is None:
         messages = []
     self.messages = messages
     if fields is None:
         # create a default empty field
         fields = [Field()]
     self.fields = fields
Exemple #6
0
    def createSubFieldsForAStaticField(self, field, align, semanticTags):
        """createSubFieldsForAStaticField:
        Analyzes the static field provided and create sub fields following
        the provided semantic tags."""
        self._logger.debug(
            "Create subfields for static field {0} : {1}".format(
                field.getName(), align))

        if len(field.getLocalFields()) > 0:
            self._logger.warning(
                "Impossible to create sub fields for this field since its not cleaned"
            )
            return

        subFields = []

        currentTag = None
        currentTagLength = 0

        for index, tag in list(semanticTags.items()):
            if tag != currentTag:
                # Create a sub field
                subFieldValue = align[index - currentTagLength:index]
                if len(subFieldValue) > 0:
                    subFields.append(subFieldValue)
                currentTagLength = 0
            currentTag = tag
            currentTagLength += 1
        if currentTagLength > 0:
            subFieldValue = align[-currentTagLength:]
            if len(subFieldValue) > 0:
                subFields.append(subFieldValue)

        if len(subFields) > 1:
            for iSubField, subFieldValue in enumerate(subFields):
                subField = Field(b"{0}_{1}".format(field.getName(), iSubField),
                                 b"({0})".format(subFieldValue),
                                 field.getSymbol())
                field.addLocalField(subField)
Exemple #7
0
    def reset(self, field):
        """Resets the format (field hierarchy and definition domain) of
        the specified field.


        :param field: the field we want to reset
        :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :raise Exception if something bad happens
        """

        if field is None:
            raise TypeError(
                "The field to reset must be specified and cannot be None")

        self._logger.debug("Reset the definition of field {0} ({1})".format(
            field.name, field.id))
        field.clearFields()

        if isinstance(field, Symbol):
            field.fields = [Field()]

        if isinstance(field, Field):
            field.domain = Raw(None)
    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
Exemple #9
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
Exemple #10
0
    def buildPacket(self, payload):
        """Build a raw IP packet including the IP layer and its payload.

        :parameter payload: the payload to write on the channel
        :type payload: binary object
        """

        ip_ver = Field(name='Version', domain=BitArray(value=bitarray('0100')))  # IP Version 4
        ip_ihl = Field(name='Header length', domain=BitArray(bitarray('0000')))
        ip_tos = Field(name='TOS', domain=Data(dataType=BitArray(nbBits=8), originalValue=bitarray('00000000'), svas=SVAS.PERSISTENT))
        ip_tot_len = Field(name='Total length', domain=BitArray(bitarray('0000000000000000')))
        ip_id = Field(name='Identification number', domain=BitArray(nbBits=16))
        ip_flags = Field(name='Flags', domain=Data(dataType=BitArray(nbBits=3), originalValue=bitarray('000'), svas=SVAS.PERSISTENT))
        ip_frag_off = Field(name='Fragment offset', domain=Data(dataType=BitArray(nbBits=13), originalValue=bitarray('0000000000000'), svas=SVAS.PERSISTENT))
        ip_ttl = Field(name='TTL', domain=Data(dataType=BitArray(nbBits=8), originalValue=bitarray('10000000'), svas=SVAS.PERSISTENT))
        ip_proto = Field(name='Protocol', domain=Integer(value=self.upperProtocol, unitSize=AbstractType.UNITSIZE_8, endianness=AbstractType.ENDIAN_BIG, sign=AbstractType.SIGN_UNSIGNED))
        ip_checksum = Field(name='Checksum', domain=BitArray(bitarray('0000000000000000')))
        ip_saddr = Field(name='Source address', domain=IPv4(self.localIP))
        ip_daddr = Field(name='Destination address', domain=IPv4(self.remoteIP))
        ip_payload = Field(name='Payload', domain=payload)

        ip_ihl.domain = Size([ip_ver,
                              ip_ihl,
                              ip_tos,
                              ip_tot_len,
                              ip_id, ip_flags,
                              ip_frag_off,
                              ip_ttl, ip_proto,
                              ip_checksum,
                              ip_saddr,
                              ip_daddr], dataType=BitArray(nbBits=4), factor=1/float(32))
        ip_tot_len.domain = Size([ip_ver,
                                  ip_ihl,
                                  ip_tos,
                                  ip_tot_len,
                                  ip_id,
                                  ip_flags,
                                  ip_frag_off,
                                  ip_ttl,
                                  ip_proto,
                                  ip_checksum,
                                  ip_saddr,
                                  ip_daddr,
                                  ip_payload], dataType=Raw(nbBytes=2), factor=1/float(8))
        ip_checksum.domain = InternetChecksum(fields=[ip_ver,
                                                      ip_ihl,
                                                      ip_tos,
                                                      ip_tot_len,
                                                      ip_id,
                                                      ip_flags,
                                                      ip_frag_off,
                                                      ip_ttl,
                                                      ip_proto,
                                                      ip_checksum,
                                                      ip_saddr,
                                                      ip_daddr], dataType=Raw(nbBytes=2))
        
        packet = Symbol(name='IP layer', fields=[ip_ver,
                                                 ip_ihl,
                                                 ip_tos,
                                                 ip_tot_len,
                                                 ip_id,
                                                 ip_flags,
                                                 ip_frag_off,
                                                 ip_ttl,
                                                 ip_proto,
                                                 ip_checksum,
                                                 ip_saddr,
                                                 ip_daddr,
                                                 ip_payload])
        return packet.specialize()
Exemple #11
0
    def initHeader(self):
        """Initialize the IP header according to the IP format definition.

        """

        # Ethernet header

        # Retrieve remote MAC address
        dstMacAddr = get_mac_address(ip=self.remoteIP)
        if dstMacAddr is not None:
            dstMacAddr = dstMacAddr.replace(':', '')
            dstMacAddr = binascii.unhexlify(dstMacAddr)
        else:
            # Force ARP resolution
            p = subprocess.Popen(["/bin/ping", "-c1", self.remoteIP])
            p.wait()
            time.sleep(0.1)

            dstMacAddr = get_mac_address(ip=self.remoteIP)
            if dstMacAddr is not None:
                dstMacAddr = dstMacAddr.replace(':', '')
                dstMacAddr = binascii.unhexlify(dstMacAddr)
            else:
                raise Exception(
                    "Cannot resolve IP address to a MAC address for IP: '{}'".
                    format(self.remoteIP))

        # Retrieve local MAC address
        srcMacAddr = self.get_interface_addr(bytes(self.interface, 'utf-8'))[1]

        eth_dst = Field(name='eth.dst', domain=Raw(dstMacAddr))
        eth_src = Field(name='eth.src', domain=Raw(srcMacAddr))
        eth_type = Field(name='eth.type', domain=Raw(b"\x08\x00"))

        # IP header

        ip_ver = Field(name='ip.version',
                       domain=BitArray(value=bitarray('0100')))  # IP Version 4
        ip_ihl = Field(name='ip.hdr_len', domain=BitArray(bitarray('0000')))
        ip_tos = Field(name='ip.tos',
                       domain=Data(dataType=BitArray(nbBits=8),
                                   originalValue=bitarray('00000000'),
                                   svas=SVAS.PERSISTENT))
        ip_tot_len = Field(name='ip.len',
                           domain=BitArray(bitarray('0000000000000000')))
        ip_id = Field(name='ip.id', domain=BitArray(nbBits=16))
        ip_flags = Field(name='ip.flags',
                         domain=Data(dataType=BitArray(nbBits=3),
                                     originalValue=bitarray('000'),
                                     svas=SVAS.PERSISTENT))
        ip_frag_off = Field(name='ip.fragment',
                            domain=Data(
                                dataType=BitArray(nbBits=13),
                                originalValue=bitarray('0000000000000'),
                                svas=SVAS.PERSISTENT))
        ip_ttl = Field(name='ip.ttl',
                       domain=Data(dataType=BitArray(nbBits=8),
                                   originalValue=bitarray('01000000'),
                                   svas=SVAS.PERSISTENT))
        ip_proto = Field(name='ip.proto',
                         domain=Integer(value=self.upperProtocol,
                                        unitSize=AbstractType.UNITSIZE_8,
                                        endianness=AbstractType.ENDIAN_BIG,
                                        sign=AbstractType.SIGN_UNSIGNED))
        ip_checksum = Field(name='ip.checksum',
                            domain=BitArray(bitarray('0000000000000000')))
        ip_saddr = Field(name='ip.src', domain=IPv4(self.localIP))
        ip_daddr = Field(name='ip.dst', domain=IPv4(self.remoteIP))
        ip_payload = Field(name='ip.payload', domain=Raw())

        ip_ihl.domain = Size([
            ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id, ip_flags, ip_frag_off,
            ip_ttl, ip_proto, ip_checksum, ip_saddr, ip_daddr
        ],
                             dataType=BitArray(nbBits=4),
                             factor=1 / float(32))
        ip_tot_len.domain = Size([
            ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id, ip_flags, ip_frag_off,
            ip_ttl, ip_proto, ip_checksum, ip_saddr, ip_daddr, ip_payload
        ],
                                 dataType=Integer(
                                     unitSize=AbstractType.UNITSIZE_16,
                                     sign=AbstractType.SIGN_UNSIGNED),
                                 factor=1 / float(8))
        ip_checksum.domain = InternetChecksum(
            fields=[
                ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id, ip_flags,
                ip_frag_off, ip_ttl, ip_proto, ip_checksum, ip_saddr, ip_daddr
            ],
            dataType=Raw(nbBytes=2, unitSize=AbstractType.UNITSIZE_16))

        self.header = Symbol(name='Ethernet layer',
                             fields=[
                                 eth_dst, eth_src, eth_type, ip_ver, ip_ihl,
                                 ip_tos, ip_tot_len, ip_id, ip_flags,
                                 ip_frag_off, ip_ttl, ip_proto, ip_checksum,
                                 ip_saddr, ip_daddr, ip_payload
                             ])
Exemple #12
0
    def initHeader(self):
        """Initialize the IP header according to the IP format definition.

        """

        ip_ver = Field(
            name='ip.version', domain=BitArray(
                value=bitarray('0100')))  # IP Version 4
        ip_ihl = Field(name='ip.hdr_len', domain=BitArray(bitarray('0000')))
        ip_tos = Field(
            name='ip.tos',
            domain=Data(
                dataType=BitArray(nbBits=8),
                originalValue=bitarray('00000000'),
                svas=SVAS.PERSISTENT))
        ip_tot_len = Field(
            name='ip.len', domain=BitArray(bitarray('0000000000000000')))
        ip_id = Field(name='ip.id', domain=BitArray(nbBits=16))
        ip_flags = Field(name='ip.flags', domain=Data(dataType=BitArray(nbBits=3), originalValue=bitarray('000'), svas=SVAS.PERSISTENT))
        ip_frag_off = Field(name='ip.fragment', domain=Data(dataType=BitArray(nbBits=13), originalValue=bitarray('0000000000000'), svas=SVAS.PERSISTENT))
        ip_ttl = Field(name='ip.ttl', domain=Data(dataType=BitArray(nbBits=8), originalValue=bitarray('01000000'), svas=SVAS.PERSISTENT))
        ip_proto = Field(name='ip.proto', domain=Integer(value=self.upperProtocol, unitSize=AbstractType.UNITSIZE_8, endianness=AbstractType.ENDIAN_BIG, sign=AbstractType.SIGN_UNSIGNED))
        ip_checksum = Field(name='ip.checksum', domain=BitArray(bitarray('0000000000000000')))
        ip_saddr = Field(name='ip.src', domain=IPv4(self.localIP))
        ip_daddr = Field(
            name='ip.dst', domain=IPv4(self.remoteIP))
        ip_payload = Field(name='ip.payload', domain=Raw())

        ip_ihl.domain = Size([ip_ver,
                              ip_ihl,
                              ip_tos,
                              ip_tot_len,
                              ip_id, ip_flags,
                              ip_frag_off,
                              ip_ttl, ip_proto,
                              ip_checksum,
                              ip_saddr,
                              ip_daddr], dataType=BitArray(nbBits=4), factor=1/float(32))
        ip_tot_len.domain = Size([ip_ver,
                                  ip_ihl,
                                  ip_tos,
                                  ip_tot_len,
                                  ip_id,
                                  ip_flags,
                                  ip_frag_off,
                                  ip_ttl,
                                  ip_proto,
                                  ip_checksum,
                                  ip_saddr,
                                  ip_daddr,
                                  ip_payload], dataType=Integer(unitSize=AbstractType.UNITSIZE_16, sign=AbstractType.SIGN_UNSIGNED), factor=1/float(8))
        ip_checksum.domain = InternetChecksum(fields=[ip_ver,
                                                      ip_ihl,
                                                      ip_tos,
                                                      ip_tot_len,
                                                      ip_id,
                                                      ip_flags,
                                                      ip_frag_off,
                                                      ip_ttl,
                                                      ip_proto,
                                                      ip_checksum,
                                                      ip_saddr,
                                                      ip_daddr], dataType=Raw(nbBytes=2, unitSize=AbstractType.UNITSIZE_16))

        self.header = Symbol(name='IP layer', fields=[ip_ver,
                                                      ip_ihl,
                                                      ip_tos,
                                                      ip_tot_len,
                                                      ip_id,
                                                      ip_flags,
                                                      ip_frag_off,
                                                      ip_ttl,
                                                      ip_proto,
                                                      ip_checksum,
                                                      ip_saddr,
                                                      ip_daddr,
                                                      ip_payload])
Exemple #13
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
Exemple #14
0
 def __create_fields(self, symbol, results):
     size_of_size = 1
     for result in results:
         field_to_split, maxSize, indexInField = self.__getFieldFromIndex(
             result[0], symbol)
         self._logger.warning("[Field to split] : " + field_to_split.name +
                              "\n")
         first_field_dep, maxSizefd, indexInFieldfd = self.__getFieldFromIndex(
             result[1], symbol)
         if indexInFieldfd != 0:
             #Create a subfield in the first_field_dependency
             values_first_field_dep = first_field_dep.getValues()
             if len(set(values_first_field_dep)) > 1:
                 #Alt field
                 values_first_field_dep_before = []
                 values_first_field_dep_after = []
                 for value in values_first_field_dep:
                     values_first_field_dep_before.append(
                         value[:int(indexInFieldfd / 8)])
                     values_first_field_dep_after.append(
                         value[int(indexInFieldfd / 8):])
                 first_field_dep_before = Field(
                     domain=Alt(values_first_field_dep_before),
                     name=first_field_dep.name + "-0")
                 first_field_dep_after = Field(
                     domain=Alt(values_first_field_dep_after),
                     name=first_field_dep.name + "-1")
             else:
                 #Static field
                 value = values_first_field_dep[0]
                 value_first_field_dep_before = value[:indexInFieldfd]
                 value_first_field_dep_after = value[indexInFieldfd:]
                 first_field_dep_before = Field(
                     domain=Raw(value_first_field_dep_before),
                     name=first_field_dep.name + "-0")
                 first_field_dep_after = Field(
                     domain=Raw(value_first_field_dep_after),
                     name=first_field_dep.name + "-1")
             first_field_dep.fields = [
                 first_field_dep_before, first_field_dep_after
             ]
         self._logger.warning("[First field dependency] : " +
                              first_field_dep.name + "\n")
         field_dep = self.__get_field_dep(symbol, first_field_dep)
         #Check if static or Alt:
         values_before = []
         values_after = []
         field_to_split_values = field_to_split.getValues()
         if len(set(field_to_split_values)) > 1:
             #Alt field
             for value in field_to_split_values:
                 values_before.append(value[:int(indexInField / 8)])
                 values_after.append(value[int(indexInField / 8) +
                                           size_of_size:])
             #AltField before =>
             altField_before_Size = Field(domain=Alt(values_before),
                                          name=field_to_split.name +
                                          "-Before_SizeF")
             altField_after_Size = Field(domain=Alt(values_after),
                                         name=field_to_split.name +
                                         "-After_Size")
             sizeField = Field(domain=Size(field_dep),
                               name=field_to_split.name + "-Size")
             field_to_split.fields = [
                 altField_before_Size, sizeField, altField_after_Size
             ]
         else:
             #Static field
             value_before = field_to_split_values[0][:int(indexInField / 8)]
             value_after = field_to_split_values[0][int(indexInField / 8) +
                                                    size_of_size:]
             staticField_before_Size = Field(domain=Raw(value_before),
                                             name=field_to_split.name +
                                             "-Before_SizeF")
             staticField_after_Size = Field(domain=Raw(value_after),
                                            name=field_to_split.name +
                                            "-After_Size")
             sizeField = Field(domain=Size(field_dep),
                               name=field_to_split.name + "-Size")
             field_to_split.fields = [
                 staticField_before_Size, sizeField, staticField_after_Size
             ]
Exemple #15
0
 def create_field(self, name, did):
     domain = self.get_domain(did)
     field = Field(name=name, domain=domain)
     self.__fields[str(field.id)] = field
     return field
Exemple #16
0
    def initHeader(self):
        """Initialize the IP header according to the IP format definition.

        """

        ip_ver = Field(name='ip.version',
                       domain=BitArray(value=bitarray('0100')))  # IP Version 4
        ip_ihl = Field(name='ip.hdr_len', domain=BitArray(bitarray('0000')))
        ip_tos = Field(name='ip.tos',
                       domain=Data(dataType=BitArray(nbBits=8),
                                   originalValue=bitarray('00000000'),
                                   svas=SVAS.PERSISTENT))
        ip_tot_len = Field(name='ip.len',
                           domain=BitArray(bitarray('0000000000000000')))
        ip_id = Field(name='ip.id', domain=BitArray(nbBits=16))
        ip_flags = Field(name='ip.flags',
                         domain=Data(dataType=BitArray(nbBits=3),
                                     originalValue=bitarray('000'),
                                     svas=SVAS.PERSISTENT))
        ip_frag_off = Field(name='ip.fragment',
                            domain=Data(
                                dataType=BitArray(nbBits=13),
                                originalValue=bitarray('0000000000000'),
                                svas=SVAS.PERSISTENT))
        ip_ttl = Field(name='ip.ttl',
                       domain=Data(dataType=BitArray(nbBits=8),
                                   originalValue=bitarray('01000000'),
                                   svas=SVAS.PERSISTENT))
        ip_proto = Field(name='ip.proto',
                         domain=Integer(value=self.upperProtocol,
                                        unitSize=AbstractType.UNITSIZE_8,
                                        endianness=AbstractType.ENDIAN_BIG,
                                        sign=AbstractType.SIGN_UNSIGNED))
        ip_checksum = Field(name='ip.checksum',
                            domain=BitArray(bitarray('0000000000000000')))
        ip_saddr = Field(name='ip.src', domain=IPv4(self.localIP))
        ip_daddr = Field(name='ip.dst', domain=IPv4(self.remoteIP))
        ip_payload = Field(name='ip.payload', domain=Raw())

        ip_ihl.domain = Size([
            ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id, ip_flags, ip_frag_off,
            ip_ttl, ip_proto, ip_checksum, ip_saddr, ip_daddr
        ],
                             dataType=BitArray(nbBits=4),
                             factor=1 / float(32))
        ip_tot_len.domain = Size([
            ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id, ip_flags, ip_frag_off,
            ip_ttl, ip_proto, ip_checksum, ip_saddr, ip_daddr, ip_payload
        ],
                                 dataType=Integer(
                                     unitSize=AbstractType.UNITSIZE_16,
                                     sign=AbstractType.SIGN_UNSIGNED),
                                 factor=1 / float(8))
        ip_checksum.domain = InternetChecksum(
            fields=[
                ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id, ip_flags,
                ip_frag_off, ip_ttl, ip_proto, ip_checksum, ip_saddr, ip_daddr
            ],
            dataType=Raw(nbBytes=2, unitSize=AbstractType.UNITSIZE_16))

        self.header = Symbol(name='IP layer',
                             fields=[
                                 ip_ver, ip_ihl, ip_tos, ip_tot_len, ip_id,
                                 ip_flags, ip_frag_off, ip_ttl, ip_proto,
                                 ip_checksum, ip_saddr, ip_daddr, ip_payload
                             ])
Exemple #17
0
    def cluster(self, field, keyField):
        """Create and return new symbols according to a specific key
        field.

        >>> import binascii
        >>> from netzob.all import *
        >>> samples = [b"00ff2f000000", b"000020000000", b"00ff2f000000"]
        >>> messages = [RawMessage(data=binascii.unhexlify(sample)) for sample in samples]
        >>> f1 = Field(Raw(nbBytes=1))
        >>> f2 = Field(Raw(nbBytes=2))
        >>> f3 = Field(Raw(nbBytes=3))
        >>> symbol = Symbol([f1, f2, f3], messages=messages)
        >>> symbol.addEncodingFunction(TypeEncodingFunction(HexaString))
        >>> newSymbols = Format.clusterByKeyField(symbol, f2)
        >>> for sym in list(newSymbols.values()):
        ...     sym.addEncodingFunction(TypeEncodingFunction(HexaString))
        ...     print(sym.name + ":")
        ...     print(sym)
        Symbol_ff2f:
        Field | Field  | Field   
        ----- | ------ | --------
        '00'  | 'ff2f' | '000000'
        '00'  | 'ff2f' | '000000'
        ----- | ------ | --------
        Symbol_0020:
        Field | Field  | Field   
        ----- | ------ | --------
        '00'  | '0020' | '000000'
        ----- | ------ | --------


        :param field: the field we want to split in new symbols
        :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :param keyField: the field used as a key during the splitting operation
        :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :raise Exception if something bad happens
        """

        # Safe checks
        if field is None:
            raise TypeError("'field' should not be None")
        if keyField is None:
            raise TypeError("'keyField' should not be None")
        if keyField not in field.fields:
            raise TypeError("'keyField' is not a child of 'field'")

        newSymbols = collections.OrderedDict()

        keyFieldMessageValues = keyField.getMessageValues(
            encoded=False, styled=False)
        newSymbolsSplittedMessages = {}

        # we identify what would be the best type of the key field
        keyFieldType = ASCII
        for message, keyFieldValue in list(keyFieldMessageValues.items()):
            # If the value cannot be parsed as ASCII, we convert it to HexaString
            if not ASCII().canParse(
                    TypeConverter.convert(keyFieldValue, Raw, BitArray)):
                keyFieldType = HexaString
                break

            # Even if the value is theoritically parsable as ASCII, some caracters cannot be encoded, so we double check
            tmp_value = TypeConverter.convert(keyFieldValue, Raw, ASCII)
            tmp2_value = TypeConverter.convert(tmp_value, ASCII, Raw)
            if keyFieldValue != tmp2_value:
                # This means we cannot retrieve the original value by encoding and then decoding in ASCII
                keyFieldType = HexaString
                break

        # we create a symbol for each of these uniq values
        for message, keyFieldValue in list(keyFieldMessageValues.items()):
            keyFieldValue = TypeConverter.convert(keyFieldValue, Raw,
                                                  keyFieldType)
            if keyFieldValue not in list(newSymbols.keys()):
                if type(keyFieldValue) is str:
                    symbolName = "Symbol_{0}".format(keyFieldValue)
                else:
                    symbolName = "Symbol_{0}".format(
                        keyFieldValue.decode("utf-8"))
                newSymbols[keyFieldValue] = Symbol(
                    name=symbolName, messages=[message])
                splittedMessages = DataAlignment.align(
                    [message.data], field, encoded=False)
                newSymbolsSplittedMessages[
                    keyFieldValue] = [splittedMessages[0]]
            else:
                newSymbols[keyFieldValue].messages.append(message)
                splittedMessages = DataAlignment.align(
                    [message.data], field, encoded=False)
                newSymbolsSplittedMessages[keyFieldValue].append(
                    splittedMessages[0])

        for newSymbolKeyValue, newSymbol in list(newSymbols.items()):
            # we recreate the same fields in this new symbol as the fields that exist in the original symbol
            newSymbol.clearFields()
            for i, f in enumerate(field.fields):
                if f == keyField:
                    newFieldDomain = TypeConverter.convert(newSymbolKeyValue,
                                                           keyFieldType, Raw)
                else:
                    newFieldDomain = set()
                    for j in range(
                            len(newSymbolsSplittedMessages[
                                newSymbolKeyValue])):
                        newFieldDomain.add(newSymbolsSplittedMessages[
                            newSymbolKeyValue][j][i])
                    newFieldDomain = list(newFieldDomain)
                newF = Field(name=f.name, domain=newFieldDomain)
                newF.parent = newSymbol
                newSymbol.fields.append(newF)

            # we remove endless fields that accepts no values
            cells = newSymbol.getCells(
                encoded=False, styled=False, transposed=False)
            max_i_cell_with_value = 0
            for line in cells:
                for i_cell, cell in enumerate(line):
                    if cell != '' and max_i_cell_with_value < i_cell:
                        max_i_cell_with_value = i_cell
            newSymbol.clearFields()
            for i, f in enumerate(field.fields[:max_i_cell_with_value + 1]):
                if f == keyField:
                    newFieldDomain = TypeConverter.convert(newSymbolKeyValue,
                                                           keyFieldType, Raw)
                else:
                    newFieldDomain = set()
                    for j in range(
                            len(newSymbolsSplittedMessages[
                                newSymbolKeyValue])):
                        newFieldDomain.add(newSymbolsSplittedMessages[
                            newSymbolKeyValue][j][i])
                    newFieldDomain = list(newFieldDomain)
                newF = Field(name=f.name, domain=newFieldDomain)
                newF.parent = newSymbol
                newSymbol.fields.append(newF)

        return newSymbols
Exemple #18
0
    def execute(self, field):
        """Executes the field edition following the specified messages.
        Children of the specified field will be replaced with new fields.

        :param field: the format definition that will be user
        :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :raise Exception: if something bad happens
        """

        if field is None:
            raise TypeError("The field cannot be None")
        fieldValues = [
            TypeConverter.convert(data, Raw, HexaString)
            for data in field.getValues(encoded=False)
        ]

        if len(fieldValues) == 0:
            raise Exception("No value found in the field.")

        # Retrieve longuest field value
        maxLengthFieldValue = len(max(fieldValues, key=len))

        # definies the step following specified unitsize
        stepUnitsize = self.__computeStepForUnitsize()

        # Vertical identification of variation
        indexedValues = []
        for i in range(0, maxLengthFieldValue, stepUnitsize):
            currentIndexValue = []
            for fieldValue in fieldValues:
                if i < len(fieldValue):
                    currentIndexValue.append(
                        fieldValue[i:min(len(fieldValue), i + stepUnitsize)])
                else:
                    currentIndexValue.append(b'')
            indexedValues.append(currentIndexValue)

        # If requested, merges the adjacent static fields
        if self.mergeAdjacentStaticFields:
            result = []
            staticSequences = []
            for values in indexedValues:
                if len(set(values)) == 1:
                    # static
                    staticSequences.append(values[0])
                else:
                    # dynamic
                    if len(staticSequences) > 0:
                        result.append([b''.join(staticSequences)])
                        staticSequences = []
                    result.append(values)
            if len(staticSequences) > 0:
                result.append([b''.join(staticSequences)])
            indexedValues = result

        # If requested, merges the adjacent dynamic fields
        if self.mergeAdjacentDynamicFields:
            result = []
            dynamicSequences = []
            for values in indexedValues:
                if len(set(values)) > 1:
                    # dynamic
                    dynamicSequences.append(values)
                else:
                    # static
                    if len(dynamicSequences) > 0:
                        dynValues = zip(*dynamicSequences)
                        tmp_result = []
                        for d in dynValues:
                            tmp_result.append(b''.join(
                                [x if x is not None else b'' for x in d]))
                        result.append(tmp_result)
                        dynamicSequences = []
                    result.append(values)
            if len(dynamicSequences) > 0:
                dynValues = zip(*dynamicSequences)
                tmp_result = []
                for d in dynValues:
                    tmp_result.append(b''.join(
                        [x if x is not None else b'' for x in d]))
                result.append(tmp_result)

            indexedValues = result

        # Create a field for each entry
        newFields = []
        for (i, val) in enumerate(indexedValues):
            fName = "Field-{0}".format(i)
            fDomain = DomainFactory.normalizeDomain([
                Raw(TypeConverter.convert(v, HexaString, BitArray))
                for v in set(val)
            ])
            newFields.append(Field(domain=fDomain, name=fName))

        # attach encoding functions
        for newField in newFields:
            newField.encodingFunctions = list(field.encodingFunctions.values())

        field.fields = newFields
    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
Exemple #20
0
    def __automate_mid_field_creation(self, results, symbol, endianness):
        """
                This method attempts to create a CRC field. It creates either a big or little endian CRC relation field using
                 the value b'\xca\xfe\x00\x00\x00\x00\xba\xbe' to compute the CRC
                , the b'\x00\x00\x00\x00' is then replaced by the computed CRC in the message.

                :param results: list of CRC indexes
                :param symbol: The symbol in wich we want to define CRC fields
                :param endianness: A string stating the endianness of the CRC, should either be "big" or "little"
                """
        domain_field_list = []
        subfields = []
        for crcindex in results:
            searchedfield, field_size, field_index = self.__getFieldFromIndex(crcindex, symbol)
            # Get all the fields after the current field (to define the CRC domain Relation
            afterField = False

            if field_size / 8 == 4:
                for i,f in enumerate(symbol.fields):
                    if f.name == searchedfield.name:
                        domain_field_list.append(symbol.fields[i-1])
                        domain_field_list.append(symbol.fields[i+1])
                # Is the field just CRC or more?
                if endianness == 'little':
                    searchedfield.name = "CRC32_mid_LE" + str(crcindex)
                else:
                    searchedfield.name = "CRC32_mid_BE" + str(crcindex)
                searchedfield.domain = CRC32(domain_field_list, endianness=endianness)
            elif field_size > 4:
                # The Field is the CRC and something else.
                if field_index == 0:
                    # CRC at beginning of field. Create new fields after CRC
                    # Create a list of possible values
                    val_list = []
                    for val in searchedfield.getValues():
                        val_list.append(val[4:])
                        # Make a set
                    val_set = set(val_list)
                    newf = self.__define_field(val_set,searchedfield)
                    #Compute second field (the one before the CRC
                    val_list = [] #List containing the first four bytes used to compute CRC32 (the 4 bytes prior to the CRC)
                    temp_field_list = []
                    for prevalue in symbol.getValues():
                        prevalue = prevalue[crcindex - 4:crcindex]
                        val_list.append(prevalue)
                    val_list = set(val_list)
                    for i, f in enumerate(symbol.fields):
                        if f.name == searchedfield.name:
                            prevField,minSize,maxSize = self.__getFieldFromIndex(crcindex - 1,symbol)
                            if maxSize >= 4:
                                #The four bytes are contained in only one field. We create a subfield
                                newf2 = self.__define_field(val_list, temp)
                            else:
                                #The four bytes are split into several fields. We delete all thes fields and create a new field and insert it at the index of the first of these fields in symbol.fields()
                                for j in range(1,4):
                                    try:
                                        prevField, minSize, maxSize = self.__getFieldFromIndex(crcindex - j, symbol)
                                    except:
                                        pass
                                    temp_field_list.append(prevField)
                                    temp_field_set = set(temp_field_list) #All the fields containing the four bytes
                                    for fiel in temp_field_set:
                                        miny = 99999
                                        stuffToDel = []
                                        for y,fol in enumerate(symbol.fields):
                                            if fol == fiel:
                                                if y < miny:
                                                    miny = y
                                                    stuffToDel.append(y)
                                                    temp = symbol.fields[y]
                    newf2 = self.__define_field(val_list,temp)
                    domain_field_list.append(newf2)
                    domain_field_list.append(Field(domain=Raw(b'\x00\x00\x00\x00')))
                    domain_field_list.append(newf)
                    if endianness == 'little':
                        crc32field = Field(name="CRC32_mid_LE" + str(crcindex),
                                           domain=CRC32(domain_field_list, endianness=endianness))
                    else:
                        crc32field = Field(name="CRC32_mid_BE" + str(crcindex),
                                           domain=CRC32(domain_field_list, endianness=endianness))
                    subfields.append(crc32field)
                    subfields.append(newf)
                elif field_index / 8 + 4 == field_size / 8:
                    # CRC at end of field. Create new fields before CRC
                    # Create a list of possible values
                    val_list = []
                    for val in searchedfield.getValues():
                        val_list.append(val[:field_index])
                        # Make a set
                    val_set = set(val_list)
                    newf = self.__define_field(val_set,searchedfield)
                    #Compute second field (the one after the CRC
                    val_list = [] #List containing the last four bytes used to compute CRC32 (the 4 bytes after the CRC)
                    temp_field_list = []
                    for prevalue in symbol.getValues():
                        prevalue = prevalue[crcindex:crcindex+4]
                        val_list.append(prevalue)
                    val_list = set(val_list)
                    for i, f in enumerate(symbol.fields):
                        if f.name == searchedfield.name:
                            prevField,minSize,maxSize = self.__getFieldFromIndex(crcindex + 1,symbol)
                            if maxSize >= 4:
                                #The four bytes are contained in only one field. We create a subfield
                                newf2 = self.__define_field(val_list,temp)
                            else:
                                #The four bytes are split into several fields. We delete all thes fields and create a new field and insert it at the index of the first of these fields in symbol.fields()
                                for j in range(1,4):
                                    prevField, minSize, maxSize = self.__getFieldFromIndex(crcindex + j, symbol)
                                    temp_field_list.append(prevField)
                                    temp_field_list = set(temp_field_list) #All the fields containing the four bytes
                                    for fiel in set(temp_field_list):
                                        miny = 99999
                                        for y,fol in enumerate(symbol.fields):
                                            if fol == fiel:
                                                if y < miny:
                                                    miny = y
                                                    temp = symbol.fields[y]
                                                del symbol.fields[y]
                                        symbol.fields[miny] = self.__define_field(val_list,temp)
                    newf2 = self.__define_field(val_list,temp)
                    domain_field_list.append(newf)
                    domain_field_list.append(Field(domain=Raw(b'\x00\x00\x00\x00')))
                    domain_field_list.append(newf2)
                    if endianness == 'little':
                        crc32field = Field(name="CRC32_mid_LE" + str(crcindex),
                                           domain=CRC32(domain_field_list, endianness=endianness))
                    else:
                        crc32field = Field(name="CRC32_mid_BE" + str(crcindex),
                                           domain=CRC32(domain_field_list, endianness=endianness))
                    subfields.append(newf)
                    subfields.append(crc32field)
                else:
                    # CRC in the middle. Create new fields before and after CRC
                    val_list1 = []
                    val_list2 = []
                    for val in searchedfield.getValues():
                        val_list1.append(val[4:])
                        val_list2.append(val[:field_index])
                    # Make a set
                    val_set1 = set(val_list1)
                    val_set2 = set(val_list2)
                    newf1 = self.__define_field(val_set1,searchedfield)
                    newf2 = self.__define_field(val_set2,searchedfield)
                    domain_field_list.insert(0, newf2)
                    if endianness == 'little':
                        crc32field = Field(name="CRC32_LE" + str(crcindex),
                                           domain=CRC32(domain_field_list, endianness=endianness))
                    else:
                        crc32field = Field(name="CRC32_BE" + str(crcindex),
                                           domain=CRC32(domain_field_list, endianness=endianness))
                    subfields.append(newf1)
                    subfields.append(crc32field)
                    subfields.append(newf2)
                searchedfield.fields = subfields
Exemple #21
0
    def __automate_field_creation(self,results,symbol,endianness):
        """
        This method attempts to create a CRC field. It creates either a big or little
        endian CRC relation field using all the following fields to compute the CRC.

        :param results: list of CRC indexes
        :param symbol: The symbol in wich we want to define CRC fields
        :param endianness: A string stating the endianness of the CRC, should either be "big" or "little"
        """
        domain_field_list = []
        subfields = []
        for crcindex in results:
            searchedfield, field_size, field_index = self.__getFieldFromIndex(crcindex, symbol)
            # Get all the fields after the current field (to define the CRC domain Relation
            afterField = False
            for f in symbol.fields:
                if afterField:
                    domain_field_list.append(f)
                elif f.name == searchedfield.name:
                    afterField = True
            if field_size / 8 == 4:
                # Is the field just CRC or more?
                if endianness == 'little':
                    searchedfield.name = "CRC32_LE" + str(crcindex)
                else:
                    searchedfield.name = "CRC32_BE" + str(crcindex)
                searchedfield.domain = CRC32(domain_field_list, endianness=endianness)
            elif field_size > 4:
                # The Field is the CRC and something else.
                if field_index == 0:
                    # CRC at beginning of field. Create new fields after CRC
                    # Create a list of possible values
                    val_list = []
                    for val in searchedfield.getValues():
                        val_list.append(val[4:])
                        # Make a set
                    val_set = set(val_list)
                    newf = self.__define_field(val_set,searchedfield)
                    domain_field_list.insert(0, newf)
                    if endianness == 'little':
                        crc32field = Field(name="CRC32_LE" + str(crcindex), domain=CRC32(domain_field_list,endianness=endianness))
                    else:
                        crc32field = Field(name="CRC32_BE" + str(crcindex), domain=CRC32(domain_field_list,endianness=endianness))
                    subfields.append(crc32field)
                    subfields.append(newf)
                elif field_index / 8 + 4 == field_size / 8:
                    # CRC at end of field. Create new fields before CRC
                    # Create a list of possible values
                    val_list = []
                    for val in searchedfield.getValues():
                        val_list.append(val[:field_index])
                        # Make a set
                    val_set = set(val_list)
                    newf = self.__define_field(val_set,searchedfield)
                    if endianness == 'little':
                        crc32field = Field(name="CRC32_LE" + str(crcindex), domain=CRC32(domain_field_list,endianness=endianness))
                    else:
                        crc32field = Field(name="CRC32_BE" + str(crcindex), domain=CRC32(domain_field_list,endianness=endianness))
                    subfields.append(newf)
                    subfields(crc32field)
                else:
                    # CRC in the middle. Create new fields before and after CRC
                    val_list1 = []
                    val_list2 = []
                    for val in searchedfield.getValues():
                        val_list1.append(val[4:])
                        val_list2.append(val[:field_index])
                    # Make a set
                    val_set1 = set(val_list1)
                    val_set2 = set(val_list2)
                    newf1 = self.__define_field(val_set1,searchedfield)
                    newf2 = self.__define_field(val_set2,searchedfield)
                    domain_field_list.insert(0, newf2)
                    if endianness == 'little':
                        crc32field = Field(name="CRC32_LE" + str(crcindex), domain=CRC32(domain_field_list,endianness=endianness))
                    else:
                        crc32field = Field(name="CRC32_BE" + str(crcindex), domain=CRC32(domain_field_list,endianness=endianness))
                    subfields.append(newf1)
                    subfields.append(crc32field)
                    subfields.append(newf2)
                searchedfield.fields = subfields
Exemple #22
0
    def initHeader(self):
        """Initialize the IP header according to the IP format definition.

        """

        # Ethernet header

        # Retrieve remote MAC address
        dstMacAddr = arpreq.arpreq(self.remoteIP)
        if dstMacAddr is not None:
            dstMacAddr = dstMacAddr.replace(':', '')
            dstMacAddr = binascii.unhexlify(dstMacAddr)
        else:
            # Force ARP resolution
            p = subprocess.Popen(["/bin/ping", "-c1", self.remoteIP])
            p.wait()
            time.sleep(0.1)

            dstMacAddr = arpreq.arpreq(self.remoteIP)
            if dstMacAddr is not None:
                dstMacAddr = dstMacAddr.replace(':', '')
                dstMacAddr = binascii.unhexlify(dstMacAddr)
            else:
                raise Exception("Cannot resolve IP address to a MAC address for IP: '{}'".format(self.remoteIP))

        # Retrieve local MAC address
        srcMacAddr = self.get_interface_addr(bytes(self.interface, 'utf-8'))[1]

        eth_dst = Field(name='eth.dst', domain=Raw(dstMacAddr))
        eth_src = Field(name='eth.src', domain=Raw(srcMacAddr))
        eth_type = Field(name='eth.type', domain=Raw(b"\x08\x00"))


        # IP header

        ip_ver = Field(
            name='ip.version', domain=BitArray(
                value=bitarray('0100')))  # IP Version 4
        ip_ihl = Field(name='ip.hdr_len', domain=BitArray(bitarray('0000')))
        ip_tos = Field(
            name='ip.tos',
            domain=Data(
                dataType=BitArray(nbBits=8),
                originalValue=bitarray('00000000'),
                svas=SVAS.PERSISTENT))
        ip_tot_len = Field(
            name='ip.len', domain=BitArray(bitarray('0000000000000000')))
        ip_id = Field(name='ip.id', domain=BitArray(nbBits=16))
        ip_flags = Field(name='ip.flags', domain=Data(dataType=BitArray(nbBits=3), originalValue=bitarray('000'), svas=SVAS.PERSISTENT))
        ip_frag_off = Field(name='ip.fragment', domain=Data(dataType=BitArray(nbBits=13), originalValue=bitarray('0000000000000'), svas=SVAS.PERSISTENT))
        ip_ttl = Field(name='ip.ttl', domain=Data(dataType=BitArray(nbBits=8), originalValue=bitarray('01000000'), svas=SVAS.PERSISTENT))
        ip_proto = Field(name='ip.proto', domain=Integer(value=self.upperProtocol, unitSize=AbstractType.UNITSIZE_8, endianness=AbstractType.ENDIAN_BIG, sign=AbstractType.SIGN_UNSIGNED))
        ip_checksum = Field(name='ip.checksum', domain=BitArray(bitarray('0000000000000000')))
        ip_saddr = Field(name='ip.src', domain=IPv4(self.localIP))
        ip_daddr = Field(
            name='ip.dst', domain=IPv4(self.remoteIP))
        ip_payload = Field(name='ip.payload', domain=Raw())

        ip_ihl.domain = Size([ip_ver,
                              ip_ihl,
                              ip_tos,
                              ip_tot_len,
                              ip_id, ip_flags,
                              ip_frag_off,
                              ip_ttl, ip_proto,
                              ip_checksum,
                              ip_saddr,
                              ip_daddr], dataType=BitArray(nbBits=4), factor=1/float(32))
        ip_tot_len.domain = Size([ip_ver,
                                  ip_ihl,
                                  ip_tos,
                                  ip_tot_len,
                                  ip_id,
                                  ip_flags,
                                  ip_frag_off,
                                  ip_ttl,
                                  ip_proto,
                                  ip_checksum,
                                  ip_saddr,
                                  ip_daddr,
                                  ip_payload], dataType=Integer(unitSize=AbstractType.UNITSIZE_16, sign=AbstractType.SIGN_UNSIGNED), factor=1/float(8))
        ip_checksum.domain = InternetChecksum(fields=[ip_ver,
                                                      ip_ihl,
                                                      ip_tos,
                                                      ip_tot_len,
                                                      ip_id,
                                                      ip_flags,
                                                      ip_frag_off,
                                                      ip_ttl,
                                                      ip_proto,
                                                      ip_checksum,
                                                      ip_saddr,
                                                      ip_daddr], dataType=Raw(nbBytes=2, unitSize=AbstractType.UNITSIZE_16))
        
        self.header = Symbol(name='Ethernet layer', fields=[eth_dst,
                                                            eth_src,
                                                            eth_type,
                                                            ip_ver,
                                                            ip_ihl,
                                                            ip_tos,
                                                            ip_tot_len,
                                                            ip_id,
                                                            ip_flags,
                                                            ip_frag_off,
                                                            ip_ttl,
                                                            ip_proto,
                                                            ip_checksum,
                                                            ip_saddr,
                                                            ip_daddr,
                                                            ip_payload])
Exemple #23
0
 def setUp(self) -> None:
     """
     Construct AbstractFields with the same name.
     Use a subclass implementing AbstractField to instantiate.
     """
     self.afs = [Field(name="NEMESYS")] * 5
Exemple #24
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
    def cluster(self, field, keyField):
        """Create and return new symbols according to a specific key
        field.

        >>> import binascii
        >>> from netzob.all import *
        >>> samples = [b"00ff2f000000", b"000020000000", b"00ff2f000000"]
        >>> messages = [RawMessage(data=binascii.unhexlify(sample)) for sample in samples]
        >>> f1 = Field(Raw(nbBytes=1))
        >>> f2 = Field(Raw(nbBytes=2))
        >>> f3 = Field(Raw(nbBytes=3))
        >>> symbol = Symbol([f1, f2, f3], messages=messages)
        >>> symbol.addEncodingFunction(TypeEncodingFunction(HexaString))
        >>> newSymbols = Format.clusterByKeyField(symbol, f2)
        >>> for sym in list(newSymbols.values()):
        ...     sym.addEncodingFunction(TypeEncodingFunction(HexaString))
        ...     print(sym.name + ":")
        ...     print(sym)
        Symbol_ff2f:
        Field | Field  | Field   
        ----- | ------ | --------
        '00'  | 'ff2f' | '000000'
        '00'  | 'ff2f' | '000000'
        ----- | ------ | --------
        Symbol_0020:
        Field | Field  | Field   
        ----- | ------ | --------
        '00'  | '0020' | '000000'
        ----- | ------ | --------


        :param field: the field we want to split in new symbols
        :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :param keyField: the field used as a key during the splitting operation
        :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField`
        :raise Exception if something bad happens
        """

        # Safe checks
        if field is None:
            raise TypeError("'field' should not be None")
        if keyField is None:
            raise TypeError("'keyField' should not be None")
        if keyField not in field.fields:
            raise TypeError("'keyField' is not a child of 'field'")

        newSymbols = collections.OrderedDict()

        keyFieldMessageValues = keyField.getMessageValues(encoded=False,
                                                          styled=False)
        newSymbolsSplittedMessages = {}

        # we identify what would be the best type of the key field
        keyFieldType = ASCII
        for message, keyFieldValue in list(keyFieldMessageValues.items()):
            # If the value cannot be parsed as ASCII, we convert it to HexaString
            if not ASCII().canParse(
                    TypeConverter.convert(keyFieldValue, Raw, BitArray)):
                keyFieldType = HexaString
                break

            # Even if the value is theoritically parsable as ASCII, some caracters cannot be encoded, so we double check
            tmp_value = TypeConverter.convert(keyFieldValue, Raw, ASCII)
            tmp2_value = TypeConverter.convert(tmp_value, ASCII, Raw)
            if keyFieldValue != tmp2_value:
                # This means we cannot retrieve the original value by encoding and then decoding in ASCII
                keyFieldType = HexaString
                break

        # we create a symbol for each of these uniq values
        for message, keyFieldValue in list(keyFieldMessageValues.items()):
            keyFieldValue = TypeConverter.convert(keyFieldValue, Raw,
                                                  keyFieldType)
            if keyFieldValue not in list(newSymbols.keys()):
                if type(keyFieldValue) is str:
                    symbolName = "Symbol_{0}".format(keyFieldValue)
                else:
                    symbolName = "Symbol_{0}".format(
                        keyFieldValue.decode("utf-8"))
                newSymbols[keyFieldValue] = Symbol(name=symbolName,
                                                   messages=[message])
                splittedMessages = DataAlignment.align([message.data],
                                                       field,
                                                       encoded=False)
                newSymbolsSplittedMessages[keyFieldValue] = [
                    splittedMessages[0]
                ]
            else:
                newSymbols[keyFieldValue].messages.append(message)
                splittedMessages = DataAlignment.align([message.data],
                                                       field,
                                                       encoded=False)
                newSymbolsSplittedMessages[keyFieldValue].append(
                    splittedMessages[0])

        for newSymbolKeyValue, newSymbol in list(newSymbols.items()):
            # we recreate the same fields in this new symbol as the fields that exist in the original symbol
            newSymbol.clearFields()
            for i, f in enumerate(field.fields):
                if f == keyField:
                    newFieldDomain = TypeConverter.convert(
                        newSymbolKeyValue, keyFieldType, Raw)
                else:
                    newFieldDomain = set()
                    for j in range(
                            len(newSymbolsSplittedMessages[newSymbolKeyValue])
                    ):
                        newFieldDomain.add(
                            newSymbolsSplittedMessages[newSymbolKeyValue][j]
                            [i])
                    newFieldDomain = list(newFieldDomain)
                newF = Field(name=f.name, domain=newFieldDomain)
                newF.parent = newSymbol
                newSymbol.fields.append(newF)

            # we remove endless fields that accepts no values
            cells = newSymbol.getCells(encoded=False,
                                       styled=False,
                                       transposed=False)
            max_i_cell_with_value = 0
            for line in cells:
                for i_cell, cell in enumerate(line):
                    if cell != '' and max_i_cell_with_value < i_cell:
                        max_i_cell_with_value = i_cell
            newSymbol.clearFields()
            for i, f in enumerate(field.fields[:max_i_cell_with_value + 1]):
                if f == keyField:
                    newFieldDomain = TypeConverter.convert(
                        newSymbolKeyValue, keyFieldType, Raw)
                else:
                    newFieldDomain = set()
                    for j in range(
                            len(newSymbolsSplittedMessages[newSymbolKeyValue])
                    ):
                        newFieldDomain.add(
                            newSymbolsSplittedMessages[newSymbolKeyValue][j]
                            [i])
                    newFieldDomain = list(newFieldDomain)
                newF = Field(name=f.name, domain=newFieldDomain)
                newF.parent = newSymbol
                newSymbol.fields.append(newF)

        return newSymbols
Exemple #26
0
    def _createSubFieldsForADynamicField(self, field, align, semanticTags):
        """Analyzes the dynamic field provided and create sub fields following
        the provided semantic tags."""

        if field is None:
            raise TypeError("Field cannot be None")
        if align is None:
            raise TypeError("Align cannot be None")
        if semanticTags is None:
            raise TypeError("SemanticTags cannot be None")

        self._logger.debug(
            "Create subfields for dynamic field {0} : {1}".format(
                field.name, field.regex))

        subFields = []

        currentTag = None
        currentTagLength = 0

        semanticTagsForEachMessage = field.getSemanticTagsByMessage()

        for index, tag in list(semanticTags.items()):
            if tag != currentTag:
                # Create a sub field
                if currentTagLength > 0:
                    values = self._getFieldValuesWithTag(
                        field, semanticTagsForEachMessage, currentTag)
                    subFields.append((currentTag, values))
                currentTagLength = 0
            currentTag = tag
            currentTagLength += 1
        if currentTagLength > 0:
            values = self._getFieldValuesWithTag(field,
                                                 semanticTagsForEachMessage,
                                                 currentTag)
            subFields.append((currentTag, values))

        self._logger.debug("Identified subFields : {0}".format(subFields))

        for iSubField, (tag, values) in enumerate(subFields):
            if len(values) > 0:
                if tag == b"None":
                    minValue = None
                    maxValue = None
                    for v in values:
                        if minValue is None or len(v) < minValue:
                            minValue = len(v)
                        if maxValue is None or len(v) > maxValue:
                            maxValue = len(v)
                    subField = Field(
                        b"{0}_{1}".format(field.getName(), iSubField),
                        b"(.{" + str(minValue) + b"," + str(maxValue) + b"})",
                        field.getSymbol())

                    field.addLocalField(subField)
                else:
                    # create regex based on unique values
                    newRegex = '|'.join(list(set(values)))
                    newRegex = b"({0})".format(newRegex)
                    subField = Field(
                        b"{0}_{1}".format(field.getName(), iSubField),
                        newRegex, field.getSymbol())
                    field.addLocalField(subField)
Exemple #27
0
    def __seek_ip(self, ip, symbol, create_fields=False, two_terms=False):

        #Convert IP to hex value:
        hexipstring = binascii.hexlify(socket.inet_aton(ip))
        hexipstring = binascii.unhexlify(hexipstring)
        index_list = []
        for message in symbol.messages:
            results = self.__core_find(message.data, hexipstring, index_list,
                                       two_terms)
            #Change stdout to get message print in buffer
            old_stdout = sys.stdout
            sys.stdout = buffer1 = io.StringIO()
            print(message)
            sys.stdout = old_stdout
            #Print results using click
            self._logger.warning("Results for [Message] : \n" +
                                 buffer1.getvalue() + "\n")
            self._logger.warning("[Number of results found] : " +
                                 str(results.total_length) + "\n")
            self._logger.warning("Result indexes in message: \n ")
            self._logger.warning("[Whole IP Big Endian] : " +
                                 str(results.full_be) + "\n")
            self._logger.warning("[Three last terms of IP Big Endian] : " +
                                 str(results.one_less_be) + "\n")
            self._logger.warning("[Two last terms of IP Big Endian] : " +
                                 str(results.two_less_be) + "\n")
            self._logger.warning("[Whole IP Little Endian] : " +
                                 str(results.full_le) + "\n")
            self._logger.warning("[Three last terms of IP Little Endian] : " +
                                 str(results.one_less_le) + "\n")
            self._logger.warning("[Two last terms of IP Little Endian] : " +
                                 str(results.two_less_le) + "\n")
            if create_fields:
                self._logger.warning("Attempting to create new fields")
                if symbol.fields:
                    self._logger.warning("Refining search to fields...")
                    for field in symbol.fields:
                        subfield_index_list = []
                        field_values = field.getValues()
                        number_of_values = len(set(field_values))
                        # Get field length
                        max_length = max([len(i) for i in field_values])
                        # Check if values in messages are different for need to create an alternative field or a simple raw field (above 1 if several values):
                        if number_of_values > 1:
                            # More than one value => MUST CREATE ALT FIELD
                            # TODO
                            pass
                        else:
                            mess = field_values[0]
                            field_result = self.__core_find(
                                mess, hexipstring, index_list, two_terms)
                            if field_result.full_be or field_result.one_less_be or field_result.two_less_be or field_result.full_le or field_result.one_less_le or field_result.two_less_le:
                                # Searchstring not always split in between fields => Need to create subfields
                                self._logger.warning(
                                    "Searchstring inside fields, creating subfields..."
                                )
                                # Create field dict which contains fields and index
                                fields_dict = dict()
                                if number_of_values > 1:
                                    #More than one value => MUST CREATE ALT FIELD
                                    #TODO
                                    pass
                                else:
                                    #Can create simple static subfield
                                    for i in field_result.full_be:
                                        fields_dict[i] = Field(
                                            name='FullIpBe' + str(i),
                                            domain=Raw(hexipstring))
                                        subfield_index_list.append(i)
                                        subfield_index_list.append(i + 4)
                                    for i in field_result.one_less_be:
                                        fields_dict[i] = Field(
                                            name='ThreeTIpBe' + str(i),
                                            domain=Raw(hexipstring[1:]))
                                        subfield_index_list.append(i)
                                        subfield_index_list.append(i + 3)
                                    for i in field_result.two_less_be:
                                        fields_dict[i] = Field(
                                            name='TwoTIpBe' + str(i),
                                            domain=Raw(hexipstring[2:]))
                                        subfield_index_list.append(i)
                                        subfield_index_list.append(i + 2)
                                    for i in field_result.full_le:
                                        fields_dict[i] = Field(
                                            name='FullIpLe' + str(i),
                                            domain=Raw(hexipstring[::-1]))
                                        subfield_index_list.append(i)
                                        subfield_index_list.append(i + 4)
                                    for i in field_result.one_less_le:
                                        fields_dict[i] = Field(
                                            name='ThreeTIpLe' + str(i),
                                            domain=Raw(hexipstring[1:][::-1]))
                                        subfield_index_list.append(i)
                                        subfield_index_list.append(i + 3)
                                        fields_dict[i] = Field(
                                            name='TwoTIpLe' + str(i),
                                            domain=Raw(hexipstring[2:][::-1]))
                                        subfield_index_list.append(i)
                                        subfield_index_list.append(i + 2)
                                    #Sort list in order
                                    subfield_index_list.append(max_length)
                                    subfield_index_list.insert(0, 0)
                                    #Remove duplicates (there shouldn't be any!)
                                    subfield_index_list = list(
                                        set(subfield_index_list))
                                    subfield_index_list = sorted(
                                        subfield_index_list, key=int)
                                    #Create static field for every two elements of the subfield index_list as they represent beginning and end
                                    for i, x in enumerate(subfield_index_list):
                                        #Check if index is pair
                                        if (i % 2 == 0):
                                            #Create static field and store it's beginning index in the structure
                                            try:
                                                fields_dict[x] = Field(
                                                    name='Field' + str(i),
                                                    domain=Raw(field_values[0][
                                                        subfield_index_list[i]:
                                                        subfield_index_list[i +
                                                                            1]]
                                                               ))
                                            except:
                                                fields_dict[x] = Field(
                                                    name='Field' + str(i),
                                                    domain=Raw(
                                                        field_values[0]
                                                        [subfield_index_list[
                                                            i]:]))
                                        else:
                                            # Don't do shit
                                            pass
                                    #Create a list of all subfields in order
                                    od = collections.OrderedDict(
                                        sorted(fields_dict.items()))
                                    field_list = list(od.values())
                                if not field.fields:
                                    #No subfields
                                    field.fields = field_list
                                else:
                                    #Already contains subfields. We need to just insert our IP subfields in it.
                                    #Get the indexes of Fields which have a name other than FieldX (where X is a number)
                                    only_Ip_fields_dict = dict()
                                    for index, element in fields_dict.items():
                                        if not element.name[:5] == "Field":
                                            only_Ip_fields_dict[
                                                index] = element
                                    #Find to which field these indexes belong to in the old symbol
                                    for index, element in only_Ip_fields_dict.items(
                                    ):
                                        new_field_dict = dict()
                                        field_to_split, maxSize, indexInField = self.__getFieldFromIndex(
                                            index, field)
                                        indexInField = int(indexInField / 8)
                                        new_field_dict[indexInField] = element
                                        if field_to_split.getValues(
                                        )[0][:indexInField]:
                                            new_field_dict[0] = Field(
                                                name='FieldBeforeIp' +
                                                str(index),
                                                domain=Raw(
                                                    field_to_split.getValues()
                                                    [0][:indexInField]))
                                        new_field_dict[indexInField] = element
                                        #Get Size of the IP Field
                                        minSize, sizeIp = element.domain.dataType.size
                                        sizeIp = int(sizeIp / 8)
                                        if field_to_split.getValues(
                                        )[0][indexInField + sizeIp:]:
                                            new_field_dict[
                                                indexInField + sizeIp] = Field(
                                                    name='FieldAfterIp' +
                                                    str(index),
                                                    domain=Raw(field_to_split.
                                                               getValues()[0]
                                                               [indexInField +
                                                                sizeIp:]))
                                        od = collections.OrderedDict(
                                            sorted(new_field_dict.items()))
                                        field_list = list(od.values())
                                        #DELETE EMPTY DOMAIN FIELDS
                                        field_to_split.fields = field_list
                            else:
                                #Searchstring always split in between other fields => Delete fields and create new ones Or just return indexes, and let user redefine fields manually
                                # symbol.fields = []
                                self._logger.warning(
                                    "Searchstring in between fields...")
                                self._logger.warning(
                                    "[1] : Delete all fields and replace by IPFIELDS"
                                    + "\n")
                                self._logger.warning(
                                    "[ANY] : Just print the index in the message"
                                    + "\n")
        return