Protocol Overview

See the Quickstart guide for an intro to using Fuzzungus in general and a basic protocol definition example.

Overview

Requests are messages, Blocks are chunks within a message, and Primitives are the elements (bytes, strings, numbers, checksums, etc.) that make up a Block/Request.

Example

Here is an example of an HTTP message. It demonstrates how to use Request, Block, and several primitives:

req = Request("HTTP-Request",children=(
    Block("Request-Line", children=(
        Group("Method", values= ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"]),
        Delim("space-1", " "),
        String("URI", "/index.html"),
        Delim("space-2", " "),
        String("HTTP-Version", "HTTP/1.1"),
        Static("CRLF", "\r\n"),
    )),
    Block("Host-Line", children=(
        String("Host-Key", "Host:"),
        Delim("space", " "),
        String("Host-Value", "example.com"),
        Static("CRLF", "\r\n"),
    )),
    Static("CRLF", "\r\n"),
))

Making Your Own Block/Primitive

To make your own block/primitive:

  1. Create an object that inherits from Fuzzable or FuzzableBlock

  2. Override mutations and/or encode.

  3. Add it to the _init.py_ files :
    • In the primitives or blocks folder :
      • Import it : from .$primitiveName import $PrimitiveName

      • Add it in the __all__ table

    • In the boofuzz folder :
      • In the from .primitives import ()

      • In the __all__ table as $PrimitiveName

If your block depends on references to other blocks, the way a checksum or length field depends on other parts of the message, see the Size source code for an example of how to avoid recursion issues, and Be Careful. :)

class boofuzz.Fuzzable(name=None, default_value=None, fuzzable=True, fuzz_values=None, *args, **kwargs)[source]

Bases: object

Parent class for all primitives and blocks.

When making new fuzzable types, one will typically override mutations() and/or encode().

mutations() is a generator function yielding mutations, typically of type bytes.

encode() is a function that takes a value and encodes it.

The value comes from mutations() or default_value.

FuzzableBlock types can also encode the data generated

by child nodes.

Implementors may also want to override num_mutations() – the default implementation manually exhausts mutations() to get a number.

The rest of the methods are used by boofuzz to handle fuzzing and are typically not overridden.

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. Can be a static value, or a ReferenceValueTestCaseSession, defaults to None

  • fuzzable (bool, optional) – Enable fuzzing of this primitive, defaults to True

  • fuzz_values (list, optional) – List of custom fuzz values to add to the normal mutations, defaults to None

property context_path

Dot-delimited string that describes the path up to this element. Configured after the object is attached to a Request.

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

property fuzzable

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

get_mutations()[source]

Iterate mutations. Used by boofuzz framework.

Yields:

list of Mutation – Mutations

get_num_mutations()[source]

Get the number of mutations for this element.

get_value(mutation_context=None)[source]

Helper method to get the currently applicable value.

This is either the default value, or the active mutation value as dictated by mutation_context.

Parameters:

mutation_context (MutationContext)

Returns:

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

property name

Element name, should be unique for each instance.

Return type:

str

name_counter = 0
num_mutations(default_value)[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

original_value(test_case_context=None)[source]

Original, non-mutated value of element.

Parameters:

test_case_context (ProtocolSession) – Used to resolve ReferenceValueTestCaseSession type default values.

Returns:

property qualified_name

Dot-delimited name that describes the request name and the path to the element within the request.

Example: “request1.block1.block2.node1”

random_generation()[source]

Abstract methode to generate random values for the element.

render(mutation_context=None)[source]

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

property request: Request | None

Reference to the Request to which this object is attached.

stop_mutations()[source]

Stop yielding mutations on the currently running mutations() call.

Used by boofuzz to stop fuzzing an element when it’s already caused several failures.

Returns:

None

Return type:

NoneType

class boofuzz.FuzzableBlock(name=None, request=None, children=None, *args, **kwargs)[source]

Bases: Fuzzable

Fuzzable type designed to have children elements.

FuzzableBlock overrides the following methods, changing the default behavior for any type based on FuzzableBlock:

  1. mutations() Iterate through the mutations yielded by all child nodes.

  2. num_mutations() Sum the mutations represented by each child node.

  3. encode() Call get_child_data().

FuzzableBlock adds the following methods:

  1. get_child_data() Render and concatenate all child nodes.

  2. push() Add an additional child node; generally used only internally.

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

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

  • children (boofuzz.Fuzzable, optional) – List of child nodes (typically given to FuzzableBlock types)m 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

get_child_data(mutation_context)[source]

Get child or referenced data for this node.

For blocks that reference other data from the message structure (e.g. size, checksum, blocks). See FuzzableBlock for an example.

Parameters:

mutation_context (MutationContext) – Mutation context.

Returns:

Child data.

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

push(item)[source]

Push a child element onto this block’s stack.

Parameters:

item (Fuzzable) – Some wrapped Fuzzable element

Returns: None

Flagging blocks/primitives as depreciated

Depending of Fuzzungus evolution, you may need to flag some blocks/primitives as depreciated. To do so, here are two methods.

First method with the warnings package

import warnings
warnings.warn('setDaemon() is deprecated, set the daemon attribute instead',DeprecationWarning, stacklevel=2)

Second method with the deprecated package

from deprecated import deprecated
@deprecated(version='x.x.x', reason="Use YourClass instead")

See Deprecated - PyPi.