diff --git a/fuzzers/FRET/benchmark/.gitignore b/fuzzers/FRET/benchmark/.gitignore new file mode 100644 index 0000000000..a488ac44ed --- /dev/null +++ b/fuzzers/FRET/benchmark/.gitignore @@ -0,0 +1,3 @@ +timedump +corpora +build diff --git a/fuzzers/FRET/benchmark/Makefile b/fuzzers/FRET/benchmark/Makefile new file mode 100644 index 0000000000..b7597901e7 --- /dev/null +++ b/fuzzers/FRET/benchmark/Makefile @@ -0,0 +1,28 @@ +corpora/%/seed: + mkdir -p $$(dirname $@) + LINE=$$(grep "^$$(basename $*)" target_symbols.csv); \ + export \ + KERNEL=benchmark/build/$*.elf \ + FUZZ_MAIN=$$(echo $$LINE | cut -d, -f2) \ + FUZZ_INPUT=$$(echo $$LINE | cut -d, -f3) \ + FUZZ_INPUT_LEN=$$(echo $$LINE | cut -d, -f4) \ + BREAKPOINT=$$(echo $$LINE | cut -d, -f5) \ + SEED_DIR=benchmark/corpora/$* \ + DUMP_SEED=seed; \ + ../fuzzer.sh + +timedump/%: corpora/%/seed + mkdir -p $$(dirname $@) + LINE=$$(grep "^$$(basename $*)" target_symbols.csv); \ + export \ + KERNEL=benchmark/build/$*.elf \ + FUZZ_MAIN=$$(echo $$LINE | cut -d, -f2) \ + FUZZ_INPUT=$$(echo $$LINE | cut -d, -f3) \ + FUZZ_INPUT_LEN=$$(echo $$LINE | cut -d, -f4) \ + BREAKPOINT=$$(echo $$LINE | cut -d, -f5) \ + SEED_DIR=benchmark/corpora/$* \ + TIME_DUMP=benchmark/$@; \ + ../fuzzer.sh + + + + + 5 + + + + +clean: + rm -rf corpora timedump \ No newline at end of file diff --git a/fuzzers/FRET/benchmark/target_symbols.csv b/fuzzers/FRET/benchmark/target_symbols.csv new file mode 100644 index 0000000000..17e5e598e7 --- /dev/null +++ b/fuzzers/FRET/benchmark/target_symbols.csv @@ -0,0 +1,2 @@ +kernel,main_function,input_symbol,input_size,return_function +mpeg2,main,mpeg2_oldorgframe,90112,mpeg2_return \ No newline at end of file diff --git a/fuzzers/FRET/fuzzer.sh b/fuzzers/FRET/fuzzer.sh index 557364ed11..68c4fc2f6c 100755 --- a/fuzzers/FRET/fuzzer.sh +++ b/fuzzers/FRET/fuzzer.sh @@ -1,10 +1,14 @@ #!/usr/bin/env bash +parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P ) +cd "$parent_path" + [ -n "$1" -a "$1" != "+" -a -z "$KERNEL" ] && export KERNEL="$1" [ -n "$2" -a "$2" != "+" -a -z "$FUZZ_MAIN" ] && export FUZZ_MAIN="$2" [ -n "$3" -a "$3" != "+" -a -z "$FUZZ_INPUT" ] && export FUZZ_INPUT="$3" -[ -n "$4" -a "$4" != "+" -a -z "$BREAKPOINT" ] && export BREAKPOINT="$4" -[ -n "$5" -a "$5" != "+" -a -z "$FUZZ_ITERS" ] && export FUZZ_ITERS="$5" -[ -n "$6" -a "$6" != "+" -a -z "$TIME_DUMP" ] && export TIME_DUMP="$6" -[ -n "$7" -a "$7" != "+" -a -z "$DO_SHOWMAP" ] && export DO_SHOWMAP="$7" -[ -n "$8" -a "$8" != "+" -a -z "$SHOWMAP_TEXTINPUT" ] && export SHOWMAP_TEXTINPUT="$8" +[ -n "$4" -a "$4" != "+" -a -z "$FUZZ_INPUT_LEN" ] && export FUZZ_INPUT_LEN="$4" +[ -n "$5" -a "$5" != "+" -a -z "$BREAKPOINT" ] && export BREAKPOINT="$5" +[ -n "$6" -a "$6" != "+" -a -z "$FUZZ_ITERS" ] && export FUZZ_ITERS="$6" +[ -n "$7" -a "$7" != "+" -a -z "$TIME_DUMP" ] && export TIME_DUMP="$7" +[ -n "$8" -a "$8" != "+" -a -z "$DO_SHOWMAP" ] && export DO_SHOWMAP="$8" +[ -n "$9" -a "$9" != "+" -a -z "$SHOWMAP_TEXTINPUT" ] && export SHOWMAP_TEXTINPUT="$9" target/debug/qemu_systemmode -icount shift=3,align=off,sleep=off -machine mps2-an385 -monitor null -kernel $KERNEL -serial null -nographic -S -semihosting --semihosting-config enable=on,target=native # -snapshot -drive if=none,format=qcow2,file=dummy.qcow2 \ No newline at end of file diff --git a/fuzzers/FRET/src/fuzzer.rs b/fuzzers/FRET/src/fuzzer.rs index 87bc11f73f..68e34746ae 100644 --- a/fuzzers/FRET/src/fuzzer.rs +++ b/fuzzers/FRET/src/fuzzer.rs @@ -28,7 +28,7 @@ use libafl::{ stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, - prelude::{SimpleMonitor, SimpleEventManager}, Evaluator, + prelude::{SimpleMonitor, SimpleEventManager, AsMutSlice}, Evaluator, }; use libafl_qemu::{ edges, edges::QemuEdgeCoverageHelper, elf::EasyElf, emu::Emulator, GuestPhysAddr, QemuExecutor, @@ -142,6 +142,10 @@ pub fn fuzz() { libafl_int_offset = 0; } + if let Ok(input_len) = env::var("FUZZ_INPUT_LEN") { + unsafe {MAX_INPUT_SIZE = str::parse::(&input_len).expect("FUZZ_INPUT_LEN was not a number");} + } + let mut run_client = |state: Option<_>, mut mgr, _core_id| { // Initialize QEMU let args: Vec = env::args().collect(); @@ -283,7 +287,15 @@ pub fn fuzz() { fuzzer.evaluate_input(&mut state, &mut executor, &mut mgr, BytesInput::new(show_input)) .unwrap(); } else { - if state.corpus().count() < 1 { + if let Ok(sf) = env::var("SEED_DIR") { + state + .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[PathBuf::from(&sf)]) + .unwrap_or_else(|_| { + println!("Failed to load initial corpus at {:?}", &corpus_dirs); + process::exit(0); + }); + println!("We imported {} inputs from seedfile.", state.corpus().count()); + } else if state.corpus().count() < 1 { state .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs) .unwrap_or_else(|_| { @@ -325,6 +337,28 @@ pub fn fuzz() { Ok(()) }; + // Special case where no fuzzing happens, but standard input is dumped + if let Ok(input_dump) = env::var("DUMP_SEED") { + // Initialize QEMU + let args: Vec = env::args().collect(); + let env: Vec<(String, String)> = env::vars().collect(); + let emu = Emulator::new(&args, &env); + + emu.set_breakpoint(main_addr); + unsafe { + emu.run(); + + let mut buf = [0u8].repeat(MAX_INPUT_SIZE); + emu.read_phys_mem(input_addr, buf.as_mut_slice()); + + let dir = env::var("SEED_DIR").map_or("./corpus".to_string(), |x| x); + let filename = if input_dump == "" {"input"} else {&input_dump}; + println!("Dumping input to: {}/{}",&dir,filename); + fs::write(format!("{}/{}",&dir,filename), buf).expect("could not write input dump"); + } + return +} + #[cfg(feature = "singlecore")] { let monitor = SimpleMonitor::new(|s| println!("{}", s));