Update fuzzbench and fuzzbench_qemu, delete fuzzbench_gsoc

This commit is contained in:
Andrea Fioraldi 2021-12-21 11:26:04 +01:00
parent 2aa0ca5ef1
commit 0cce1e2b91
14 changed files with 107 additions and 568 deletions

View File

@ -1,4 +1,4 @@
//! A singlethreade libfuzzer-like fuzzer that can auto-restart.
//! A singlethreaded libfuzzer-like fuzzer that can auto-restart.
use clap::{App, Arg};
use core::{cell::RefCell, time::Duration};
@ -28,14 +28,13 @@ use libafl::{
events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or,
feedbacks::{AflMapFeedback, CrashFeedback, MapFeedbackState, TimeFeedback},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
mutators::{
scheduled::{havoc_mutations, StdScheduledMutator},
token_mutations::I2SRandReplace,
tokens_mutations, Tokens,
scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations,
StdMOptMutator, StdScheduledMutator, Tokens,
},
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
stages::{
@ -176,7 +175,7 @@ fn fuzz(
#[cfg(unix)]
let file_null = File::open("/dev/null")?;
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
// 'While the monitor are state, they are usually used in the broker - which is likely never restarted
let monitor = SimpleMonitor::new(|s| {
#[cfg(unix)]
writeln!(&mut stdout_cpy, "{}", s).unwrap();
@ -221,7 +220,7 @@ fn fuzz(
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
AflMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
@ -255,13 +254,17 @@ fn fuzz(
}
let calibration = CalibrationStage::new(&mut state, &edges_observer);
let mutator = StdScheduledMutator::new(havoc_mutations());
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator
let mutator = StdMOptMutator::new(&mut state, havoc_mutations().merge(tokens_mutations()), 5)?;
let power = PowerMutationalStage::new(mutator, PowerSchedule::FAST, &edges_observer);
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
// A minimization+queue policy to get testcasess from the corpus
//let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new());
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
// A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
@ -301,15 +304,8 @@ fn fuzz(
timeout * 10,
));
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a basic mutator
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let mutational = StdMutationalStage::new(mutator);
// The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, mutational, power);
let mut stages = tuple_list!(calibration, tracing, i2s, power);
// Read tokens
if let Some(tokenfile) = tokenfile {
@ -336,7 +332,6 @@ fn fuzz(
dup2(null_fd, io::stdout().as_raw_fd())?;
dup2(null_fd, io::stderr().as_raw_fd())?;
}
// reopen file to make sure we're at the end
log.replace(
OpenOptions::new()
@ -350,3 +345,4 @@ fn fuzz(
// Never reached
Ok(())
}

View File

@ -1,2 +0,0 @@
libpng-*
fuzzer

View File

@ -1,32 +0,0 @@
[package]
name = "fuzzbench"
version = "0.7.0"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
edition = "2021"
[features]
default = ["std"]
std = []
[profile.release]
lto = true
codegen-units = 1
opt-level = 3
debug = true
[build-dependencies]
cc = { version = "1.0", features = ["parallel"] }
which = { version = "4.0.2" }
num_cpus = "1.0"
[dependencies]
libafl = { path = "../../libafl/" }
libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "sancov_cmplog", "libfuzzer"] }
# TODO Include it only when building cc
libafl_cc = { path = "../../libafl_cc/" }
clap = { version = "3.0.0-rc.4", features = ["default"] }
nix = "0.23.0"
[lib]
name = "fuzzbench"
crate-type = ["staticlib"]

View File

@ -1,48 +0,0 @@
FUZZER_NAME="fuzzer"
PROJECT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
PHONY: all
all: fuzzer
target/release/libafl_cxx: src/* src/bin/*
# Build the libpng libfuzzer library
cargo build --release
target/release/libafl_cc: target/release/libafl_cxx
fuzz.o: fuzz.c target/release/libafl_cc
target/release/libafl_cc -O3 -c $^ -o $@
fuzzer: target/release/libafl_cxx fuzz.o
# Build the fuzzer compiler
cargo build --release
# Build the harness
target/release/libafl_cxx \
fuzz.o \
-o $(FUZZER_NAME) \
-lm -lz
clean:
rm ./$(FUZZER_NAME) || true
rm fuzz.o || true
run: all
./$(FUZZER_NAME)
short_test: all
rm -rf libafl_unix_shmem_server || true
mkdir in || true
echo a > in/a
# Allow sigterm as exit code
(timeout 11s ./$(FUZZER_NAME) out in || [ $$? -eq 124 ])
rm -rf out || true
rm -rf in || true
test: all
mkdir in || true
echo a > in/a
(timeout 60s ./$(FUZZER_NAME) out in || [ $$? -eq 124 ])
rm -rf out || true
rm -rf in || true

View File

@ -1,17 +0,0 @@
# Fuzzbench Harness
This folder contains an example fuzzer tailored for fuzzbench.
It uses the best possible setting, with the exception of a SimpleRestartingEventManager instead of an LlmpEventManager - since fuzzbench is single threaded.
Real fuzz campaigns should consider using multithreaded LlmpEventManager, see the other examples.
## Build
To build this example, run `cargo build --release`.
This will build the fuzzer compilers (`libafl_cc` and `libafl_cpp`) with `src/lib.rs` as fuzzer.
The fuzzer uses the libfuzzer compatibility layer and the SanitizerCoverage runtime functions for coverage feedback.
These can then be used to build libfuzzer harnesses in the software project of your choice.
Finally, just run the resulting binary with `out_dir`, `in_dir`.
In any real-world scenario, you should use `taskset` to pin each client to an empty CPU core, the lib does not pick an empty core automatically (yet).

View File

@ -1,15 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd)
abort();
}
/*
int main() {
char buf [10] = {0};
LLVMFuzzerTestOneInput(buf, 10);
}*/

View File

@ -1,36 +0,0 @@
use libafl_cc::{ClangWrapper, CompilerWrapper, LLVMPasses};
use std::env;
pub fn main() {
let args: Vec<String> = env::args().collect();
if args.len() > 1 {
let mut dir = env::current_exe().unwrap();
let wrapper_name = dir.file_name().unwrap().to_str().unwrap();
let is_cpp = match wrapper_name[wrapper_name.len()-2..].to_lowercase().as_str() {
"cc" => false,
"++" | "pp" | "xx" => true,
_ => panic!("Could not figure out if c or c++ warpper was called. Expected {:?} to end with c or cxx", dir),
};
dir.pop();
let mut cc = ClangWrapper::new();
if let Some(code) = cc
.cpp(is_cpp)
// silence the compiler wrapper output, needed for some configure scripts.
.silence(true)
.from_args(&args)
.expect("Failed to parse the command line")
.link_staticlib(&dir, "fuzzbench")
.add_arg("-fsanitize-coverage=trace-pc-guard,trace-cmp")
.add_pass(LLVMPasses::CmpLogRtn)
.run()
.expect("Failed to run the wrapped compiler")
{
std::process::exit(code);
}
} else {
panic!("LibAFL CC: No Arguments given");
}
}

View File

@ -1,5 +0,0 @@
pub mod libafl_cc;
fn main() {
libafl_cc::main()
}

View File

@ -1,350 +0,0 @@
//! A singlethreade libfuzzer-like fuzzer that can auto-restart.
use clap::{App, Arg};
use core::{cell::RefCell, time::Duration};
#[cfg(unix)]
use nix::{self, unistd::dup};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::{
env,
fs::{self, File, OpenOptions},
io::{self, Write},
path::PathBuf,
process,
};
use libafl::{
bolts::{
current_nanos, current_time,
os::dup2,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
},
corpus::{
Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, PowerQueueCorpusScheduler,
},
events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
mutators::{
scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations,
StdMOptMutator, Tokens,
},
observers::{StdMapObserver, TimeObserver},
stages::{
calibrate::CalibrationStage,
power::{PowerMutationalStage, PowerSchedule},
TracingStage,
},
state::{HasCorpus, HasMetadata, StdState},
Error,
};
use libafl_targets::{
libfuzzer_initialize, libfuzzer_test_one_input, CmpLogObserver, CMPLOG_MAP, EDGES_MAP,
MAX_EDGES_NUM,
};
/// The fuzzer main (as `no_mangle` C function)
#[no_mangle]
pub fn libafl_main() {
// Registry the metadata types used in this fuzzer
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let res = match App::new("libafl_fuzzbench")
.version("0.4.0")
.author("AFLplusplus team")
.about("LibAFL-based fuzzer for Fuzzbench")
.arg(
Arg::new("out")
.help("The directory to place finds in ('corpus')")
.required(true)
.index(1)
.takes_value(true),
)
.arg(
Arg::new("in")
.help("The directory to read initial inputs from ('seeds')")
.required(true)
.index(2)
.takes_value(true),
)
.arg(
Arg::new("tokens")
.short('x')
.long("tokens")
.help("A file to read tokens from, to be used during fuzzing")
.takes_value(true),
)
.arg(
Arg::new("logfile")
.short('l')
.long("logfile")
.help("Duplicates all output to this file")
.default_value("libafl.log"),
)
.arg(
Arg::new("timeout")
.short('t')
.long("timeout")
.help("Timeout for each individual execution, in milliseconds")
.default_value("1200"),
)
.try_get_matches()
{
Ok(res) => res,
Err(err) => {
println!(
"Syntax: {}, [-x dictionary] corpus_dir seed_dir\n{:?}",
env::current_exe()
.unwrap_or_else(|_| "fuzzer".into())
.to_string_lossy(),
err.info,
);
return;
}
};
println!(
"Workdir: {:?}",
env::current_dir().unwrap().to_string_lossy().to_string()
);
// For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir.
let mut out_dir = PathBuf::from(res.value_of("out").unwrap().to_string());
if fs::create_dir(&out_dir).is_err() {
println!("Out dir at {:?} already exists.", &out_dir);
if !out_dir.is_dir() {
println!("Out dir at {:?} is not a valid directory!", &out_dir);
return;
}
}
let mut crashes = out_dir.clone();
crashes.push("crashes");
out_dir.push("queue");
let in_dir = PathBuf::from(res.value_of("in").unwrap().to_string());
if !in_dir.is_dir() {
println!("In dir at {:?} is not a valid directory!", &in_dir);
return;
}
let tokens = res.value_of("tokens").map(PathBuf::from);
let logfile = PathBuf::from(res.value_of("logfile").unwrap().to_string());
let timeout = Duration::from_millis(
res.value_of("timeout")
.unwrap()
.to_string()
.parse()
.expect("Could not parse timeout in milliseconds"),
);
fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout)
.expect("An error occurred while fuzzing");
}
/// The actual fuzzer
fn fuzz(
corpus_dir: PathBuf,
objective_dir: PathBuf,
seed_dir: PathBuf,
tokenfile: Option<PathBuf>,
logfile: PathBuf,
timeout: Duration,
) -> Result<(), Error> {
let log = RefCell::new(
OpenOptions::new()
.append(true)
.create(true)
.open(&logfile)?,
);
#[cfg(unix)]
let mut stdout_cpy = unsafe {
let new_fd = dup(io::stdout().as_raw_fd())?;
File::from_raw_fd(new_fd)
};
#[cfg(unix)]
let file_null = File::open("/dev/null")?;
// 'While the monitor are state, they are usually used in the broker - which is likely never restarted
let monitor = SimpleMonitor::new(|s| {
#[cfg(unix)]
writeln!(&mut stdout_cpy, "{}", s).unwrap();
#[cfg(windows)]
println!("{}", s);
writeln!(log.borrow_mut(), "{:?} {}", current_time(), s).unwrap();
});
// We need a shared map to store our state before a crash.
// This way, we are able to continue fuzzing afterwards.
let mut shmem_provider = StdShMemProvider::new()?;
let (state, mut mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider)
{
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
Ok(res) => res,
Err(err) => match err {
Error::ShuttingDown => {
return Ok(());
}
_ => {
panic!("Failed to setup the restarter: {}", err);
}
},
};
// Create an observation channel using the coverage map
// We don't use the hitcounts (see the Cargo.toml, we use pcguard_edges)
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
let edges_observer = StdMapObserver::new("edges", edges);
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
StdState::new(
// RNG
StdRand::with_seed(current_nanos()),
// Corpus that will be evolved, we keep it in memory for performance
OnDiskCorpus::new(corpus_dir).unwrap(),
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
)
});
println!("Let's fuzz :)");
// The actual target run starts here.
// Call LLVMFUzzerInitialize() if present.
let args: Vec<String> = env::args().collect();
if libfuzzer_initialize(&args) == -1 {
println!("Warning: LLVMFuzzerInitialize failed with -1")
}
let calibration = CalibrationStage::new(&mut state, &edges_observer);
// Setup a MOPT mutator
let mutator = StdMOptMutator::new(
&mut state,
havoc_mutations()
.merge(tokens_mutations())
.merge(tuple_list!(I2SRandReplace::new())),
5,
)?;
let power = PowerMutationalStage::new(mutator, PowerSchedule::FAST, &edges_observer);
// A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
// A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
// The wrapped harness function, calling out to the LLVM-style harness
let mut harness = |input: &BytesInput| {
let target = input.target_bytes();
let buf = target.as_slice();
libfuzzer_test_one_input(buf);
ExitKind::Ok
};
let mut tracing_harness = harness;
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let mut executor = TimeoutExecutor::new(
InProcessExecutor::new(
&mut harness,
tuple_list!(edges_observer, time_observer),
&mut fuzzer,
&mut state,
&mut mgr,
)?,
timeout,
);
// Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new(TimeoutExecutor::new(
InProcessExecutor::new(
&mut tracing_harness,
tuple_list!(cmplog_observer),
&mut fuzzer,
&mut state,
&mut mgr,
)?,
// Give it more time!
timeout * 10,
));
// The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, power);
// Read tokens
if let Some(tokenfile) = tokenfile {
if state.metadata().get::<Tokens>().is_none() {
state.add_metadata(Tokens::from_tokens_file(tokenfile)?);
}
}
// In case the corpus is empty (on first run), reset
if state.corpus().count() < 1 {
state
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()])
.unwrap_or_else(|_| {
println!("Failed to load initial corpus at {:?}", &seed_dir);
process::exit(0);
});
println!("We imported {} inputs from disk.", state.corpus().count());
}
// Remove target ouput (logs still survive)
#[cfg(unix)]
{
let null_fd = file_null.as_raw_fd();
dup2(null_fd, io::stdout().as_raw_fd())?;
dup2(null_fd, io::stderr().as_raw_fd())?;
}
// reopen file to make sure we're at the end
log.replace(
OpenOptions::new()
.append(true)
.create(true)
.open(&logfile)?,
);
fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?;
// Never reached
Ok(())
}

View File

@ -1,2 +1 @@
build/
qemu-libafl-bridge/
libpng-*

View File

@ -0,0 +1,43 @@
FUZZER_NAME="libpng_harness"
PROJECT_DIR=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
UNAME := $(shell uname)
PHONY: all
all: fuzzer
libpng-1.6.37:
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
tar -xvf libpng-1.6.37.tar.xz
target/release/fuzzbench_qemu: src/*
cargo build --release
libpng-1.6.37/.libs/libpng16.a: libpng-1.6.37
cd libpng-1.6.37 && ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes
$(MAKE) -C libpng-1.6.37
cc -c $(PROJECT_DIR)/libfuzzer_main.c
# Build the libpng harness
c++ \
$(PROJECT_DIR)/../libfuzzer_libpng/harness.cc \
$(PROJECT_DIR)/libpng-1.6.37/.libs/libpng16.a \
libfuzzer_main.o \
-I$(PROJECT_DIR)/libpng-1.6.37/ \
-o $(FUZZER_NAME) \
-lm -lz
fuzzer: target/release/fuzzbench_qemu libpng-1.6.37/.libs/libpng16.a
clean:
rm ./$(FUZZER_NAME) libfuzzer_main.o
$(MAKE) -C libpng-1.6.37 clean
run: all
cargo run --release -- --libafl-in ../libfuzzer_libpng/corpus --libafl-out ./out ./$(FUZZER_NAME)
short_test: all
rm -rf libafl_unix_shmem_server || true
timeout 10s cargo run --release -- --libafl-in ../libfuzzer_libpng/corpus --libafl-out ./out ./$(FUZZER_NAME) &
test: all
timeout 60s cargo run --release -- --libafl-in ../libfuzzer_libpng/corpus --libafl-out ./out ./$(FUZZER_NAME) &

View File

@ -1,19 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
char o = 0;
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
// printf("Got %ld bytes.\n", Size);
o += 1;
if (Size >= 4 && *(uint32_t*)Data == 0xaabbccdd)
abort();
}
int main() {
char buf [10] = {0};
LLVMFuzzerTestOneInput(buf, 10);
}

View File

@ -0,0 +1,11 @@
#include <stdint.h>
#include <stdlib.h>
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
int main() {
char buf [10] = {0};
LLVMFuzzerTestOneInput(buf, 10);
}

View File

@ -22,33 +22,42 @@ use libafl::{
shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge},
},
corpus::{Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler},
corpus::{
Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, PowerQueueCorpusScheduler,
},
events::SimpleRestartingEventManager,
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
mutators::{
scheduled::{havoc_mutations, StdScheduledMutator},
tokens_mutations, I2SRandReplace, Tokens,
scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations,
StdMOptMutator, StdScheduledMutator, Tokens,
},
observers::{HitcountsMapObserver, TimeObserver, VariableMapObserver},
stages::{ShadowTracingStage, StdMutationalStage},
stages::{
calibrate::CalibrationStage,
power::{PowerMutationalStage, PowerSchedule},
ShadowTracingStage, StdMutationalStage,
},
state::{HasCorpus, HasMetadata, StdState},
Error,
};
use libafl_qemu::{
asan::QemuAsanHelper,
//asan::QemuAsanHelper,
cmplog,
cmplog::{CmpLogObserver, QemuCmpLogHelper},
edges,
edges::QemuEdgeCoverageHelper,
elf::EasyElf,
emu, filter_qemu_args, init_with_asan,
snapshot::QemuSnapshotHelper,
MmapPerms, QemuExecutor, Regs,
emu,
filter_qemu_args,
//snapshot::QemuSnapshotHelper,
MmapPerms,
QemuExecutor,
Regs,
};
/// The fuzzer main
@ -57,9 +66,9 @@ pub fn main() {
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let mut args: Vec<String> = env::args().collect();
let mut env: Vec<(String, String)> = env::vars().collect();
init_with_asan(&mut args, &mut env);
let args: Vec<String> = env::args().collect();
let env: Vec<(String, String)> = env::vars().collect();
emu::init(&args, &env);
let res = match App::new("libafl_qemu_fuzzbench")
.version("0.4.0")
@ -256,7 +265,7 @@ fn fuzz(
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let objective = CrashFeedback::new();
// create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -274,8 +283,18 @@ fn fuzz(
)
});
let calibration = CalibrationStage::new(&mut state, &edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator
let mutator = StdMOptMutator::new(&mut state, havoc_mutations().merge(tokens_mutations()), 5)?;
let power = PowerMutationalStage::new(mutator, PowerSchedule::FAST, &edges_observer);
// A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new());
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
// A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
@ -307,7 +326,7 @@ fn fuzz(
tuple_list!(
QemuEdgeCoverageHelper::new(),
QemuCmpLogHelper::new(),
QemuAsanHelper::new(),
//QemuAsanHelper::new(),
//QemuSnapshotHelper::new()
),
tuple_list!(edges_observer, time_observer),
@ -340,13 +359,8 @@ fn fuzz(
let tracing = ShadowTracingStage::new(&mut executor);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(I2SRandReplace::new());
// Setup a mutational stage with a basic bytes mutator
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let mut stages = tuple_list!(tracing, i2s, StdMutationalStage::new(mutator));
// The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power);
// Remove target ouput (logs still survive)
#[cfg(unix)]