From c05e4efbe9b4e7d1ff078b7a392621f2ca7572e6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 1 Dec 2020 14:40:30 +0100 Subject: renamed examples/ to utils/ --- docs/custom_mutators.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/custom_mutators.md') diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 53f783fe..6e16ba0f 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -268,8 +268,8 @@ afl-fuzz /path/to/program ## 4) Example -Please see [example.c](../examples/custom_mutators/example.c) and -[example.py](../examples/custom_mutators/example.py) +Please see [example.c](../utils/custom_mutators/example.c) and +[example.py](../utils/custom_mutators/example.py) ## 5) Other Resources -- cgit 1.4.1 From 1f34b9f8e185998e4c9c4b96b0c1878b6615115a Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 4 Dec 2020 05:28:36 +0100 Subject: added python mutator, documentation --- docs/custom_mutators.md | 11 +++++++++++ include/afl-fuzz.h | 36 +++++++++++++++++++----------------- src/afl-fuzz-python.c | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 17 deletions(-) (limited to 'docs/custom_mutators.md') diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 6e16ba0f..6d3c9f38 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -34,6 +34,7 @@ C/C++: 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); 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); 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); @@ -57,6 +58,9 @@ def fuzz_count(buf, add_buf, max_size): def fuzz(buf, add_buf, max_size): return mutated_out +def describe(max_description_length): + return "description_of_current_mutation" + def post_process(buf): return out_buf @@ -112,6 +116,13 @@ def introspection(): 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. +- `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` performs a single custom mutation on a given input. This diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 92465e7e..4efa1a6c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -312,6 +312,7 @@ enum { /* 10 */ PY_FUNC_QUEUE_GET, /* 11 */ PY_FUNC_QUEUE_NEW_ENTRY, /* 12 */ PY_FUNC_INTROSPECTION, + /* 13 */ PY_FUNC_DESCRIBE, PY_FUNC_COUNT }; @@ -755,7 +756,7 @@ struct custom_mutator { * When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can * 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*) */ const char *(*afl_custom_introspection)(void *data); @@ -771,7 +772,7 @@ struct custom_mutator { * * (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_size Size of the test case * @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) * - * @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 * output * @param[in] buf_size Size of the input/output data @@ -805,12 +806,13 @@ struct custom_mutator { * * (Optional) * - * @param data pointer returned in afl_custom_init for this fuzz case - * @param[in] max_size Maximum size of the mutated output. The mutation must - * not produce data larger than max_size. - * @return A valid ptr to a 0-terminated string, or NULL on error. + * @param data pointer returned by afl_customm_init for this custom mutator + * @paramp[in] max_description_len maximum size avaliable for the description. + * A longer return string is legal, but will be truncated. + * @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 @@ -819,7 +821,7 @@ struct custom_mutator { * (Optional) If this functionality is not needed, simply don't define this * 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_size Size of the test case * @param[out] out_buf Pointer to the buffer storing the test case after @@ -846,7 +848,7 @@ struct custom_mutator { * * (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_size Size of the test case * @return The amount of possible iteration steps to trim the input. @@ -865,7 +867,7 @@ struct custom_mutator { * * (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. * The library can reuse a buffer for each call * and will have to free the buf (for example in deinit) @@ -880,7 +882,7 @@ struct custom_mutator { * * (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. * @return The next trim iteration index (from 0 to the maximum amount of * steps returned in init_trim). Negative on error. @@ -893,7 +895,7 @@ struct custom_mutator { * * (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 * output * @param[in] buf_size Size of input data @@ -912,7 +914,7 @@ struct custom_mutator { * * (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). */ u8 (*afl_custom_havoc_mutation_probability)(void *data); @@ -922,7 +924,7 @@ struct custom_mutator { * * (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 * @return Return True(1) if the fuzzer will fuzz the queue entry, and * False(0) otherwise. @@ -935,7 +937,7 @@ struct custom_mutator { * * (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_orig_queue File name of the original queue entry. This * argument can be NULL while initializing the fuzzer @@ -945,7 +947,7 @@ struct 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); diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 9ac4403b..8760194c 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -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) { (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"); if (!py_functions[PY_FUNC_FUZZ]) 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] = PyObject_GetAttrString(py_module, "fuzz_count"); 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_DESCRIBE]) { + + mutator->afl_custom_describe = custom_describe_py; + + } + if (py_functions[PY_FUNC_POST_PROCESS]) { mutator->afl_custom_post_process = post_process_py; -- cgit 1.4.1 From cf0c49dec5341791d4a1f5f8f796dbce370696bf Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Tue, 8 Dec 2020 17:46:29 +0100 Subject: typos/wording --- docs/custom_mutators.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'docs/custom_mutators.md') diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index 6d3c9f38..a2c544e3 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -106,7 +106,7 @@ def introspection(): of fuzzing attempts with this input based on a few factors. If however the custom mutator wants to set this number instead on how often it is called for a specific queue entry, use this function. - This function in mostly useful if **not** `AFL_CUSTOM_MUTATOR_ONLY` is used. + This function is most useful if `AFL_CUSTOM_MUTATOR_ONLY` is **not** used. - `fuzz` (optional): @@ -114,19 +114,19 @@ def introspection(): additional test case. Note that this function is optional - but it makes sense to use it. 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 if you are using it e.g. as a post processing library. - `describe` (optional): - When this function is called, is shall describe the current testcase, + When this function is called, it 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. + to name the written testcase file after a crash occurred. Using it can help to reproduce crashing mutations. - `havoc_mutation` and `havoc_mutation_probability` (optional): `havoc_mutation` performs a single custom mutation on a given input. This - mutation is stacked with the other mutations in havoc. The other method, + mutation is stacked with other mutations in havoc. The other method, `havoc_mutation_probability`, returns the probability that `havoc_mutation` is called in havoc. By default, it is 6%. @@ -182,7 +182,7 @@ trimmed input. Here's a quick API description: on this input (e.g. if your input has n elements and you want to remove them one by one, return n, if you do a binary search, return log(n), and so on). - If your trimming algorithm doesn't allow you to determine the amount of + If your trimming algorithm doesn't allow to determine the amount of (remaining) steps easily (esp. while running), then you can alternatively return 1 here and always return 0 in `post_trim` until you are finished and no steps remain. In that case, returning 1 in `post_trim` will end the @@ -224,19 +224,20 @@ Optionally, the following environment variables are supported: - `AFL_PYTHON_ONLY` - Deprecated and removed, use `AFL_CUSTOM_MUTATOR_ONLY` instead - trimming can cause the same test breakage like havoc and splice. + Deprecated and removed, use `AFL_CUSTOM_MUTATOR_ONLY` instead. - `AFL_DEBUG` - When combined with `AFL_NO_UI`, this causes the C trimming code to emit additional messages about the performance and actions of your custom trimmer. Use this to see if it works :) + When combined with `AFL_NO_UI`, this causes the C trimming code to emit + additional messages about the performance and actions of your custom + trimmer. Use this to see if it works :) ## 3) Usage ### Prerequisite -For Python mutator, the python 3 or 2 development package is required. On -Debian/Ubuntu/Kali this can be done: +For Python mutators, the python 3 or 2 development package is required. On +Debian/Ubuntu/Kali it can be installed like this: ```bash sudo apt install python3-dev @@ -254,13 +255,13 @@ In case your setup is different, set the necessary variables like this: ### Custom Mutator Preparation -For C/C++ mutator, the source code must be compiled as a shared object: +For C/C++ mutators, the source code must be compiled as a shared object: ```bash gcc -shared -Wall -O3 example.c -o example.so ``` Note that if you specify multiple custom mutators, the corresponding functions will be called in the order in which they are specified. e.g first `post_process` function of -`example_first.so` will be called and then that of `example_second.so` +`example_first.so` will be called and then that of `example_second.so`. ### Run -- cgit 1.4.1