diff --git a/README.md b/README.md
index 119426f6..800c2121 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
- Release Version: [3.00c](https://github.com/AFLplusplus/AFLplusplus/releases)
+ Release Version: [3.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
- Github Version: 3.01a
+ Github Version: 3.11a
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@@ -25,14 +25,14 @@
For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast`
with `AFL_LLVM_CMPLOG=1`.
-## Major changes in afl++ 3.0 + 3.1
+## Major changes in afl++ 3.00 + 3.10
-With afl++ 3.1 we introduced the following changes from previous behaviours:
+With afl++ 3.10 we introduced the following changes from previous behaviours:
* The '+' feature of the '-t' option now means to auto-calculate the timeout
with the value given being the maximum timeout. The original meaning of
"skipping timeouts instead of abort" is now inherent to the -t option.
-With afl++ 3.0 we introduced changes that break some previous afl and afl++
+With afl++ 3.00 we introduced changes that break some previous afl and afl++
behaviours and defaults:
* There are no llvm_mode and gcc_plugin subdirectories anymore and there is
diff --git a/afl-system-config b/afl-system-config
index d5e5ceae..9905ac81 100755
--- a/afl-system-config
+++ b/afl-system-config
@@ -49,6 +49,12 @@ if [ "$PLATFORM" = "FreeBSD" ] ; then
sysctl kern.elf64.aslr.enable=0
} > /dev/null
echo Settings applied.
+ cat <${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
echo Settings applied.; \
}
diff --git a/custom_mutators/rust/.gitignore b/custom_mutators/rust/.gitignore
new file mode 100644
index 00000000..088ba6ba
--- /dev/null
+++ b/custom_mutators/rust/.gitignore
@@ -0,0 +1,10 @@
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
diff --git a/custom_mutators/rust/Cargo.toml b/custom_mutators/rust/Cargo.toml
new file mode 100644
index 00000000..e36d24b5
--- /dev/null
+++ b/custom_mutators/rust/Cargo.toml
@@ -0,0 +1,8 @@
+[workspace]
+members = [
+ "custom_mutator-sys",
+ "custom_mutator",
+ "example",
+ # Lain needs a nightly toolchain
+ # "example_lain",
+]
\ No newline at end of file
diff --git a/custom_mutators/rust/README.md b/custom_mutators/rust/README.md
new file mode 100644
index 00000000..e2cc38b4
--- /dev/null
+++ b/custom_mutators/rust/README.md
@@ -0,0 +1,11 @@
+# Rust Custom Mutators
+
+Bindings to create custom mutators in Rust.
+
+These bindings are documented with rustdoc. To view the documentation run
+```cargo doc -p custom_mutator --open```.
+
+A minimal example can be found in `example`. Build it using `cargo build --example example_mutator`.
+
+An example using [lain](https://github.com/microsoft/lain) for structured fuzzing can be found in `example_lain`.
+Since lain requires a nightly rust toolchain, you need to set one up before you can play with it.
diff --git a/custom_mutators/rust/custom_mutator-sys/Cargo.toml b/custom_mutators/rust/custom_mutator-sys/Cargo.toml
new file mode 100644
index 00000000..104f7df0
--- /dev/null
+++ b/custom_mutators/rust/custom_mutator-sys/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "custom_mutator-sys"
+version = "0.1.0"
+authors = ["Julius Hohnerlein "]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+
+[build-dependencies]
+bindgen = "0.56"
diff --git a/custom_mutators/rust/custom_mutator-sys/build.rs b/custom_mutators/rust/custom_mutator-sys/build.rs
new file mode 100644
index 00000000..3c88a90d
--- /dev/null
+++ b/custom_mutators/rust/custom_mutator-sys/build.rs
@@ -0,0 +1,42 @@
+extern crate bindgen;
+
+use std::env;
+use std::path::PathBuf;
+
+// this code is largely taken straight from the handbook: https://github.com/fitzgen/bindgen-tutorial-bzip2-sys
+fn main() {
+ // Tell cargo to invalidate the built crate whenever the wrapper changes
+ println!("cargo:rerun-if-changed=wrapper.h");
+
+ // The bindgen::Builder is the main entry point
+ // to bindgen, and lets you build up options for
+ // the resulting bindings.
+ let bindings = bindgen::Builder::default()
+ // The input header we would like to generate
+ // bindings for.
+ .header("wrapper.h")
+ .whitelist_type("afl_state_t")
+ .blacklist_type(r"u\d+")
+ .opaque_type(r"_.*")
+ .opaque_type("FILE")
+ .opaque_type("in_addr(_t)?")
+ .opaque_type("in_port(_t)?")
+ .opaque_type("sa_family(_t)?")
+ .opaque_type("sockaddr_in(_t)?")
+ .opaque_type("time_t")
+ .rustfmt_bindings(true)
+ .size_t_is_usize(true)
+ // Tell cargo to invalidate the built crate whenever any of the
+ // included header files changed.
+ .parse_callbacks(Box::new(bindgen::CargoCallbacks))
+ // Finish the builder and generate the bindings.
+ .generate()
+ // Unwrap the Result and panic on failure.
+ .expect("Unable to generate bindings");
+
+ // Write the bindings to the $OUT_DIR/bindings.rs file.
+ let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
+ bindings
+ .write_to_file(out_path.join("bindings.rs"))
+ .expect("Couldn't write bindings!");
+}
diff --git a/custom_mutators/rust/custom_mutator-sys/src/lib.rs b/custom_mutators/rust/custom_mutator-sys/src/lib.rs
new file mode 100644
index 00000000..a38a13a8
--- /dev/null
+++ b/custom_mutators/rust/custom_mutator-sys/src/lib.rs
@@ -0,0 +1,5 @@
+#![allow(non_upper_case_globals)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+
+include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
diff --git a/custom_mutators/rust/custom_mutator-sys/wrapper.h b/custom_mutators/rust/custom_mutator-sys/wrapper.h
new file mode 100644
index 00000000..81cdb90f
--- /dev/null
+++ b/custom_mutators/rust/custom_mutator-sys/wrapper.h
@@ -0,0 +1,4 @@
+#include "../../../include/afl-fuzz.h"
+#include "../../../include/common.h"
+#include "../../../include/config.h"
+#include "../../../include/debug.h"
diff --git a/custom_mutators/rust/custom_mutator/Cargo.toml b/custom_mutators/rust/custom_mutator/Cargo.toml
new file mode 100644
index 00000000..2d3cdbfa
--- /dev/null
+++ b/custom_mutators/rust/custom_mutator/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "custom_mutator"
+version = "0.1.0"
+authors = ["Julius Hohnerlein "]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[features]
+afl_internals = ["custom_mutator-sys"]
+
+[dependencies]
+custom_mutator-sys = { path = "../custom_mutator-sys", optional=true }
diff --git a/custom_mutators/rust/custom_mutator/src/lib.rs b/custom_mutators/rust/custom_mutator/src/lib.rs
new file mode 100644
index 00000000..b82af250
--- /dev/null
+++ b/custom_mutators/rust/custom_mutator/src/lib.rs
@@ -0,0 +1,634 @@
+//! Somewhat safe and somewhat ergonomic bindings for creating [AFL++](https://github.com/AFLplusplus/AFLplusplus) [custom mutators](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/custom_mutators.md) in Rust.
+//!
+//! # Usage
+//! AFL++ custom mutators are expected to be dynamic libraries which expose a set of symbols.
+//! Check out [`CustomMutator`] to see which functions of the API are supported.
+//! Then use [`export_mutator`] to export the correct symbols for your mutator.
+//! In order to use the mutator, your crate needs to be a library crate and have a `crate-type` of `cdylib`.
+//! Putting
+//! ```yaml
+//! [lib]
+//! crate-type = ["cdylib"]
+//! ```
+//! into your `Cargo.toml` should do the trick.
+//! The final executable can be found in `target/(debug|release)/your_crate_name.so`.
+//! # Example
+//! See [`export_mutator`] for an example.
+//!
+//! # On `panic`s
+//! This binding is panic-safe in that it will prevent panics from unwinding into AFL++. Any panic will `abort` at the boundary between the custom mutator and AFL++.
+//!
+//! # Access to AFL++ internals
+//! This crate has an optional feature "afl_internals", which gives access to AFL++'s internal state.
+//! The state is passed to [`CustomMutator::init`], when the feature is activated.
+//!
+//! _This is completely unsafe and uses automatically generated types extracted from the AFL++ source._
+use std::{ffi::CStr, fmt::Debug};
+
+#[cfg(feature = "afl_internals")]
+#[doc(hidden)]
+pub use custom_mutator_sys::afl_state;
+
+#[allow(unused_variables)]
+#[doc(hidden)]
+pub trait RawCustomMutator {
+ #[cfg(feature = "afl_internals")]
+ fn init(afl: &'static afl_state, seed: c_uint) -> Self
+ where
+ Self: Sized;
+ #[cfg(not(feature = "afl_internals"))]
+ fn init(seed: u32) -> Self
+ where
+ Self: Sized;
+
+ fn fuzz<'b, 's: 'b>(
+ &'s mut self,
+ buffer: &'b mut [u8],
+ add_buff: Option<&[u8]>,
+ max_size: usize,
+ ) -> Option<&'b [u8]>;
+
+ fn fuzz_count(&mut self, buffer: &[u8]) -> u32 {
+ 1
+ }
+
+ fn queue_new_entry(&mut self, filename_new_queue: &CStr, _filename_orig_queue: Option<&CStr>) {}
+
+ fn queue_get(&mut self, filename: &CStr) -> bool {
+ true
+ }
+
+ fn describe(&mut self, max_description: usize) -> Option<&CStr> {
+ None
+ }
+
+ fn introspection(&mut self) -> Option<&CStr> {
+ None
+ }
+
+ /*fn post_process(&self, buffer: &[u8], unsigned char **out_buf)-> usize;
+ int afl_custom_init_trim(&self, buffer: &[u8]);
+ size_t afl_custom_trim(&self, unsigned char **out_buf);
+ int afl_custom_post_trim(&self, unsigned char success);
+ size_t afl_custom_havoc_mutation(&self, buffer: &[u8], unsigned char **out_buf, size_t max_size);
+ unsigned char afl_custom_havoc_mutation_probability(&self);*/
+}
+
+/// Wrappers for the custom mutator which provide the bridging between the C API and CustomMutator.
+/// These wrappers are not intended to be used directly, rather export_mutator will use them to publish the custom mutator C API.
+#[doc(hidden)]
+pub mod wrappers {
+ #[cfg(feature = "afl_internals")]
+ use custom_mutator_sys::afl_state;
+
+ use core::slice;
+ use std::{
+ any::Any,
+ convert::TryInto,
+ ffi::{c_void, CStr},
+ mem::ManuallyDrop,
+ os::raw::c_char,
+ panic::catch_unwind,
+ process::abort,
+ ptr::null,
+ };
+
+ use crate::RawCustomMutator;
+
+ /// A structure to be used as the data pointer for our custom mutator. This was used as additional storage and is kept for now in case its needed later.
+ /// Also has some convenience functions for FFI conversions (from and to ptr) and tries to make misuse hard (see [`FFIContext::from`]).
+ struct FFIContext {
+ mutator: M,
+ }
+
+ impl FFIContext {
+ fn from(ptr: *mut c_void) -> ManuallyDrop> {
+ assert!(!ptr.is_null());
+ ManuallyDrop::new(unsafe { Box::from_raw(ptr as *mut Self) })
+ }
+
+ fn into_ptr(self: Box) -> *const c_void {
+ Box::into_raw(self) as *const c_void
+ }
+
+ #[cfg(feature = "afl_internals")]
+ fn new(afl: &'static afl_state, seed: u32) -> Box {
+ Box::new(Self {
+ mutator: M::init(afl, seed),
+ })
+ }
+ #[cfg(not(feature = "afl_internals"))]
+ fn new(seed: u32) -> Box {
+ Box::new(Self {
+ mutator: M::init(seed),
+ })
+ }
+ }
+
+ /// panic handler called for every panic
+ fn panic_handler(method: &str, panic_info: Box) -> ! {
+ use std::ops::Deref;
+ let cause = panic_info
+ .downcast_ref::()
+ .map(String::deref)
+ .unwrap_or_else(|| {
+ panic_info
+ .downcast_ref::<&str>()
+ .copied()
+ .unwrap_or("")
+ });
+ eprintln!("A panic occurred at {}: {}", method, cause);
+ abort()
+ }
+
+ /// Internal function used in the macro
+ #[cfg(not(feature = "afl_internals"))]
+ pub fn afl_custom_init_(seed: u32) -> *const c_void {
+ match catch_unwind(|| FFIContext::::new(seed).into_ptr()) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_init", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ #[cfg(feature = "afl_internals")]
+ pub fn afl_custom_init_(
+ afl: Option<&'static afl_state>,
+ seed: u32,
+ ) -> *const c_void {
+ match catch_unwind(|| {
+ let afl = afl.expect("mutator func called with NULL afl");
+ FFIContext::::new(afl, seed).into_ptr()
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_init", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub unsafe fn afl_custom_fuzz_(
+ data: *mut c_void,
+ buf: *mut u8,
+ buf_size: usize,
+ out_buf: *mut *const u8,
+ add_buf: *mut u8,
+ add_buf_size: usize,
+ max_size: usize,
+ ) -> usize {
+ match catch_unwind(|| {
+ let mut context = FFIContext::::from(data);
+ if buf.is_null() {
+ panic!("null buf passed to afl_custom_fuzz")
+ }
+ if out_buf.is_null() {
+ panic!("null out_buf passed to afl_custom_fuzz")
+ }
+ let buff_slice = slice::from_raw_parts_mut(buf, buf_size);
+ let add_buff_slice = if add_buf.is_null() {
+ None
+ } else {
+ Some(slice::from_raw_parts(add_buf, add_buf_size))
+ };
+ match context
+ .mutator
+ .fuzz(buff_slice, add_buff_slice, max_size.try_into().unwrap())
+ {
+ Some(buffer) => {
+ *out_buf = buffer.as_ptr();
+ buffer.len().try_into().unwrap()
+ }
+ None => {
+ // return the input buffer with 0-length to let AFL skip this mutation attempt
+ *out_buf = buf;
+ 0
+ }
+ }
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_fuzz", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub unsafe fn afl_custom_fuzz_count_(
+ data: *mut c_void,
+ buf: *const u8,
+ buf_size: usize,
+ ) -> u32 {
+ match catch_unwind(|| {
+ let mut context = FFIContext::::from(data);
+ if buf.is_null() {
+ panic!("null buf passed to afl_custom_fuzz")
+ }
+ let buf_slice = slice::from_raw_parts(buf, buf_size);
+ // see https://doc.rust-lang.org/nomicon/borrow-splitting.html
+ let ctx = &mut **context;
+ let mutator = &mut ctx.mutator;
+ mutator.fuzz_count(buf_slice)
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_fuzz_count", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub fn afl_custom_queue_new_entry_(
+ data: *mut c_void,
+ filename_new_queue: *const c_char,
+ filename_orig_queue: *const c_char,
+ ) {
+ match catch_unwind(|| {
+ let mut context = FFIContext::::from(data);
+ if filename_new_queue.is_null() {
+ panic!("received null filename_new_queue in afl_custom_queue_new_entry");
+ }
+ let filename_new_queue = unsafe { CStr::from_ptr(filename_new_queue) };
+ let filename_orig_queue = if !filename_orig_queue.is_null() {
+ Some(unsafe { CStr::from_ptr(filename_orig_queue) })
+ } else {
+ None
+ };
+ context
+ .mutator
+ .queue_new_entry(filename_new_queue, filename_orig_queue);
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_queue_new_entry", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub unsafe fn afl_custom_deinit_(data: *mut c_void) {
+ match catch_unwind(|| {
+ // drop the context
+ ManuallyDrop::into_inner(FFIContext::::from(data));
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_deinit", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub fn afl_custom_introspection_(data: *mut c_void) -> *const c_char {
+ match catch_unwind(|| {
+ let mut context = FFIContext::::from(data);
+ if let Some(res) = context.mutator.introspection() {
+ res.as_ptr()
+ } else {
+ null()
+ }
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_introspection", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub fn afl_custom_describe_(
+ data: *mut c_void,
+ max_description_len: usize,
+ ) -> *const c_char {
+ match catch_unwind(|| {
+ let mut context = FFIContext::::from(data);
+ if let Some(res) = context.mutator.describe(max_description_len) {
+ res.as_ptr()
+ } else {
+ null()
+ }
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_describe", err),
+ }
+ }
+
+ /// Internal function used in the macro
+ pub fn afl_custom_queue_get_(
+ data: *mut c_void,
+ filename: *const c_char,
+ ) -> u8 {
+ match catch_unwind(|| {
+ let mut context = FFIContext::::from(data);
+ assert!(!filename.is_null());
+
+ context
+ .mutator
+ .queue_get(unsafe { CStr::from_ptr(filename) }) as u8
+ }) {
+ Ok(ret) => ret,
+ Err(err) => panic_handler("afl_custom_queue_get", err),
+ }
+ }
+}
+
+/// exports the given Mutator as a custom mutator as the C interface that AFL++ expects.
+/// It is not possible to call this macro multiple times, because it would define the custom mutator symbols multiple times.
+/// # Example
+/// ```
+/// # #[macro_use] extern crate custom_mutator;
+/// # #[cfg(feature = "afl_internals")]
+/// # use custom_mutator::afl_state;
+/// # use custom_mutator::CustomMutator;
+/// struct MyMutator;
+/// impl CustomMutator for MyMutator {
+/// /// ...
+/// # type Error = ();
+/// # #[cfg(feature = "afl_internals")]
+/// # fn init(_afl_state: &afl_state, _seed: u32) -> Result {unimplemented!()}
+/// # #[cfg(not(feature = "afl_internals"))]
+/// # fn init(_seed: u32) -> Result {unimplemented!()}
+/// # fn fuzz<'b,'s:'b>(&'s mut self, _buffer: &'b mut [u8], _add_buff: Option<&[u8]>, _max_size: usize) -> Result