about summary refs log tree commit diff
path: root/docs/custom_mutators.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/custom_mutators.md')
-rw-r--r--docs/custom_mutators.md86
1 files changed, 64 insertions, 22 deletions
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index a22c809b..61d711e4 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -4,6 +4,11 @@ This file describes how you can implement custom mutations to be used in AFL.
 For now, we support C/C++ library and Python module, collectivelly named as the
 custom mutator.
 
+There is also experimental support for Rust in `custom_mutators/rust`.
+Please refer to that directory for documentation.
+Run ```cargo doc -p custom_mutator --open``` in that directory to view the
+documentation in your web browser.
+
 Implemented by
 - C/C++ library (`*.so`): Khaled Yakdan from Code Intelligence (<yakdan@code-intelligence.de>)
 - Python module: Christian Holler from Mozilla (<choller@mozilla.com>)
@@ -31,16 +36,19 @@ performed with the custom mutator.
 
 C/C++:
 ```c
-void *afl_custom_init(afl_t *afl, unsigned int seed);
-size_t afl_custom_fuzz(void *data, uint8_t *buf, size_t buf_size, u8 **out_buf, uint8_t *add_buf, size_t add_buf_size, size_t max_size);
-size_t afl_custom_post_process(void *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf);
-int32_t afl_custom_init_trim(void *data, uint8_t *buf, size_t buf_size);
-size_t afl_custom_trim(void *data, uint8_t **out_buf);
-int32_t afl_custom_post_trim(void *data, int success);
-size_t afl_custom_havoc_mutation(void *data, u8 *buf, size_t buf_size, u8 **out_buf, size_t max_size);
-uint8_t afl_custom_havoc_mutation_probability(void *data);
-uint8_t afl_custom_queue_get(void *data, const uint8_t *filename);
-void afl_custom_queue_new_entry(void *data, const uint8_t *filename_new_queue, const uint8_t *filename_orig_queue);
+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);
+int afl_custom_post_trim(void *data, unsigned char success);
+size_t afl_custom_havoc_mutation(void *data, unsigned char *buf, size_t buf_size, unsigned char **out_buf, size_t max_size);
+unsigned char afl_custom_havoc_mutation_probability(void *data);
+unsigned char afl_custom_queue_get(void *data, const unsigned char *filename);
+void afl_custom_queue_new_entry(void *data, const unsigned char *filename_new_queue, const unsigned int *filename_orig_queue);
+const char* afl_custom_introspection(my_mutator_t *data);
 void afl_custom_deinit(void *data);
 ```
 
@@ -49,9 +57,15 @@ Python:
 def init(seed):
     pass
 
+def fuzz_count(buf, add_buf, max_size):
+    return cnt
+
 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
 
@@ -77,6 +91,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
     pass
 ```
 
+def introspection():
+    return string
+
 ### Custom Mutation
 
 - `init`:
@@ -88,18 +105,33 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
     This method determines whether the custom fuzzer should fuzz the current
     queue entry or not
 
+- `fuzz_count` (optional):
+
+    When a queue entry is selected to be fuzzed, afl-fuzz selects the number
+    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 is most useful if `AFL_CUSTOM_MUTATOR_ONLY` is **not** used.
+
 - `fuzz` (optional):
 
     This method performs custom mutations on a given input. It also accepts an
     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, it shall describe the current testcase,
+    generated by the last mutation. This will be called, for example,
+    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%.
 
@@ -114,10 +146,19 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
     `post_process` function. This function is then transforming the data into the
     format expected by the API before executing the target.
 
+    This can return any python object that implements the buffer protocol and
+    supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
+
 - `queue_new_entry` (optional):
 
     This methods is called after adding a new test case to the queue.
 
+- `introspection` (optional):
+
+    This method is called after a new queue entry, crash or timeout is
+    discovered if compiled with INTROSPECTION. The custom mutator can then
+    return a string (const char *) that reports the exact mutations used.
+
 - `deinit`:
 
     The last method to be called, deinitializing the state.
@@ -146,7 +187,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
@@ -188,19 +229,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
@@ -218,13 +260,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
 
@@ -243,8 +285,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