def __init__(self, value, num_bytes=1, fuzzable=True, name=None): ''' :type value: str or bytes :param value: value to mutate :param num_bytes: number of consequtive bytes to flip (invert) :param fuzzable: is field fuzzable (default: True) :param name: name of the object (default: None) :raises: ``KittyException`` if num_bytes is bigger than the value length :raises: ``KittyException`` if num_bytes is not positive ''' kassert.is_of_types(value, (bytes, bytearray, str)) value = strToBytes(value) if len(value) < num_bytes: raise KittyException('len(value) <= num_bytes', (len(value), num_bytes)) if num_bytes <= 0: raise KittyException('num_bytes(%d) <= 0' % (num_bytes)) super(ByteFlip, self).__init__(value=value, encoder=ENC_STR_DEFAULT, fuzzable=fuzzable, name=name) self._data_len = len(value) self._num_bytes = num_bytes self._num_mutations = self._data_len - (num_bytes - 1)
def __init__(self, field, comp_type, comp_value): ''' :param field: (name of) field that should meet the condition :param comp_type: how to compare the values. One of ('>', '<', '>=', '<=', '==', '!=') :param comp_value: value to compare the field to :example: Render the content of the `If` container only if the value in the field called "name" is not 'kitty' :: Template([ String('kitty', name='name'), If(Compare('name', '!=', 'kitty'), [ String('current name is not kitty') ]) ]) ''' super(Compare, self).__init__(field=field) self._comp_type = comp_type if comp_type in Compare._comparison_types: if comp_type not in ['==', '!='] and isinstance(comp_value, str): raise KittyException('can\'t use comparison type "%s" with comparison value of type str' % comp_type) self._comp_fn = Compare._comparison_types[comp_type] else: raise KittyException('unknown comparison type (%s)' % (comp_type)) if isinstance(comp_value, six.string_types): comp_value = strToBytes(comp_value) self._comp_value = comp_value
def __init__(self, field, comp_type, comp_value): ''' :param field: (name of) field that should meet the condition :param comp_type: how to compare the values. One of ('>', '<', '>=', '<=', '==', '!=') :param comp_value: value to compare the field to :example: Render the content of the `If` container only if the value in the field called "name" is not 'kitty' :: Template([ String('kitty', name='name'), If(Compare('name', '!=', 'kitty'), [ String('current name is not kitty') ]) ]) ''' super(Compare, self).__init__(field=field) self._comp_type = comp_type if comp_type in Compare._comparison_types: if comp_type not in ['==', '!='] and isinstance(comp_value, str): raise KittyException( 'can\'t use comparison type "%s" with comparison value of type str' % comp_type) self._comp_fn = Compare._comparison_types[comp_type] else: raise KittyException('unknown comparison type (%s)' % (comp_type)) if isinstance(comp_value, six.string_types): comp_value = strToBytes(comp_value) self._comp_value = comp_value
def _mutate(self): if self._step: length = self._min_length + self._step * self._current_index else: length = self._random.randint(self._min_length, self._max_length) current_bytes = '' for _ in range(length // 8 + 1): current_bytes += chr(self._random.randint(0, 255)) self._current_value = Bits(bytes=strToBytes(current_bytes))[:length]
def _mutate(self): start, end = self._start_end() pre = self._default_value[:start] current = self._default_value[start:end] if sys.version_info >= (3,): mutated = ''.join(chr(c ^ 0xff) for c in current) else: mutated = ''.join(chr(ord(c) ^ 0xff) for c in current) post = self._default_value[end:] self.set_current_value(pre + strToBytes(mutated) + post)
def _mutate(self): start, end = self._start_end() pre = self._default_value[:start] current = self._default_value[start:end] if sys.version_info >= (3, ): mutated = ''.join(chr(c ^ 0xff) for c in current) else: mutated = ''.join(chr(ord(c) ^ 0xff) for c in current) post = self._default_value[end:] self.set_current_value(pre + strToBytes(mutated) + post)
def __init__(self, value, encoder=ENC_STR_DEFAULT, name=None): ''' :type value: str :param value: default value :type encoder: :class:`~kitty.model.low_level.encoder.StrEncoder` :param encoder: encoder for the field (default: ENC_STR_DEFAULT) :param name: name of the object (default: None) :example: :: Static('this will never change') ''' value = strToBytes(value) super(Static, self).__init__(value=value, encoder=encoder, fuzzable=False, name=name)
def __init__( self, value, min_length, max_length, unused_bits=0, seed=1235, num_mutations=25, step=None, encoder=ENC_BITS_DEFAULT, fuzzable=True, name=None): ''' :type value: str :param value: default value, the last *unsused_bits* will be removed from the value :param min_length: minimal length of the field (in bits) :param max_length: maximal length of the field (in bits) :param unused_bits: how many bits from the value are not used (default: 0) :param seed: seed for the random number generator, to allow consistency between runs (default: 1235) :param num_mutations: number of mutations to perform (if step is None) (default:25) :type step: int :param step: step between lengths of each mutation (default: None) :type encoder: :class:`~kitty.model.low_level.encoder.BitsEncoder` :param encoder: encoder for the field (default: ENC_BITS_DEFAULT) :param fuzzable: is field fuzzable (default: True) :param name: name of the object (default: None) :examples: :: RandomBits(value='1234', min_length=0, max_length=75, unused_bits=0, step=15) RandomBits(value='1234', min_length=0, max_length=75, unused_bits=3, num_mutations=80) ''' if unused_bits not in range(8): raise KittyException('unused bits (%d) is not between 0-7' % unused_bits) value = Bits(bytes=strToBytes(value)) if unused_bits: value = value[:-unused_bits] super(RandomBits, self).__init__(value=value, encoder=encoder, fuzzable=fuzzable, name=name) self._validate_lengths(min_length, max_length) self._min_length = min_length self._max_length = max_length self._num_mutations = num_mutations self._step = step self._random = Random() self._seed = seed self._random.seed(self._seed) if self._step: if self._step < 0: raise KittyException('step (%d) < 0' % (step)) self._num_mutations = (self._max_length - self._min_length) // self._step
def __init__(self, value, max_size=None, encoder=ENC_STR_DEFAULT, fuzzable=True, name=None): ''' :type value: str or bytes :param value: default value :param max_size: maximal size of the string before encoding (default: None) :type encoder: :class:`~kitty.model.low_level.encoder.StrEncoder` :param encoder: encoder for the field :param fuzzable: is field fuzzable (default: True) :param name: name of the object (default: None) :example: :: String('this is the default value', max_size=5) ''' self._max_size = None if max_size is None else max_size value = strToBytes(value) super(String, self).__init__(value=value, encoder=encoder, fuzzable=fuzzable, name=name)
def __init__(self, pad_length, pad_data=b'\x00', fields=[], fuzzable=True, name=None): ''' :param pad_length: length to pad up to (in bits) :param pad_data: data to pad with (default: b'\x00') :param fields: enclosed field(s) (default: []) :param fuzzable: is fuzzable (default: True) :param name: (unique) name of the template (default: None) :example: Pad a string with ' 's so it is at least 20 bytes :: Pad(fields=String('padded'), pad_data=' ', pad_length=20) # default result will be: 'padded ' ''' super(Pad, self).__init__(fields=fields, encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name) self._pad_length = pad_length self._pad_data = Bits(bytes=strToBytes(pad_data))
def __init__(self, value, num_bits=1, fuzzable=True, name=None): ''' :param value: value to mutate (str or bytes) :param num_bits: number of consequtive bits to flip (invert) :param fuzzable: is field fuzzable (default: True) :param name: name of the object (default: None) :raises: ``KittyException`` if num_bits is bigger than the value length in bits :raises: ``KittyException`` if num_bits is not positive ''' kassert.is_of_types(value, (bytes, bytearray, str)) value = strToBytes(value) if len(value) * 8 < num_bits: raise KittyException('len of value in bits(%d) < num_bits(%d)' % (len(value) * 8, num_bits)) if num_bits <= 0: raise KittyException('num_bits(%d) <= 0' % (num_bits)) super(BitFlip, self).__init__(value=Bits(bytes=value), encoder=ENC_BITS_DEFAULT, fuzzable=fuzzable, name=name) self._data_len = len(value) * 8 self._num_bits = num_bits self._num_mutations = self._data_len - (num_bits - 1)
def _encode_func(self, s): return hexlify(strToBytes(s))
def testFlipTwoBitsOnSingleByte(self): expected_mutations = map(lambda i: strToBytes(chr(3 << i)), range(7)) self._testBase(b'\x00', 2, expected_mutations)
def _encode_func(self, s): return strToBytes(s) + b'\x00'
def _default_value(self, data_size): return strToBytes(''.join( map(lambda x: chr(x % 0x100), range(data_size))))
def testFlipSingleBitOnSingleByte(self): expected_mutations = map(lambda i: strToBytes(chr(1 << i)), range(8)) self._testBase(b'\x00', 1, expected_mutations)
def _default_value(self, data_size): return strToBytes(''.join(map(lambda x: chr(x % 0x100), range(data_size))))