Ejemplo n.º 1
0
    def _deserializeAlignment(self, regex, mask, unitSize=AbstractType.UNITSIZE_8):
        """
        deserializeAlignment: Transforms the C extension results
        in a python readable way
        @param regex the C returned regex
        @param mask the C returned mask
        @param unitSize the unitSize
        @returns the python alignment
        """
        if not (unitSize == AbstractType.UNITSIZE_8 or unitSize == AbstractType.UNITSIZE_4):
            raise ValueError("Deserializing with unitSize {0} not yet implemented, only 4 and 8 supported.".format(unitSize))

        align = ""
        for i, c in enumerate(mask):
            if c != '\x02':
                if c == '\x01':
                    if unitSize == AbstractType.UNITSIZE_8:
                        align += "--"
                    elif unitSize == AbstractType.UNITSIZE_4:
                        align += "-"
                else:
                    if unitSize == AbstractType.UNITSIZE_8:
                        align += TypeConverter.convert(regex[i:i + 1], Raw, HexaString)
                    elif unitSize == AbstractType.UNITSIZE_4:
                        align += TypeConverter.convert(regex[i:i + 1], Raw, HexaString)[1:]
        return align
Ejemplo n.º 2
0
    def _computeExpectedValue(self, parsingPath):
        self._logger.debug("compute expected value for Internet checksum field")
                
        # first checks the pointed fields all have a value
        hasValue = True
        for field in self.fieldDependencies:
            if field.domain != self and not parsingPath.isDataAvailableForVariable(field.domain):
                self._logger.debug("Field : {0} has no value".format(field.id))
                hasValue = False

        if not hasValue:
            raise Exception("Expected value cannot be computed, some dependencies are missing for domain {0}".format(self))
        else:
            fieldValues = []
            for field in self.fieldDependencies:
                if field.domain is self:
                    fieldSize = random.randint(field.domain.dataType.size[0], field.domain.dataType.size[1])
                    fieldValue = "\x00"* (fieldSize / 8)
                else:
                    fieldValue = TypeConverter.convert(parsingPath.getDataAssignedToVariable(field.domain), BitArray, Raw)
                if fieldValue is None:
                    break
                else:
                    fieldValues.append(fieldValue)

            fieldValues = ''.join(fieldValues)
            # compute the checksum of this value
            chsum = self.__checksum(fieldValues)
            b = TypeConverter.convert(chsum, Integer, BitArray, src_unitSize=AbstractType.UNITSIZE_16, src_sign = AbstractType.SIGN_UNSIGNED)
            return b
Ejemplo n.º 3
0
    def mutate(self, prefixDescription=None):
        """Generate various mutations of the current ASCII value.

        Mutations are first applied on the ASCII value than, each obtained mutations generates
        new bitarray mutations.
        ASCII mutations are:

        * Original Version
        * Original Version in Upper case
        * Original Version in Lower case

        >>> from netzob.all import *
        >>> t = ASCII("helloworld")
        >>> print t.mutate()
        {'ascii(inversed)-bits(littleEndian)': bitarray('00100110001101100100111011110110111011101111011000110110001101101010011000010110'), 'ascii(inversed-upper)-bits(littleEndian)': bitarray('00100010001100100100101011110010111010101111001000110010001100101010001000010010'), 'ascii(upper)-bits(littleEndian)': bitarray('00010010101000100011001000110010111100101110101011110010010010100011001000100010'), 'ascii-bits(bigEndian)': bitarray('01101000011001010110110001101100011011110111011101101111011100100110110001100100'), 'ascii(inversed)-bits(bigEndian)': bitarray('01100100011011000111001001101111011101110110111101101100011011000110010101101000'), 'ascii(upper)-bits(bigEndian)': bitarray('01001000010001010100110001001100010011110101011101001111010100100100110001000100'), 'ascii-bits(littleEndian)': bitarray('00010110101001100011011000110110111101101110111011110110010011100011011000100110'), 'ascii(inversed-upper)-bits(bigEndian)': bitarray('01000100010011000101001001001111010101110100111101001100010011000100010101001000')}


        :keyword prefixDescription: prefix to attach to the description of the generated mutation.
        :type prefixDescription: :class:`str`
        :return: a dict of computed mutations having the same types than the initial one.
        :rtype: :class:`dict`<str>=:class:`netzob.Common.Models.Types.AbstractType.AbstractType`
        """
        if prefixDescription is None:
            prefixDescription = ""
        else:
            prefixDescription += "-"

        from netzob.Common.Models.Types.TypeConverter import TypeConverter
        from netzob.Common.Models.Types.BitArray import BitArray

        if self.value is None:
            val = self.generate()
        else:
            val = self.value

        strValue = TypeConverter.convert(val, BitArray, ASCII)

        mutations = dict()

        mutations["{0}ascii".format(prefixDescription)] = strValue
        mutations["{0}ascii(inversed)".format(prefixDescription)] = strValue[::-1]
        if strValue != strValue.upper():
            mutations["{0}ascii(upper)".format(prefixDescription)] = strValue.upper()
            mutations["{0}ascii(inversed-upper)".format(prefixDescription)] = strValue[::-1].upper()
        if strValue != strValue.lower():
            mutations["{0}ascii(lower)".format(prefixDescription)] = strValue.lower()
            mutations["{0}ascii(inversed-lower)".format(prefixDescription)] = strValue[::-1].lower()

        results = dict()
        for mutationName, mutationValue in mutations.iteritems():
            ba = BitArray(TypeConverter.convert(mutationValue, ASCII, BitArray))
            results.update(ba.mutate(mutationName))

        return results
Ejemplo n.º 4
0
    def writeSymbol(self, symbol):
        """Write the specified symbol on the communication channel
        after specializing it into a contextualized message.

        :param symbol: the symbol to write on the channel
        :type symbol: :class:`netzob.Common.Models.Vocabulary.Symbol.Symbol`
        :raise TypeError if parameter is not valid and Exception if an exception occurs.
        """
        if symbol is None:
            raise TypeError("The symbol to write on the channel cannot be None")

        self._logger.info("Going to specialize symbol: '{0}' (id={1}).".format(symbol.name, symbol.id))
        
        dataBin = self.specializer.specializeSymbol(symbol).generatedContent

        self.memory = self.specializer.memory
        self.parser.memory = self.memory
        data = TypeConverter.convert(dataBin, BitArray, Raw)
        symbol.messages.append(RawMessage(data))

        self._logger.info("Data generated from symbol '{0}':\n{1}.".format(symbol.name, symbol))
        
        self._logger.info("Going to write to communication channel...")
        self.channel.write(data)
        self._logger.info("Writing to commnunication channel donne..")
Ejemplo n.º 5
0
    def _computeExpectedValue(self, parsingPath):
        self._logger.debug("compute expected value for Size field")
                
        # first checks the pointed fields all have a value
        hasValue = True
        for field in self.fieldDependencies:
            if field.domain != self and not parsingPath.isDataAvailableForVariable(field.domain):
                self._logger.debug("Field : {0} has no value".format(field.id))
                hasValue = False

        if not hasValue:
            raise Exception("Expected value cannot be computed, some dependencies are missing for domain {0}".format(self))
        else:
            size = 0
            for field in self.fieldDependencies:
                if field.domain is self:
                    fieldValue = self.dataType.generate()
                else:
                    fieldValue = parsingPath.getDataAssignedToVariable(field.domain)
                if fieldValue is None:
                    break
                else:
                    tmpLen = len(fieldValue)
                    size += tmpLen

            size = int(size * self.factor + self.offset)
            b = TypeConverter.convert(size, Decimal, BitArray)
            
#            while len(b)<self.dataType.size[0]:
#                b.insert(0, False)
        return b
Ejemplo n.º 6
0
    def generate(self, generationStrategy=None):
        """Generates a random Raw that respects the requested size.

        >>> from netzob.all import *
        >>> a = Raw(nbBytes=(10))
        >>> gen = a.generate()
        >>> print len(gen)
        80

        >>> from netzob.all import *
        >>> a = Raw(nbBytes=(10, 20))
        >>> gen = a.generate()
        >>> print 10<=len(gen) and 20<=len(gen)
        True



        """
        from netzob.Common.Models.Types.TypeConverter import TypeConverter
        from netzob.Common.Models.Types.BitArray import BitArray

        minSize, maxSize = self.size
        if maxSize is None:
            maxSize = AbstractType.MAXIMUM_GENERATED_DATA_SIZE
        if minSize is None:
            minSize = 0

        generatedSize = random.randint(minSize, maxSize)
        return TypeConverter.convert(os.urandom(generatedSize / 8), Raw, BitArray)
Ejemplo n.º 7
0
 def __repr__(self):
     if self.value is not None:
         from netzob.Common.Models.Types.TypeConverter import TypeConverter
         from netzob.Common.Models.Types.BitArray import BitArray
         return str(TypeConverter.convert(self.value, BitArray, self.__class__))
     else:
         return str(self.value)
Ejemplo n.º 8
0
    def generate(self, generationStrategy=None):
        """Generates a random ASCII that respects the requested size.

        >>> from netzob.all import *
        >>> a = ASCII(nbChars=10)
        >>> gen = a.generate()
        >>> len(gen)/8
        10

        >>> b = ASCII("netzob")
        >>> gen = b.generate()
        >>> print len(gen)>0
        True

        """
        from netzob.Common.Models.Types.TypeConverter import TypeConverter
        from netzob.Common.Models.Types.BitArray import BitArray

        minSize, maxSize = self.nbChars
        if maxSize is None:
            maxSize = AbstractType.MAXIMUM_GENERATED_DATA_SIZE
        if minSize is None:
            minSize = 0

        generatedSize = random.randint(minSize, maxSize)
        randomContent = ''.join([random.choice(string.letters + string.digits) for i in xrange(generatedSize)])
        return TypeConverter.convert(randomContent, ASCII, BitArray)
Ejemplo n.º 9
0
    def __init__(self, value=None, size=(None, None)):
        if value is not None and not isinstance(value, bitarray):
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            value = TypeConverter.convert(value, HexaString, BitArray)

        super(HexaString, self).__init__(self.__class__.__name__, value, size)
Ejemplo n.º 10
0
 def __str__(self):
     from netzob.Common.Models.Types.TypeConverter import TypeConverter
     from netzob.Common.Models.Types.BitArray import BitArray
     if self.value is not None:
         return "{0}={1} ({2})".format(self.typeName, TypeConverter.convert(self.value, BitArray, self.__class__), self.size)
     else:
         return "{0}={1} ({2})".format(self.typeName, self.value, self.size)
Ejemplo n.º 11
0
    def specialize(self, memory=None, generationStrategy=None):
        """Specialize and generate an hexastring which content
        follows the fields definitions attached to the field of the symbol.

        >>> from netzob.all import *
        >>> f1 = Field(domain=ASCII(nbChars=5))
        >>> f0 = Field(domain=Size(f1))
        >>> s = Symbol(fields=[f0, f1])
        >>> result = s.specialize()
        >>> print result[0]
        \x05
        >>> print len(result)
        6

        :keyword generationStrategy: if set, the strategy will be used to generate the fields definitions
        :type generaionrStrategy: :class:``

        :return: a generated content represented as a Raw
        :rtype: :class:`str``
        :raises: :class:`netzob.Common.Models.Vocabulary.AbstractField.GenerationException` if an error occurs while generating a message
        """
        from netzob.Common.Models.Vocabulary.Domain.Specializer.MessageSpecializer import MessageSpecializer
        msg = MessageSpecializer(memory=memory)
        spePath = msg.specializeSymbol(self)

        if spePath is not None:
            return TypeConverter.convert(spePath.generatedContent, BitArray, Raw)
Ejemplo n.º 12
0
    def specializeSymbol(self, symbol):
        """This method generates a message based on the provided symbol definition."""
        if symbol is None:
            raise Exception("Specified symbol is None")

        self._logger.debug("Specifies symbol '{0}'.".format(symbol.name))

        # this variable host all the specialization path
        specializingPaths = [SpecializingPath(memory=self.memory)]

        for field in symbol.fields:
            self._logger.debug("Specializing field {0}".format(field.name))

            fieldDomain = field.domain
            if fieldDomain is None:
                raise Exception("Cannot specialize field '{0}' since it defines no domain".format(fieldDomain))
        
            fs = FieldSpecializer(field, presets = self.presets)

            newSpecializingPaths = []
            for specializingPath in specializingPaths:
                newSpecializingPaths.extend(fs.specialize(specializingPath))

            specializingPaths = newSpecializingPaths

        if len(specializingPaths) > 1:
            self._logger.info("TODO: multiple valid paths found when specializing this message.")

        if len(specializingPaths) == 0:
            raise Exception("Cannot specialize this symbol.")

        retainedPath = specializingPaths[0]

        generatedContent = None
        # let's configure the generated content
        for field in symbol.fields:
            # TODO: only support one level of children... must be improved
            if len(field.fields) > 0:
                d = None
                for child in field.fields:
                    if d is None:
                        d = retainedPath.getDataAssignedToVariable(child.domain).copy()
                    else:
                        d += retainedPath.getDataAssignedToVariable(child.domain).copy()
                
            else:
                d = retainedPath.getDataAssignedToVariable(field.domain)
                
            if generatedContent is None:
                generatedContent = d.copy()
            else:
                generatedContent += d.copy()

        retainedPath.generatedContent = generatedContent

        self._logger.debug("Specialized message: {0}".format(TypeConverter.convert(retainedPath.generatedContent, BitArray, ASCII)))
        self.memory = retainedPath.memory

        return retainedPath
Ejemplo n.º 13
0
 def __str__(self):
     if self.value is not None:
         from netzob.Common.Models.Types.TypeConverter import TypeConverter
         from netzob.Common.Models.Types.BitArray import BitArray
         from netzob.Common.Models.Types.HexaString import HexaString
         return "{0}={1} ({2})".format(self.typeName, repr(TypeConverter.convert(self.value, BitArray, Raw)), self.size)
     else:
         return "{0}={1} ({2})".format(self.typeName, self.value, self.size)
Ejemplo n.º 14
0
 def _generateDataValues(self, cellsData):
     result = []
     for data in cellsData:
         if len(data) > 0:
             result.append(TypeConverter.convert(data[:8], Raw, Decimal))  # We take only the first 8 octets
         else:
             result.append(0)
     return result
Ejemplo n.º 15
0
    def encode(data, unitSize=AbstractType.UNITSIZE_32, endianness=AbstractType.defaultEndianness(), sign=AbstractType.SIGN_UNSIGNED):
        from netzob.Common.Models.Types.Raw import Raw
        from netzob.Common.Models.Types.TypeConverter import TypeConverter
        from netzob.Common.Models.Types.Integer import Integer

        intValue = TypeConverter.convert(data, Raw, Integer, dst_unitSize=AbstractType.UNITSIZE_32, dst_sign=AbstractType.SIGN_UNSIGNED)
        parsedTimestamp = datetime.fromtimestamp(intValue)

        return parsedTimestamp.strftime("%c")        
Ejemplo n.º 16
0
    def __init__(self, value=None, nbBytes=None, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()):
        if value is not None and not isinstance(value, bitarray):
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            value = TypeConverter.convert(value, Raw, BitArray)

        nbBits = self._convertNbBytesinNbBits(nbBytes)

        super(Raw, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
Ejemplo n.º 17
0
    def __init__(self, value=None, nbChars=(None, None), unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()):
        if value is not None and not isinstance(value, bitarray):
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            value = TypeConverter.convert(value, ASCII, BitArray, src_unitSize=unitSize, src_endianness=endianness, src_sign=sign, dst_unitSize=unitSize, dst_endianness=endianness, dst_sign=sign)
        else:
            value = None

        self.nbChars = nbChars
        nbBits = self._convertNbCharsInNbBits(self.nbChars)

        super(ASCII, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
Ejemplo n.º 18
0
    def _sizeRelation(self, x, x_attribute, y, y_attribute):
        if x_attribute == self.ATTR_SIZE:
            if len(x) > 0:
                x = len(x)
        else:
            if len(x) > 0:
                x = TypeConverter.convert(x[:8], Raw, Integer)
            else:
                x = 0
        if y_attribute == self.ATTR_SIZE:
            if len(y) > 0:
                y = len(y)
        else:
            if len(y) > 0:
                y = TypeConverter.convert(y[:8], Raw, Integer)
            else:
                y = 0

        if x == y:
            return True
        else:
            return False
Ejemplo n.º 19
0
    def canParse(self, data, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()):
        """Computes if specified data can be parsed as a Timestamp with the predefined constraints.

        >>> from netzob.all import *
        >>> time = Timestamp()
        >>> time.canParse(TypeConverter.convert(1444494130, Integer, BitArray, src_unitSize=AbstractType.UNITSIZE_32))
        True
        >>> # A timestamp is nothing else than 32bits parsed as an unsigned long
        >>> time.canParse(TypeConverter.convert("test", ASCII, BitArray))
        True
        >>> time.canParse(TypeConverter.convert("te", ASCII, BitArray))
        False
        
        However, some constrains over the definition of the Timestamp can be set to restrain the accepted values

        >>> from netzob.all import *
        >>> time = Timestamp(epoch=Timestamp.EPOCH_WINDOWS, unity=Timestamp.UNITY_NANOSECOND, unitSize = AbstractType.UNITSIZE_64)
        >>> # the returned year is < 1900
        >>> time.canParse(TypeConverter.convert("test", ASCII, BitArray))
        False

        """

        if data is None:
            raise TypeError("data cannot be None")
         
        # Timestamp must be 8 bits modulo length
        if len(data) % 8 != 0:
            return False

        if len(data) < int(self.unitSize):
            return False

        try:

            value = TypeConverter.convert(data[:int(self.unitSize)], BitArray, Integer, dst_unitSize=AbstractType.UNITSIZE_32, dst_sign=AbstractType.SIGN_UNSIGNED)

            # convert the value in seconds
            value = value / self.unity

            # add the utc now with the epoch
            timestamp_datetime = self.epoch + timedelta(seconds=value)
            
            # convert obtained datetime to timestamp in seconds 
            result_sec = int( timestamp_datetime.strftime('%s') )
            
            datetime.fromtimestamp(result_sec)
        except Exception:
            return False
        
        return True
Ejemplo n.º 20
0
    def _computeExpectedValue(self, parsingPath):
        self._logger.debug("compute expected value for Size field")
                
        # first checks the pointed fields all have a value
        hasValue = True
        for field in self.fieldDependencies:
            if field.domain != self and not parsingPath.isDataAvailableForVariable(field.domain):
                self._logger.debug("Field : {0} has no value".format(field.id))
                hasValue = False

        if not hasValue:
            raise Exception("Expected value cannot be computed, some dependencies are missing for domain {0}".format(self))
        else:
            size = 0
            for field in self.fieldDependencies:
                if field.domain is self:
                    fieldValue = self.dataType.generate()
                else:
                    fieldValue = parsingPath.getDataAssignedToVariable(field.domain)
                if fieldValue is None:
                    break
                else:
                    tmpLen = len(fieldValue)
                    size += tmpLen


            size = int(size * self.factor + self.offset)
            size_raw = TypeConverter.convert(size, Integer, Raw, src_unitSize=self.dataType.unitSize)        
            b = TypeConverter.convert(size_raw, Raw, BitArray)
            
            # add heading '0'
            while len(b)<self.dataType.size[0]:
                b.insert(0, False)

            # in some cases (when unitSize and size are not equal), it may require to delete some '0' in front
            while len(b)>self.dataType.size[0]:
                b.remove(0)
        return b
Ejemplo n.º 21
0
    def specialize(self, memory=None, generationStrategy=None, presets=None):
        """Specialize and generate an hexastring which content
        follows the fields definitions attached to the field of the symbol.

        >>> from netzob.all import *
        >>> f1 = Field(domain=ASCII(nbChars=5))
        >>> f0 = Field(domain=Size(f1))
        >>> s = Symbol(fields=[f0, f1])
        >>> result = s.specialize()
        >>> print result[0]
        \x05
        >>> print len(result)
        6

        You can also preset the value of some variables included in the symbol definition.

        >>> from netzob.all import *
        >>> f1 = Field(domain=ASCII("hello "))
        >>> f2 = Field(domain=ASCII(nbChars=(1,10)))
        >>> s = Symbol(fields = [f1, f2])
        >>> presetValues = dict()
        >>> presetValues[f2] = TypeConverter.convert("antoine", ASCII, BitArray)
        >>> print s.specialize(presets = presetValues)
        hello antoine

        A preseted valued bypasses all the constraints checks on your field definition.
        For example, in the following example it can be use to bypass a size field definition.

        >>> from netzob.all import *
        >>> f1 = Field()
        >>> f2 = Field(domain=Raw(nbBytes=(10,15)))
        >>> f1.domain = Size(f2)
        >>> s = Symbol(fields=[f1, f2])
        >>> presetValues = {f1: TypeConverter.convert("\xff", Raw, BitArray)}        
        >>> print repr(s.specialize(presets = presetValues)[0])
        '\\xff'

        :keyword generationStrategy: if set, the strategy will be used to generate the fields definitions
        :type generaionrStrategy: :class:``

        :return: a generated content represented as a Raw
        :rtype: :class:`str``
        :raises: :class:`netzob.Common.Models.Vocabulary.AbstractField.GenerationException` if an error occurs while generating a message
        """
        from netzob.Common.Models.Vocabulary.Domain.Specializer.MessageSpecializer import MessageSpecializer
        msg = MessageSpecializer(memory=memory, presets=presets)
        spePath = msg.specializeSymbol(self)

        if spePath is not None:
            return TypeConverter.convert(spePath.generatedContent, BitArray, Raw)
Ejemplo n.º 22
0
    def generate(self, generationStrategy=None):
        """Generates a random IPv4 which follows the constraints.

        >>> from netzob.all import *
        >>> f = Field(IPv4())
        >>> len(f.specialize())
        4

        >>> f = Field(IPv4("192.168.0.10"))
        >>> TypeConverter.convert(f.specialize(), Raw, IPv4)
        IPAddress('192.168.0.10')

        >>> f = Field(IPv4(network="10.10.10.0/24"))
        >>> TypeConverter.convert(f.specialize(), Raw, IPv4) in IPNetwork("10.10.10.0/24")
        True

        """
        from netzob.Common.Models.Types.BitArray import BitArray
        from netzob.Common.Models.Types.TypeConverter import TypeConverter
        from netzob.Common.Models.Types.Raw import Raw

        if self.value is not None:
            return self.value
        elif self.network is not None:
            ip = random.choice(self.network)
            return TypeConverter.convert(ip.packed, Raw, BitArray, src_unitSize=self.unitSize, src_endianness=self.endianness, src_sign=self.sign, dst_unitSize=self.unitSize, dst_endianness=self.endianness, dst_sign=self.sign)
        else:
            not_valid = [10, 127, 169, 172, 192]

            first = random.randrange(1, 256)
            while first in not_valid:
                first = random.randrange(1, 256)

            strip = ".".join([str(first), str(random.randrange(1, 256)), str(random.randrange(1, 256)), str(random.randrange(1, 256))])

            ip = IPv4.encode(strip)
            return TypeConverter.convert(ip.packed, Raw, BitArray, src_unitSize=self.unitSize, src_endianness=self.endianness, src_sign=self.sign, dst_unitSize=self.unitSize, dst_endianness=self.endianness, dst_sign=self.sign)
Ejemplo n.º 23
0
    def __checksum(self, msg):
        self._logger.fatal("Computing checksum of {0}, {1}".format(TypeConverter.convert(msg, Raw, HexaString), len(msg)))
    
        def carry_around_add(a, b):
            c = a + b
            return (c & 0xffff) + (c >> 16)

        s = 0
        for i in range(0, len(msg), 2):
            if i + 1 >= len(msg):
                w = ord(msg[i]) & 0xFF
            else:        
                w = ord(msg[i]) + (ord(msg[i+1]) << 8)
            s = carry_around_add(s, w)
        res = ~s & 0xffff
        self._logger.fatal(res)
        return res
Ejemplo n.º 24
0
    def __init__(self, value=None, network=None, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()):
        """Builds an IPv4 domain with optional constraints.

        :parameter value: specify a constraints over the expected value.
        :type value: an str, an IPAddress or an int which can be parsed as an IPv4 (ex. "192.168.0.10")
        :parameter network: if no value is specified (None), a constraints over the network the parsed IP belongs can be specified with this parameter (ex. "192.168.0.0/24")
        :type network: an str or an IPAddress which can be parsed as a network IPv4
        """

        if value is not None and not isinstance(value, bitarray):
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            value = TypeConverter.convert(value, IPv4, BitArray, src_unitSize=unitSize, src_endianness=endianness, src_sign=sign, dst_unitSize=unitSize, dst_endianness=endianness, dst_sign=sign)

        self.network = network

        super(IPv4, self).__init__(self.__class__.__name__, value, 32, unitSize=unitSize, endianness=endianness, sign=sign)
Ejemplo n.º 25
0
    def __init__(self, value=None, interval=None, nbUnits=None, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()):
        if value is not None and not isinstance(value, bitarray):
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            interval = value
            value = TypeConverter.convert(value, Decimal, BitArray, src_unitSize=unitSize, src_endianness=endianness, src_sign=sign, dst_unitSize=unitSize, dst_endianness=endianness, dst_sign=sign)
        else:
            value = None

        if interval is not None:
            nbBits = int(self._computeNbUnitSizeForInterval(interval, unitSize, sign)) * int(unitSize)
        elif nbUnits is not None:
            nbBits = nbUnits * int(unitSize)
        else:
            nbBits = int(unitSize)

        super(Decimal, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
Ejemplo n.º 26
0
    def specialize(self):
        """Specialize the current field to build a raw data that
        follows the fields definitions attached to current element.

        This method allows to generate some content following the field definition:

        >>> from netzob.all import *
        >>> f = Field("hello")
        >>> print '\\n'.join([f.specialize() for x in range(3)])
        hello
        hello
        hello

        This method also applies on multiple fields using a Symbol

        >>> fHello = Field("hello ")
        >>> fName = Field("zoby")
        >>> s = Symbol([fHello, fName])
        >>> print '\\n'.join([s.specialize() for x in range(3)])
        hello zoby
        hello zoby
        hello zoby

        :return: a generated content represented with an hexastring
        :rtype: :class:`str``
        :raises: :class:`netzob.Common.Models.Vocabulary.AbstractField.GenerationException` if an error occurs while generating a message
        """
        self._logger.debug("Specializes field {0}".format(self.name))
        if self.__domain is None:
            raise InvalidDomainException("The domain is not defined.")
            
        from netzob.Common.Models.Vocabulary.Domain.Specializer.FieldSpecializer import FieldSpecializer
        fs = FieldSpecializer(self)
        specializingPaths = fs.specialize()

        if len(specializingPaths) < 1:
            raise Exception("Cannot specialize this field")
            
        specializingPath = specializingPaths[0]

        self._logger.debug("field specializing done: {0}".format(specializingPath))
        if specializingPath is None:
            raise Exception("The specialization of the field {0} returned no result.".format(self.name))

        return TypeConverter.convert(specializingPath.getDataAssignedToVariable(self.domain), BitArray, Raw)
Ejemplo n.º 27
0
    def execute(self):
        """Execute the alignment of data following specified field
        """
        if self.data is None:
            raise TypeError("Data cannot be None")
        if self.field is None:
            raise TypeError("Field cannot be None")

        # Aligned messages are stored in a MatrixList for better display
        result = MatrixList()        

        # We retrieve all the leaf fields of the root of the provided field
        rootLeafFields = self.__root._getLeafFields(depth=self.depth)
            
        # if self.__root != self.field:
        #     targetedFieldLeafFields = self.field._getLeafFields(depth=self.depth)
        # else:
        targetedFieldLeafFields = rootLeafFields

        result.headers = [str(field.name) for field in targetedFieldLeafFields]
        from netzob.Common.Models.Vocabulary.Domain.Parser.MessageParser import MessageParser
        for d in self.data:
            mp = MessageParser()
            # alignedMsg = mp.parseRaw(TypeConverter.convert(d, HexaString, Raw), targetedFieldLeafFields)
            alignedMsg = mp.parseRaw(d, targetedFieldLeafFields)            

            alignedEncodedMsg = []
            for ifield, currentField in enumerate(targetedFieldLeafFields):

                # now we apply encoding and mathematic functions
                fieldValue = alignedMsg[ifield]
            
                if self.encoded and len(currentField.encodingFunctions.values()) > 0:
                    for encodingFunction in currentField.encodingFunctions.values():
                        fieldValue = encodingFunction.encode(fieldValue)
                else:
                    fieldValue = TypeConverter.convert(fieldValue, BitArray, Raw)

                if currentField in self.field._getLeafFields(depth=self.depth):
                    alignedEncodedMsg.append(fieldValue)

            result.append(alignedEncodedMsg)

        return result
Ejemplo n.º 28
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, len(entryVal) / 2)))
            else:
                newField = Field(Raw(TypeConverter.convert(entryVal, HexaString, Raw)))
            step1Fields.append(newField)

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

        field.fields = step1Fields
Ejemplo n.º 29
0
    def parseRaw_new(self, dataToParse, fields):
        self._logger.debug("New parsing method executed on {}".format(dataToParse))

        bitArrayToParse = TypeConverter.convert(dataToParse, Raw, BitArray)

        # building a new parsing path
        currentParsingPath = ParsingPath(bitArrayToParse.copy(), self.memory)
        currentParsingPath.assignDataToField(bitArrayToParse.copy(), fields[0])

        # field iterator
        i_current_field = 0
        
        parsingResult = self.parseField_new(currentParsingPath, fields, i_current_field)

        result = []
        for field in fields:
            result.append(parsingResult.getDataAssignedToField(field))

        self.memory = parsingResult.memory
    
        return result
Ejemplo n.º 30
0
    def __init__(self, value=None, epoch=EPOCH_UNIX, unity=UNITY_SECOND, unitSize=AbstractType.UNITSIZE_32, endianness=AbstractType.defaultEndianness(), sign=AbstractType.SIGN_UNSIGNED):
        """Builds a Timestamp domain with optional constraints.

        :param value: specifies the value of the timestamp.
        :type value: an int, a long or a bitarray
        :param epoch: the initial date expressed in UTC from which timestamp is measured. Default value is the UNIX Epoch.
        :type datetime.datetime
        :param unity: specifies the unity of the timestamp (seconds, milliseconds, nanoseconds). Default value is SECOND.
        :type unity: int
        """
        if value is not None and not isinstance(value, bitarray):
            # converts the specified value in bitarray
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            from netzob.Common.Models.Types.Integer import Integer
            value = TypeConverter.convert(value, Integer, BitArray, src_unitSize=unitSize, src_endianness=endianness, src_sign=sign)

        self.epoch = epoch
        self.unity = unity

        super(Timestamp, self).__init__(self.__class__.__name__, value, 32, unitSize=unitSize, endianness=endianness, sign=sign)
Ejemplo n.º 31
0
    def encodeChild(self, variable, readingToken):
        result = []

        if not readingToken.isValueForVariableAvailable(variable):
            return result

        if variable.varType == "Data" or variable.varType == "Size" or variable.varType == "InternetChecksum":
            val = readingToken.getValueForVariable(variable)
            encodedVal = TypeConverter.convert(val, BitArray, variable.dataType.__class__)
            result.append(str(encodedVal))
        elif variable.varType == "Agg" or variable.varType == "Alt":
            for child in variable.children:
                result.extend(self.encodeChild(child, readingToken))
        elif variable.varType == "Eol":
            # nothing to encode when child is EOL
            pass
        else:
            raise Exception("Unknown type of variable: {0}".format(variable.varType))

        if len(result) == 0:
            return ''
        else:
            return ''.join(result)
Ejemplo n.º 32
0
    def regenerate(self, variableSpecializerPath, moreCallBackAccepted=True):
        """This method participates in the specialization proces.

        It creates a VariableSpecializerResult in the provided path that
        contains a generated value that follows the definition of the Data
        """
        self._logger.debug("Regenerate size {0}".format(self))
        if variableSpecializerPath is None:
            raise Exception("VariableSpecializerPath cannot be None")

        try:
            newValue = self._computeExpectedValue(variableSpecializerPath)
            variableSpecializerPath.addResult(self, newValue)
        except Exception, e:
            self._logger.debug("Cannot specialize since no value is available for the size dependencies, we create a callback function in case it can be computed later: {0}".format(e))
            pendingValue = TypeConverter.convert("PENDING VALUE", ASCII, BitArray)
            variableSpecializerPath.addResult(self, pendingValue)
            if moreCallBackAccepted:
#                for field in self.fields:
                variableSpecializerPath.registerFieldCallBack(self.fields, self, parsingCB=False)

            else:
                raise e
Ejemplo n.º 33
0
    def convertValue(self, typeClass, dst_unitSize=None, dst_endianness=None, dst_sign=None):
        """Convert the current data in the netzob type
        specified in parameter.

        :parameter typeClass: the netzob class to which the current data must be converted
        :type typeClass: type
        :keyword dst_unitSize: the unitsize of the destination value. Values must be one of AbstractType.UNITSIZE_*. if None, the value is the default one.
        :type dst_unitSize: str
        :keyword dst_endianness: the endianness of the destination value. Values must be AbstractType.ENDIAN_BIG or AbstractType.ENDIAN_LITTLE. if None, the value is the default one.
        :type dst_endianness: str
        :keyword dst_sign: the sign of the destination. Values must be AbstractType.SIGN_SIGNED or AbstractType.SIGN_UNSIGNED. if None, the value is the default one.
        :type dst_sign: str
        :return: the converted current value in the specified netzob type
        :rtype: :class:`netzob.Common.Models.AbstractType.AbstractType`
        """
        if typeClass is None:
            raise TypeError("TypeClass cannot be None")
        if typeClass not in AbstractType.supportedTypes():
            raise TypeError("Requested typeClass ({0}) is not supported.".format(typeClass))

        if dst_unitSize is None:
            dst_unitSize = AbstractType.defaultUnitSize()
        if dst_endianness is None:
            dst_endianness = AbstractType.defaultEndianness()
        if dst_sign is None:
            dst_sign = AbstractType.defaultSign()

        if dst_unitSize not in AbstractType.supportedUnitSizes():
            raise TypeError("Dst_unitsize is not supported.")
        if dst_endianness not in AbstractType.supportedEndianness():
            raise TypeError("Dst_endianness is not supported.")
        if dst_sign not in AbstractType.supportedSign():
            raise TypeError("Sign is not supported.")

        from netzob.Common.Models.Types.TypeConverter import TypeConverter
        from netzob.Common.Models.Types.BitArray import BitArray
        return typeClass(TypeConverter.convert(self.value, BitArray, typeClass, src_unitSize=self.unitSize, src_endianness=self.endianness, src_sign=self.sign, dst_unitSize=dst_unitSize, dst_endianness=dst_endianness, dst_sign=dst_sign), unitSize=dst_unitSize, endianness=dst_endianness, sign=dst_sign)
Ejemplo n.º 34
0
    def __init__(self,
                 value=None,
                 epoch=EPOCH_UNIX,
                 unity=UNITY_SECOND,
                 unitSize=AbstractType.UNITSIZE_32,
                 endianness=AbstractType.defaultEndianness(),
                 sign=AbstractType.SIGN_UNSIGNED):
        """Builds a Timestamp domain with optional constraints.

        :param value: specifies the value of the timestamp.
        :type value: an int, a long or a bitarray
        :param epoch: the initial date expressed in UTC from which timestamp is measured. Default value is the UNIX Epoch.
        :type datetime.datetime
        :param unity: specifies the unity of the timestamp (seconds, milliseconds, nanoseconds). Default value is SECOND.
        :type unity: int
        """
        if value is not None and not isinstance(value, bitarray):
            # converts the specified value in bitarray
            from netzob.Common.Models.Types.TypeConverter import TypeConverter
            from netzob.Common.Models.Types.BitArray import BitArray
            from netzob.Common.Models.Types.Integer import Integer
            value = TypeConverter.convert(value,
                                          Integer,
                                          BitArray,
                                          src_unitSize=unitSize,
                                          src_endianness=endianness,
                                          src_sign=sign)

        self.epoch = epoch
        self.unity = unity

        super(Timestamp, self).__init__(self.__class__.__name__,
                                        value,
                                        32,
                                        unitSize=unitSize,
                                        endianness=endianness,
                                        sign=sign)
Ejemplo n.º 35
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.Common.Models.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('')
            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([''.join(staticSequences)])
                        staticSequences = []
                    result.append(values)
            if len(staticSequences) > 0:
                result.append([''.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 = map(None, *dynamicSequences)
                        tmp_result = []
                        for d in dynValues:
                            tmp_result.append(''.join(
                                [x if x is not None else '' for x in d]))
                        result.append(tmp_result)
                        dynamicSequences = []
                    result.append(values)
            if len(dynamicSequences) > 0:
                dynValues = map(None, *dynamicSequences)
                tmp_result = []
                for d in dynValues:
                    tmp_result.append(''.join(
                        [x if x is not None else '' 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 = field.encodingFunctions.values()

        field.fields = newFields
Ejemplo n.º 36
0
    def cluster(self, field, keyField):
        """Create and return new symbols according to a specific key
        field.

        >>> import binascii
        >>> from netzob.all import *
        >>> samples = ["00ff2f000000",	"000020000000",	"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 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.Common.Models.Vocabulary.AbstractField.AbstractField`
        :param keyField: the field used as a key during the splitting operation
        :type field: :class:`netzob.Common.Models.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 = {}

        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 keyFieldMessageValues.iteritems():
            # 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 keyFieldMessageValues.iteritems():
            keyFieldValue = TypeConverter.convert(keyFieldValue, Raw,
                                                  keyFieldType)
            if keyFieldValue not in newSymbols.keys():
                symbolName = "Symbol_{0}".format(keyFieldValue)
                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 newSymbols.iteritems():
            # 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
Ejemplo n.º 37
0
 def __str__(self):
     result = []
     for var, value in self.memory.iteritems():
         result.append("{0}: {1}".format(
             var, TypeConverter.convert(value, BitArray, Raw)))
     return '\n'.join(result)
Ejemplo n.º 38
0
    def canParse(self,
                 data,
                 unitSize=AbstractType.defaultUnitSize(),
                 endianness=AbstractType.defaultEndianness(),
                 sign=AbstractType.defaultSign()):
        """Computes if specified data can be parsed as an IPv4 with the predefined constraints.

        >>> from netzob.all import *
        >>> ip = IPv4()
        >>> ip.canParse("192.168.0.10")
        True
        >>> ip.canParse("198.128.0.100")
        True
        >>> ip.canParse("256.0.0.1")
        False
        >>> ip.canParse("127.0.0.1")
        True
        >>> ip.canParse("127.0.0.-1")
        False
        >>> ip.canParse("::")
        False
        >>> ip.canParse("0.0.0.0")
        False


        And with some constraints over the expected IPv4:


        >>> ip = IPv4("192.168.0.10")
        >>> ip.canParse("192.168.0.10")
        True
        >>> ip.canParse("192.168.1.10")
        False
        >>> ip.canParse(3232235530)
        True
        >>> ip = IPv4("167.20.14.20")
        >>> ip.canParse(3232235530)
        False
        >>> ip.canParse(3232235530)
        False


        or with contraints over the expected network the ipv4 belongs to:


        >>> ip = IPv4(network="192.168.0.0/24")
        >>> ip.canParse("192.168.0.10")
        True
        >>> ip.canParse("192.168.1.10")
        False

        :param data: the data to check
        :type data: python raw
        :return: True if data can be parsed as a Raw which is always the case (if len(data)>0)
        :rtype: bool
        :raise: TypeError if the data is None
        """

        if data is None:
            raise TypeError("data cannot be None")

        try:
            ip = IPv4.encode(data,
                             unitSize=unitSize,
                             endianness=endianness,
                             sign=sign)
            if ip is None or ip.version != 4 or ip.is_netmask():
                return False
        except:
            return False
        try:
            if self.value is not None:
                from netzob.Common.Models.Types.TypeConverter import TypeConverter
                from netzob.Common.Models.Types.BitArray import BitArray
                return self.value == TypeConverter.convert(
                    data,
                    IPv4,
                    BitArray,
                    src_unitSize=unitSize,
                    src_endianness=endianness,
                    src_sign=sign,
                    dst_unitSize=self.unitSize,
                    dst_endianness=self.endianness,
                    dst_sign=self.sign)
            elif self.network is not None:
                return ip in self.network
        except:
            return False

        return True
Ejemplo n.º 39
0
    def searchDataInMessage(self,
                            data,
                            message,
                            addTags=True,
                            dataLabels=None):
        """Search in the specified message any of the given data. These data will be searched as
        it but also under various format.

        >>> from netzob.all import *
        >>> message = RawMessage("Reversing protocols with Netzob")
        >>> sData = [ASCII("protocol")]
        >>> se = SearchEngine()
        >>> results = se.searchDataInMessage(sData, message)
        >>> print results
        1 occurence(s) found.
        >>> for result in results:
        ...    print result
        ...    print repr(result.searchTask.properties["data"])
        Found ascii-bits(bigEndian) at [(80L, 144L)] of bitarray('01010010011001010111011001100101011100100111001101101001011011100110011100100000011100000111001001101111011101000110111101100011011011110110110001110011001000000111011101101001011101000110100000100000010011100110010101110100011110100110111101100010')
        protocol


        :parameter data: the data to search after. Data must be provided with their netzob type.
        :type data: a list of :class:`netzob.Common.Models.Types.AbstractType.AbstractType`.
        :parameter message: the message in which the search will take place
        :type message: :class:`netzob.Common.Models.Vocabulary.Messages.AbstractMessage`
        :keyword addTags: if set to True, visualization functions are added to the message to highlights found results.
        :type addTags: :class:`bool`
        :keyword dataLabels: an optionnal dict to attach to each data a label to simplify search results identification
        :type dataLabels: dict

        :return: a search results detailling where and how occurrences where found. Occurences are also
        identified in the message through dedicated visualization functions automaticaly added to the message.
        :rtype: :class:`netzob.Inference.Vocabulary.SearchEngine.SearchResults.SearchResults`

        """

        if data is None or len(data) == 0:
            raise TypeError("At least one data should be specified.")

        if message is None:
            raise TypeError("Message cannot be None")

        searchTasks = []
        for d in data:
            # normalize the given data
            normedData = AbstractType.normalize(d)

            # build search tasks
            props = dict()
            props['message'] = message
            props['data'] = d
            if dataLabels is not None and d in dataLabels.keys():
                props['label'] = dataLabels[d]

            searchTasks.extend(self.__buildSearchTasks(normedData, props))

        # fetch the content of the message and convert it to bitarray
        target = TypeConverter.convert(message.data, Raw, BitArray)

        # Generate search cases
        searchCases = itertools.product([target], searchTasks)

        searchResults = self.__search(searchCases)

        # If requested, we tag the results in the message using visualization functions
        # if addTags:
        #     for searchResult in searchResults:
        #         for (startPos, endPos) in searchResult.ranges:
        #             self._logger.info("function from {} to {}".format(startPos, endPos))
        #             message.visualizationFunctions.append(HighlightFunction(startPos, endPos))
        return searchResults
Ejemplo n.º 40
0
    def specializeSymbol(self, symbol):
        """This method generates a message based on the provided symbol definition."""
        if symbol is None:
            raise Exception("Specified symbol is None")

        self._logger.debug("Specifies symbol '{0}'.".format(symbol.name))

        # this variable host all the specialization path
        specializingPaths = [SpecializingPath(memory=self.memory)]

        for field in symbol.fields:
            self._logger.debug("Specializing field {0}".format(field.name))

            fieldDomain = field.domain
            if fieldDomain is None:
                raise Exception(
                    "Cannot specialize field '{0}' since it defines no domain".
                    format(fieldDomain))

            fs = FieldSpecializer(field, presets=self.presets)

            newSpecializingPaths = []
            for specializingPath in specializingPaths:
                newSpecializingPaths.extend(fs.specialize(specializingPath))

            specializingPaths = newSpecializingPaths

        if len(specializingPaths) > 1:
            self._logger.info(
                "TODO: multiple valid paths found when specializing this message."
            )

        if len(specializingPaths) == 0:
            raise Exception("Cannot specialize this symbol.")

        retainedPath = specializingPaths[0]

        generatedContent = None
        # let's configure the generated content
        for field in symbol.fields:
            # TODO: only support one level of children... must be improved
            if len(field.fields) > 0:
                d = None
                for child in field.fields:
                    if d is None:
                        d = retainedPath.getDataAssignedToVariable(
                            child.domain).copy()
                    else:
                        d += retainedPath.getDataAssignedToVariable(
                            child.domain).copy()

            else:
                d = retainedPath.getDataAssignedToVariable(field.domain)

            if generatedContent is None:
                generatedContent = d.copy()
            else:
                generatedContent += d.copy()

        retainedPath.generatedContent = generatedContent

        self._logger.debug("Specialized message: {0}".format(
            TypeConverter.convert(retainedPath.generatedContent, BitArray,
                                  ASCII)))
        self.memory = retainedPath.memory

        return retainedPath
Ejemplo n.º 41
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 = ["aaaaff000000ff10",	"bbff110010ff00000011",	"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 = ["434d446964656e74696679230400000066726564", "5245536964656e74696679230000000000000000", "434d44696e666f2300000000", "524553696e666f230000000004000000696e666f","434d4473746174732300000000","52455373746174732300000000050000007374617473","434d4461757468656e7469667923090000006d7950617373776421","52455361757468656e74696679230000000000000000","434d44656e6372797074230a00000031323334353674657374","524553656e637279707423000000000a00000073707176777436273136","434d4464656372797074230a00000073707176777436273136","5245536465637279707423000000000a00000031323334353674657374","434d446279652300000000","524553627965230000000000000000","434d446964656e746966792307000000526f626572746f","5245536964656e74696679230000000000000000","434d44696e666f2300000000","524553696e666f230000000004000000696e666f","434d4473746174732300000000","52455373746174732300000000050000007374617473","434d4461757468656e74696679230a000000615374726f6e67507764","52455361757468656e74696679230000000000000000","434d44656e63727970742306000000616263646566","524553656e6372797074230000000006000000232021262724","434d44646563727970742306000000232021262724","52455364656372797074230000000006000000616263646566","434d446279652300000000","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='CMDidentify' ((0, 88)))
              |--   Data (Raw='RESidentify' ((0, 88)))
              |--   Data (Raw='CMDinfo' ((0, 56)))
              |--   Data (Raw='RESinfo' ((0, 56)))
              |--   Data (Raw='CMDstats' ((0, 64)))
              |--   Data (Raw='RESstats' ((0, 64)))
              |--   Data (Raw='CMDauthentify' ((0, 104)))
              |--   Data (Raw='RESauthentify' ((0, 104)))
              |--   Data (Raw='CMDencrypt' ((0, 80)))
              |--   Data (Raw='RESencrypt' ((0, 80)))
              |--   Data (Raw='CMDdecrypt' ((0, 80)))
              |--   Data (Raw='RESdecrypt' ((0, 80)))
              |--   Data (Raw='CMDbye' ((0, 48)))
              |--   Data (Raw='RESbye' ((0, 48)))
 
        :param field : the field to consider when spliting
        :type: :class:`netzob.Common.Models.Vocabulary.AbstractField.AbstractField`
        :param delimiter : the delimiter used to split messages of the field
        :type: :class:`netzob.Common.Models.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.izip_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 = field.encodingFunctions.values()
                newFields.append(newField)
                iField += 1

            fieldName = "Field-sep-" + TypeConverter.convert(
                delimiter.value, BitArray, HexaString)

            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