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.Model.Types.TypeConverter import TypeConverter from netzob.Model.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) elif nbUnits is not None: nbBits = nbUnits * int(unitSize) else: nbBits = int(unitSize) super(Integer, self).__init__(self.__class__.__name__, value, nbBits, unitSize=unitSize, endianness=endianness, sign=sign)
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 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.Model.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.debug("Specializing 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) self.channel.write(data) self._logger.debug("Writing to commnunication channel done..")
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.Types.TypeConverter import TypeConverter from netzob.Model.Types.BitArray import BitArray return str(TypeConverter.convert(self.value, BitArray, self.__class__)) else: return str(self.value)
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 cluster(self, field, keyField): """Create and return new symbols according to a specific key field. >>> import binascii >>> from netzob.all import * >>> samples = [b"00ff2f000000", b"000020000000", b"00ff2f000000"] >>> messages = [RawMessage(data=binascii.unhexlify(sample)) for sample in samples] >>> f1 = Field(Raw(nbBytes=1)) >>> f2 = Field(Raw(nbBytes=2)) >>> f3 = Field(Raw(nbBytes=3)) >>> symbol = Symbol([f1, f2, f3], messages=messages) >>> symbol.addEncodingFunction(TypeEncodingFunction(HexaString)) >>> newSymbols = Format.clusterByKeyField(symbol, f2) >>> for sym in list(newSymbols.values()): ... sym.addEncodingFunction(TypeEncodingFunction(HexaString)) ... print(sym.name + ":") ... print(sym) Symbol_ff2f: Field | Field | Field ----- | ------ | -------- '00' | 'ff2f' | '000000' '00' | 'ff2f' | '000000' ----- | ------ | -------- Symbol_0020: Field | Field | Field ----- | ------ | -------- '00' | '0020' | '000000' ----- | ------ | -------- :param field: the field we want to split in new symbols :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField` :param keyField: the field used as a key during the splitting operation :type field: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField` :raise Exception if something bad happens """ # Safe checks if field is None: raise TypeError("'field' should not be None") if keyField is None: raise TypeError("'keyField' should not be None") if keyField not in field.fields: raise TypeError("'keyField' is not a child of 'field'") newSymbols = collections.OrderedDict() keyFieldMessageValues = keyField.getMessageValues(encoded=False, styled=False) newSymbolsSplittedMessages = {} # we identify what would be the best type of the key field keyFieldType = ASCII for message, keyFieldValue in list(keyFieldMessageValues.items()): # If the value cannot be parsed as ASCII, we convert it to HexaString if not ASCII().canParse( TypeConverter.convert(keyFieldValue, Raw, BitArray)): keyFieldType = HexaString break # Even if the value is theoritically parsable as ASCII, some caracters cannot be encoded, so we double check tmp_value = TypeConverter.convert(keyFieldValue, Raw, ASCII) tmp2_value = TypeConverter.convert(tmp_value, ASCII, Raw) if keyFieldValue != tmp2_value: # This means we cannot retrieve the original value by encoding and then decoding in ASCII keyFieldType = HexaString break # we create a symbol for each of these uniq values for message, keyFieldValue in list(keyFieldMessageValues.items()): keyFieldValue = TypeConverter.convert(keyFieldValue, Raw, keyFieldType) if keyFieldValue not in list(newSymbols.keys()): if type(keyFieldValue) is str: symbolName = "Symbol_{0}".format(keyFieldValue) else: symbolName = "Symbol_{0}".format( keyFieldValue.decode("utf-8")) newSymbols[keyFieldValue] = Symbol(name=symbolName, messages=[message]) splittedMessages = DataAlignment.align([message.data], field, encoded=False) newSymbolsSplittedMessages[keyFieldValue] = [ splittedMessages[0] ] else: newSymbols[keyFieldValue].messages.append(message) splittedMessages = DataAlignment.align([message.data], field, encoded=False) newSymbolsSplittedMessages[keyFieldValue].append( splittedMessages[0]) for newSymbolKeyValue, newSymbol in list(newSymbols.items()): # we recreate the same fields in this new symbol as the fields that exist in the original symbol newSymbol.clearFields() for i, f in enumerate(field.fields): if f == keyField: newFieldDomain = TypeConverter.convert( newSymbolKeyValue, keyFieldType, Raw) else: newFieldDomain = set() for j in range( len(newSymbolsSplittedMessages[newSymbolKeyValue]) ): newFieldDomain.add( newSymbolsSplittedMessages[newSymbolKeyValue][j] [i]) newFieldDomain = list(newFieldDomain) newF = Field(name=f.name, domain=newFieldDomain) newF.parent = newSymbol newSymbol.fields.append(newF) # we remove endless fields that accepts no values cells = newSymbol.getCells(encoded=False, styled=False, transposed=False) max_i_cell_with_value = 0 for line in cells: for i_cell, cell in enumerate(line): if cell != '' and max_i_cell_with_value < i_cell: max_i_cell_with_value = i_cell newSymbol.clearFields() for i, f in enumerate(field.fields[:max_i_cell_with_value + 1]): if f == keyField: newFieldDomain = TypeConverter.convert( newSymbolKeyValue, keyFieldType, Raw) else: newFieldDomain = set() for j in range( len(newSymbolsSplittedMessages[newSymbolKeyValue]) ): newFieldDomain.add( newSymbolsSplittedMessages[newSymbolKeyValue][j] [i]) newFieldDomain = list(newFieldDomain) newF = Field(name=f.name, domain=newFieldDomain) newF.parent = newSymbol newSymbol.fields.append(newF) return newSymbols
def split(field, delimiter): """Split a field (or symbol) with a specific delimiter. The delimiter can be passed either as an ASCII, a Raw, an HexaString, or any objects that inherit from AbstractType. >>> from netzob.all import * >>> samples = [b"aaaaff000000ff10", b"bbff110010ff00000011", b"ccccccccfffe1f000000ff12"] >>> messages = [RawMessage(data=sample) for sample in samples] >>> symbol = Symbol(messages=messages[:3]) >>> Format.splitDelimiter(symbol, ASCII("ff")) >>> print(symbol) Field-0 | Field-sep-6666 | Field-2 | Field-sep-6666 | Field-4 ---------- | -------------- | ------------ | -------------- | ---------- 'aaaa' | 'ff' | '000000' | 'ff' | '10' 'bb' | 'ff' | '110010' | 'ff' | '00000011' 'cccccccc' | 'ff' | 'fe1f000000' | 'ff' | '12' ---------- | -------------- | ------------ | -------------- | ---------- >>> samples = [b"434d446964656e74696679230400000066726564", b"5245536964656e74696679230000000000000000", b"434d44696e666f2300000000", b"524553696e666f230000000004000000696e666f", b"434d4473746174732300000000", b"52455373746174732300000000050000007374617473", b"434d4461757468656e7469667923090000006d7950617373776421", b"52455361757468656e74696679230000000000000000", b"434d44656e6372797074230a00000031323334353674657374", b"524553656e637279707423000000000a00000073707176777436273136", b"434d4464656372797074230a00000073707176777436273136", b"5245536465637279707423000000000a00000031323334353674657374", b"434d446279652300000000", b"524553627965230000000000000000", b"434d446964656e746966792307000000526f626572746f", b"5245536964656e74696679230000000000000000", b"434d44696e666f2300000000", b"524553696e666f230000000004000000696e666f", b"434d4473746174732300000000", b"52455373746174732300000000050000007374617473", b"434d4461757468656e74696679230a000000615374726f6e67507764", b"52455361757468656e74696679230000000000000000", b"434d44656e63727970742306000000616263646566", b"524553656e6372797074230000000006000000232021262724", b"434d44646563727970742306000000232021262724", b"52455364656372797074230000000006000000616263646566", b"434d446279652300000000", b"524553627965230000000000000000"] >>> messages = [RawMessage(data=TypeConverter.convert(sample, HexaString, Raw)) for sample in samples] >>> symbol = Symbol(messages=messages) >>> symbol.encodingFunctions.add(TypeEncodingFunction(ASCII)) # Change visualization to hexastring >>> Format.splitDelimiter(symbol, ASCII("#")) >>> print(symbol) Field-0 | Field-sep-23 | Field-2 | Field-sep-23 | Field-4 --------------- | ------------ | -------------------- | ------------ | ------- 'CMDidentify' | '#' | '....fred' | '' | '' 'RESidentify' | '#' | '........' | '' | '' 'CMDinfo' | '#' | '....' | '' | '' 'RESinfo' | '#' | '........info' | '' | '' 'CMDstats' | '#' | '....' | '' | '' 'RESstats' | '#' | '........stats' | '' | '' 'CMDauthentify' | '#' | '....myPasswd!' | '' | '' 'RESauthentify' | '#' | '........' | '' | '' 'CMDencrypt' | '#' | '....123456test' | '' | '' 'RESencrypt' | '#' | "........spqvwt6'16" | '' | '' 'CMDdecrypt' | '#' | "....spqvwt6'16" | '' | '' 'RESdecrypt' | '#' | '........123456test' | '' | '' 'CMDbye' | '#' | '....' | '' | '' 'RESbye' | '#' | '........' | '' | '' 'CMDidentify' | '#' | '....Roberto' | '' | '' 'RESidentify' | '#' | '........' | '' | '' 'CMDinfo' | '#' | '....' | '' | '' 'RESinfo' | '#' | '........info' | '' | '' 'CMDstats' | '#' | '....' | '' | '' 'RESstats' | '#' | '........stats' | '' | '' 'CMDauthentify' | '#' | '....aStrongPwd' | '' | '' 'RESauthentify' | '#' | '........' | '' | '' 'CMDencrypt' | '#' | '....abcdef' | '' | '' 'RESencrypt' | '#' | '........' | '#' | " !&'$" 'CMDdecrypt' | '#' | '....' | '#' | " !&'$" 'RESdecrypt' | '#' | '........abcdef' | '' | '' 'CMDbye' | '#' | '....' | '' | '' 'RESbye' | '#' | '........' | '' | '' --------------- | ------------ | -------------------- | ------------ | ------- >>> print(symbol.fields[0]._str_debug()) Field-0 |-- Alt |-- Data (Raw=b'CMDidentify' ((0, 88))) |-- Data (Raw=b'RESidentify' ((0, 88))) |-- Data (Raw=b'CMDinfo' ((0, 56))) |-- Data (Raw=b'RESinfo' ((0, 56))) |-- Data (Raw=b'CMDstats' ((0, 64))) |-- Data (Raw=b'RESstats' ((0, 64))) |-- Data (Raw=b'CMDauthentify' ((0, 104))) |-- Data (Raw=b'RESauthentify' ((0, 104))) |-- Data (Raw=b'CMDencrypt' ((0, 80))) |-- Data (Raw=b'RESencrypt' ((0, 80))) |-- Data (Raw=b'CMDdecrypt' ((0, 80))) |-- Data (Raw=b'RESdecrypt' ((0, 80))) |-- Data (Raw=b'CMDbye' ((0, 48))) |-- Data (Raw=b'RESbye' ((0, 48))) Below is another example of the FieldSplitDelimiter usage: it splits fields based on a Raw string. >>> from netzob.all import * >>> samples = [b"\\x01\\x02\\x03\\xff\\x04\\x05\\xff\\x06\\x07", b"\\x01\\x02\\xff\\x03\\x04\\x05\\x06\\xff\\x07", b"\\x01\\xff\\x02\\x03\\x04\\x05\\x06"] >>> messages = [RawMessage(data=sample) for sample in samples] >>> symbol = Symbol(messages=messages) >>> Format.splitDelimiter(symbol, Raw(b"\\xff")) >>> print(symbol) Field-0 | Field-sep-ff | Field-2 | Field-sep-ff | Field-4 -------------- | ------------ | ---------------------- | ------------ | ---------- '\\x01\\x02\\x03' | b'\\xff' | '\\x04\\x05' | b'\\xff' | '\\x06\\x07' '\\x01\\x02' | b'\\xff' | '\\x03\\x04\\x05\\x06' | b'\\xff' | '\\x07' '\\x01' | b'\\xff' | '\\x02\\x03\\x04\\x05\\x06' | '' | '' -------------- | ------------ | ---------------------- | ------------ | ---------- :param field : the field to consider when spliting :type: :class:`netzob.Model.Vocabulary.AbstractField.AbstractField` :param delimiter : the delimiter used to split messages of the field :type: :class:`netzob.Model.Types.AbstractType.AbstractType` """ if delimiter is None: raise TypeError("Delimiter cannot be None.") if field is None: raise TypeError("Field cannot be None.") if len(field.messages) < 1: raise ValueError("The associated symbol does not contain any message.") # Find message substrings after applying delimiter splittedMessages = [] for cell in field.getValues(encoded=False, styled=False): splittedMessage = cell.split(delimiter.value.tobytes()) splittedMessages.append(splittedMessage) import itertools # Inverse the array, so that columns contains observed values for each field splittedMessages = list(itertools.zip_longest(*splittedMessages)) # If the delimiter does not create splitted fields if len(splittedMessages) <= 1: return # Else, we add (2*len(splittedMessages)-1) fields newFields = [] iField = -1 for i in range(len(splittedMessages)): iField += 1 fieldDomain = list() # temporary set that hosts all the observed values to prevent useless duplicate ones observedValues = set() has_inserted_empty_value = False isEmptyField = True # To avoid adding an empty field for v in splittedMessages[i]: if v != "" and v is not None: isEmptyField = False if v not in observedValues: fieldDomain.append(Raw(v)) observedValues.add(v) else: if not has_inserted_empty_value: fieldDomain.append(Raw(nbBytes=0)) has_inserted_empty_value = True if not isEmptyField: newField = Field(domain=DomainFactory.normalizeDomain(fieldDomain), name="Field-"+str(iField)) newField.encodingFunctions = list(field.encodingFunctions.values()) newFields.append(newField) iField += 1 str_delimiter = TypeConverter.convert(delimiter.value, BitArray, HexaString).decode('utf-8') fieldName = "Field-sep-{}".format(str_delimiter) newFields.append(Field(domain=Alt([delimiter, Raw(nbBytes=0)]), name=fieldName)) newFields.pop() # Reset the field from netzob.Inference.Vocabulary.Format import Format Format.resetFormat(field) # Create a field for each entry field.fields = newFields
def 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 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(b"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 [(80, 144)] 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.Model.Types.AbstractType.AbstractType`. :parameter message: the message in which the search will take place :type message: :class:`netzob.Model.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 list(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
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
def __str__(self): result = [] for var, value in list(self.memory.items()): result.append("{0}: {1}".format( var, TypeConverter.convert(value, BitArray, Raw))) return '\n'.join(result)
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.Types.AbstractType.AbstractType` """ if prefixDescription is None: prefixDescription = "" else: prefixDescription += "-" from netzob.Model.Types.TypeConverter import TypeConverter from netzob.Model.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 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.Types.TypeConverter import TypeConverter from netzob.Model.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