aboutsummaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-05-10 13:57:47 +0200
committerGitHub <noreply@github.com>2021-05-10 13:57:47 +0200
commit8b7a7b29c60f11cdf6226b3e418e87a5c3f5caac (patch)
tree6ce9d90644f161d21d802e9cbe48eb38467684e9 /utils
parentd0225c2c4d465968660a08c93857fed354e539b1 (diff)
downloadafl++-8b7a7b29c60f11cdf6226b3e418e87a5c3f5caac.tar.gz
Push to stable (#895)
* sync (#886) * Create FUNDING.yml * Update FUNDING.yml * moved custom_mutator examples * unicorn speedtest makefile cleanup * fixed example location * fix qdbi * update util readme * Frida persistent (#880) * Added x64 support for persistent mode (function call only), in-memory teest cases and complog * Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC * Various minor fixes and finished support for AFL_INST_LIBS * Review changes Co-authored-by: Your Name <you@example.com> * nits * fix frida mode * Integer overflow/underflow fixes in libdislocator (#889) * libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t' * libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads * Bumped warnings up to the max and fixed remaining issues (#890) Co-authored-by: Your Name <you@example.com> * nits * frida mode - support non-pie * nits * nit * update grammar mutator * Fixes for aarch64, OSX and other minor issues (#891) Co-authored-by: Your Name <you@example.com> * nits * nits * fix PCGUARD, build aflpp_driver with fPIC * Added representative fuzzbench test and test for libxml (#893) * Added representative fuzzbench test and test for libxml * Added support for building FRIDA from source with FRIDA_SOURCE=1 Co-authored-by: Your Name <you@example.com> * nits * update changelog * typos * fixed potential double free in custom trim (#881) * error handling, freeing mem * frida: complog -> cmplog * fix statsd writing * let aflpp_qemu_driver_hook.so build fail gracefully * fix stdin trimming * Support for AFL_ENTRYPOINT (#898) Co-authored-by: Your Name <you@example.com> * remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used * reverse push (#901) * Create FUNDING.yml * Update FUNDING.yml * disable QEMU static pie Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com> * clarify that no modifications are required. * add new test for frida_mode (please review) * typos * fix persistent mode (64-bit) * set ARCH for linux intel 32-bit for frida-gum-devkit * prepare for 32-bit support (later) * not on qemu 3 anymore * unicorn mips fixes * instrumentation further move to C++11 (#900) * unicorn fixes * more unicorn fixes * Fix memory errors when trim causes testcase growth (#881) (#903) * Revert "fixed potential double free in custom trim (#881)" This reverts commit e9d2f72382cab75832721d859c3e731da071435d. * Revert "fix custom trim for increasing data" This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667. * Fix memory errors when trim causes testcase growth Modify trim_case_custom to avoid writing into in_buf because some custom mutators can cause the testcase to grow rather than shrink. Instead of modifying in_buf directly, we write the update out to the disk when trimming is complete, and then the caller is responsible for refreshing the in-memory buffer from the file. This is still a bit sketchy because it does need to modify q->len in order to notify the upper layers that something changed, and it could end up telling upper layer code that the q->len is *bigger* than the buffer (q->testcase_buf) that contains it, which is asking for trouble down the line somewhere... * Fix an unlikely situation Put back some `unlikely()` calls that were in the e9d2f72382cab75832721d859c3e731da071435d commit that was reverted. * typo * Exit on time (#904) * Variable AFL_EXIT_ON_TIME description has been added. Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added. afl->exit_on_time variable initialization has been added. The asignment of a value to the afl->afl_env.afl_exit_on_time variable from environment variables has been added. Code to exit on timeout if new path not found has been added. * Type of afl_exit_on_time variable has been changed. Variable exit_on_time has been added to the afl_state_t structure. * Command `export AFL_EXIT_WHEN_DONE=1` has been added. * Millisecond to second conversion has been added. Call get_cur_time() has been added. * Revert to using the saved current time value. * Useless check has been removed. * fix new path to custom-mutators * ensure crashes/README.txt exists * fix * Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906) Co-authored-by: Your Name <you@example.com> * Fix numeric overflow in cmplog implementation (#907) Co-authored-by: Your Name <you@example.com> * testcase fixes for unicorn * remove merge conflict artifacts * fix afl-plot * Changes to remove binaries from frida_mode (#913) Co-authored-by: Your Name <you@example.com> * Frida cmplog fail fast (#914) * Changes to remove binaries from frida_mode * Changes to make cmplog fail fast Co-authored-by: Your Name <you@example.com> * afl-plot: relative time * arch linux and mac os support for afl-system-config * typo * code-format * update documentation Co-authored-by: Dominik Maier <domenukk@gmail.com> Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Co-authored-by: Your Name <you@example.com> Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com> Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com> Co-authored-by: hexcoder- <heiko@hexco.de> Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com> Co-authored-by: David CARLIER <devnexen@gmail.com> Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com> Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Diffstat (limited to 'utils')
-rw-r--r--utils/README.md3
-rw-r--r--utils/afl_proxy/afl-proxy.c29
-rw-r--r--utils/aflpp_driver/GNUmakefile6
-rw-r--r--utils/aflpp_driver/aflpp_qemu_driver_hook.c10
-rw-r--r--utils/custom_mutators/Makefile7
-rw-r--r--utils/custom_mutators/README.md35
-rw-r--r--utils/custom_mutators/XmlMutatorMin.py348
-rw-r--r--utils/custom_mutators/common.py40
-rw-r--r--utils/custom_mutators/custom_mutator_helpers.h342
-rw-r--r--utils/custom_mutators/example.c376
-rw-r--r--utils/custom_mutators/example.py187
-rw-r--r--utils/custom_mutators/post_library_gif.so.c165
-rw-r--r--utils/custom_mutators/post_library_png.so.c163
-rw-r--r--utils/custom_mutators/simple-chunk-replace.py66
-rw-r--r--utils/custom_mutators/simple_example.c74
-rw-r--r--utils/custom_mutators/wrapper_afl_min.py123
-rw-r--r--utils/libdislocator/libdislocator.so.c21
-rwxr-xr-xutils/qbdi_mode/template.cpp2
-rw-r--r--utils/qemu_persistent_hook/read_into_rdi.c10
19 files changed, 48 insertions, 1959 deletions
diff --git a/utils/README.md b/utils/README.md
index 336b6b6c..b157424f 100644
--- a/utils/README.md
+++ b/utils/README.md
@@ -32,7 +32,8 @@ Here's a quick overview of the stuff you can find in this directory:
with additional gdb metadata.
- custom_mutators - examples for the afl++ custom mutator interface in
- C and Python
+ C and Python. Note: They were moved to
+ ../custom_mutators/examples/
- distributed_fuzzing - a sample script for synchronizing fuzzer instances
across multiple machines (see parallel_fuzzing.md).
diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c
index aa7a361a..6006e238 100644
--- a/utils/afl_proxy/afl-proxy.c
+++ b/utils/afl_proxy/afl-proxy.c
@@ -70,6 +70,10 @@ static void __afl_map_shm(void) {
char *id_str = getenv(SHM_ENV_VAR);
char *ptr;
+ /* NOTE TODO BUG FIXME: if you want to supply a variable sized map then
+ uncomment the following: */
+
+ /*
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) {
u32 val = atoi(ptr);
@@ -77,6 +81,8 @@ static void __afl_map_shm(void) {
}
+ */
+
if (__afl_map_size > MAP_SIZE) {
if (__afl_map_size > FS_OPT_MAX_MAPSIZE) {
@@ -189,10 +195,7 @@ static u32 __afl_next_testcase(u8 *buf, u32 max_len) {
/* report that we are starting the target */
if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0;
- if (status < 1)
- return 0;
- else
- return status;
+ return status;
}
@@ -210,7 +213,7 @@ int main(int argc, char *argv[]) {
/* This is were the testcase data is written into */
u8 buf[1024]; // this is the maximum size for a test case! set it!
- u32 len;
+ s32 len;
/* here you specify the map size you need that you are reporting to
afl-fuzz. Any value is fine as long as it can be divided by 32. */
@@ -222,10 +225,20 @@ int main(int argc, char *argv[]) {
while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) {
- /* here you have to create the magic that feeds the buf/len to the
- target and write the coverage to __afl_area_ptr */
+ if (len > 4) { // the minimum data size you need for the target
+
+ /* here you have to create the magic that feeds the buf/len to the
+ target and write the coverage to __afl_area_ptr */
- // ... the magic ...
+ // ... the magic ...
+
+ // remove this, this is just to make afl-fuzz not complain when run
+ if (buf[0] == 0xff)
+ __afl_area_ptr[1] = 1;
+ else
+ __afl_area_ptr[2] = 2;
+
+ }
/* report the test case is done and wait for the next */
__afl_end_testcase();
diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile
index 8ac054a6..ad99b893 100644
--- a/utils/aflpp_driver/GNUmakefile
+++ b/utils/aflpp_driver/GNUmakefile
@@ -7,7 +7,7 @@ ifneq "" "$(LLVM_BINDIR)"
LLVM_BINDIR := $(LLVM_BINDIR)/
endif
-CFLAGS := -O3 -funroll-loops -g
+CFLAGS := -O3 -funroll-loops -g -fPIC
all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so
@@ -33,10 +33,10 @@ libAFLQemuDriver.a: aflpp_qemu_driver.o
-cp -vf libAFLQemuDriver.a ../../
aflpp_qemu_driver_hook.so: aflpp_qemu_driver_hook.o
- -$(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so
+ -test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built."
aflpp_qemu_driver_hook.o: aflpp_qemu_driver_hook.c
- -$(LLVM_BINDIR)clang -fPIC $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c
+ -test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built."
test: debug
#clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c
diff --git a/utils/aflpp_driver/aflpp_qemu_driver_hook.c b/utils/aflpp_driver/aflpp_qemu_driver_hook.c
index d3dd98b0..2979fadc 100644
--- a/utils/aflpp_driver/aflpp_qemu_driver_hook.c
+++ b/utils/aflpp_driver/aflpp_qemu_driver_hook.c
@@ -3,12 +3,12 @@
#include <stdint.h>
#include <string.h>
-void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
- uint8_t *input_buf, uint32_t input_buf_len) {
-
#define g2h(x) ((void *)((unsigned long)(x) + guest_base))
#define h2g(x) ((uint64_t)(x)-guest_base)
+void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
// In this example the register RDI is pointing to the memory location
// of the target buffer, and the length of the input is in RSI.
// This can be seen with a debugger, e.g. gdb (and "disass main")
@@ -16,11 +16,11 @@ void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
memcpy(g2h(regs->rdi), input_buf, input_buf_len);
regs->rsi = input_buf_len;
+}
+
#undef g2h
#undef h2g
-}
-
int afl_persistent_hook_init(void) {
// 1 for shared memory input (faster), 0 for normal input (you have to use
diff --git a/utils/custom_mutators/Makefile b/utils/custom_mutators/Makefile
deleted file mode 100644
index 9849f3f4..00000000
--- a/utils/custom_mutators/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-all: libexamplemutator.so
-
-libexamplemutator.so:
- $(CC) $(CFLAGS) -D_FORTIFY_SOURCE=2 -O3 -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so
-
-clean:
- rm -rf libexamplemutator.so
diff --git a/utils/custom_mutators/README.md b/utils/custom_mutators/README.md
deleted file mode 100644
index 655f7a5e..00000000
--- a/utils/custom_mutators/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Examples for the custom mutator
-
-These are example and helper files for the custom mutator feature.
-See [docs/custom_mutators.md](../../docs/custom_mutators.md) for more information
-
-Note that if you compile with python3.7 you must use python3 scripts, and if
-you use python2.7 to compile python2 scripts!
-
-simple_example.c - most simplest example. generates a random sized buffer
- filled with 'A'
-
-example.c - this is a simple example written in C and should be compiled to a
- shared library. Use make to compile it and produce libexamplemutator.so
-
-example.py - this is the template you can use, the functions are there but they
- are empty
-
-post_library_gif.so.c - fix a fuzz input to ensure it is valid for GIF
-
-post_library_png.so.c - fix a fuzz input to ensure it is valid for PNG
-
-simple-chunk-replace.py - this is a simple example where chunks are replaced
-
-common.py - this can be used for common functions and helpers.
- the examples do not use this though. But you can :)
-
-wrapper_afl_min.py - mutation of XML documents, loads XmlMutatorMin.py
-
-XmlMutatorMin.py - module for XML mutation
-
-custom_mutator_helpers.h is an header that defines some helper routines
-like surgical_havoc_mutate() that allow to perform a randomly chosen
-mutation from a subset of the havoc mutations.
-If you do so, you have to specify -I /path/to/AFLplusplus/include when
-compiling.
diff --git a/utils/custom_mutators/XmlMutatorMin.py b/utils/custom_mutators/XmlMutatorMin.py
deleted file mode 100644
index 3e6cd0ff..00000000
--- a/utils/custom_mutators/XmlMutatorMin.py
+++ /dev/null
@@ -1,348 +0,0 @@
-#!/usr/bin/python
-
-""" Mutation of XML documents, should be called from one of its wrappers (CLI, AFL, ...) """
-
-from __future__ import print_function
-from copy import deepcopy
-from lxml import etree as ET
-import random, re, io
-
-
-###########################
-# The XmlMutatorMin class #
-###########################
-
-
-class XmlMutatorMin:
-
- """
- Optionals parameters:
- seed Seed used by the PRNG (default: "RANDOM")
- verbose Verbosity (default: False)
- """
-
- def __init__(self, seed="RANDOM", verbose=False):
-
- """ Initialize seed, database and mutators """
-
- # Verbosity
- self.verbose = verbose
-
- # Initialize PRNG
- self.seed = str(seed)
- if self.seed == "RANDOM":
- random.seed()
- else:
- if self.verbose:
- print("Static seed '%s'" % self.seed)
- random.seed(self.seed)
-
- # Initialize input and output documents
- self.input_tree = None
- self.tree = None
-
- # High-level mutators (no database needed)
- hl_mutators_delete = [
- "del_node_and_children",
- "del_node_but_children",
- "del_attribute",
- "del_content",
- ] # Delete items
- hl_mutators_fuzz = ["fuzz_attribute"] # Randomly change attribute values
-
- # Exposed mutators
- self.hl_mutators_all = hl_mutators_fuzz + hl_mutators_delete
-
- def __parse_xml(self, xml):
-
- """ Parse an XML string. Basic wrapper around lxml.parse() """
-
- try:
- # Function parse() takes care of comments / DTD / processing instructions / ...
- tree = ET.parse(io.BytesIO(xml))
- except ET.ParseError:
- raise RuntimeError("XML isn't well-formed!")
- except LookupError as e:
- raise RuntimeError(e)
-
- # Return a document wrapper
- return tree
-
- def __exec_among(self, module, functions, min_times, max_times):
-
- """ Randomly execute $functions between $min and $max times """
-
- for i in xrange(random.randint(min_times, max_times)):
- # Function names are mangled because they are "private"
- getattr(module, "_XmlMutatorMin__" + random.choice(functions))()
-
- def __serialize_xml(self, tree):
-
- """ Serialize a XML document. Basic wrapper around lxml.tostring() """
-
- return ET.tostring(
- tree, with_tail=False, xml_declaration=True, encoding=tree.docinfo.encoding
- )
-
- def __ver(self, version):
-
- """ Helper for displaying lxml version numbers """
-
- return ".".join(map(str, version))
-
- def reset(self):
-
- """ Reset the mutator """
-
- self.tree = deepcopy(self.input_tree)
-
- def init_from_string(self, input_string):
-
- """ Initialize the mutator from a XML string """
-
- # Get a pointer to the top-element
- self.input_tree = self.__parse_xml(input_string)
-
- # Get a working copy
- self.tree = deepcopy(self.input_tree)
-
- def save_to_string(self):
-
- """ Return the current XML document as UTF-8 string """
-
- # Return a text version of the tree
- return self.__serialize_xml(self.tree)
-
- def __pick_element(self, exclude_root_node=False):
-
- """ Pick a random element from the current document """
-
- # Get a list of all elements, but nodes like PI and comments
- elems = list(self.tree.getroot().iter(tag=ET.Element))
-
- # Is the root node excluded?
- if exclude_root_node:
- start = 1
- else:
- start = 0
-
- # Pick a random element
- try:
- elem_id = random.randint(start, len(elems) - 1)
- elem = elems[elem_id]
- except ValueError:
- # Should only occurs if "exclude_root_node = True"
- return (None, None)
-
- return (elem_id, elem)
-
- def __fuzz_attribute(self):
-
- """ Fuzz (part of) an attribute value """
-
- # Select a node to modify
- (rand_elem_id, rand_elem) = self.__pick_element()
-
- # Get all the attributes
- attribs = rand_elem.keys()
-
- # Is there attributes?
- if len(attribs) < 1:
- if self.verbose:
- print("No attribute: can't replace!")
- return
-
- # Pick a random attribute
- rand_attrib_id = random.randint(0, len(attribs) - 1)
- rand_attrib = attribs[rand_attrib_id]
-
- # We have the attribute to modify
- # Get its value
- attrib_value = rand_elem.get(rand_attrib)
- # print("- Value: " + attrib_value)
-
- # Should we work on the whole value?
- func_call = "(?P<func>[a-zA-Z:\-]+)\((?P<args>.*?)\)"
- p = re.compile(func_call)
- l = p.findall(attrib_value)
- if random.choice((True, False)) and l:
- # Randomly pick one the function calls
- (func, args) = random.choice(l)
- # Split by "," and randomly pick one of the arguments
- value = random.choice(args.split(","))
- # Remove superfluous characters
- unclean_value = value
- value = value.strip(" ").strip("'")
- # print("Selected argument: [%s]" % value)
- else:
- value = attrib_value
-
- # For each type, define some possible replacement values
- choices_number = (
- "0",
- "11111",
- "-128",
- "2",
- "-1",
- "1/3",
- "42/0",
- "1094861636 idiv 1.0",
- "-1123329771506872 idiv 3.8",
- "17=$numericRTF",
- str(3 + random.randrange(0, 100)),
- )
-
- choices_letter = (
- "P" * (25 * random.randrange(1, 100)),
- "%s%s%s%s%s%s",
- "foobar",
- )
-
- choices_alnum = (
- "Abc123",
- "020F0302020204030204",
- "020F0302020204030204" * (random.randrange(5, 20)),
- )
-
- # Fuzz the value
- if random.choice((True, False)) and value == "":
-
- # Empty
- new_value = value
-
- elif random.choice((True, False)) and value.isdigit():
-
- # Numbers
- new_value = random.choice(choices_number)
-
- elif random.choice((True, False)) and value.isalpha():
-
- # Letters
- new_value = random.choice(choices_letter)
-
- elif random.choice((True, False)) and value.isalnum():
-
- # Alphanumeric
- new_value = random.choice(choices_alnum)
-
- else:
-
- # Default type
- new_value = random.choice(choices_alnum + choices_letter + choices_number)
-
- # If we worked on a substring, apply changes to the whole string
- if value != attrib_value:
- # No ' around empty values
- if new_value != "" and value != "":
- new_value = "'" + new_value + "'"
- # Apply changes
- new_value = attrib_value.replace(unclean_value, new_value)
-
- # Log something
- if self.verbose:
- print(
- "Fuzzing attribute #%i '%s' of tag #%i '%s'"
- % (rand_attrib_id, rand_attrib, rand_elem_id, rand_elem.tag)
- )
-
- # Modify the attribute
- rand_elem.set(rand_attrib, new_value.decode("utf-8"))
-
- def __del_node_and_children(self):
-
- """High-level minimizing mutator
- Delete a random node and its children (i.e. delete a random tree)"""
-
- self.__del_node(True)
-
- def __del_node_but_children(self):
-
- """High-level minimizing mutator
- Delete a random node but its children (i.e. link them to the parent of the deleted node)"""
-
- self.__del_node(False)
-
- def __del_node(self, delete_children):
-
- """ Called by the __del_node_* mutators """
-
- # Select a node to modify (but the root one)
- (rand_elem_id, rand_elem) = self.__pick_element(exclude_root_node=True)
-
- # If the document includes only a top-level element
- # Then we can't pick a element (given that "exclude_root_node = True")
-
- # Is the document deep enough?
- if rand_elem is None:
- if self.verbose:
- print("Can't delete a node: document not deep enough!")
- return
-
- # Log something
- if self.verbose:
- but_or_and = "and" if delete_children else "but"
- print(
- "Deleting tag #%i '%s' %s its children"
- % (rand_elem_id, rand_elem.tag, but_or_and)
- )
-
- if delete_children is False:
- # Link children of the random (soon to be deleted) node to its parent
- for child in rand_elem:
- rand_elem.getparent().append(child)
-
- # Remove the node
- rand_elem.getparent().remove(rand_elem)
-
- def __del_content(self):
-
- """High-level minimizing mutator
- Delete the attributes and children of a random node"""
-
- # Select a node to modify
- (rand_elem_id, rand_elem) = self.__pick_element()
-
- # Log something
- if self.verbose:
- print("Reseting tag #%i '%s'" % (rand_elem_id, rand_elem.tag))
-
- # Reset the node
- rand_elem.clear()
-
- def __del_attribute(self):
-
- """High-level minimizing mutator
- Delete a random attribute from a random node"""
-
- # Select a node to modify
- (rand_elem_id, rand_elem) = self.__pick_element()
-
- # Get all the attributes
- attribs = rand_elem.keys()
-
- # Is there attributes?
- if len(attribs) < 1:
- if self.verbose:
- print("No attribute: can't delete!")
- return
-
- # Pick a random attribute
- rand_attrib_id = random.randint(0, len(attribs) - 1)
- rand_attrib = attribs[rand_attrib_id]
-
- # Log something
- if self.verbose:
- print(
- "Deleting attribute #%i '%s' of tag #%i '%s'"
- % (rand_attrib_id, rand_attrib, rand_elem_id, rand_elem.tag)
- )
-
- # Delete the attribute
- rand_elem.attrib.pop(rand_attrib)
-
- def mutate(self, min=1, max=5):
-
- """ Execute some high-level mutators between $min and $max times, then some medium-level ones """
-
- # High-level mutation
- self.__exec_among(self, self.hl_mutators_all, min, max)
diff --git a/utils/custom_mutators/common.py b/utils/custom_mutators/common.py
deleted file mode 100644
index 44a5056a..00000000
--- a/utils/custom_mutators/common.py
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env python
-# encoding: utf-8
-"""
-Module containing functions shared between multiple AFL modules
-
-@author: Christian Holler (:decoder)
-
-@license:
-
-This Source Code Form is subject to the terms of the Mozilla Public
-License, v. 2.0. If a copy of the MPL was not distributed with this
-file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-@contact: choller@mozilla.com
-"""
-
-from __future__ import print_function
-import random
-import os
-import re
-
-
-def randel(l):
- if not l:
- return None
- return l[random.randint(0, len(l) - 1)]
-
-
-def randel_pop(l):
- if not l:
- return None
- return l.pop(random.randint(0, len(l) - 1))
-
-
-def write_exc_example(data, exc):
- exc_name = re.sub(r"[^a-zA-Z0-9]", "_", repr(exc))
-
- if not os.path.exists(exc_name):
- with open(exc_name, "w") as f:
- f.write(data)
diff --git a/utils/custom_mutators/custom_mutator_helpers.h b/utils/custom_mutators/custom_mutator_helpers.h
deleted file mode 100644
index 62e6efba..00000000
--- a/utils/custom_mutators/custom_mutator_helpers.h
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef CUSTOM_MUTATOR_HELPERS
-#define CUSTOM_MUTATOR_HELPERS
-
-#include "config.h"
-#include "types.h"
-#include <stdlib.h>
-
-#define INITIAL_GROWTH_SIZE (64)
-
-#define RAND_BELOW(limit) (rand() % (limit))
-
-/* Use in a struct: creates a name_buf and a name_size variable. */
-#define BUF_VAR(type, name) \
- type * name##_buf; \
- size_t name##_size;
-/* this fills in `&structptr->something_buf, &structptr->something_size`. */
-#define BUF_PARAMS(struct, name) \
- (void **)&struct->name##_buf, &struct->name##_size
-
-typedef struct {
-
-} afl_t;
-
-static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
-
- static s8 interesting_8[] = {INTERESTING_8};
- static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
- static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
-
- switch (RAND_BELOW(12)) {
-
- case 0: {
-
- /* Flip a single bit somewhere. Spooky! */
-
- s32 bit_idx = ((RAND_BELOW(end - begin) + begin) << 3) + RAND_BELOW(8);
-
- out_buf[bit_idx >> 3] ^= 128 >> (bit_idx & 7);
-
- break;
-
- }
-
- case 1: {
-
- /* Set byte to interesting value. */
-
- u8 val = interesting_8[RAND_BELOW(sizeof(interesting_8))];
- out_buf[(RAND_BELOW(end - begin) + begin)] = val;
-
- break;
-
- }
-
- case 2: {
-
- /* Set word to interesting value, randomly choosing endian. */
-
- if (end - begin < 2) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 1) break;
-
- switch (RAND_BELOW(2)) {
-
- case 0:
- *(u16 *)(out_buf + byte_idx) =
- interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)];
- break;
- case 1:
- *(u16 *)(out_buf + byte_idx) =
- SWAP16(interesting_16[RAND_BELOW(sizeof(interesting_16) >> 1)]);
- break;
-
- }
-
- break;
-
- }
-
- case 3: {
-
- /* Set dword to interesting value, randomly choosing endian. */
-
- if (end - begin < 4) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 3) break;
-
- switch (RAND_BELOW(2)) {
-
- case 0:
- *(u32 *)(out_buf + byte_idx) =
- interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
- break;
- case 1:
- *(u32 *)(out_buf + byte_idx) =
- SWAP32(interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
- break;
-
- }
-
- break;
-
- }
-
- case 4: {
-
- /* Set qword to interesting value, randomly choosing endian. */
-
- if (end - begin < 8) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 7) break;
-
- switch (RAND_BELOW(2)) {
-
- case 0:
- *(u64 *)(out_buf + byte_idx) =
- (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
- break;
- case 1:
- *(u64 *)(out_buf + byte_idx) = SWAP64(
- (s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
- break;
-
- }
-
- break;
-
- }
-
- case 5: {
-
- /* Randomly subtract from byte. */
-
- out_buf[(RAND_BELOW(end - begin) + begin)] -= 1 + RAND_BELOW(ARITH_MAX);
-
- break;
-
- }
-
- case 6: {
-
- /* Randomly add to byte. */
-
- out_buf[(RAND_BELOW(end - begin) + begin)] += 1 + RAND_BELOW(ARITH_MAX);
-
- break;
-
- }
-
- case 7: {
-
- /* Randomly subtract from word, random endian. */
-
- if (end - begin < 2) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 1) break;
-
- if (RAND_BELOW(2)) {
-
- *(u16 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
-
- } else {
-
- u16 num = 1 + RAND_BELOW(ARITH_MAX);
-
- *(u16 *)(out_buf + byte_idx) =
- SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) - num);
-
- }
-
- break;
-
- }
-
- case 8: {
-
- /* Randomly add to word, random endian. */
-
- if (end - begin < 2) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 1) break;
-
- if (RAND_BELOW(2)) {
-
- *(u16 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
-
- } else {
-
- u16 num = 1 + RAND_BELOW(ARITH_MAX);
-
- *(u16 *)(out_buf + byte_idx) =
- SWAP16(SWAP16(*(u16 *)(out_buf + byte_idx)) + num);
-
- }
-
- break;
-
- }
-
- case 9: {
-
- /* Randomly subtract from dword, random endian. */
-
- if (end - begin < 4) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 3) break;
-
- if (RAND_BELOW(2)) {
-
- *(u32 *)(out_buf + byte_idx) -= 1 + RAND_BELOW(ARITH_MAX);
-
- } else {
-
- u32 num = 1 + RAND_BELOW(ARITH_MAX);
-
- *(u32 *)(out_buf + byte_idx) =
- SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) - num);
-
- }
-
- break;
-
- }
-
- case 10: {
-
- /* Randomly add to dword, random endian. */
-
- if (end - begin < 4) break;
-
- s32 byte_idx = (RAND_BELOW(end - begin) + begin);
-
- if (byte_idx >= end - 3) break;
-
- if (RAND_BELOW(2)) {
-
- *(u32 *)(out_buf + byte_idx) += 1 + RAND_BELOW(ARITH_MAX);
-
- } else {
-
- u32 num = 1 + RAND_BELOW(ARITH_MAX);
-
- *(u32 *)(out_buf + byte_idx) =
- SWAP32(SWAP32(*(u32 *)(out_buf + byte_idx)) + num);
-
- }
-
- break;
-
- }
-
- case 11: {
-
- /* Just set a random byte to a random value. Because,
- why not. We use XOR with 1-255 to eliminate the
- possibility of a no-op. */
-
- out_buf[(RAND_BELOW(end - begin) + begin)] ^= 1 + RAND_BELOW(255);
-
- break;
-
- }
-
- }
-
-}
-
-/* This function calculates the next power of 2 greater or equal its argument.
- @return The rounded up power of 2 (if no overflow) or 0 on overflow.
-*/
-static inline size_t next_pow2(size_t in) {
-
- if (in == 0 || in > (size_t)-1)
- return 0; /* avoid undefined behaviour under-/overflow */
- size_t out = in - 1;
- out |= out >> 1;
- out |= out >> 2;
- out |= out >> 4;
- out |= out >> 8;
- out |= out >> 16;
- return out + 1;
-
-}
-
-/* This function makes sure *size is > size_needed after call.
- It will realloc *buf otherwise.
- *size will grow exponentially as per:
- https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
- Will return NULL and free *buf if size_needed is <1 or realloc failed.
- @return For convenience, this function returns *buf.
- */
-static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
-
- /* No need to realloc */
- if (likely(size_needed && *size >= size_needed)) return *buf;
-
- /* No initial size was set */
- if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
-
- /* grow exponentially */
- size_t next_size = next_pow2(size_needed);
-
- /* handle overflow */
- if (!next_size) { next_size = size_needed; }
-
- /* alloc */
- *buf = realloc(*buf, next_size);
- *size = *buf ? next_size : 0;
-
- return *buf;
-
-}
-
-/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
-static inline void afl_swap_bufs(void **buf1, size_t *size1, void **buf2,
- size_t *size2) {
-
- void * scratch_buf = *buf1;
- size_t scratch_size = *size1;
- *buf1 = *buf2;
- *size1 = *size2;
- *buf2 = scratch_buf;
- *size2 = scratch_size;
-
-}
-
-#undef INITIAL_GROWTH_SIZE
-
-#endif
-
diff --git a/utils/custom_mutators/example.c b/utils/custom_mutators/example.c
deleted file mode 100644
index 23add128..00000000
--- a/utils/custom_mutators/example.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- New Custom Mutator for AFL++
- Written by Khaled Yakdan <yakdan@code-intelligence.de>
- Andrea Fioraldi <andreafioraldi@gmail.com>
- Shengtuo Hu <h1994st@gmail.com>
- Dominik Maier <mail@dmnk.co>
-*/
-
-// You need to use -I /path/to/AFLplusplus/include
-#include "custom_mutator_helpers.h"
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#define DATA_SIZE (100)
-
-static const char *commands[] = {
-
- "GET",
- "PUT",
- "DEL",
-
-};
-
-typedef struct my_mutator {
-
- afl_t *afl;
-
- // any additional data here!
- size_t trim_size_current;
- int trimmming_steps;
- int cur_step;
-
- // Reused buffers:
- BUF_VAR(u8, fuzz);
- BUF_VAR(u8, data);
- BUF_VAR(u8, havoc);
- BUF_VAR(u8, trim);
- BUF_VAR(u8, post_process);
-
-} my_mutator_t;
-
-/**
- * Initialize this custom mutator
- *
- * @param[in] afl a pointer to the internal state object. Can be ignored for
- * now.
- * @param[in] seed A seed for this mutator - the same seed should always mutate
- * in the same way.
- * @return Pointer to the data object this custom mutator instance should use.
- * There may be multiple instances of this mutator in one afl-fuzz run!
- * Return NULL on error.
- */
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
-
- srand(seed); // needed also by surgical_havoc_mutate()
-
- my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
- if (!data) {
-
- perror("afl_custom_init alloc");
- return NULL;
-
- }
-
- data->afl = afl;
-
- return data;
-
-}
-
-/**
- * Perform custom mutations on a given input
- *
- * (Optional for now. Required in the future)
- *
- * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @param[in] buf Pointer to input data to be mutated
- * @param[in] buf_size Size of input data
- * @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
- * error.
- * @param[in] add_buf Buffer containing the additional test case
- * @param[in] add_buf_size Size of the additional test case
- * @param[in] max_size Maximum size of the mutated output. The mutation must not
- * produce data larger than max_size.
- * @return Size of the mutated output.
- */
-size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
- u8 **out_buf, uint8_t *add_buf,
- size_t add_buf_size, // add_buf can be NULL
- size_t max_size) {
-
- // 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;
-
- // maybe_grow is optimized to be quick for reused buffers.
- u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size);
- if (!mutated_out) {
-
- *out_buf = NULL;
- perror("custom mutator allocation (maybe_grow)");
- return 0; /* afl-fuzz will very likely error out after this. */
-
- }
-
- // 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
- int i;
- for (i = 0; i < 8; ++i) {
-
- // Randomly perform one of the (no len modification) havoc mutations
- surgical_havoc_mutate(mutated_out, 3, mutated_size);
-
- }
-
- *out_buf = mutated_out;
- return mutated_size;
-
-}
-
-/**
- * A post-processing function to use right before AFL writes the test case to
- * disk in order to execute the target.
- *
- * (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] 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 containing the test case after
- * processing. External library should allocate memory for out_buf.
- * The buf pointer may be reused (up to the given buf_size);
- * @return Size of the output buffer after processing or the needed amount.
- * A return of 0 indicates an error.
- */
-size_t afl_custom_post_process(my_mutator_t *data, uint8_t *buf,
- size_t buf_size, uint8_t **out_buf) {
-
- uint8_t *post_process_buf =
- maybe_grow(BUF_PARAMS(data, post_process), buf_size + 5);
- if (!post_process_buf) {
-
- perror("custom mutator realloc failed.");
- *out_buf = NULL;
- return 0;
-
- }
-
- memcpy(post_process_buf + 5, buf, buf_size);
- post_process_buf[0] = 'A';
- post_process_buf[1] = 'F';
- post_process_buf[2] = 'L';
- post_process_buf[3] = '+';
- post_process_buf[4] = '+';
-
- *out_buf = post_process_buf;
-
- return buf_size + 5;
-
-}
-
-/**
- * This method is called at the start of each trimming operation and receives
- * the initial buffer. It should return the amount of iteration steps possible
- * 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
- * (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
- * trimming routine. The whole current index/max iterations stuff is only used
- * to show progress.
- *
- * (Optional)
- *
- * @param data pointer returned in afl_custom_init for this fuzz case
- * @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.
- * negative on error.
- */
-int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf,
- size_t buf_size) {
-
- // We simply trim once
- data->trimmming_steps = 1;
-
- data->cur_step = 0;
-
- if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) {
-
- perror("init_trim grow");
- return -1;
-
- }
-
- memcpy(data->trim_buf, buf, buf_size);
-
- data->trim_size_current = buf_size;
-
- return data->trimmming_steps;
-
-}
-
-/**
- * This method is called for each trimming operation. It doesn't have any
- * arguments because we already have the initial buffer from init_trim and we
- * can memorize the current state in *data. This can also save
- * reparsing steps for each iteration. It should return the trimmed input
- * buffer, where the returned data must not exceed the initial input data in
- * length. Returning anything that is larger than the original data (passed
- * to init_trim) will result in a fatal abort of AFLFuzz.
- *
- * (Optional)
- *
- * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @param[out] out_buf Pointer to the buffer containing the trimmed test case.
- * External library should allocate memory for out_buf.
- * AFL++ will not release the memory after saving the test case.
- * Keep a ref in *data.
- * *out_buf = NULL is treated as error.
- * @return Pointer to the size of the trimmed test case
- */
-size_t afl_custom_trim(my_mutator_t *data, uint8_t **out_buf) {
-
- *out_buf = data->trim_buf;
-
- // Remove the last byte of the trimming input
- return data->trim_size_current - 1;
-
-}
-
-/**
- * This method is called after each trim operation to inform you if your
- * trimming step was successful or not (in terms of coverage). If you receive
- * a failure here, you should reset your input to the last known good state.
- *
- * (Optional)
- *
- * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @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 ret on failure.
- */
-int32_t afl_custom_post_trim(my_mutator_t *data, int success) {
-
- if (success) {
-
- ++data->cur_step;
- return data->cur_step;
-
- }
-
- return data->trimmming_steps;
-
-}
-
-/**
- * Perform a single custom mutation on a given input.
- * This mutation is stacked with the other muatations in havoc.
- *
- * (Optional)
- *
- * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @param[in] buf Pointer to the input data to be mutated and the mutated
- * output
- * @param[in] buf_size Size of input data
- * @param[out] out_buf The output buffer. buf can be reused, if the content
- * fits. *out_buf = NULL is treated as error.
- * @param[in] max_size Maximum size of the mutated output. The mutation must
- * not produce data larger than max_size.
- * @return Size of the mutated output.
- */
-size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size,
- u8 **out_buf, size_t max_size) {
-
- if (buf_size == 0) {
-
- *out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1);
- if (!*out_buf) {
-
- perror("custom havoc: maybe_grow");
- return 0;
-
- }
-
- **out_buf = rand() % 256;
- buf_size = 1;
-
- } else {
-
- // We reuse buf here. It's legal and faster.
- *out_buf = buf;
-
- }
-
- size_t victim = rand() % buf_size;
- (*out_buf)[victim] += rand() % 10;
-
- return buf_size;
-
-}
-
-/**
- * Return the probability (in percentage) that afl_custom_havoc_mutation
- * is called in havoc. By default it is 6 %.
- *
- * (Optional)
- *
- * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @return The probability (0-100).
- */
-uint8_t afl_custom_havoc_mutation_probability(my_mutator_t *data) {
-
- return 5; // 5 %
-
-}
-
-/**
- * Determine whether the fuzzer should fuzz the queue entry or not.
- *
- * (Optional)
- *
- * @param[in] data pointer returned in afl_custom_init for this fuzz case
- * @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.
- */
-uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
-
- return 1;
-
-}
-
-/**
- * Allow for additional analysis (e.g. calling a different tool that does a
- * different kind of coverage and saves this for the custom mutator).
- *
- * (Optional)
- *
- * @param data pointer returned in afl_custom_init for this fuzz case
- * @param filename_new_queue File name of the new queue entry
- * @param filename_orig_queue File name of the original queue entry
- */
-void afl_custom_queue_new_entry(my_mutator_t * data,
- const uint8_t *filename_new_queue,
- const uint8_t *filename_orig_queue) {
-
- /* Additional analysis on the original or new test case */
-
-}
-
-/**
- * Deinitialize everything
- *
- * @param data The data ptr from afl_custom_init
- */
-void afl_custom_deinit(my_mutator_t *data) {
-
- free(data->post_process_buf);
- free(data->havoc_buf);
- free(data->data_buf);
- free(data->fuzz_buf);
- free(data->trim_buf);
- free(data);
-
-}
-
diff --git a/utils/custom_mutators/example.py b/utils/custom_mutators/example.py
deleted file mode 100644
index 3a6d22e4..00000000
--- a/utils/custom_mutators/example.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/env python
-# encoding: utf-8
-"""
-Example Python Module for AFLFuzz
-
-@author: Christian Holler (:decoder)
-
-@license:
-
-This Source Code Form is subject to the terms of the Mozilla Public
-License, v. 2.0. If a copy of the MPL was not distributed with this
-file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-@contact: choller@mozilla.com
-"""
-
-import random
-
-
-COMMANDS = [
- b"GET",
- b"PUT",
- b"DEL",
- b"AAAAAAAAAAAAAAAAA",
-]
-
-
-def init(seed):
- """
- Called once when AFLFuzz starts up. Used to seed our RNG.
-
- @type seed: int
- @param seed: A 32-bit random value
- """
- random.seed(seed)
-
-
-def deinit():
- pass
-
-
-def fuzz(buf, add_buf, max_size):
- """
- Called per fuzzing iteration.
-
- @type buf: bytearray
- @param buf: The buffer that should be mutated.
-
- @type add_buf: bytearray
- @param add_buf: A second buffer that can be used as mutation source.
-
- @type max_size: int
- @param max_size: Maximum size of the mutated output. The mutation must not
- produce data larger than max_size.
-
- @rtype: bytearray
- @return: A new bytearray containing the mutated data
- """
- ret = bytearray(100)
-
- ret[:3] = random.choice(COMMANDS)
-
- return ret
-
-
-# Uncomment and implement the following methods if you want to use a custom
-# trimming algorithm. See also the documentation for a better API description.
-
-# def init_trim(buf):
-# '''
-# Called per trimming iteration.
-#
-# @type buf: bytearray
-# @param buf: The buffer that should be trimmed.
-#
-# @rtype: int
-# @return: The maximum number of trimming steps.
-# '''
-# global ...
-#
-# # Initialize global variables
-#
-# # Figure out how many trimming steps are possible.
-# # If this is not possible for your trimming, you can
-# # return 1 instead and always return 0 in post_trim
-# # until you are done (then you return 1).
-#
-# return steps
-#
-# def trim():
-# '''
-# Called per trimming iteration.
-#
-# @rtype: bytearray
-# @return: A new bytearray containing the trimmed data.
-# '''
-# global ...
-#
-# # Implement the actual trimming here
-#
-# return bytearray(...)
-#
-# def post_trim(success):
-# '''
-# Called after each trimming operation.
-#
-# @type success: bool
-# @param success: Indicates if the last trim operation was successful.
-#
-# @rtype: int
-# @return: The next trim index (0 to max number of steps) where max
-# number of steps indicates the trimming is done.
-# '''
-# global ...
-#
-# if not success:
-# # Restore last known successful input, determine next index
-# else:
-# # Just determine the next index, based on what was successfully
-# # removed in the last step
-#
-# return next_index
-#
-# def post_process(buf):
-# '''
-# Called just before the execution to write the test case in the format
-# expected by the target
-#
-# @type buf: bytearray
-# @param buf: The buffer containing the test case to be executed
-#
-# @rtype: bytearray
-# @return: The buffer containing the test case after
-# '''
-# return buf
-#
-# def havoc_mutation(buf, max_size):
-# '''
-# Perform a single custom mutation on a given input.
-#
-# @type buf: bytearray
-# @param buf: The buffer that should be mutated.
-#
-# @type max_size: int
-# @param max_size: Maximum size of the mutated output. The mutation must not
-# produce data larger than max_size.
-#
-# @rtype: bytearray
-# @return: A new bytearray containing the mutated data
-# '''
-# return mutated_buf
-#
-# def havoc_mutation_probability():
-# '''
-# Called for each `havoc_mutation`. Return the probability (in percentage)
-# that `havoc_mutation` is called in havoc. Be default it is 6%.
-#
-# @rtype: int
-# @return: The probability (0-100)
-# '''
-# return prob
-#
-# def queue_get(filename):
-# '''
-# Called at the beginning of each fuzz iteration to determine whether the
-# test case should be fuzzed
-#
-# @type filename: str
-# @param filename: File name of the test case in the current queue entry
-#
-# @rtype: bool
-# @return: Return True if the custom mutator decides to fuzz the test case,
-# and False otherwise
-# '''
-# return True
-#
-# def queue_new_entry(filename_new_queue, filename_orig_queue):
-# '''
-# Called after adding a new test case to the queue
-#
-# @type filename_new_queue: str
-# @param filename_new_queue: File name of the new queue entry
-#
-# @type filename_orig_queue: str
-# @param filename_orig_queue: File name of the original queue entry
-# '''
-# pass
diff --git a/utils/custom_mutators/post_library_gif.so.c b/utils/custom_mutators/post_library_gif.so.c
deleted file mode 100644
index ac10f409..00000000
--- a/utils/custom_mutators/post_library_gif.so.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- american fuzzy lop++ - postprocessor library example
- --------------------------------------------------
-
- Originally written by Michal Zalewski
- Edited by Dominik Maier, 2020
-
- Copyright 2015 Google Inc. All rights reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Postprocessor libraries can be passed to afl-fuzz to perform final cleanup
- of any mutated test cases - for example, to fix up checksums in PNG files.
-
- Please heed the following warnings:
-
- 1) In almost all cases, it is more productive to comment out checksum logic
- in the targeted binary (as shown in ../libpng_no_checksum/). One possible
- exception is the process of fuzzing binary-only software in QEMU mode.
-
- 2) The use of postprocessors for anything other than checksums is
- questionable and may cause more harm than good. AFL is normally pretty good
- about dealing with length fields, magic values, etc.
-
- 3) Postprocessors that do anything non-trivial must be extremely robust to
- gracefully handle malformed data and other error conditions - otherwise,
- they will crash and take afl-fuzz down with them. Be wary of reading past
- *len and of integer overflows when calculating file offsets.
-
- In other words, THIS IS PROBABLY NOT WHAT YOU WANT - unless you really,
- honestly know what you're doing =)
-
- With that out of the way: the postprocessor library is passed to afl-fuzz
- via AFL_POST_LIBRARY. The library must be compiled with:
-
- gcc -shared -Wall -O3 post_library.so.c -o post_library.so
-
- AFL will call the afl_custom_post_process() function for every mutated output
- buffer. From there, you have three choices:
-
- 1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
- and return the original `len`.
-
- 2) If you want to skip this test case altogether and have AFL generate a
- new one, return 0 or set `*out_buf = NULL`.
- Use this sparingly - it's faster than running the target program
- with patently useless inputs, but still wastes CPU time.
-
- 3) If you want to modify the test case, allocate an appropriately-sized
- buffer, move the data into that buffer, make the necessary changes, and
- then return the new pointer as out_buf. Return an appropriate len
- afterwards.
-
- Note that the buffer will *not* be freed for you. To avoid memory leaks,
- you need to free it or reuse it on subsequent calls (as shown below).
-
- *** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
-
- Aight. The example below shows a simple postprocessor that tries to make
- sure that all input files start with "GIF89a".
-
- PS. If you don't like C, you can try out the unix-based wrapper from
- Ben Nagy instead: https://github.com/bnagy/aflfix
-
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Header that must be present at the beginning of every test case: */
-
-#define HEADER "GIF89a"
-
-typedef struct post_state {
-
- unsigned char *buf;
- size_t size;
-
-} post_state_t;
-
-void *afl_custom_init(void *afl) {
-
- post_state_t *state = malloc(sizeof(post_state_t));
- if (!state) {
-
- perror("malloc");
- return NULL;
-
- }
-
- state->buf = calloc(sizeof(unsigned char), 4096);
- if (!state->buf) {
-
- free(state);
- perror("calloc");
- return NULL;
-
- }
-
- return state;
-
-}
-
-/* The actual postprocessor routine called by afl-fuzz: */
-
-size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf,
- unsigned int len, unsigned char **out_buf) {
-
- /* Skip execution altogether for buffers shorter than 6 bytes (just to
- show how it's done). We can trust len to be sane. */
-
- if (len < strlen(HEADER)) return 0;
-
- /* Do nothing for buffers that already start with the expected header. */
-
- if (!memcmp(in_buf, HEADER, strlen(HEADER))) {
-
- *out_buf = in_buf;
- return len;
-
- }
-
- /* Allocate memory for new buffer, reusing previous allocation if
- possible. */
-
- *out_buf = realloc(data->buf, len);
-
- /* If we're out of memory, the most graceful thing to do is to return the
- original buffer and give up on modifying it. Let AFL handle OOM on its
- own later on. */
-
- if (!*out_buf) {
-
- *out_buf = in_buf;
- return len;
-
- }
-
- /* Copy the original data to the new location. */
-
- memcpy(*out_buf, in_buf, len);
-
- /* Insert the new header. */
-
- memcpy(*out_buf, HEADER, strlen(HEADER));
-
- /* Return the new len. It hasn't changed, so it's just len. */
-
- return len;
-
-}
-
-/* Gets called afterwards */
-void afl_custom_deinit(post_state_t *data) {
-
- free(data->buf);
- free(data);
-
-}
-
diff --git a/utils/custom_mutators/post_library_png.so.c b/utils/custom_mutators/post_library_png.so.c
deleted file mode 100644
index 941f7e55..00000000
--- a/utils/custom_mutators/post_library_png.so.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- american fuzzy lop++ - postprocessor for PNG
- ------------------------------------------
-
- Originally written by Michal Zalewski
-
- Copyright 2015 Google Inc. All rights reserved.
- Adapted to the new API, 2020 by Dominik Maier
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- See post_library.so.c for a general discussion of how to implement
- postprocessors. This specific postprocessor attempts to fix up PNG
- checksums, providing a slightly more complicated example than found
- in post_library.so.c.
-
- Compile with:
-
- gcc -shared -Wall -O3 post_library_png.so.c -o post_library_png.so -lz
-
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <zlib.h>
-
-#include <arpa/inet.h>
-
-/* A macro to round an integer up to 4 kB. */
-
-#define UP4K(_i) ((((_i) >> 12) + 1) << 12)
-
-typedef struct post_state {
-
- unsigned char *buf;
- size_t size;
-
-} post_state_t;
-
-void *afl_custom_init(void *afl) {
-
- post_state_t *state = malloc(sizeof(post_state_t));
- if (!state) {
-
- perror("malloc");
- return NULL;
-
- }
-
- state->buf = calloc(sizeof(unsigned char), 4096);
- if (!state->buf) {
-
- free(state);
- perror("calloc");
- return NULL;
-
- }
-
- return state;
-
-}
-
-size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf,
- unsigned int len,
- const unsigned char **out_buf) {
-
- unsigned char *new_buf = (unsigned char *)in_buf;
- unsigned int pos = 8;
-
- /* Don't do anything if there's not enough room for the PNG header
- (8 bytes). */
-
- if (len < 8) {
-
- *out_buf = in_buf;
- return len;
-
- }
-
- /* Minimum size of a zero-length PNG chunk is 12 bytes; if we
- don't have that, we can bail out. */
-
- while (pos + 12 <= len) {
-
- unsigned int chunk_len, real_cksum, file_cksum;
-
- /* Chunk length is the first big-endian dword in the chunk. */
-
- chunk_len = ntohl(*(uint32_t *)(in_buf + pos));
-
- /* Bail out if chunk size is too big or goes past EOF. */
-
- if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > len) break;
-
- /* Chunk checksum is calculated for chunk ID (dword) and the actual
- payload. */
-
- real_cksum = htonl(crc32(0, in_buf + pos + 4, chunk_len + 4));
-
- /* The in-file checksum is the last dword past the chunk data. */
-
- file_cksum = *(uint32_t *)(in_buf + pos + 8 + chunk_len);
-
- /* If the checksums do not match, we need to fix the file. */
-
- if (real_cksum != file_cksum) {
-
- /* First modification? Make a copy of the input buffer. Round size
- up to 4 kB to minimize the number of reallocs needed. */
-
- if (new_buf == in_buf) {
-
- if (len <= data->size) {
-
- new_buf = data->buf;
-
- } else {
-
- new_buf = realloc(data->buf, UP4K(len));
- if (!new_buf) {
-
- *out_buf = in_buf;
- return len;
-
- }
-
- data->buf = new_buf;
- data->size = UP4K(len);
- memcpy(new_buf, in_buf, len);
-
- }
-
- }
-
- *(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum;
-
- }
-
- /* Skip the entire chunk and move to the next one. */
-
- pos += 12 + chunk_len;
-
- }
-
- *out_buf = new_buf;
- return len;
-
-}
-
-/* Gets called afterwards */
-void afl_custom_deinit(post_state_t *data) {
-
- free(data->buf);
- free(data);
-
-}
-
diff --git a/utils/custom_mutators/simple-chunk-replace.py b/utils/custom_mutators/simple-chunk-replace.py
deleted file mode 100644
index c57218dd..00000000
--- a/utils/custom_mutators/simple-chunk-replace.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-# encoding: utf-8
-"""
-Simple Chunk Cross-Over Replacement Module for AFLFuzz
-
-@author: Christian Holler (:decoder)
-
-@license:
-
-This Source Code Form is subject to the terms of the Mozilla Public
-License, v. 2.0. If a copy of the MPL was not distributed with this
-file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-@contact: choller@mozilla.com
-"""
-
-import random
-
-
-def init(seed):
- """
- Called once when AFLFuzz starts up. Used to seed our RNG.
-
- @type seed: int
- @param seed: A 32-bit random value
- """
- # Seed our RNG
- random.seed(seed)
-
-
-def fuzz(buf, add_buf, max_size):
- """
- Called per fuzzing iteration.
-
- @type buf: bytearray
- @param buf: The buffer that should be mutated.
-
- @type add_buf: bytearray
- @param add_buf: A second buffer that can be used as mutation source.
-
- @type max_size: int
- @param max_size: Maximum size of the mutated output. The mutation must not
- produce data larger than max_size.
-
- @rtype: bytearray
- @return: A new bytearray containing the mutated data
- """
- # Make a copy of our input buffer for returning
- ret = bytearray(buf)
-
- # Take a random fragment length between 2 and 32 (or less if add_buf is shorter)
- fragment_len = random.randint(1, min(len(add_buf), 32))
-
- # Determine a random source index where to take the data chunk from
- rand_src_idx = random.randint(0, len(add_buf) - fragment_len)
-
- # Determine a random destination index where to put the data chunk
- rand_dst_idx = random.randint(0, len(buf))
-
- # Make the chunk replacement
- ret[rand_dst_idx : rand_dst_idx + fragment_len] = add_buf[
- rand_src_idx : rand_src_idx + fragment_len
- ]
-
- # Return data
- return ret
diff --git a/utils/custom_mutators/simple_example.c b/utils/custom_mutators/simple_example.c
deleted file mode 100644
index d888ec1f..00000000
--- a/utils/custom_mutators/simple_example.c
+++ /dev/null
@@ -1,74 +0,0 @@
-// This simple example just creates random buffer <= 100 filled with 'A'
-// needs -I /path/to/AFLplusplus/include
-#include "custom_mutator_helpers.h"
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-#ifndef _FIXED_CHAR
- #define _FIXED_CHAR 0x41
-#endif
-
-typedef struct my_mutator {
-
- afl_t *afl;
-
- // Reused buffers:
- BUF_VAR(u8, fuzz);
-
-} my_mutator_t;
-
-my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
-
- srand(seed);
- my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
- if (!data) {
-
- perror("afl_custom_init alloc");
- return NULL;
-
- }
-
- data->afl = afl;
-
- return data;
-
-}
-
-size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
- u8 **out_buf, uint8_t *add_buf,
- size_t add_buf_size, // add_buf can be NULL
- size_t max_size) {
-
- int size = (rand() % 100) + 1;
- if (size > max_size) size = max_size;
- u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), size);
- if (!mutated_out) {
-
- *out_buf = NULL;
- perror("custom mutator allocation (maybe_grow)");
- return 0; /* afl-fuzz will very likely error out after this. */
-
- }
-
- memset(mutated_out, _FIXED_CHAR, size);
-
- *out_buf = mutated_out;
- return size;
-
-}
-
-/**
- * Deinitialize everything
- *
- * @param data The data ptr from afl_custom_init
- */
-void afl_custom_deinit(my_mutator_t *data) {
-
- free(data->fuzz_buf);
- free(data);
-
-}
-
diff --git a/utils/custom_mutators/wrapper_afl_min.py b/utils/custom_mutators/wrapper_afl_min.py
deleted file mode 100644
index 5cd60031..00000000
--- a/utils/custom_mutators/wrapper_afl_min.py
+++ /dev/null
@@ -1,123 +0,0 @@
-#!/usr/bin/env python
-
-from XmlMutatorMin import XmlMutatorMin
-
-# Default settings (production mode)
-
-__mutator__ = None
-__seed__ = "RANDOM"
-__log__ = False
-__log_file__ = "wrapper.log"
-
-
-# AFL functions
-def log(text):
- """
- Logger
- """
-
- global __seed__
- global __log__
- global __log_file__
-
- if __log__:
- with open(__log_file__, "a") as logf:
- logf.write("[%s] %s\n" % (__seed__, text))
-
-
-def init(seed):
- """
- Called once when AFL starts up. Seed is used to identify the AFL instance in log files
- """
-
- global __mutator__
- global __seed__
-
- # Get the seed
- __seed__ = seed
-
- # Create a global mutation class
- try:
- __mutator__ = XmlMutatorMin(__seed__, verbose=__log__)
- log("init(): Mutator created")
- except RuntimeError as e:
- log("init(): Can't create mutator: %s" % e.message)
-
-
-def fuzz(buf, add_buf, max_size):
- """
- Called for each fuzzing iteration.
- """
-
- global __mutator__
-
- # Do we have a working mutator object?
- if __mutator__ is None:
- log("fuzz(): Can't fuzz, no mutator available")
- return buf
-
- # Try to use the AFL buffer
- via_buffer = True
-
- # Interpret the AFL buffer (an array of bytes) as a string
- if via_buffer:
- try:
- buf_str = str(buf)
- log("fuzz(): AFL buffer converted to a string")
- except Exception:
- via_buffer = False
- log("fuzz(): Can't convert AFL buffer to a string")
-
- # Load XML from the AFL string
- if via_buffer:
- try:
- __mutator__.init_from_string(buf_str)
- log(
- "fuzz(): Mutator successfully initialized with AFL buffer (%d bytes)"
- % len(buf_str)
- )
- except Exception:
- via_buffer = False
- log("fuzz(): Can't initialize mutator with AFL buffer")
-
- # If init from AFL buffer wasn't succesful
- if not via_buffer:
- log("fuzz(): Returning unmodified AFL buffer")
- return buf
-
- # Sucessful initialization -> mutate
- try:
- __mutator__.mutate(max=5)
- log("fuzz(): Input mutated")
- except Exception:
- log("fuzz(): Can't mutate input => returning buf")
- return buf
-
- # Convert mutated data to a array of bytes
- try:
- data = bytearray(__mutator__.save_to_string())
- log("fuzz(): Mutated data converted as bytes")
- except Exception:
- log("fuzz(): Can't convert mutated data to bytes => returning buf")
- return buf
-
- # Everything went fine, returning mutated content
- log("fuzz(): Returning %d bytes" % len(data))
- return data
-
-
-# Main (for debug)
-if __name__ == "__main__":
-
- __log__ = True
- __log_file__ = "/dev/stdout"
- __seed__ = "RANDOM"
-
- init(__seed__)
-
- in_1 = bytearray(
- "<foo ddd='eeee'>ffff<a b='c' d='456' eee='ffffff'>zzzzzzzzzzzz</a><b yyy='YYY' zzz='ZZZ'></b></foo>"
- )
- in_2 = bytearray("<abc abc123='456' abcCBA='ppppppppppppppppppppppppppppp'/>")
- out = fuzz(in_1, in_2)
- print(out)
diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c
index 1b247c86..dde78f7b 100644
--- a/utils/libdislocator/libdislocator.so.c
+++ b/utils/libdislocator/libdislocator.so.c
@@ -144,8 +144,8 @@ typedef struct {
/* Configurable stuff (use AFL_LD_* to set): */
-static u32 max_mem = MAX_ALLOC; /* Max heap usage to permit */
-static u8 alloc_verbose, /* Additional debug messages */
+static size_t max_mem = MAX_ALLOC; /* Max heap usage to permit */
+static u8 alloc_verbose, /* Additional debug messages */
hard_fail, /* abort() when max_mem exceeded? */
no_calloc_over, /* abort() on calloc() overflows? */
align_allocations; /* Force alignment to sizeof(void*) */
@@ -154,7 +154,7 @@ static u8 alloc_verbose, /* Additional debug messages */
#define __thread
#warning no thread support available
#endif
-static __thread size_t total_mem; /* Currently allocated mem */
+static _Atomic size_t total_mem; /* Currently allocated mem */
static __thread u32 call_depth; /* To avoid recursion via fprintf() */
static u32 alloc_canary;
@@ -172,9 +172,9 @@ static void *__dislocator_alloc(size_t len) {
if (total_mem + len > max_mem || total_mem + len < total_mem) {
- if (hard_fail) FATAL("total allocs exceed %u MB", max_mem / 1024 / 1024);
+ if (hard_fail) FATAL("total allocs exceed %zu MB", max_mem / 1024 / 1024);
- DEBUGF("total allocs exceed %u MB, returning NULL", max_mem / 1024 / 1024);
+ DEBUGF("total allocs exceed %zu MB, returning NULL", max_mem / 1024 / 1024);
return NULL;
@@ -500,19 +500,20 @@ size_t malloc_usable_size(const void *ptr) {
__attribute__((constructor)) void __dislocator_init(void) {
- u8 *tmp = (u8 *)getenv("AFL_LD_LIMIT_MB");
+ char *tmp = getenv("AFL_LD_LIMIT_MB");
if (tmp) {
- u8 *tok;
- s32 mmem = (s32)strtol((char *)tmp, (char **)&tok, 10);
- if (*tok != '\0' || errno == ERANGE) FATAL("Bad value for AFL_LD_LIMIT_MB");
+ char * tok;
+ unsigned long long mmem = strtoull(tmp, &tok, 10);
+ if (*tok != '\0' || errno == ERANGE || mmem > SIZE_MAX / 1024 / 1024)
+ FATAL("Bad value for AFL_LD_LIMIT_MB");
max_mem = mmem * 1024 * 1024;
}
alloc_canary = ALLOC_CANARY;
- tmp = (u8 *)getenv("AFL_RANDOM_ALLOC_CANARY");
+ tmp = getenv("AFL_RANDOM_ALLOC_CANARY");
if (tmp) arc4random_buf(&alloc_canary, sizeof(alloc_canary));
diff --git a/utils/qbdi_mode/template.cpp b/utils/qbdi_mode/template.cpp
index b2066cc8..182a014b 100755
--- a/utils/qbdi_mode/template.cpp
+++ b/utils/qbdi_mode/template.cpp
@@ -25,7 +25,7 @@
#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO)
#define INC_AFL_AREA(loc) \
asm volatile( \
- "incb (%0, %1, 1)\n" \
+ "addb $1, (%0, %1, 1)\n" \
"adcb $0, (%0, %1, 1)\n" \
: /* no out */ \
: "r"(afl_area_ptr), "r"(loc) \
diff --git a/utils/qemu_persistent_hook/read_into_rdi.c b/utils/qemu_persistent_hook/read_into_rdi.c
index c1c6642f..14b2ed85 100644
--- a/utils/qemu_persistent_hook/read_into_rdi.c
+++ b/utils/qemu_persistent_hook/read_into_rdi.c
@@ -3,12 +3,12 @@
#include <stdio.h>
#include <string.h>
-void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
- uint8_t *input_buf, uint32_t input_buf_len) {
-
#define g2h(x) ((void *)((unsigned long)(x) + guest_base))
#define h2g(x) ((uint64_t)(x)-guest_base)
+void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
// In this example the register RDI is pointing to the memory location
// of the target buffer, and the length of the input is in RSI.
// This can be seen with a debugger, e.g. gdb (and "disass main")
@@ -19,11 +19,11 @@ void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
memcpy(g2h(regs->rdi), input_buf, input_buf_len);
regs->rsi = input_buf_len;
+}
+
#undef g2h
#undef h2g
-}
-
int afl_persistent_hook_init(void) {
// 1 for shared memory input (faster), 0 for normal input (you have to use