import random
import struct
from boofuzz import helpers
from ..fuzzable import Fuzzable
[docs]
class RandomData(Fuzzable):
"""Generate a random chunk of data while maintaining a copy of the original.
A random length range can be specified. For a static length, set min/max length to be the same.
:param name: Name, for referencing later. Names should always be provided, but if not, a default name will be given,
defaults to None
:type name: str, optional
:param default_value: Value used when the element is not being fuzzed - should typically represent a valid value,
defaults to None
:type default_value: str or bytes, optional
:param min_length: Minimum length of random block, defaults to 0
:type min_length: int, optional
:param max_length: Maximum length of random block, defaults to 1
:type max_length: int, optional
:param max_mutations: Number of mutations to make before reverting to default, defaults to 25
:type max_mutations: int, optional
:param step: If not None, step count between min and max reps, otherwise random, defaults to None
:type step: int, optional
:param fuzzable: Enable/disable fuzzing of this primitive, defaults to true
:type fuzzable: bool, optional
"""
def __init__(
self, name=None, default_value="", min_length=0, max_length=1, max_mutations=25, step=None, *args, **kwargs
):
default_value = helpers.str_to_bytes(default_value)
super(RandomData, self).__init__(name=name, default_value=default_value, *args, **kwargs)
self.min_length = min_length
self.max_length = max_length
self.max_mutations = max_mutations
self.step = step
if self.step:
self.max_mutations = (self.max_length - self.min_length) // self.step + 1
def mutations(self, default_value):
"""
Mutate the primitive value returning False on completion.
Args:
default_value (str): Default value of element.
Yields:
str: Mutations
"""
local_random = random.Random(0) # We want constant random numbers to generate reproducible test cases
for i in range(0, self.get_num_mutations()):
# select a random length for this string.
if not self.step:
length = local_random.randint(self.min_length, self.max_length)
# select a length function of the mutant index and the step.
else:
length = self.min_length + i * self.step
value = b""
for _ in range(length):
value += struct.pack("B", local_random.randint(0, 255))
yield value
def encode(self, value, mutation_context):
return value
def num_mutations(self, default_value):
"""
Calculate and return the total number of mutations for this individual primitive.
Args:
default_value:
Returns:
int: Number of mutated forms this primitive can take
"""
return self.max_mutations