From 3a461944ecac47627d3e9d2afcf1c28925e2355a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 26 Feb 2021 22:36:19 +0100 Subject: [PATCH 01/18] fine tune cmplog --- include/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config.h b/include/config.h index 439f4d2f..b0b1f7b9 100644 --- a/include/config.h +++ b/include/config.h @@ -50,7 +50,7 @@ #define CMPLOG_COMBINE /* Minimum % of the corpus to perform cmplog on. Default: 10% */ -#define CMPLOG_CORPUS_PERCENT 10U +#define CMPLOG_CORPUS_PERCENT 5U /* Number of potential positions from which we decide if cmplog becomes useless, default 8096 */ From 79e02c2a9b2532624d7f187783ccbe9cbb04ce9b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Fri, 26 Feb 2021 22:54:35 +0100 Subject: [PATCH 02/18] remove debug output --- utils/persistent_mode/persistent_demo_new.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/persistent_mode/persistent_demo_new.c b/utils/persistent_mode/persistent_demo_new.c index 7e694696..285f50aa 100644 --- a/utils/persistent_mode/persistent_demo_new.c +++ b/utils/persistent_mode/persistent_demo_new.c @@ -70,7 +70,7 @@ int main(int argc, char **argv) { len = __AFL_FUZZ_TESTCASE_LEN; // do not use the macro directly in a call! - fprintf(stderr, "input: %zd \"%s\"\n", len, buf); + // fprintf(stderr, "input: %zd \"%s\"\n", len, buf); /* do we have enough data? */ if (len < 8) continue; From a5da9ce42cab1eab93cf80ca744944ae26e6ab58 Mon Sep 17 00:00:00 2001 From: julihoh Date: Sat, 27 Feb 2021 15:05:13 +0100 Subject: [PATCH 03/18] custom mutator rust support (#752) * custom mutator rust support * clarify how to view documentation for rust mutators * remove `FuzzResult` hack and clarify lifetimes of CustomMutator::fuzz * rename TErr associated tyep to Error to be more idiomatic * fix warnings * add example for fallible custom mutator * make Fallible Custom Mutator the default and implement it's handle_err method by default * rename CustomMutator::handle_err to handle_error * add example mutator using lain --- custom_mutators/rust/.gitignore | 10 + custom_mutators/rust/Cargo.toml | 7 + custom_mutators/rust/README.md | 9 + .../rust/custom_mutator-sys/Cargo.toml | 12 + .../rust/custom_mutator-sys/build.rs | 42 ++ .../rust/custom_mutator-sys/src/lib.rs | 5 + .../rust/custom_mutator-sys/wrapper.h | 4 + .../rust/custom_mutator/Cargo.toml | 13 + .../rust/custom_mutator/src/lib.rs | 637 ++++++++++++++++++ custom_mutators/rust/example/Cargo.toml | 13 + custom_mutators/rust/example/src/lib.rs | 50 ++ custom_mutators/rust/example_lain/Cargo.toml | 14 + .../rust/example_lain/rust-toolchain | 1 + custom_mutators/rust/example_lain/src/lib.rs | 60 ++ docs/custom_mutators.md | 5 + 15 files changed, 882 insertions(+) create mode 100644 custom_mutators/rust/.gitignore create mode 100644 custom_mutators/rust/Cargo.toml create mode 100644 custom_mutators/rust/README.md create mode 100644 custom_mutators/rust/custom_mutator-sys/Cargo.toml create mode 100644 custom_mutators/rust/custom_mutator-sys/build.rs create mode 100644 custom_mutators/rust/custom_mutator-sys/src/lib.rs create mode 100644 custom_mutators/rust/custom_mutator-sys/wrapper.h create mode 100644 custom_mutators/rust/custom_mutator/Cargo.toml create mode 100644 custom_mutators/rust/custom_mutator/src/lib.rs create mode 100644 custom_mutators/rust/example/Cargo.toml create mode 100644 custom_mutators/rust/example/src/lib.rs create mode 100644 custom_mutators/rust/example_lain/Cargo.toml create mode 100644 custom_mutators/rust/example_lain/rust-toolchain create mode 100644 custom_mutators/rust/example_lain/src/lib.rs 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..003bc58a --- /dev/null +++ b/custom_mutators/rust/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] +members = [ + "custom_mutator-sys", + "custom_mutator", + "example", + "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..119ac790 --- /dev/null +++ b/custom_mutators/rust/README.md @@ -0,0 +1,9 @@ +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`. + +An example using [lain](https://github.com/microsoft/lain) 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..0fb007ab --- /dev/null +++ b/custom_mutators/rust/custom_mutator/src/lib.rs @@ -0,0 +1,637 @@ +//! 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, os::raw::c_uint}; + +#[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: c_uint) -> 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, c_uint}, + 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: c_uint) -> Box { + Box::new(Self { + mutator: M::init(afl, seed), + }) + } + #[cfg(not(feature = "afl_internals"))] + fn new(seed: c_uint) -> 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: c_uint) -> *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: c_uint, + ) -> *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; +/// # use std::os::raw::c_uint; +/// struct MyMutator; +/// impl CustomMutator for MyMutator { +/// /// ... +/// # type Error = (); +/// # #[cfg(feature = "afl_internals")] +/// # fn init(_afl_state: &afl_state, _seed: c_uint) -> Result {unimplemented!()} +/// # #[cfg(not(feature = "afl_internals"))] +/// # fn init(_seed: c_uint) -> Result {unimplemented!()} +/// # fn fuzz<'b,'s:'b>(&'s mut self, _buffer: &'b mut [u8], _add_buff: Option<&[u8]>, _max_size: usize) -> Result,()> {unimplemented!()} +/// } +/// export_mutator!(MyMutator); +/// ``` +#[macro_export] +macro_rules! export_mutator { + ($mutator_type:ty) => { + #[cfg(feature = "afl_internals")] + #[no_mangle] + pub extern "C" fn afl_custom_init( + afl: ::std::option::Option<&'static $crate::afl_state>, + seed: ::std::os::raw::c_uint, + ) -> *const ::std::os::raw::c_void { + $crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed) + } + + #[cfg(not(feature = "afl_internals"))] + #[no_mangle] + pub extern "C" fn afl_custom_init( + _afl: *const ::std::os::raw::c_void, + seed: ::std::os::raw::c_uint, + ) -> *const ::std::os::raw::c_void { + $crate::wrappers::afl_custom_init_::<$mutator_type>(seed) + } + + #[no_mangle] + pub extern "C" fn afl_custom_fuzz_count( + data: *mut ::std::os::raw::c_void, + buf: *const u8, + buf_size: usize, + ) -> u32 { + unsafe { + $crate::wrappers::afl_custom_fuzz_count_::<$mutator_type>(data, buf, buf_size) + } + } + + #[no_mangle] + pub extern "C" fn afl_custom_fuzz( + data: *mut ::std::os::raw::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 { + unsafe { + $crate::wrappers::afl_custom_fuzz_::<$mutator_type>( + data, + buf, + buf_size, + out_buf, + add_buf, + add_buf_size, + max_size, + ) + } + } + + #[no_mangle] + pub extern "C" fn afl_custom_queue_new_entry( + data: *mut ::std::os::raw::c_void, + filename_new_queue: *const ::std::os::raw::c_char, + filename_orig_queue: *const ::std::os::raw::c_char, + ) { + $crate::wrappers::afl_custom_queue_new_entry_::<$mutator_type>( + data, + filename_new_queue, + filename_orig_queue, + ) + } + + #[no_mangle] + pub extern "C" fn afl_custom_queue_get( + data: *mut ::std::os::raw::c_void, + filename: *const ::std::os::raw::c_char, + ) -> u8 { + $crate::wrappers::afl_custom_queue_get_::<$mutator_type>(data, filename) + } + + #[no_mangle] + pub extern "C" fn afl_custom_introspection( + data: *mut ::std::os::raw::c_void, + ) -> *const ::std::os::raw::c_char { + $crate::wrappers::afl_custom_introspection_::<$mutator_type>(data) + } + + #[no_mangle] + pub extern "C" fn afl_custom_describe( + data: *mut ::std::os::raw::c_void, + max_description_len: usize, + ) -> *const ::std::os::raw::c_char { + $crate::wrappers::afl_custom_describe_::<$mutator_type>(data, max_description_len) + } + + #[no_mangle] + pub extern "C" fn afl_custom_deinit(data: *mut ::std::os::raw::c_void) { + unsafe { $crate::wrappers::afl_custom_deinit_::<$mutator_type>(data) } + } + }; +} + +#[cfg(test)] +/// this sanity test is supposed to just find out whether an empty mutator being exported by the macro compiles +mod sanity_test { + use std::os::raw::c_uint; + + #[cfg(feature = "afl_internals")] + use super::afl_state; + + use super::{export_mutator, RawCustomMutator}; + + struct ExampleMutator; + + impl RawCustomMutator for ExampleMutator { + #[cfg(feature = "afl_internals")] + fn init(_afl: &afl_state, _seed: c_uint) -> Self { + unimplemented!() + } + + #[cfg(not(feature = "afl_internals"))] + fn init(_seed: c_uint) -> Self { + unimplemented!() + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + _buffer: &'b mut [u8], + _add_buff: Option<&[u8]>, + _max_size: usize, + ) -> Option<&'b [u8]> { + unimplemented!() + } + } + + export_mutator!(ExampleMutator); +} + +#[allow(unused_variables)] +/// A custom mutator. +/// [`CustomMutator::handle_error`] will be called in case any method returns an [`Result::Err`]. +pub trait CustomMutator { + /// The error type. All methods must return the same error type. + type Error: Debug; + + /// The method which handles errors. + /// By default, this method will log the error to stderr if the environment variable "`AFL_CUSTOM_MUTATOR_DEBUG`" is set and non-empty. + /// After logging the error, execution will continue on a best-effort basis. + /// + /// This default behaviour can be customized by implementing this method. + fn handle_error(err: Self::Error) { + if std::env::var("AFL_CUSTOM_MUTATOR_DEBUG") + .map(|v| !v.is_empty()) + .unwrap_or(false) + { + eprintln!("Error in custom mutator: {:?}", err) + } + } + + #[cfg(feature = "afl_internals")] + fn init(afl: &'static afl_state, seed: c_uint) -> Result + where + Self: Sized; + + #[cfg(not(feature = "afl_internals"))] + fn init(seed: c_uint) -> Result + where + Self: Sized; + + fn fuzz_count(&mut self, buffer: &[u8]) -> Result { + Ok(1) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, Self::Error>; + + fn queue_new_entry( + &mut self, + filename_new_queue: &CStr, + filename_orig_queue: Option<&CStr>, + ) -> Result<(), Self::Error> { + Ok(()) + } + + fn queue_get(&mut self, filename: &CStr) -> Result { + Ok(true) + } + + fn describe(&mut self, max_description: usize) -> Result, Self::Error> { + Ok(None) + } + + fn introspection(&mut self) -> Result, Self::Error> { + Ok(None) + } +} + +impl RawCustomMutator for M +where + M: CustomMutator, + M::Error: Debug, +{ + #[cfg(feature = "afl_internals")] + fn init(afl: &'static afl_state, seed: c_uint) -> Self + where + Self: Sized, + { + match Self::init(afl, seed) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + panic!("Error in afl_custom_init") + } + } + } + + #[cfg(not(feature = "afl_internals"))] + fn init(seed: c_uint) -> Self + where + Self: Sized, + { + match Self::init(seed) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + panic!("Error in afl_custom_init") + } + } + } + + fn fuzz_count(&mut self, buffer: &[u8]) -> u32 { + match self.fuzz_count(buffer) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + 0 + } + } + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Option<&'b [u8]> { + match self.fuzz(buffer, add_buff, max_size) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + None + } + } + } + + fn queue_new_entry(&mut self, filename_new_queue: &CStr, filename_orig_queue: Option<&CStr>) { + match self.queue_new_entry(filename_new_queue, filename_orig_queue) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + } + } + } + + fn queue_get(&mut self, filename: &CStr) -> bool { + match self.queue_get(filename) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + false + } + } + } + + fn describe(&mut self, max_description: usize) -> Option<&CStr> { + match self.describe(max_description) { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + None + } + } + } + + fn introspection(&mut self) -> Option<&CStr> { + match self.introspection() { + Ok(r) => r, + Err(e) => { + Self::handle_error(e); + None + } + } + } +} diff --git a/custom_mutators/rust/example/Cargo.toml b/custom_mutators/rust/example/Cargo.toml new file mode 100644 index 00000000..0c89b200 --- /dev/null +++ b/custom_mutators/rust/example/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "example" +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] +custom_mutator = { path = "../custom_mutator" } + +[lib] +crate-type = ["cdylib"] \ No newline at end of file diff --git a/custom_mutators/rust/example/src/lib.rs b/custom_mutators/rust/example/src/lib.rs new file mode 100644 index 00000000..4f9345c0 --- /dev/null +++ b/custom_mutators/rust/example/src/lib.rs @@ -0,0 +1,50 @@ +#![allow(unused_variables)] + +use custom_mutator::{export_mutator, CustomMutator}; +use std::os::raw::c_uint; + +struct ExampleMutator; + +impl CustomMutator for ExampleMutator { + type Error = (); + + fn init(seed: c_uint) -> Result { + Ok(Self) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, ()> { + buffer.reverse(); + Ok(Some(buffer)) + } +} + +struct OwnBufferExampleMutator { + own_buffer: Vec, +} + +impl CustomMutator for OwnBufferExampleMutator { + type Error = (); + + fn init(seed: c_uint) -> Result { + Ok(Self { + own_buffer: Vec::new(), + }) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + buffer: &'b mut [u8], + add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, ()> { + self.own_buffer.reverse(); + Ok(Some(self.own_buffer.as_slice())) + } +} + +export_mutator!(ExampleMutator); diff --git a/custom_mutators/rust/example_lain/Cargo.toml b/custom_mutators/rust/example_lain/Cargo.toml new file mode 100644 index 00000000..1f68c7e0 --- /dev/null +++ b/custom_mutators/rust/example_lain/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "example_lain" +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] +custom_mutator = { path = "../custom_mutator" } +lain="0.5" + +[lib] +crate-type = ["cdylib"] \ No newline at end of file diff --git a/custom_mutators/rust/example_lain/rust-toolchain b/custom_mutators/rust/example_lain/rust-toolchain new file mode 100644 index 00000000..07ade694 --- /dev/null +++ b/custom_mutators/rust/example_lain/rust-toolchain @@ -0,0 +1 @@ +nightly \ No newline at end of file diff --git a/custom_mutators/rust/example_lain/src/lib.rs b/custom_mutators/rust/example_lain/src/lib.rs new file mode 100644 index 00000000..3336e861 --- /dev/null +++ b/custom_mutators/rust/example_lain/src/lib.rs @@ -0,0 +1,60 @@ +use custom_mutator::{export_mutator, CustomMutator}; +use lain::{ + mutator::Mutator, + prelude::*, + rand::{rngs::StdRng, SeedableRng}, +}; +use std::os::raw::c_uint; + +#[derive(Debug, Mutatable, NewFuzzed, BinarySerialize)] +struct MyStruct { + field_1: u8, + + #[lain(bits = 3)] + field_2: u8, + + #[lain(bits = 5)] + field_3: u8, + + #[lain(min = 5, max = 10000)] + field_4: u32, + + #[lain(ignore)] + ignored_field: u64, +} + +struct LainMutator { + mutator: Mutator, + buffer: Vec, +} + +impl CustomMutator for LainMutator { + type Error = (); + + fn init(seed: c_uint) -> Result { + Ok(Self { + mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)), + buffer: Vec::new(), + }) + } + + fn fuzz<'b, 's: 'b>( + &'s mut self, + _buffer: &'b mut [u8], + _add_buff: Option<&[u8]>, + max_size: usize, + ) -> Result, ()> { + // we just sample an instance of MyStruct, ignoring the current input + let instance = MyStruct::new_fuzzed(&mut self.mutator, None); + let size = instance.serialized_size(); + if size > max_size { + return Err(()); + } + self.buffer.clear(); + self.buffer.reserve(size); + instance.binary_serialize::<_, BigEndian>(&mut self.buffer); + Ok(Some(self.buffer.as_slice())) + } +} + +export_mutator!(LainMutator); diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index a2c544e3..61d711e4 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -4,6 +4,11 @@ This file describes how you can implement custom mutations to be used in AFL. For now, we support C/C++ library and Python module, collectivelly named as the custom mutator. +There is also experimental support for Rust in `custom_mutators/rust`. +Please refer to that directory for documentation. +Run ```cargo doc -p custom_mutator --open``` in that directory to view the +documentation in your web browser. + Implemented by - C/C++ library (`*.so`): Khaled Yakdan from Code Intelligence () - Python module: Christian Holler from Mozilla () From c219502f0fe654927c3f74f9791f786f0740f344 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 27 Feb 2021 15:52:36 +0100 Subject: [PATCH 04/18] some rust cleanup --- custom_mutators/rust/Cargo.toml | 3 +- custom_mutators/rust/README.md | 6 ++- .../rust/custom_mutator/src/lib.rs | 39 +++++++++---------- custom_mutators/rust/example/Cargo.toml | 6 ++- .../src/{lib.rs => example_mutator.rs} | 7 ++-- custom_mutators/rust/example_lain/Cargo.toml | 4 +- .../src/{lib.rs => lain_mutator.rs} | 3 +- 7 files changed, 35 insertions(+), 33 deletions(-) rename custom_mutators/rust/example/src/{lib.rs => example_mutator.rs} (84%) rename custom_mutators/rust/example_lain/src/{lib.rs => lain_mutator.rs} (94%) diff --git a/custom_mutators/rust/Cargo.toml b/custom_mutators/rust/Cargo.toml index 003bc58a..e36d24b5 100644 --- a/custom_mutators/rust/Cargo.toml +++ b/custom_mutators/rust/Cargo.toml @@ -3,5 +3,6 @@ members = [ "custom_mutator-sys", "custom_mutator", "example", - "example_lain", + # 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 index 119ac790..e2cc38b4 100644 --- a/custom_mutators/rust/README.md +++ b/custom_mutators/rust/README.md @@ -1,9 +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`. +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) can be found in `example_lain`. +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/src/lib.rs b/custom_mutators/rust/custom_mutator/src/lib.rs index 0fb007ab..b82af250 100644 --- a/custom_mutators/rust/custom_mutator/src/lib.rs +++ b/custom_mutators/rust/custom_mutator/src/lib.rs @@ -23,7 +23,7 @@ //! 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, os::raw::c_uint}; +use std::{ffi::CStr, fmt::Debug}; #[cfg(feature = "afl_internals")] #[doc(hidden)] @@ -37,7 +37,7 @@ pub trait RawCustomMutator { where Self: Sized; #[cfg(not(feature = "afl_internals"))] - fn init(seed: c_uint) -> Self + fn init(seed: u32) -> Self where Self: Sized; @@ -87,7 +87,7 @@ pub mod wrappers { convert::TryInto, ffi::{c_void, CStr}, mem::ManuallyDrop, - os::raw::{c_char, c_uint}, + os::raw::c_char, panic::catch_unwind, process::abort, ptr::null, @@ -112,13 +112,13 @@ pub mod wrappers { } #[cfg(feature = "afl_internals")] - fn new(afl: &'static afl_state, seed: c_uint) -> Box { + 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: c_uint) -> Box { + fn new(seed: u32) -> Box { Box::new(Self { mutator: M::init(seed), }) @@ -143,7 +143,7 @@ pub mod wrappers { /// Internal function used in the macro #[cfg(not(feature = "afl_internals"))] - pub fn afl_custom_init_(seed: c_uint) -> *const c_void { + 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), @@ -154,7 +154,7 @@ pub mod wrappers { #[cfg(feature = "afl_internals")] pub fn afl_custom_init_( afl: Option<&'static afl_state>, - seed: c_uint, + seed: u32, ) -> *const c_void { match catch_unwind(|| { let afl = afl.expect("mutator func called with NULL afl"); @@ -328,16 +328,15 @@ pub mod wrappers { /// # #[cfg(feature = "afl_internals")] /// # use custom_mutator::afl_state; /// # use custom_mutator::CustomMutator; -/// # use std::os::raw::c_uint; /// struct MyMutator; /// impl CustomMutator for MyMutator { /// /// ... /// # type Error = (); /// # #[cfg(feature = "afl_internals")] -/// # fn init(_afl_state: &afl_state, _seed: c_uint) -> Result {unimplemented!()} +/// # fn init(_afl_state: &afl_state, _seed: u32) -> Result {unimplemented!()} /// # #[cfg(not(feature = "afl_internals"))] -/// # fn init(_seed: c_uint) -> Result {unimplemented!()} -/// # fn fuzz<'b,'s:'b>(&'s mut self, _buffer: &'b mut [u8], _add_buff: Option<&[u8]>, _max_size: usize) -> Result,()> {unimplemented!()} +/// # 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, Self::Error> {unimplemented!()} /// } /// export_mutator!(MyMutator); /// ``` @@ -350,7 +349,7 @@ macro_rules! export_mutator { afl: ::std::option::Option<&'static $crate::afl_state>, seed: ::std::os::raw::c_uint, ) -> *const ::std::os::raw::c_void { - $crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed) + $crate::wrappers::afl_custom_init_::<$mutator_type>(afl, seed as u32) } #[cfg(not(feature = "afl_internals"))] @@ -359,7 +358,7 @@ macro_rules! export_mutator { _afl: *const ::std::os::raw::c_void, seed: ::std::os::raw::c_uint, ) -> *const ::std::os::raw::c_void { - $crate::wrappers::afl_custom_init_::<$mutator_type>(seed) + $crate::wrappers::afl_custom_init_::<$mutator_type>(seed as u32) } #[no_mangle] @@ -442,8 +441,6 @@ macro_rules! export_mutator { #[cfg(test)] /// this sanity test is supposed to just find out whether an empty mutator being exported by the macro compiles mod sanity_test { - use std::os::raw::c_uint; - #[cfg(feature = "afl_internals")] use super::afl_state; @@ -453,12 +450,12 @@ mod sanity_test { impl RawCustomMutator for ExampleMutator { #[cfg(feature = "afl_internals")] - fn init(_afl: &afl_state, _seed: c_uint) -> Self { + fn init(_afl: &afl_state, _seed: u32) -> Self { unimplemented!() } #[cfg(not(feature = "afl_internals"))] - fn init(_seed: c_uint) -> Self { + fn init(_seed: u32) -> Self { unimplemented!() } @@ -497,12 +494,12 @@ pub trait CustomMutator { } #[cfg(feature = "afl_internals")] - fn init(afl: &'static afl_state, seed: c_uint) -> Result + fn init(afl: &'static afl_state, seed: u32) -> Result where Self: Sized; #[cfg(not(feature = "afl_internals"))] - fn init(seed: c_uint) -> Result + fn init(seed: u32) -> Result where Self: Sized; @@ -544,7 +541,7 @@ where M::Error: Debug, { #[cfg(feature = "afl_internals")] - fn init(afl: &'static afl_state, seed: c_uint) -> Self + fn init(afl: &'static afl_state, seed: u32) -> Self where Self: Sized, { @@ -558,7 +555,7 @@ where } #[cfg(not(feature = "afl_internals"))] - fn init(seed: c_uint) -> Self + fn init(seed: u32) -> Self where Self: Sized, { diff --git a/custom_mutators/rust/example/Cargo.toml b/custom_mutators/rust/example/Cargo.toml index 0c89b200..070d23b1 100644 --- a/custom_mutators/rust/example/Cargo.toml +++ b/custom_mutators/rust/example/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "example" +name = "example_mutator" version = "0.1.0" authors = ["Julius Hohnerlein "] edition = "2018" @@ -9,5 +9,7 @@ edition = "2018" [dependencies] custom_mutator = { path = "../custom_mutator" } -[lib] +[[example]] +name = "example_mutator" +path = "./src/example_mutator.rs" crate-type = ["cdylib"] \ No newline at end of file diff --git a/custom_mutators/rust/example/src/lib.rs b/custom_mutators/rust/example/src/example_mutator.rs similarity index 84% rename from custom_mutators/rust/example/src/lib.rs rename to custom_mutators/rust/example/src/example_mutator.rs index 4f9345c0..9b9d4997 100644 --- a/custom_mutators/rust/example/src/lib.rs +++ b/custom_mutators/rust/example/src/example_mutator.rs @@ -1,14 +1,13 @@ #![allow(unused_variables)] use custom_mutator::{export_mutator, CustomMutator}; -use std::os::raw::c_uint; struct ExampleMutator; impl CustomMutator for ExampleMutator { type Error = (); - fn init(seed: c_uint) -> Result { + fn init(seed: u32) -> Result { Ok(Self) } @@ -17,7 +16,7 @@ impl CustomMutator for ExampleMutator { buffer: &'b mut [u8], add_buff: Option<&[u8]>, max_size: usize, - ) -> Result, ()> { + ) -> Result, Self::Error> { buffer.reverse(); Ok(Some(buffer)) } @@ -30,7 +29,7 @@ struct OwnBufferExampleMutator { impl CustomMutator for OwnBufferExampleMutator { type Error = (); - fn init(seed: c_uint) -> Result { + fn init(seed: u32) -> Result { Ok(Self { own_buffer: Vec::new(), }) diff --git a/custom_mutators/rust/example_lain/Cargo.toml b/custom_mutators/rust/example_lain/Cargo.toml index 1f68c7e0..29d606a4 100644 --- a/custom_mutators/rust/example_lain/Cargo.toml +++ b/custom_mutators/rust/example_lain/Cargo.toml @@ -10,5 +10,7 @@ edition = "2018" custom_mutator = { path = "../custom_mutator" } lain="0.5" -[lib] +[[example]] +name = "example_lain" +path = "./src/lain_mutator.rs" crate-type = ["cdylib"] \ No newline at end of file diff --git a/custom_mutators/rust/example_lain/src/lib.rs b/custom_mutators/rust/example_lain/src/lain_mutator.rs similarity index 94% rename from custom_mutators/rust/example_lain/src/lib.rs rename to custom_mutators/rust/example_lain/src/lain_mutator.rs index 3336e861..22e5fe73 100644 --- a/custom_mutators/rust/example_lain/src/lib.rs +++ b/custom_mutators/rust/example_lain/src/lain_mutator.rs @@ -4,7 +4,6 @@ use lain::{ prelude::*, rand::{rngs::StdRng, SeedableRng}, }; -use std::os::raw::c_uint; #[derive(Debug, Mutatable, NewFuzzed, BinarySerialize)] struct MyStruct { @@ -31,7 +30,7 @@ struct LainMutator { impl CustomMutator for LainMutator { type Error = (); - fn init(seed: c_uint) -> Result { + fn init(seed: u32) -> Result { Ok(Self { mutator: Mutator::new(StdRng::seed_from_u64(seed as u64)), buffer: Vec::new(), From af628b16d1b601f75e46f4b0475a055088019263 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 27 Feb 2021 16:29:29 +0100 Subject: [PATCH 05/18] added rust binding reference --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index c4347baf..e434e7d6 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -118,6 +118,7 @@ sending a mail to . mutation reproduction on crashing inputs - new env. var. AFL_NO_COLOR (or AFL_NO_COLOUR) to suppress colored console output (when configured with USE_COLOR and not ALWAYS_COLORED) + - added Rust bindings for custom mutators (thanks @julihoh) - instrumentation - We received an enhanced gcc_plugin module from AdaCore, thank you very much!! From 8e051fd075e2854930bf828c5d23fe6dc648e1ed Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 27 Feb 2021 16:37:00 +0100 Subject: [PATCH 06/18] fixed rust bindings placement --- docs/Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index e434e7d6..192d6ee2 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -42,6 +42,7 @@ sending a mail to . - switched to an even faster RNG - added hghwng's patch for faster trace map analysis - printing suggestions for mistyped `AFL_` env variables + - added Rust bindings for custom mutators (thanks @julihoh) - afl-cc - allow instrumenting LLVMFuzzerTestOneInput - fixed endless loop for allow/blocklist lines starting with a @@ -118,7 +119,6 @@ sending a mail to . mutation reproduction on crashing inputs - new env. var. AFL_NO_COLOR (or AFL_NO_COLOUR) to suppress colored console output (when configured with USE_COLOR and not ALWAYS_COLORED) - - added Rust bindings for custom mutators (thanks @julihoh) - instrumentation - We received an enhanced gcc_plugin module from AdaCore, thank you very much!! From 2ad495ad0a9e4721cf20354af4c4f7222d6c239e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 27 Feb 2021 17:19:00 +0100 Subject: [PATCH 07/18] reworked unicornafl documentation --- unicorn_mode/README.md | 55 ++++++++++++++++++++----------- unicorn_mode/samples/c/COMPILE.md | 2 +- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/unicorn_mode/README.md b/unicorn_mode/README.md index f6bd4d12..b3df44fa 100644 --- a/unicorn_mode/README.md +++ b/unicorn_mode/README.md @@ -8,19 +8,19 @@ The CompareCoverage and NeverZero counters features are by Andrea Fioraldi Date: Sat, 27 Feb 2021 17:58:25 +0100 Subject: [PATCH 08/18] disable the generation of core files in DragonFly BSD --- afl-system-config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/afl-system-config b/afl-system-config index d5e5ceae..ba8ad3a3 100755 --- a/afl-system-config +++ b/afl-system-config @@ -60,8 +60,8 @@ if [ "$PLATFORM" = "OpenBSD" ] ; then DONE=1 fi if [ "$PLATFORM" = "DragonFly" ] ; then - echo - echo 'System security features cannot be disabled on DragonFly.' + /sbin/sysctl kern.corefile=/dev/null + echo Settings applied. DONE=1 fi if [ "$PLATFORM" = "NetBSD" ] ; then From 79f1a44a01775ab28ad39f21f09e084fcd773c98 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 27 Feb 2021 18:14:50 +0100 Subject: [PATCH 09/18] fix qasan search path --- qemu_mode/qemuafl | 2 +- src/afl-common.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl index 213f3b27..e36a30eb 160000 --- a/qemu_mode/qemuafl +++ b/qemu_mode/qemuafl @@ -1 +1 @@ -Subproject commit 213f3b27dd099ef352181c48cd75c0f20a73e3f0 +Subproject commit e36a30ebca57ca433a5d6e20b1a32975aabb761b diff --git a/src/afl-common.c b/src/afl-common.c index 078ffb9d..c341bb97 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -372,11 +372,11 @@ u8 *get_libqasan_path(u8 *own_loc) { } - if (!access(BIN_PATH "/libqasan.so", X_OK)) { + if (!access(AFL_PATH "/libqasan.so", X_OK)) { if (cp) { ck_free(cp); } - return ck_strdup(BIN_PATH "/libqasan.so"); + return ck_strdup(AFL_PATH "/libqasan.so"); } From 36846836ed5abe99c6f4a32bc52848d6d328328a Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Sat, 27 Feb 2021 18:26:57 +0100 Subject: [PATCH 10/18] libqasan: read and write hooks --- qemu_mode/libqasan/hooks.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c index 405dddae..9adef8cd 100644 --- a/qemu_mode/libqasan/hooks.c +++ b/qemu_mode/libqasan/hooks.c @@ -26,6 +26,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "libqasan.h" #include "map_macro.h" +ssize_t (*__lq_libc_write)(int, const void *, size_t); +ssize_t (*__lq_libc_read)(int, void *, size_t); char *(*__lq_libc_fgets)(char *, int, FILE *); int (*__lq_libc_atoi)(const char *); long (*__lq_libc_atol)(const char *); @@ -35,6 +37,8 @@ void __libqasan_init_hooks(void) { __libqasan_init_malloc(); + __lq_libc_write = ASSERT_DLSYM(write); + __lq_libc_read = ASSERT_DLSYM(read); __lq_libc_fgets = ASSERT_DLSYM(fgets); __lq_libc_atoi = ASSERT_DLSYM(atoi); __lq_libc_atol = ASSERT_DLSYM(atol); @@ -42,6 +46,30 @@ void __libqasan_init_hooks(void) { } +ssize_t write(int fd, const void *buf, size_t count) { + + void *rtv = __builtin_return_address(0); + + QASAN_DEBUG("%14p: write(%d, %p, %ld)\n", rtv, fd, buf, count); + ssize_t r = __lq_libc_write(fd, buf, count); + QASAN_DEBUG("\t\t = %p\n", r); + + return r; + +} + +ssize_t read(int fd, void *buf, size_t count) { + + void *rtv = __builtin_return_address(0); + + QASAN_DEBUG("%14p: read(%d, %p, %ld)\n", rtv, fd, buf, count); + ssize_t r = __lq_libc_read(fd, buf, count); + QASAN_DEBUG("\t\t = %p\n", r); + + return r; + +} + #ifdef __ANDROID__ size_t malloc_usable_size(const void *ptr) { From 1cad645400d9d96d2a29cebade704f5b0cc69c8b Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Sat, 27 Feb 2021 18:30:04 +0100 Subject: [PATCH 11/18] fix %ld in hooks.c --- qemu_mode/libqasan/hooks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c index 9adef8cd..d7563a66 100644 --- a/qemu_mode/libqasan/hooks.c +++ b/qemu_mode/libqasan/hooks.c @@ -52,7 +52,7 @@ ssize_t write(int fd, const void *buf, size_t count) { QASAN_DEBUG("%14p: write(%d, %p, %ld)\n", rtv, fd, buf, count); ssize_t r = __lq_libc_write(fd, buf, count); - QASAN_DEBUG("\t\t = %p\n", r); + QASAN_DEBUG("\t\t = %ld\n", r); return r; @@ -64,7 +64,7 @@ ssize_t read(int fd, void *buf, size_t count) { QASAN_DEBUG("%14p: read(%d, %p, %ld)\n", rtv, fd, buf, count); ssize_t r = __lq_libc_read(fd, buf, count); - QASAN_DEBUG("\t\t = %p\n", r); + QASAN_DEBUG("\t\t = %ld\n", r); return r; From 6036cf8437853f0bd2d94bf8d959da58c80b889f Mon Sep 17 00:00:00 2001 From: heiko Date: Sun, 28 Feb 2021 00:24:29 +0100 Subject: [PATCH 12/18] BSD: how to avoid core dumps --- afl-system-config | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/afl-system-config b/afl-system-config index ba8ad3a3..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.; \ } From f81ef4abf41184a24d24828841c82b98b9216ddc Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 28 Feb 2021 00:12:21 +0100 Subject: [PATCH 13/18] fix afl-common compile --- src/afl-common.c | 4 ++++ utils/afl_network_proxy/GNUmakefile | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/afl-common.c b/src/afl-common.c index c341bb97..fa4aec7f 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -47,6 +47,10 @@ u8 be_quiet = 0; u8 *doc_path = ""; u8 last_intr = 0; +#ifndef AFL_PATH + #define AFL_PATH "/usr/local/lib/afl/" +#endif + void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) { u32 i = 0; diff --git a/utils/afl_network_proxy/GNUmakefile b/utils/afl_network_proxy/GNUmakefile index 25a3df82..0b55dc2c 100644 --- a/utils/afl_network_proxy/GNUmakefile +++ b/utils/afl_network_proxy/GNUmakefile @@ -1,5 +1,6 @@ PREFIX ?= /usr/local BIN_PATH = $(PREFIX)/bin +HELPER_PATH = $(PREFIX)/lib/afl DOC_PATH = $(PREFIX)/share/doc/afl PROGRAMS = afl-network-client afl-network-server @@ -31,7 +32,7 @@ afl-network-client: afl-network-client.c $(CC) $(CFLAGS) -I../../include -o afl-network-client afl-network-client.c $(LDFLAGS) afl-network-server: afl-network-server.c - $(CC) $(CFLAGS) -I../../include -o afl-network-server afl-network-server.c ../../src/afl-forkserver.c ../../src/afl-sharedmem.c ../../src/afl-common.c -DBIN_PATH=\"$(BIN_PATH)\" $(LDFLAGS) + $(CC) $(CFLAGS) -I../../include -o afl-network-server afl-network-server.c ../../src/afl-forkserver.c ../../src/afl-sharedmem.c ../../src/afl-common.c -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" $(LDFLAGS) clean: rm -f $(PROGRAMS) *~ core From 5cf0655071a83b1c87490be8399fe2365f087223 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 28 Feb 2021 10:01:35 +0100 Subject: [PATCH 14/18] metrics --- docs/docs.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/docs.md b/docs/docs.md index 0f98bd54..ed6ec85e 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -63,6 +63,31 @@ The project does not require writing new documentation or tutorials beside the cheat sheet. The technical information for the cheat sheet will be provided by us. +## Metrics + +afl++ is a the highest performant fuzzer publicly available - but is also the +most feature rich and complex. With the publicity of afl++' success and +deployment in Google projects internally and externally and availability as +a package on most Linux distributions we see more and more issues being +created and help requests on our Discord channel that would not be +necessary if people would have read through all our documentation - which +is unrealistic. + +We expect the the new documenation after this project to be cleaner, easier +accessible and lighter to digest by our users, resulting in much less +help requests. On the other hand the amount of users using afl++ should +increase as well as it will be more accessible which would also increase +questions again - but overall resulting in a reduction of help requests. + +In numbers: we currently have per week on average 5 issues on Github, +10 questions on discord and 1 on mailing lists that would not be necessary +with perfect documentation and perfect people. + +We would consider this project a success if afterwards we only have +2 issues on Github and 3 questions on discord anymore that would be answered +by reading the documentation. The mailing list is usually used by the most +novice users and we don't expect any less questions there. + ## Project Budget We have zero experience with technical writers, so this is very hard for us @@ -70,13 +95,19 @@ to calculate. We expect it to be a lot of work though because of the amount of documentation we have that needs to be restructured and partially rewritten (44 documents with 13k total lines of content). +We assume the daily rate of a very good and experienced technical writer in +times of a pandemic to be ~500$ (according to web research), and calculate +the overall amout of work to be around 20 days for everything incl. the +graphics (but again - this is basically just guessing). + Technical Writer 10000$ Volunteer stipends 0$ (waved) T-Shirts for the top 10 contributors and helpers to this documentation project: 10 afl++ logo t-shirts 20$ each 200$ 10 shipping cost of t-shirts 10$ each 100$ - + Total: 10.300$ +(in the submission form 10.280$ was entered) ## Additional Information From e389eb9842532b4f6cdb40733f374f1cb887fdd0 Mon Sep 17 00:00:00 2001 From: "R. Elliott Childre" Date: Sun, 28 Feb 2021 15:08:59 -0500 Subject: [PATCH 15/18] Fix printf specifiers of (s)size_t in QAsan hooks * size_t specifier is %zu or %zx * ssize_t specifier is %zd Helpful for cross compiling --- qemu_mode/libqasan/hooks.c | 62 +++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/qemu_mode/libqasan/hooks.c b/qemu_mode/libqasan/hooks.c index d7563a66..9c406c74 100644 --- a/qemu_mode/libqasan/hooks.c +++ b/qemu_mode/libqasan/hooks.c @@ -50,9 +50,9 @@ ssize_t write(int fd, const void *buf, size_t count) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: write(%d, %p, %ld)\n", rtv, fd, buf, count); + QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count); ssize_t r = __lq_libc_write(fd, buf, count); - QASAN_DEBUG("\t\t = %ld\n", r); + QASAN_DEBUG("\t\t = %zd\n", r); return r; @@ -62,9 +62,9 @@ ssize_t read(int fd, void *buf, size_t count) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: read(%d, %p, %ld)\n", rtv, fd, buf, count); + QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count); ssize_t r = __lq_libc_read(fd, buf, count); - QASAN_DEBUG("\t\t = %ld\n", r); + QASAN_DEBUG("\t\t = %zd\n", r); return r; @@ -82,7 +82,7 @@ size_t malloc_usable_size(void *ptr) { QASAN_DEBUG("%14p: malloc_usable_size(%p)\n", rtv, ptr); size_t r = __libqasan_malloc_usable_size((void *)ptr); - QASAN_DEBUG("\t\t = %ld\n", r); + QASAN_DEBUG("\t\t = %zu\n", r); return r; @@ -92,7 +92,7 @@ void *malloc(size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: malloc(%ld)\n", rtv, size); + QASAN_DEBUG("%14p: malloc(%zu)\n", rtv, size); void *r = __libqasan_malloc(size); QASAN_DEBUG("\t\t = %p\n", r); @@ -104,7 +104,7 @@ void *calloc(size_t nmemb, size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: calloc(%ld, %ld)\n", rtv, nmemb, size); + QASAN_DEBUG("%14p: calloc(%zu, %zu)\n", rtv, nmemb, size); void *r = __libqasan_calloc(nmemb, size); QASAN_DEBUG("\t\t = %p\n", r); @@ -116,7 +116,7 @@ void *realloc(void *ptr, size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: realloc(%p, %ld)\n", rtv, ptr, size); + QASAN_DEBUG("%14p: realloc(%p, %zu)\n", rtv, ptr, size); void *r = __libqasan_realloc(ptr, size); QASAN_DEBUG("\t\t = %p\n", r); @@ -128,7 +128,7 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: posix_memalign(%p, %ld, %ld)\n", rtv, memptr, alignment, + QASAN_DEBUG("%14p: posix_memalign(%p, %zu, %zu)\n", rtv, memptr, alignment, size); int r = __libqasan_posix_memalign(memptr, alignment, size); QASAN_DEBUG("\t\t = %d [*memptr = %p]\n", r, *memptr); @@ -141,7 +141,7 @@ void *memalign(size_t alignment, size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memalign(%ld, %ld)\n", rtv, alignment, size); + QASAN_DEBUG("%14p: memalign(%zu, %zu)\n", rtv, alignment, size); void *r = __libqasan_memalign(alignment, size); QASAN_DEBUG("\t\t = %p\n", r); @@ -153,7 +153,7 @@ void *aligned_alloc(size_t alignment, size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: aligned_alloc(%ld, %ld)\n", rtv, alignment, size); + QASAN_DEBUG("%14p: aligned_alloc(%zu, %zu)\n", rtv, alignment, size); void *r = __libqasan_aligned_alloc(alignment, size); QASAN_DEBUG("\t\t = %p\n", r); @@ -165,7 +165,7 @@ void *valloc(size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: valloc(%ld)\n", rtv, size); + QASAN_DEBUG("%14p: valloc(%zu)\n", rtv, size); void *r = __libqasan_memalign(sysconf(_SC_PAGESIZE), size); QASAN_DEBUG("\t\t = %p\n", r); @@ -177,7 +177,7 @@ void *pvalloc(size_t size) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: pvalloc(%ld)\n", rtv, size); + QASAN_DEBUG("%14p: pvalloc(%zu)\n", rtv, size); size_t page_size = sysconf(_SC_PAGESIZE); size = (size & (page_size - 1)) + page_size; void *r = __libqasan_memalign(page_size, size); @@ -216,7 +216,7 @@ int memcmp(const void *s1, const void *s2, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memcmp(%p, %p, %ld)\n", rtv, s1, s2, n); + QASAN_DEBUG("%14p: memcmp(%p, %p, %zu)\n", rtv, s1, s2, n); QASAN_LOAD(s1, n); QASAN_LOAD(s2, n); int r = __libqasan_memcmp(s1, s2, n); @@ -230,7 +230,7 @@ void *memcpy(void *dest, const void *src, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memcpy(%p, %p, %ld)\n", rtv, dest, src, n); + QASAN_DEBUG("%14p: memcpy(%p, %p, %zu)\n", rtv, dest, src, n); QASAN_LOAD(src, n); QASAN_STORE(dest, n); void *r = __libqasan_memcpy(dest, src, n); @@ -244,7 +244,7 @@ void *mempcpy(void *dest, const void *src, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: mempcpy(%p, %p, %ld)\n", rtv, dest, src, n); + QASAN_DEBUG("%14p: mempcpy(%p, %p, %zu)\n", rtv, dest, src, n); QASAN_LOAD(src, n); QASAN_STORE(dest, n); void *r = (uint8_t *)__libqasan_memcpy(dest, src, n) + n; @@ -258,7 +258,7 @@ void *memmove(void *dest, const void *src, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memmove(%p, %p, %ld)\n", rtv, dest, src, n); + QASAN_DEBUG("%14p: memmove(%p, %p, %zu)\n", rtv, dest, src, n); QASAN_LOAD(src, n); QASAN_STORE(dest, n); void *r = __libqasan_memmove(dest, src, n); @@ -272,7 +272,7 @@ void *memset(void *s, int c, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memset(%p, %d, %ld)\n", rtv, s, c, n); + QASAN_DEBUG("%14p: memset(%p, %d, %zu)\n", rtv, s, c, n); QASAN_STORE(s, n); void *r = __libqasan_memset(s, c, n); QASAN_DEBUG("\t\t = %p\n", r); @@ -285,7 +285,7 @@ void *memchr(const void *s, int c, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memchr(%p, %d, %ld)\n", rtv, s, c, n); + QASAN_DEBUG("%14p: memchr(%p, %d, %zu)\n", rtv, s, c, n); void *r = __libqasan_memchr(s, c, n); if (r == NULL) QASAN_LOAD(s, n); @@ -301,7 +301,7 @@ void *memrchr(const void *s, int c, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memrchr(%p, %d, %ld)\n", rtv, s, c, n); + QASAN_DEBUG("%14p: memrchr(%p, %d, %zu)\n", rtv, s, c, n); QASAN_LOAD(s, n); void *r = __libqasan_memrchr(s, c, n); QASAN_DEBUG("\t\t = %p\n", r); @@ -315,7 +315,7 @@ void *memmem(const void *haystack, size_t haystacklen, const void *needle, void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: memmem(%p, %ld, %p, %ld)\n", rtv, haystack, haystacklen, + QASAN_DEBUG("%14p: memmem(%p, %zu, %p, %zu)\n", rtv, haystack, haystacklen, needle, needlelen); QASAN_LOAD(haystack, haystacklen); QASAN_LOAD(needle, needlelen); @@ -331,7 +331,7 @@ void bzero(void *s, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: bzero(%p, %ld)\n", rtv, s, n); + QASAN_DEBUG("%14p: bzero(%p, %zu)\n", rtv, s, n); QASAN_STORE(s, n); __libqasan_memset(s, 0, n); @@ -343,7 +343,7 @@ void explicit_bzero(void *s, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: bzero(%p, %ld)\n", rtv, s, n); + QASAN_DEBUG("%14p: bzero(%p, %zu)\n", rtv, s, n); QASAN_STORE(s, n); __libqasan_memset(s, 0, n); @@ -353,7 +353,7 @@ int bcmp(const void *s1, const void *s2, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: bcmp(%p, %p, %ld)\n", rtv, s1, s2, n); + QASAN_DEBUG("%14p: bcmp(%p, %p, %zu)\n", rtv, s1, s2, n); QASAN_LOAD(s1, n); QASAN_LOAD(s2, n); int r = __libqasan_bcmp(s1, s2, n); @@ -411,7 +411,7 @@ int strncasecmp(const char *s1, const char *s2, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: strncasecmp(%p, %p, %ld)\n", rtv, s1, s2, n); + QASAN_DEBUG("%14p: strncasecmp(%p, %p, %zu)\n", rtv, s1, s2, n); size_t l1 = __libqasan_strnlen(s1, n); QASAN_LOAD(s1, l1); size_t l2 = __libqasan_strnlen(s2, n); @@ -461,7 +461,7 @@ int strncmp(const char *s1, const char *s2, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: strncmp(%p, %p, %ld)\n", rtv, s1, s2, n); + QASAN_DEBUG("%14p: strncmp(%p, %p, %zu)\n", rtv, s1, s2, n); size_t l1 = __libqasan_strnlen(s1, n); QASAN_LOAD(s1, l1); size_t l2 = __libqasan_strnlen(s2, n); @@ -492,7 +492,7 @@ char *strncpy(char *dest, const char *src, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: strncpy(%p, %p, %ld)\n", rtv, dest, src, n); + QASAN_DEBUG("%14p: strncpy(%p, %p, %zu)\n", rtv, dest, src, n); size_t l = __libqasan_strnlen(src, n); QASAN_STORE(dest, n); void *r; @@ -551,7 +551,7 @@ size_t strlen(const char *s) { QASAN_DEBUG("%14p: strlen(%p)\n", rtv, s); size_t r = __libqasan_strlen(s); QASAN_LOAD(s, r + 1); - QASAN_DEBUG("\t\t = %ld\n", r); + QASAN_DEBUG("\t\t = %zu\n", r); return r; @@ -561,10 +561,10 @@ size_t strnlen(const char *s, size_t n) { void *rtv = __builtin_return_address(0); - QASAN_DEBUG("%14p: strnlen(%p, %ld)\n", rtv, s, n); + QASAN_DEBUG("%14p: strnlen(%p, %zu)\n", rtv, s, n); size_t r = __libqasan_strnlen(s, n); QASAN_LOAD(s, r); - QASAN_DEBUG("\t\t = %ld\n", r); + QASAN_DEBUG("\t\t = %zu\n", r); return r; @@ -651,7 +651,7 @@ size_t wcslen(const wchar_t *s) { QASAN_DEBUG("%14p: wcslen(%p)\n", rtv, s); size_t r = __libqasan_wcslen(s); QASAN_LOAD(s, sizeof(wchar_t) * (r + 1)); - QASAN_DEBUG("\t\t = %ld\n", r); + QASAN_DEBUG("\t\t = %zu\n", r); return r; From 07884e00549b247d59c6289e58808aae401eeb79 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 09:37:07 +0100 Subject: [PATCH 16/18] feodora qemu lib fix --- qemu_mode/build_qemu_support.sh | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 50e5d4e8..815e77d6 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -374,10 +374,20 @@ if [ "$ORIG_CROSS" = "" ]; then fi fi -if ! command -v "$CROSS" > /dev/null -then +if ! command -v "$CROSS" > /dev/null ; then + if [ "$CPU_TARGET" = "$(uname -m)" ] ; then + echo "[+] Building afl++ qemu support libraries with CC=$CC" + echo "[+] Building libcompcov ..." + make -C libcompcov && echo "[+] libcompcov ready" + echo "[+] Building unsigaction ..." + make -C unsigaction && echo "[+] unsigaction ready" + echo "[+] Building libqasan ..." + make -C libqasan && echo "[+] unsigaction ready" + else echo "[!] Cross compiler $CROSS could not be found, cannot compile libcompcov libqasan and unsigaction" + fi else + echo "[+] Building afl++ qemu support libraries with CC=$CROSS" echo "[+] Building libcompcov ..." make -C libcompcov CC=$CROSS && echo "[+] libcompcov ready" echo "[+] Building unsigaction ..." From 0c38850f955a608529bdd02cc39dc68713ef8528 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 09:43:35 +0100 Subject: [PATCH 17/18] 3.10c release --- README.md | 10 +++++----- docs/Changelog.md | 14 +++++++------- include/config.h | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 119426f6..800c2121 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ Logo - 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/docs/Changelog.md b/docs/Changelog.md index 192d6ee2..f3e15b6a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,7 +9,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++3.01a (dev) +### Version ++3.10c (release) - Mac OS ARM64 support - Android support fixed and updated by Joey Jiaojg - thanks! - New selective instrumentation option with __AFL_COVERAGE_* commands @@ -49,10 +49,10 @@ sending a mail to . comment (thanks to Zherya for reporting) - cmplog/redqueen now also tracks floating point, _ExtInt() + 128bit - cmplog/redqueen can now process basic libc++ and libstdc++ - std::string comparisons (though no position or length type variants) - - added support for __afl_coverage_interesting() for LTO and - and our own PCGUARD (llvm 10.0.1+), read more about this function - and selective coverage in instrumentation/README.instrument_list.md + std::string comparisons (no position or length type variants) + - added support for __afl_coverage_interesting() for LTO and our + own PCGUARD (llvm 10.0.1+), read more about this function and + selective coverage in instrumentation/README.instrument_list.md - added AFL_LLVM_INSTRUMENT option NATIVE for native clang pc-guard support (less performant than our own), GCC for old afl-gcc and CLANG for old afl-clang @@ -68,12 +68,12 @@ sending a mail to . - unicornafl - Substantial speed gains in python bindings for certain use cases - Improved rust bindings - - Added a new example harness to compare python, c, and rust bindings + - Added a new example harness to compare python, c and rust bindings - afl-cmin and afl-showmap now support the -f option - afl_plot now also generates a graph on the discovered edges - changed default: no memory limit for afl-cmin and afl-cmin.bash - warn on any _AFL and __AFL env vars. - - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars. + - set AFL_IGNORE_UNKNOWN_ENVS to not warn on unknown AFL_... env vars - added dummy Makefile to instrumentation/ - Updated utils/afl_frida to be 5% faster, 7% on x86_x64 - Added `AFL_KILL_SIGNAL` env variable (thanks @v-p-b) diff --git a/include/config.h b/include/config.h index b0b1f7b9..c583f23b 100644 --- a/include/config.h +++ b/include/config.h @@ -25,8 +25,8 @@ /* Version string: */ -// c = release, d = volatile github dev, e = experimental branch -#define VERSION "++3.01a" +// c = release, a = volatile github dev, e = experimental branch +#define VERSION "++3.10c" /****************************************************** * * From 4619a1395b9a414e5e11148d79fde3a7fa348e87 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Mar 2021 09:57:57 +0100 Subject: [PATCH 18/18] ensure proper aligning for skim patch --- instrumentation/afl-compiler-rt.o.c | 8 ++++++-- instrumentation/afl-llvm-lto-instrumentation.so.cc | 4 +--- src/afl-common.c | 2 +- src/afl-forkserver.c | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index e4aeadfa..ecb94cab 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -244,8 +244,12 @@ static void __afl_map_shm(void) { if (__afl_final_loc) { - if (__afl_final_loc % 32) - __afl_final_loc = (((__afl_final_loc + 31) >> 5) << 5); + if (__afl_final_loc % 64) { + + __afl_final_loc = (((__afl_final_loc + 63) >> 6) << 6); + + } + __afl_map_size = __afl_final_loc; if (__afl_final_loc > MAP_SIZE) { diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index f5c24e41..137bae2c 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -924,9 +924,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) { - uint32_t write_loc = afl_global_id; - - if (afl_global_id % 32) write_loc = (((afl_global_id + 32) >> 4) << 4); + uint32_t write_loc = (((afl_global_id + 63) >> 6) << 6); GlobalVariable *AFLFinalLoc = new GlobalVariable( M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc"); diff --git a/src/afl-common.c b/src/afl-common.c index fa4aec7f..a306fe5e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -1135,7 +1135,7 @@ u32 get_map_size(void) { } - if (map_size % 32) { map_size = (((map_size >> 5) + 1) << 5); } + if (map_size % 64) { map_size = (((map_size >> 6) + 1) << 6); } } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9ee59822..fd5edc98 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -656,11 +656,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } - if (unlikely(tmp_map_size % 32)) { + if (unlikely(tmp_map_size % 64)) { // should not happen WARNF("Target reported non-aligned map size of %u", tmp_map_size); - tmp_map_size = (((tmp_map_size + 31) >> 5) << 5); + tmp_map_size = (((tmp_map_size + 63) >> 6) << 6); }