about summary refs log tree commit diff
path: root/utils/custom_mutators/XmlMutatorMin.py
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/custom_mutators/XmlMutatorMin.py
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/custom_mutators/XmlMutatorMin.py')
-rw-r--r--utils/custom_mutators/XmlMutatorMin.py348
1 files changed, 0 insertions, 348 deletions
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)