Blocks

Request

The Request class has push and pop methods for creating it. Whenever a new Block is opened/started, it is pushed onto the “block stack”. Note that this is different than the “stack”. When a Block is closed, it is popped.

When the Request is assembled in the fuzz definition, its stack should be empty. To accomplish this, all blocks should be closed.

class boofuzz.Request(name=None, children: tuple[BasePrimitive, ...] = None, timeout_check: bool = True, fragmentation: Callable = None, fragmentation_length: int = 516, receive_data_after_transmit: bool = True, answer_must_contain: list[str | bytes] | None = None, answer_must_not_contain: list[str | bytes] | None = None)[source]

Bases: FuzzableBlock, Node

Top level container. Can hold any block structure or primitive.

This can essentially be thought of as a super-block, root-block, daddy-block or whatever other alias you prefer.

Here are the parameters of the Request class:

Parameters:
  • name (str, optional) – Name of this request

  • children (boofuzz.Fuzzable, optional) – Children of this request, defaults to None

  • timeout_check (bool, optional) – If True, check for timeout, defaults to True

  • fragmentation (Callable, optional) – Fragmentation function, defaults to None

  • fragmentation_length (int, optional) – Fragmentation length, defaults to 516

  • receive_data_after_transmit (bool, optional) – default to True, force the request to not wait answer if False

  • answer_must_contain (list[str|bytes], optional) – List of strings or bytes that the answer must contain, defaults to None

  • answer_must_not_contain (list[str|bytes], optional) – List of strings or bytes that the answer must not contain, defaults to None

And it’s attributes:

Parameters:
  • parent_session (boofuzz.Session) – Parent session of this Request, so children can now access parameters of session.

  • smooth_rtt (float) – Smoothed Round Trip Time

  • rtt_variations (float) – Round Trip Time Variations

analyze_answer(data: bytes, session: Session) None[source]

If answer_must_contains or answer_must_not_contains is filled, when we got an anwer, we analyze it and log it

Returns:

None

calculate_rto(rtt: float, alpha: float = 0.125, beta: float = 0.25, k: int = 4) float[source]

Public method to calculate a new retransmission timeout using TCP formula :

\[ \begin{align}\begin{aligned}srtt = (1 - g).srtt + g.rtt\\rttvar = (1 - h).rttvar + h.|rtt - srtt|\\RTO = srtt + 4.rttvar\end{aligned}\end{align} \]

See RFC 6298 for more information.

Parameters:
  • rtt (float) – The new round trip time

  • alpha (float) – The alpha value of the formula. This gain factor determines how quickly the smoothed round-trip time (srtt) responds to changes in the measured round-trip time. A larger alpha makes srtt more sensitive to recent changes, making it adapt faster to network conditions. A smaller alpha makes srtt more stable but slower to react to changes. Optional, defaults to 0.125

  • beta (float) – The beta value of the formula. This gain factor affects how the round-trip time variation (rttvar) responds to changes in the deviation of the measured round-trip time from srtt. A larger beta makes rttvar more sensitive to fluctuations, capturing changes in variability more quickly. A smaller beta makes rttvar more stable but slower to adapt to new conditions. Optional, defaults to 0.25

  • k (int) – The k value of the formula. A larger value provides more buffer. Changes not recommended.

Returns:

The new retransmission timeout

property fuzzable

If False, this element should not be mutated in normal fuzzing.

get_mutations(default_value=None, skip_elements=None)[source]

Iterate mutations. Used by boofuzz framework.

Yields:

list of Mutation – Mutations

get_num_mutations()[source]

Get the number of mutations for this element.

property name

Element name, should be unique for each instance.

Return type:

str

pop()[source]

The last open block was closed, so pop it off of the block stack.

push(item)[source]

Push an item into the block structure. If no block is open, the item goes onto the request stack. otherwise, the item goes onto the last open blocks stack.

What this method does: 1. Sets context_path for each pushed FuzzableWrapper. 2. Sets request for each FuzzableWrapper 3. Checks for duplicate qualified_name items 4. Adds item to self.names map (based on qualified_name) 5. Adds the item to self.stack, or to the stack of the currently opened block.

Also: Manages block_stack, mostly an implementation detail to help static protocol definition

@type item: BasePrimitive | Block | Request | Size | Repeat @param item: Some primitive/block/request/etc.

render(mutation_context=None)[source]

Render after applying mutation, if applicable. :type mutation_context: MutationContext

resolve_name(context_path, name)[source]

Names are resolved thus: #. If the name starts with a dot, it is treated as a relative path name in the style of PEP 328.

  1. “.” refers to the current directory, so to speak.

  2. “..” refers to the next directory up.

  3. “…” refers to another directory up, and so forth.

  1. If the name does _not_ start with a dot, it is treated as an absolute name.

  2. Backwards compatibility: If the absolute name fails to resolve, the engine searches for any block or

    primitive with that name. If more or less than exactly one match is found, an error results.

Parameters:
  • context_path – The “current working directory” for resolving the name. E.g. “block_1.block_2”.

  • name – The name being resolved. May be absolute or relative.

Returns:

walk(stack=None)[source]

Recursively walk through and yield every primitive and block on the request stack.

@param stack: Set to none – used internally by recursive calls.

If None, uses self.stack.

@rtype: Sulley Primitives @return: Sulley Primitives

Block

class boofuzz.Block(name=None, default_value=None, request=None, children=None, group=None, encoder=None, dep=None, dep_value=None, dep_values=None, dep_compare='==', *args, **kwargs)[source]

Bases: FuzzableBlock

The basic building block. Can contain primitives, sizers, checksums or other blocks.

Parameters:
  • name (str, optional) – Name, for referencing later. Names should always be provided, but if not, a default name will be given, defaults to None

  • default_value (Any, optional) – Value used when the element is not being fuzzed - should typically represent a valid value, defaults to None

  • request (boofuzz.Request, optional) – Request this block belongs to, defaults to None

  • children (boofuzz.Fuzzable, optional) – Children of this block, defaults to None

  • group (str, optional) – Name of group to associate this block with, defaults to None

  • encoder (callable, optional) – Optional pointer to a function to pass rendered data to prior to return, defaults to None

  • dep (str, optional) – Optional primitive whose specific value this block is dependant on, defaults to None

  • dep_value (bytes, optional) – Value that field “dep” must contain for block to be rendered, defaults to None

  • dep_values (list, optional) – Values that field “dep” may contain for block to be rendered, defaults to None

  • dep_compare (str, optional) – Comparison method to apply to dependency (==, !=, >, >=, <, <=), defaults to None

encode(value, mutation_context)[source]

Takes a value and encodes/renders/serializes it to a bytes (byte string).

Optional if mutations() yields bytes.

Example: Yield strings with mutations() and encode them to UTF-8 using encode().

Default behavior: Return value.

Parameters:
  • value – Value to encode. Type should match the type yielded by mutations()

  • mutation_context (MutationContext) – Context for current mutation, if any.

Returns:

Encoded/serialized value.

Return type:

bytes

mutations(default_value, skip_elements=None)[source]

Generator to yield mutation values for this element.

Values are either plain values or callable functions that take a “default value” and mutate it. Functions are used when the default or “normal” value influences the fuzzed value. Functions are used because the “normal” value is sometimes dynamic and not known at the time of generation.

Each mutation should be a pre-rendered value. That is, it must be suitable to pass to encode().

Default: Empty iterator.

Parameters:

default_value

num_mutations(default_value=None)[source]

Return the total number of mutations for this element (not counting “fuzz_values”).

Default implementation exhausts the mutations() generator, which is inefficient. Override if you can provide a value more efficiently, or if exhausting the mutations() generator has side effects.

Parameters:

default_value – Use if number of mutations depends on the default value. Provided by FuzzableWrapper. Note: It is generally good behavior to have a consistent number of mutations for a given default value length.

Returns:

Number of mutated forms this primitive can take

Return type:

int

Checksum

Sulley’s Checksum class creates a block that calculates the checksum of another block.

Algorithms

Checksum contains only the Sulley block logic for a checksum, not specific algorithm implementations. Algorithms are implemented with a library or a free function.

Recursion

To enable a checksum to be calculated over its parent block, it is necessary to account for recursion. This is done with a recursion flag. When Checksum renders itself for the sake of calculations, it will set a recursion flag on itself. Then, when the parent block again renders the Checksum, Checksum will check its own recursion flag and return its default value.

Note: To avoid recursion problems with Size, it is important that Checksum’s length method not call render on itself.

UDP

UDP is special in that it is computed over a pseudo-header, including selected fields from IPv4 and the entire UDP header and payload. The IPv4 fields are:

  • IPv4 Source Address

  • IPv4 Destination Address

  • Protocol (should always be UDP)

  • Length of UDP header+payload

Note that these fields do not themselves need to be individually fuzzed, since fuzzing any of them would result in a bad checksum – and a bad checksum can be checked by fuzzing the checksum field itself.

Designs considered:

  1. Passing a reference to the IPv4 Sulley Block and navigating to its children.

  2. Passing source and destination addresses directly to the Checksum constructor.

  3. Passing references to the source and destination Sulley Blocks into the Checksum constructor.

Option 1 was rejected as being too involved. It would need to know the structure of the IPv4 Sulley Block, which would result in complexity and possibly duplicated information.

Option 2 was rejected as inferior to 1 and 3. With option 2, when the IPv4 source or destination address is being fuzzed, the UDP checksum will automatically start failing. This could draw attention away from the IPv4 src/dst fields for the sake of fuzzing.

With option 3, when the IPv4 src/dst fields are being fuzzed, the UDP checksum will still pass. Furthermore, taking a reference to two Sulley Blocks is relatively easy.

Source Code

class boofuzz.Checksum(name=None, block_name=None, request=None, algorithm='crc32', length=0, endian='<', ipv4_src_block_name=None, ipv4_dst_block_name=None, *args, **kwargs)[source]

Bases: BasePrimitive

Checksum bound to the block with the specified name.

The algorithm may be chosen by name with the algorithm parameter, or a custom function may be specified with the algorithm parameter.

The length field is only necessary for custom algorithms. When using your own custom checksum function, the return value should be the calculated checksum of the data.

Function signature: <function_name>(data_bytes). Returns a number represented as a bytes type.

Recursive checksums are supported; the checksum field itself will render as all zeros for the sake of checksum or length calculations.

Parameters:
  • name (str, optional) – Name, for referencing later. Names should always be provided, but if not, a default name will be given, defaults to None

  • block_name (str) – Name of target block for checksum calculations.

  • request (boofuzz.Request, optional) – Request this block belongs to

  • algorithm (str, function def name, optional) – Checksum algorithm to use from this list, default is crc32 (crc32, crc32c, adler32, md5, sha1, ipv4, udp). See above for custom checksum function example.

  • length (int, optional) – Length of checksum, auto-calculated by default. Must be specified manually when using custom algorithm, defaults to 0

  • endian (chr, optional) – Endianness of the bit field (LITTLE_ENDIAN: <, BIG_ENDIAN: >), defaults to LITTLE_ENDIAN

  • ipv4_src_block_name (str, optional) – Required for ‘udp’ algorithm. Name of block yielding IPv4 source address, defaults to None

  • ipv4_dst_block_name (str, optional) – Required for ‘udp’ algorithm. Name of block yielding IPv4 destination address, defaults to None

  • fuzzable (bool, optional) – Enable/disable fuzzing of this block, defaults to true

checksum_lengths = {'adler32': 4, 'crc32': 4, 'crc32c': 4, 'ipv4': 2, 'md5': 16, 'sha1': 20, 'udp': 2}
encode(value, mutation_context)[source]

Takes a value and encodes/renders/serializes it to a bytes (byte string).

Optional if mutations() yields bytes.

Example: Yield strings with mutations() and encode them to UTF-8 using encode().

Default behavior: Return value.

Parameters:
  • value – Value to encode. Type should match the type yielded by mutations()

  • mutation_context (MutationContext) – Context for current mutation, if any.

Returns:

Encoded/serialized value.

Return type:

bytes

Repeat

class boofuzz.Repeat(name=None, block_name=None, request=None, min_reps=0, max_reps=25, step=1, variable=None, default_value=None, *args, **kwargs)[source]

Bases: Fuzzable

Repeat the rendered contents of the specified block cycling from min_reps to max_reps counting by step.

By default renders to nothing. This block modifier is useful for fuzzing overflows in table entries. This block modifier MUST come after the block it is being applied to.

Parameters:
  • name (str, optional) – Name, for referencing later. Names should always be provided, but if not, a default name will be given, defaults to None

  • block_name (str, optional) – Name of block to repeat

  • request (boofuzz.Request, optional) – Request this block belongs to, defaults to None

  • min_reps (int, optional) – Minimum number of block repetitions, defaults to 0

  • max_reps (int, optional) – Maximum number of block repetitions, defaults to None

  • step (int, optional) – Step count between min and max reps, defaults to 1

  • variable (Boofuzz Integer Primitive, optional) – Repetitions will be derived from this variable, disables fuzzing, defaults to None

  • default_value (Raw) – Value used when the element is not being fuzzed - should typically represent a valid value, defaults to None

  • fuzzable (bool, optional) – Enable/disable fuzzing of this block, defaults to true

encode(value, mutation_context)[source]

Takes a value and encodes/renders/serializes it to a bytes (byte string).

Optional if mutations() yields bytes.

Example: Yield strings with mutations() and encode them to UTF-8 using encode().

Default behavior: Return value.

Parameters:
  • value – Value to encode. Type should match the type yielded by mutations()

  • mutation_context (MutationContext) – Context for current mutation, if any.

Returns:

Encoded/serialized value.

Return type:

bytes

mutations(default_value)[source]

Generator to yield mutation values for this element.

Values are either plain values or callable functions that take a “default value” and mutate it. Functions are used when the default or “normal” value influences the fuzzed value. Functions are used because the “normal” value is sometimes dynamic and not known at the time of generation.

Each mutation should be a pre-rendered value. That is, it must be suitable to pass to encode().

Default: Empty iterator.

Parameters:

default_value

num_mutations(default_value)[source]

Determine the number of repetitions we will be making.

@rtype: int @return: Number of mutated forms this primitive can take. :param default_value:

Size

The Size class creates a block that calculates the size of another block.

Calculation

To calculate the size of its target block, Size simply calls len() on the target (all Sulley Primitives must support __len__()).

Design Considerations

Size was originally calculated by rendering the target block, or using callbacks to wait for it to get rendered. This resulted in dependency issues if a block contained both Size and Checksum primitives, or in blocks that referenced each other. Checksum naturally depends on Size’s value, but if Size depends on Checksum’s value, we have a recursion problem.

The current design is motivated by the fact that, in reality, Size does not depend on Checksum’s value. Depending on the length method rather than rendering more closely matches reality.

class boofuzz.Size(name=None, block_name=None, request=None, offset=0, length=4, endian='<', output_format='binary', inclusive=False, signed=False, math=None, *args, **kwargs)[source]

Bases: Fuzzable

Create a sizer block bound to the block with the specified name.

Size blocks that size their own parent or grandparent are allowed.

Parameters:
  • name (str, optional) – Name, for referencing later. Names should always be provided, but if not, a default name will be given, defaults to None

  • block_name (str, optional) – Name of block to apply sizer to.

  • request (boofuzz.Request, optional) – Request this block belongs to.

  • offset (int, optional) – Offset for calculated size value, defaults to 0

  • length (int, optional) – Length of sizer, defaults to 4

  • endian (chr, optional) – Endianness of the bit field (LITTLE_ENDIAN: <, BIG_ENDIAN: >), defaults to LITTLE_ENDIAN

  • output_format (str, optional) – Output format, “binary” or “ascii”, defaults to binary

  • inclusive (bool, optional) – Should the sizer count its own length? Defaults to False

  • signed (bool, optional) – Make size signed vs. unsigned (applicable only with format=”ascii”), defaults to False

  • math (def, optional) – Apply the mathematical op defined in this function to the size, defaults to None

  • fuzzable (bool, optional) – Enable/disable fuzzing of this block, defaults to true

encode(value, mutation_context)[source]

Takes a value and encodes/renders/serializes it to a bytes (byte string).

Optional if mutations() yields bytes.

Example: Yield strings with mutations() and encode them to UTF-8 using encode().

Default behavior: Return value.

Parameters:
  • value – Value to encode. Type should match the type yielded by mutations()

  • mutation_context (MutationContext) – Context for current mutation, if any.

Returns:

Encoded/serialized value.

Return type:

bytes

mutations(default_value)[source]

Generator to yield mutation values for this element.

Values are either plain values or callable functions that take a “default value” and mutate it. Functions are used when the default or “normal” value influences the fuzzed value. Functions are used because the “normal” value is sometimes dynamic and not known at the time of generation.

Each mutation should be a pre-rendered value. That is, it must be suitable to pass to encode().

Default: Empty iterator.

Parameters:

default_value

num_mutations(default_value)[source]

Wrap the num_mutations routine of the internal bit_field primitive.

Parameters:

default_value

Return type:

int

Returns:

Number of mutated forms this primitive can take.

Aligned

class boofuzz.Aligned(name=None, modulus=1, request=None, pattern=b'\x00', *args, **kwargs)[source]

Bases: FuzzableBlock

FuzzableBlock that aligns its contents to a certain number of bytes

Parameters:
  • name (str, optional) – Name, for referencing later. Names should always be provided, but if not, a default name will be given, defaults to None

  • modulus (int, optional) – Pad length of child content to this many bytes, defaults to 1

  • request (boofuzz.Request, optional) – Request this block belongs to

  • pattern (bytes, optional) – Pad using these byte(s)

  • fuzzable (bool, optional) – Enable/disable fuzzing of this block, defaults to true

encode(value, mutation_context)[source]

Takes a value and encodes/renders/serializes it to a bytes (byte string).

Optional if mutations() yields bytes.

Example: Yield strings with mutations() and encode them to UTF-8 using encode().

Default behavior: Return value.

Parameters:
  • value – Value to encode. Type should match the type yielded by mutations()

  • mutation_context (MutationContext) – Context for current mutation, if any.

Returns:

Encoded/serialized value.

Return type:

bytes