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" or variable.varType == "CRC32": val = readingToken.getValueForVariable(variable) encodedVal = TypeConverter.convert(val, BitArray, variable.dataType.__class__) 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)) raise Exception("Unknown type of variable: {0}".format( variable.varType)) if len(result) == 0: return '' else: return ''.join(result)
def __init__(self, value=None, nbBytes=None, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign(), alphabet=None): if value is not None and not isinstance(value, bitarray): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray if isinstance(value, str): value = TypeConverter.convert(bytes(value, "utf-8"), Raw, BitArray) elif isinstance(value, bytes): value = TypeConverter.convert(value, Raw, BitArray) nbBits = self._convertNbBytesinNbBits(nbBytes) self.alphabet = alphabet super(Raw, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
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 = b"" for i, c in enumerate(mask): if c != 2: if c == 1: if unitSize == AbstractType.UNITSIZE_8: align += b"--" elif unitSize == AbstractType.UNITSIZE_4: align += b"-" 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
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: # Integer only may be 1, 2, 4, or 8 bytes long, so for conversion # we need to add 0 padding at the front of the raw numbers if len(y) == 3: padded_y = b'\x00' + y elif len(y) in (5,6,7): padding_length = 8 - len(y) padded_y = padding_length * b'\x00' + y else: padded_y = y y = TypeConverter.convert(padded_y[:8], Raw, Integer) else: y = 0 if x == y: return True else: return False
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.Model.Vocabulary.Types.BitArray import BitArray from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
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.Model.Vocabulary.Types.BitArray import BitArray from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def _update_presets(self, symbol): """Update the presets dict, according to the symbol definition. """ if self.presets is None: return new_keys = {} old_keys = [] for k, v in list(self.presets.items()): # Handle case where k is a Field if isinstance(k, Field): if isinstance(v, bitarray): continue elif hasattr(k.domain, "dataType"): self.presets[k] = TypeConverter.convert(v, k.domain.dataType.__class__, BitArray, src_unitSize=k.domain.dataType.unitSize, dst_unitSize=k.domain.dataType.unitSize, src_sign=k.domain.dataType.sign, dst_sign=k.domain.dataType.sign, src_endianness=k.domain.dataType.endianness, dst_endianness=k.domain.dataType.endianness) else: raise Exception("Cannot find the default dataType for field '{}'".format(k)) # Handle case where k is a string elif isinstance(k, str): # Retrieve associated Field based on its string name for f in symbol.getLeafFields(includePseudoFields=True): if f.name == k: if isinstance(v, bitarray): new_keys[f] = v old_keys.append(k) elif hasattr(f.domain, "dataType"): new_keys[f] = TypeConverter.convert(v, f.domain.dataType.__class__, BitArray, src_unitSize=f.domain.dataType.unitSize, dst_unitSize=f.domain.dataType.unitSize, src_sign=f.domain.dataType.sign, dst_sign=f.domain.dataType.sign, src_endianness=f.domain.dataType.endianness, dst_endianness=f.domain.dataType.endianness) old_keys.append(k) else: raise Exception("Cannot find the default dataType for field '{}'".format(f)) break else: raise Exception("Preset's keys must be of Field or string types") # Replace string keys by their equivalent Field keys for old_key in old_keys: self.presets.pop(old_key) self.presets.update(new_keys)
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 is not self and not parsingPath.isDataAvailableForVariable(field.domain): self._logger.debug("The following field domain has no value: '{0}'".format(field.domain)) 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 = TypeConverter.convert(b"\x00" * int(fieldSize / 8), Raw, BitArray) else: fieldValue = parsingPath.getDataAssignedToVariable(field.domain) if fieldValue is None: break elif fieldValue.tobytes() == TypeConverter.convert("PENDING VALUE", ASCII, BitArray).tobytes(): # Handle case where field value is not currently known. raise Exception("Expected value cannot be computed, some dependencies are missing for domain {0}".format(self)) else: fieldValues.append(fieldValue) # Aggregate all field value in a uniq bitarray object concatFieldValues = bitarray('') for f in fieldValues: concatFieldValues += f # Convert the bitarray object in a Raw object, as the checksum function expect a Raw input concatFieldValues = TypeConverter.convert(concatFieldValues, BitArray, Raw) # compute the checksum of this value chsum = self.__checksum(concatFieldValues) b = TypeConverter.convert(chsum, Integer, BitArray, src_endianness=AbstractType.ENDIAN_LITTLE, dst_endianness=self.dataType.endianness, src_unitSize=AbstractType.UNITSIZE_16, src_sign = AbstractType.SIGN_UNSIGNED) return b
def _writeSymbol(self, symbol, presets=None): """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.Model.Vocabulary.Symbol.Symbol` :param presets: specifies how to parameterize the emitted symbol :type presets: dict :raise TypeError if parameter is not valid and Exception if an exception occurs. """ self._logger.debug("Specializing symbol '{0}' (id={1}).".format( symbol.name, symbol.id)) self.specializer.presets = presets dataBin = self.specializer.specializeSymbol(symbol).generatedContent self.specializer.presets = None self.memory = self.specializer.memory self.parser.memory = self.memory data = TypeConverter.convert(dataBin, BitArray, Raw) len_data = self.channel.write(data) self._logger.debug( "Writing {} octets to commnunication channel done..".format( len_data)) return len_data
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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def __crc32(self, msg): self._logger.debug("Computing crc32 of {0}, {1}".format( TypeConverter.convert(msg, Raw, HexaString), len(msg))) res = binascii.crc32(msg) return res
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
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 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)
def __repr__(self): r""" >>> from netzob.all import * >>> f = Field(Raw(b"\x01\x02\x03\x04")) >>> s = Symbol(fields=[f]) >>> messages = [RawMessage(s.specialize()) for x in range(5)] >>> s.messages = messages >>> print(s)# doctest: +NORMALIZE_WHITESPACE Source | Destination | Field ------ | ----------- | ------------------ None | None | '\x01\x02\x03\x04' None | None | '\x01\x02\x03\x04' None | None | '\x01\x02\x03\x04' None | None | '\x01\x02\x03\x04' None | None | '\x01\x02\x03\x04' ------ | ----------- | ------------------ """ if self.value is not None: from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray return str( TypeConverter.convert(self.value, BitArray, self.__class__)) else: return str(self.value)
def __init__(self, value=None, interval=None, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()): if value is not None and not isinstance(value, bitarray): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray interval = value value = TypeConverter.convert(value, Integer, 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) else: nbBits = int(unitSize) super(Integer, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
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 value {0}".format(self)) if variableSpecializerPath is None: raise Exception("VariableSpecializerPath cannot be None") try: newValue = self._computeExpectedValue(variableSpecializerPath) variableSpecializerPath.addResult(self, newValue) except Exception as e: self._logger.debug( "Cannot specialize since no value is available for the value 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: variableSpecializerPath.registerFieldCallBack( self.fieldDependencies, self, parsingCB=False) else: raise e return [variableSpecializerPath]
def __repr__(self): """ >>> from netzob.all import * >>> f = Field(Raw("\\x01\\x02\\x03\\x04")) >>> s = Symbol(fields=[f]) >>> messages = [RawMessage(s.specialize()) for x in range(5)] >>> s.messages = messages >>> print(s) Field ------------------ '\\x01\\x02\\x03\\x04' '\\x01\\x02\\x03\\x04' '\\x01\\x02\\x03\\x04' '\\x01\\x02\\x03\\x04' '\\x01\\x02\\x03\\x04' ------------------ """ if self.value is not None: from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray return str( TypeConverter.convert(self.value, BitArray, self.__class__)) else: return str(self.value)
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)
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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
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.0 >>> b = ASCII("netzob") >>> gen = b.generate() >>> print(len(gen)>0) True """ from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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.ascii_letters + string.digits) for i in range(generatedSize) ]) return TypeConverter.convert(randomContent, ASCII, BitArray)
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.0 >>> b = ASCII("netzob") >>> gen = b.generate() >>> print(len(gen)>0) True """ from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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.ascii_letters + string.digits) for i in range(generatedSize) ]) return TypeConverter.convert(randomContent, ASCII, BitArray)
def __init__(self, value=None, size=(None, None)): if value is not None and not isinstance(value, bitarray): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray value = TypeConverter.convert(value, HexaString, BitArray) super(HexaString, self).__init__(self.__class__.__name__, value, size)
def _writeSymbol(self, symbol, presets=None): """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.Model.Vocabulary.Symbol.Symbol` :param presets: specifies how to parameterize the emitted symbol :type presets: dict :raise TypeError if parameter is not valid and Exception if an exception occurs. """ self._logger.debug("Specializing symbol '{0}' (id={1}).".format( symbol.name, symbol.id)) self.specializer.presets = presets dataBin = self.specializer.specializeSymbol(symbol).generatedContent self.specializer.presets = None self.memory = self.specializer.memory self.parser.memory = self.memory data = TypeConverter.convert(dataBin, BitArray, Raw) len_data = self.channel.write(data) self._logger.debug("Writing {} octets to commnunication channel done..".format(len_data)) return len_data
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 value {0}".format(self)) if variableSpecializerPath is None: raise Exception("VariableSpecializerPath cannot be None") try: newValue = self._computeExpectedValue(variableSpecializerPath) variableSpecializerPath.addResult(self, newValue) except Exception as e: self._logger.debug( "Cannot specialize since no value is available for the value 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: variableSpecializerPath.registerFieldCallBack( self.fieldDependencies, self, parsingCB=False) else: raise e return [variableSpecializerPath]
def encode(self, data): data_raw = TypeConverter.convert(data, BitArray, Raw) result = None if self.encode_data: result = base64.b64encode(data_raw) else: result = base64.b64decode(data_raw) return result
def encode(self, data): self._logger.debug(data) return TypeConverter.convert(data, BitArray, self.type, dst_unitSize=self.unitSize, dst_endianness=self.endianness, dst_sign=self.sign)
def __repr__(self): if self.value != None: from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray return str( TypeConverter.convert(self.value, BitArray, self.__class__)) else: return str(self.value)
def __repr__(self): if self.value != None: from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray return str( TypeConverter.convert(self.value, BitArray, self.__class__)) else: return str(self.value)
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([str(f.specialize()) for x in range(3)])) b'hello' b'hello' b'hello' This method also applies on multiple fields using a Symbol >>> fHello = Field("hello ") >>> fName = Field("zoby") >>> s = Symbol([fHello, fName]) >>> print('\\n'.join([str(s.specialize()) for x in range(3)])) b'hello zoby' b'hello zoby' b'hello zoby' :return: a generated content represented with an hexastring :rtype: :class:`str`` :raises: :class:`netzob.Model.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.Model.Vocabulary.Domain.Specializer.FieldSpecializer import FieldSpecializer fs = FieldSpecializer(self) if self.domain.svas == SVAS.PERSISTENT: if isinstance(self.specializingPaths, list): self.specializingPaths = fs.specialize( specializingPath=self.specializingPaths[0]) else: self.specializingPaths = fs.specialize( specializingPath=self.specializingPaths) specializingPaths = self.specializingPaths else: 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)
def _generateDataValues(self, cellsData): result = [] for data in cellsData: if len(data) > 0: result.append(TypeConverter.convert( data[:8], Raw, Integer)) # We take only the first 8 octets else: result.append(0) return result
def encode(self, data): self._logger.debug(data) return TypeConverter.convert( data, BitArray, self.type, dst_unitSize=self.unitSize, dst_endianness=self.endianness, dst_sign=self.sign)
def _generateDataValues(self, cellsData): result = [] for data in cellsData: if len(data) > 0: result.append(TypeConverter.convert( data[:8], Raw, Integer)) # We take only the first 8 octets else: result.append(0) return result
def __str__(self): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def __str__(self): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def encode(self, data): data_raw = TypeConverter.convert(data, BitArray, Raw) result = None if self.compress_data: result = zlib.compress(data_raw, self.compression_level) else: result = zlib.decompress(data_raw) return result
def encode(self, data): data_raw = TypeConverter.convert(data, BitArray, Raw) result = None if self.compress_data: result = zlib.compress(data_raw, self.compression_level) else: result = zlib.decompress(data_raw) return result
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.Model.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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def _computeExpectedValue(self, parsingPath): self._logger.debug("compute expected value for CRC32 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: # Retrieve field value if field.domain is self: fieldSize = random.randint(field.domain.dataType.size[0], field.domain.dataType.size[1]) fieldValue = b"\x00" * int(fieldSize / 8) else: fieldValue = TypeConverter.convert( parsingPath.getDataAssignedToVariable(field.domain), BitArray, Raw) if fieldValue is None: break else: fieldValues.append(fieldValue) fieldValues = b''.join(fieldValues) # compute the crc of this value chsum = self.__crc32(fieldValues) b = TypeConverter.convert(chsum, Integer, BitArray, src_unitSize=AbstractType.UNITSIZE_32, src_sign=AbstractType.SIGN_UNSIGNED, src_endianness=self.endianness) return b
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.Model.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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def __str__(self): if self.value is not None: from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray from netzob.Model.Vocabulary.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)
def parseRaw(self, dataToParse, fields): """This method parses the specified raw against the specification of the provided symbol.""" if dataToParse is None or len(dataToParse) <= 0: raise Exception("Specified data to parse is empty (or None)") if fields is None: raise Exception("Specified fields is None") if len(fields) == 0: raise Exception("No field specified") bitArrayToParse = TypeConverter.convert(dataToParse, Raw, BitArray) return self.parseBitarray(bitArrayToParse, fields)
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]) 5 >>> 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)) b'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(s.specialize(presets = presetValues)[0]) 195 :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.Model.Vocabulary.AbstractField.GenerationException` if an error occurs while generating a message """ from netzob.Model.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)
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]) 5 >>> 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)) b'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(s.specialize(presets = presetValues)[0]) 195 :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.Model.Vocabulary.AbstractField.GenerationException` if an error occurs while generating a message """ from netzob.Model.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)
def __init__(self, value=None, interval=None, unitSize=None, endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()): if unitSize is None: if interval is None: # value handling if value is None: unitSize = AbstractType.defaultUnitSize() else: unitSize = Integer.checkUnitSizeForValue(value, sign) else: # interval handling if isinstance(interval, int): unitSize = Integer.checkUnitSizeForValue(interval, sign) elif len(interval) == 2: unitSizeA = Integer.checkUnitSizeForValue( interval[0], sign) unitSizeB = Integer.checkUnitSizeForValue( interval[1], sign) unitSize = max(unitSizeA, unitSizeB) else: # shouldn't happen, since _checkUnitSizeForValue raises an exception before unitSize = AbstractType.defaultUnitSize() if value is not None and not isinstance(value, bitarray): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray value = TypeConverter.convert(value, Integer, BitArray, src_unitSize=unitSize, src_endianness=endianness, src_sign=sign, dst_unitSize=unitSize, dst_endianness=endianness, dst_sign=sign) if interval is not None: nbBits = int( self._computeNbUnitSizeForInterval(interval, unitSize, sign)) * int(unitSize) else: nbBits = int(unitSize) super(Integer, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
def _generateCRC32(self, symbol): header = [] lines = [] header.append(self.ATTR_CRC32) messages = symbol.getMessages() for message in messages: line = [] data = message.getStringData() rawContent = TypeConverter.netzobRawToPythonRaw(data) valCrc32 = zlib.crc32(rawContent) & 0xFFFFFFFF line.append(str(valCrc32)) lines.append(b",".join(line)) return (header, lines)
def getMessageDetails(message): """Decode a raw network message and print the content of each encapsulated layer. :param filePathList: the messages to cluster. :type filePathList: a list of :class:`str` :param bpfFilter: a string representing a BPF filter. :type bpfFilter: :class:`str` :param importLayer: an integer representing the protocol layer to start importing. :type importLayer: :class:`int` """ decoder = Decoders.EthDecoder() return decoder.decode( TypeConverter.convert(message.data, HexaString, Raw))
def _generateSizeFieldFromBeginingOfField(self, symbol): header = [] lines = [] cells = dict() fields = symbol.fields for field in fields: if not field.isStatic(): header.append((self.ATTR_VALUE, field)) cells[field] = field.getCells(encoded=False, styled=False) for i_msg in range(0, len(symbol.getMessages())): line = [] for field in list(cells.keys()): entry = cells[field][i_msg] for k in range(2, 3, 2): if len(entry) > k: line.append( TypeConverter.netzobRawToInteger(entry[:k])) else: line.append(TypeConverter.netzobRawToInteger(entry)) lines.append(b",".join(line)) return (header, lines)
def __checksum(self, msg): self._logger.debug("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 = msg[i] & 0xFF else: w = msg[i] + (msg[i + 1] << 8) s = carry_around_add(s, w) res = ~s & 0xffff return res
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
def parseFlow(self, message, symbols): """This method parses the specified message against the specification of one or multiple consecutive symbol. It returns a list of tuples, one tuple for each consecutive symbol that participate in the flow. A tupple is made of the symbol's and its alignment of the message part it applies on. If an error occurs, an Exception is raised.""" if message is None: raise Exception("Specified cannot be None") if symbols is None or len(symbols) == 0: raise Exception( "Symbols cannot be None and must be a list of at least one symbol" ) data_to_parse_raw = message.data data_to_parse_bitarray = TypeConverter.convert(data_to_parse_raw, Raw, BitArray) for result in self._parseFlow_internal(data_to_parse_bitarray, symbols, self.memory): return result raise InvalidParsingPathException( "No parsing path returned while parsing {}".format( repr(data_to_parse_raw)))
def __init__(self, value=None, interval=None, unitSize=AbstractType.defaultUnitSize(), endianness=AbstractType.defaultEndianness(), sign=AbstractType.defaultSign()): if value is not None and not isinstance(value, bitarray): from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray interval = value value = TypeConverter.convert( value, Integer, 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) else: nbBits = int(unitSize) super(Integer, self).__init__( self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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)
def _computeExpectedValue(self, parsingPath): self._logger.debug("compute expected value for Size field") # first checks the pointed fields all have a value hasNeededData = True size = 0 remainingFields = [] for field in self.fieldDependencies: if field.domain == self: remainingFields.append(field) else: # Retrieve the size of the targeted field, if it has a fixed size if hasattr(field.domain, "dataType"): minSize, maxSize = field.domain.dataType.size if maxSize is not None and minSize == maxSize: size += minSize continue # Else, retrieve its value if it exists if parsingPath.isDataAvailableForVariable(field.domain): remainingFields.append(field) else: self._logger.debug("The following field domain has no value: '{0}'".format(field.domain)) hasNeededData = False break if not hasNeededData: raise Exception("Expected value cannot be computed, some dependencies are missing for domain {0}".format(self)) else: for field in remainingFields: # Retrieve field value if field.domain is self: fieldValue = self.dataType.generate() else: fieldValue = parsingPath.getDataAssignedToVariable( field.domain) if fieldValue is None: break # Retrieve length of field value size += len(fieldValue) size = int(size * self.factor + self.offset) size_raw = TypeConverter.convert(size, Integer, Raw, src_unitSize=self.dataType.unitSize, dst_unitSize=self.dataType.unitSize, src_sign=self.dataType.sign, dst_sign=self.dataType.sign) 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) self._logger.debug("computed value for Size field: '{}'".format(b)) return b
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") >>> values = t.mutate() >>> print(values['ascii(upper)-bits(littleEndian)']) bitarray('00010010101000100011001000110010111100101110101011110010010010100011001000100010') >>> print(values['ascii(inversed)-bits(bigEndian)']) bitarray('01100100011011000111001001101111011101110110111101101100011011000110010101101000') :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.Model.Vocabulary.Types.AbstractType.AbstractType` """ if prefixDescription is None: prefixDescription = "" else: prefixDescription += "-" from netzob.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.Types.BitArray import BitArray if self.value is None: val = self.generate() else: val = self.value strValue = TypeConverter.convert(val, BitArray, ASCII) mutations = collections.OrderedDict() 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 = collections.OrderedDict() for mutationName, mutationValue in list(mutations.items()): ba = BitArray( TypeConverter.convert(mutationValue, ASCII, BitArray)) results.update(ba.mutate(mutationName)) return results
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 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.Model.Vocabulary.Types.TypeConverter import TypeConverter from netzob.Model.Vocabulary.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
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)) self._update_presets(symbol) # 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: # do no produce content if it is a pseudo field if field.isPseudoField is True: continue # TODO: only support one level of children... must be improved if len(field.fields) > 0: d = None for child in field.fields: # do no produce content if it is a pseudo field if child.isPseudoField is True: continue 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