added python mutator, documentation

This commit is contained in:
Dominik Maier
2020-12-04 05:28:36 +01:00
parent a19b3022d9
commit 1f34b9f8e1
3 changed files with 69 additions and 17 deletions

View File

@ -34,6 +34,7 @@ C/C++:
void *afl_custom_init(afl_state_t *afl, unsigned int seed); void *afl_custom_init(afl_state_t *afl, unsigned int seed);
unsigned int afl_custom_fuzz_count(void *data, const unsigned char *buf, size_t buf_size); unsigned int afl_custom_fuzz_count(void *data, const unsigned char *buf, size_t buf_size);
size_t afl_custom_fuzz(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, unsigned char *add_buf, size_t add_buf_size, size_t max_size); size_t afl_custom_fuzz(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, unsigned char *add_buf, size_t add_buf_size, size_t max_size);
const char *afl_custom_describe(void *data, size_t max_description_len);
size_t afl_custom_post_process(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf); size_t afl_custom_post_process(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf);
int afl_custom_init_trim(void *data, unsigned char *buf, size_t buf_size); int afl_custom_init_trim(void *data, unsigned char *buf, size_t buf_size);
size_t afl_custom_trim(void *data, unsigned char **out_buf); size_t afl_custom_trim(void *data, unsigned char **out_buf);
@ -57,6 +58,9 @@ def fuzz_count(buf, add_buf, max_size):
def fuzz(buf, add_buf, max_size): def fuzz(buf, add_buf, max_size):
return mutated_out return mutated_out
def describe(max_description_length):
return "description_of_current_mutation"
def post_process(buf): def post_process(buf):
return out_buf return out_buf
@ -112,6 +116,13 @@ def introspection():
You would only skip this if `post_process` is used to fix checksums etc. You would only skip this if `post_process` is used to fix checksums etc.
so you are using it e.g. as a post processing library. so you are using it e.g. as a post processing library.
- `describe` (optional):
When this function is called, is shall describe the current testcase,
generated by the last mutation. This will be called, for example,
to give the written testcase a name after a crash ocurred.
Using it can help to reproduce crashing mutations.
- `havoc_mutation` and `havoc_mutation_probability` (optional): - `havoc_mutation` and `havoc_mutation_probability` (optional):
`havoc_mutation` performs a single custom mutation on a given input. This `havoc_mutation` performs a single custom mutation on a given input. This

View File

@ -312,6 +312,7 @@ enum {
/* 10 */ PY_FUNC_QUEUE_GET, /* 10 */ PY_FUNC_QUEUE_GET,
/* 11 */ PY_FUNC_QUEUE_NEW_ENTRY, /* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
/* 12 */ PY_FUNC_INTROSPECTION, /* 12 */ PY_FUNC_INTROSPECTION,
/* 13 */ PY_FUNC_DESCRIBE,
PY_FUNC_COUNT PY_FUNC_COUNT
}; };
@ -755,7 +756,7 @@ struct custom_mutator {
* When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can * When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can
* also give introspection information back with this function. * also give introspection information back with this function.
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @return pointer to a text string (const char*) * @return pointer to a text string (const char*)
*/ */
const char *(*afl_custom_introspection)(void *data); const char *(*afl_custom_introspection)(void *data);
@ -771,7 +772,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param buf Buffer containing the test case * @param buf Buffer containing the test case
* @param buf_size Size of the test case * @param buf_size Size of the test case
* @return The amount of fuzzes to perform on this queue entry, 0 = skip * @return The amount of fuzzes to perform on this queue entry, 0 = skip
@ -783,7 +784,7 @@ struct custom_mutator {
* *
* (Optional for now. Required in the future) * (Optional for now. Required in the future)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param[in] buf Pointer to the input data to be mutated and the mutated * @param[in] buf Pointer to the input data to be mutated and the mutated
* output * output
* @param[in] buf_size Size of the input/output data * @param[in] buf_size Size of the input/output data
@ -805,12 +806,13 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned by afl_customm_init for this custom mutator
* @param[in] max_size Maximum size of the mutated output. The mutation must * @paramp[in] max_description_len maximum size avaliable for the description.
* not produce data larger than max_size. * A longer return string is legal, but will be truncated.
* @return A valid ptr to a 0-terminated string, or NULL on error. * @return A valid ptr to a 0-terminated string.
* An empty or NULL return will result in a default description
*/ */
const char *(*afl_custom_describe)(void *data, size_t max_size); const char *(*afl_custom_describe)(void *data, size_t max_description_len);
/** /**
* A post-processing function to use right before AFL writes the test case to * A post-processing function to use right before AFL writes the test case to
@ -819,7 +821,7 @@ struct custom_mutator {
* (Optional) If this functionality is not needed, simply don't define this * (Optional) If this functionality is not needed, simply don't define this
* function. * function.
* *
* @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] data pointer returned in afl_custom_init by this custom mutator
* @param[in] buf Buffer containing the test case to be executed * @param[in] buf Buffer containing the test case to be executed
* @param[in] buf_size Size of the test case * @param[in] buf_size Size of the test case
* @param[out] out_buf Pointer to the buffer storing the test case after * @param[out] out_buf Pointer to the buffer storing the test case after
@ -846,7 +848,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param buf Buffer containing the test case * @param buf Buffer containing the test case
* @param buf_size Size of the test case * @param buf_size Size of the test case
* @return The amount of possible iteration steps to trim the input. * @return The amount of possible iteration steps to trim the input.
@ -865,7 +867,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param[out] out_buf Pointer to the buffer containing the trimmed test case. * @param[out] out_buf Pointer to the buffer containing the trimmed test case.
* The library can reuse a buffer for each call * The library can reuse a buffer for each call
* and will have to free the buf (for example in deinit) * and will have to free the buf (for example in deinit)
@ -880,7 +882,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param success Indicates if the last trim operation was successful. * @param success Indicates if the last trim operation was successful.
* @return The next trim iteration index (from 0 to the maximum amount of * @return The next trim iteration index (from 0 to the maximum amount of
* steps returned in init_trim). Negative on error. * steps returned in init_trim). Negative on error.
@ -893,7 +895,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] data pointer returned in afl_custom_init by this custom mutator
* @param[in] buf Pointer to the input data to be mutated and the mutated * @param[in] buf Pointer to the input data to be mutated and the mutated
* output * output
* @param[in] buf_size Size of input data * @param[in] buf_size Size of input data
@ -912,7 +914,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @return The probability (0-100). * @return The probability (0-100).
*/ */
u8 (*afl_custom_havoc_mutation_probability)(void *data); u8 (*afl_custom_havoc_mutation_probability)(void *data);
@ -922,7 +924,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param filename File name of the test case in the queue entry * @param filename File name of the test case in the queue entry
* @return Return True(1) if the fuzzer will fuzz the queue entry, and * @return Return True(1) if the fuzzer will fuzz the queue entry, and
* False(0) otherwise. * False(0) otherwise.
@ -935,7 +937,7 @@ struct custom_mutator {
* *
* (Optional) * (Optional)
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
* @param filename_new_queue File name of the new queue entry * @param filename_new_queue File name of the new queue entry
* @param filename_orig_queue File name of the original queue entry. This * @param filename_orig_queue File name of the original queue entry. This
* argument can be NULL while initializing the fuzzer * argument can be NULL while initializing the fuzzer
@ -945,7 +947,7 @@ struct custom_mutator {
/** /**
* Deinitialize the custom mutator. * Deinitialize the custom mutator.
* *
* @param data pointer returned in afl_custom_init for this fuzz case * @param data pointer returned in afl_custom_init by this custom mutator
*/ */
void (*afl_custom_deinit)(void *data); void (*afl_custom_deinit)(void *data);

View File

@ -111,6 +111,37 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
} }
static const char *custom_describe_py(void * py_mutator,
size_t max_description_len) {
PyObject *py_args, *py_value;
py_args = PyTuple_New(1);
PyLong_FromSize_t(max_description_len);
/* add_buf */
py_value = PyLong_FromSize_t(max_description_len);
if (!py_value) {
Py_DECREF(py_args);
FATAL("Failed to convert arguments");
}
PyTuple_SetItem(py_args, 0, py_value);
py_value = PyObject_CallObject(
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_DESCRIBE], py_args);
Py_DECREF(py_args);
if (py_value != NULL) { return PyBytes_AsString(py_value); }
return NULL;
}
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
(void)afl; (void)afl;
@ -156,6 +187,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz"); py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ]) if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate"); py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
py_functions[PY_FUNC_DESCRIBE] =
PyObject_GetAttrString(py_module, "describe");
py_functions[PY_FUNC_FUZZ_COUNT] = py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count"); PyObject_GetAttrString(py_module, "fuzz_count");
if (!py_functions[PY_FUNC_FUZZ]) if (!py_functions[PY_FUNC_FUZZ])
@ -342,6 +375,12 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; } if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
if (py_functions[PY_FUNC_DESCRIBE]) {
mutator->afl_custom_describe = custom_describe_py;
}
if (py_functions[PY_FUNC_POST_PROCESS]) { if (py_functions[PY_FUNC_POST_PROCESS]) {
mutator->afl_custom_post_process = post_process_py; mutator->afl_custom_post_process = post_process_py;