Added documentation and a simple example for the custom mutator functionality

This commit is contained in:
Khaled Yakdan 2019-09-04 22:57:52 +02:00
parent aad485128e
commit 1b3f971330
3 changed files with 91 additions and 0 deletions

View File

@ -369,7 +369,24 @@ static u32 a_extras_cnt; /* Total number of tokens available */
static u8* (*post_handler)(u8* buf, u32* len); static u8* (*post_handler)(u8* buf, u32* len);
/* hooks for the custom mutator function */ /* hooks for the custom mutator function */
/**
* Perform custom mutations on a given input
* @param data Input data to be mutated
* @param size Size of input data
* @param mutated_out Buffer to store the mutated input
* @param max_size Maximum size of the mutated output. The mutation must not produce data larger than max_size.
* @param seed Seed used for the mutation. The mutation should produce the same output given the same seed.
* @return Size of the mutated output.
*/
static size_t (*custom_mutator)(u8 *data, size_t size, u8* mutated_out, size_t max_size, unsigned int seed); static size_t (*custom_mutator)(u8 *data, size_t size, u8* mutated_out, size_t max_size, unsigned int seed);
/**
* A post-processing function to use right before AFL writes the test case to disk in order to execute the target.
* If this functionality is not needed, Simply don't define this function.
* @param data Buffer containing the test case to be executed.
* @param size Size of the test case.
* @param new_data Buffer to store the test case after processing
* @return Size of data after processing.
*/
static size_t (*pre_save_handler)(u8 *data, size_t size, u8 **new_data); static size_t (*pre_save_handler)(u8 *data, size_t size, u8 **new_data);

View File

@ -0,0 +1,40 @@
/*
Simple Custom Mutator for AFL
Written by Khaled Yakdan <yakdan@code-intelligence.de>
This a simple mutator that assumes that the generates messages starting with one
of the three strings GET, PUT, or DEL followed by a payload. The mutator randomly
selects a commend and mutates the payload of the seed provided as input.
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
static const char *commands[] = {
"GET",
"PUT",
"DEL",
};
static size_t data_size = 100;
size_t afl_custom_mutator (uint8_t *data, size_t size, uint8_t* mutated_out, size_t max_size, unsigned int seed) {
// Seed the PRNG
srand(seed);
// Make sure that the packet size does not exceed the maximum size expected by the fuzzer
size_t mutated_size = data_size <= max_size ? data_size : max_size;
// Randomly select a command string to add as a header to the packet
memcpy(mutated_out, commands[rand() % 3], 3);
// Mutate the payload of the packet
for (int i = 3 ; i < mutated_size ; i++) {
mutated_out[i] = (data[i] + rand() % 10) & 0xff;
}
return mutated_size;
}

34
docs/custom_mutator.txt Normal file
View File

@ -0,0 +1,34 @@
==================================================
Adding custom mutators to AFL using
==================================================
This file describes how you can implement custom mutations to be used in AFL.
Implemented by Khaled Yakdan from Code Intelligence <yakdan@code-intelligence.de>
1) Description
--------------
Custom mutator libraries can be passed to afl-fuzz to perform custom mutations
on test cases beyond those available in AFL - for example, to enable structure-aware
fuzzing by using libraries that perform mutations according to a given grammar.
The custom mutator library is passed to afl-fuzz via the AFL_CUSTOM_MUTATOR_LIBRARY
environment variable. The library must export the afl_custom_mutator() function and
must be compiled as a shared object. For example:
$CC -shared -Wall -O3 <lib-name>.c -o <lib-name>.so
AFL will call the afl_custom_mutator() function every time it needs to mutate
a test case. For some cases, the format of the mutated data returned from
the custom mutator is not suitable to directly execute the target with this input.
For example, when using libprotobuf-mutator, the data returned is in a protobuf
format which corresponds to a given grammar. In order to execute the target,
the protobuf data must be converted to the plain-text format expected by the target.
In such scenarios, the user can define the afl_pre_save_handler() function. This function
is then transforms the data into the format expected by the API before executing the target.
afl_pre_save_handler is optional and does not have to be implemented if its functionality
is not needed.
2) Example
----------
A simple example is provided in ../custom_mutators/