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
def mergeFields(self, field1, field2): """Merge specified fields. >>> import binascii >>> from netzob.all import * >>> samples = ["00ff2f000000", "000010000000", "00fe1f000000"] >>> messages = [RawMessage(data=binascii.unhexlify(sample)) for sample in samples] >>> f1 = Field(Raw(nbBytes=1), name="f1") >>> f2 = Field(Raw(nbBytes=2), name="f2") >>> f3 = Field(Raw(nbBytes=2), name="f3") >>> f4 = Field(Raw(nbBytes=1), name="f4") >>> symbol = Symbol([f1, f2, f3, f4], messages=messages) >>> symbol.addEncodingFunction(TypeEncodingFunction(HexaString)) >>> print symbol f1 | f2 | f3 | f4 ---- | ------ | ------ | ---- '00' | 'ff2f' | '0000' | '00' '00' | '0010' | '0000' | '00' '00' | 'fe1f' | '0000' | '00' ---- | ------ | ------ | ---- >>> fo = FieldOperations() >>> fo.mergeFields(f2, f3) >>> print symbol f1 | Merge | f4 ---- | ---------- | ---- '00' | 'ff2f0000' | '00' '00' | '00100000' | '00' '00' | 'fe1f0000' | '00' ---- | ---------- | ---- >>> fo.mergeFields(symbol.fields[0], symbol.fields[1]) >>> print symbol Merge | f4 ------------ | ---- '00ff2f0000' | '00' '0000100000' | '00' '00fe1f0000' | '00' ------------ | ---- >>> fo.mergeFields(symbol.fields[0], symbol.fields[1]) >>> print symbol Merge -------------- '00ff2f000000' '000010000000' '00fe1f000000' -------------- :param field1: the left field to merge :type field1: :class:`netzob.Common.Models.Vocabulary.AbstractField.AbstractField` :param field2: the right field to merge :type field2: :class:`netzob.Common.Models.Vocabulary.AbstractField.AbstractField` :raise Exception if something bad happens """ if field1 is None or field2 is None: raise TypeError("Fields cannot be None") if field1 == field2: raise ValueError("Cannot merge a unique field (field1 == field2)") self._logger.debug("Merging field {0} with field {1}".format(field1.name, field2.name)) if field1.parent is not field2.parent: raise ValueError("Specified fields don't have the same parent, only fields with same parents can be merged.") # retrieve indexes of specified fields iField1 = None iField2 = None for iField, field in enumerate(field1.parent.fields): if field == field1: iField1 = iField elif field == field2: iField2 = iField if iField1 is None: raise ValueError("Cannot retrieve position of field1 in its parent fields") if iField2 is None: raise ValueError("Cannot retrieve position of field2 in its parent fields") if iField2 != iField1 + 1: raise ValueError("Field1 must be directly on the left of field2 (iField1={0}, iField2={1})".format(iField1, iField2)) # build a new field domain newDomain = Agg([field1.domain, field2.domain]) newField = Field(domain=newDomain, name="Merge") newField.encodingFunctions = field1.encodingFunctions.values() parent = field1.parent before = parent.fields[:iField1] after = parent.fields[iField2 + 1:] parent.fields = before + [newField] + after
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 '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 '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' | '#' | '........' | '' | '' :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 = set() isEmptyField = True # To avoid adding an empty field emptyValueFound = False for v in splittedMessages[i]: if v != "" and v is not None: isEmptyField = False fieldDomain.add(Raw(v)) else: fieldDomain.add(Raw(nbBytes=0)) if not isEmptyField: fieldDomain = list(fieldDomain) 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