python mutator examples added

This commit is contained in:
van Hauser
2019-06-20 12:22:46 +02:00
parent 4e3d921f1a
commit d10ebd1a68
6 changed files with 218 additions and 0 deletions

View File

@ -21,6 +21,9 @@ american fuzzy lop plus plus
https://github.com/andreafioraldi/afl and got the community patches applied https://github.com/andreafioraldi/afl and got the community patches applied
to it. to it.
C. Hoellers Python mutator module support was added too
(https://github.com/choeller/afl)
So all in all this is the best-of AFL that is currently out there :-) So all in all this is the best-of AFL that is currently out there :-)

View File

@ -12,6 +12,8 @@ Adding custom mutators to AFL using Python modules
NOTE: This is for Python 2.7 ! NOTE: This is for Python 2.7 !
Anyone who wants to add Python 3.7 support is happily welcome :) Anyone who wants to add Python 3.7 support is happily welcome :)
For an example and a template see ../python_mutators/
1) Description and purpose 1) Description and purpose
-------------------------- --------------------------
@ -50,6 +52,7 @@ is requested.
There is also optional support for a trimming API, see the section below for There is also optional support for a trimming API, see the section below for
further information about this feature. further information about this feature.
3) How to compile AFLFuzz with Python support 3) How to compile AFLFuzz with Python support
--------------------------------------------- ---------------------------------------------
@ -91,6 +94,7 @@ AFL_DEBUG - When combined with AFL_NO_UI, this causes the C trimming code
to emit additional messages about the performance and actions to emit additional messages about the performance and actions
of your custom Python trimmer. Use this to see if it works :) of your custom Python trimmer. Use this to see if it works :)
5) Order and statistics 5) Order and statistics
----------------------- -----------------------
@ -99,6 +103,7 @@ the havoc stage). In the statistics however, it shows up as the third number
under "havoc". That's because I'm lazy and I didn't want to mess with the UI under "havoc". That's because I'm lazy and I didn't want to mess with the UI
too much ;) too much ;)
6) Trimming support 6) Trimming support
------------------- -------------------

11
python_mutators/README Normal file
View File

@ -0,0 +1,11 @@
These are example and helper files for the AFL_PYTHON_MODULE feature.
See docs/python_mutators.txt for more information
example.py - this is the template you can use, the functions are there
but they are empty
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 :)

37
python_mutators/common.py Normal file
View File

@ -0,0 +1,37 @@
#!/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)

103
python_mutators/example.py Normal file
View File

@ -0,0 +1,103 @@
#!/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
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)
return 0
def fuzz(buf, add_buf):
'''
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.
@rtype: bytearray
@return: A new bytearray containing the mutated data
'''
ret = bytearray(buf)
# Do something interesting with ret
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

View File

@ -0,0 +1,59 @@
#!/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)
return 0
def fuzz(buf, add_buf):
'''
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.
@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