diff --git a/fuzzers/libfuzzer/compiler b/fuzzers/libfuzzer/compiler index 13ff4dc299..056a86af34 100755 --- a/fuzzers/libfuzzer/compiler +++ b/fuzzers/libfuzzer/compiler @@ -32,6 +32,8 @@ def cc_mode(): args = common_opts() args += sys.argv[1:] + args += ["-fsanitize-coverage=trace-pc-guard,trace-cmp"] + if os.getenv("AFL_USE_ASAN"): args += ["-fsanitize=address"] if os.getenv("AFL_USE_MSAN"): @@ -53,6 +55,8 @@ def ld_mode(): os.path.join(script_dir, "runtime", "rt.o"), os.path.join(script_dir, "target", "release", "liblibfuzzer.a"), ] + + args += ["-fsanitize-coverage=trace-pc-guard,trace-cmp"] if os.getenv("AFL_USE_ASAN"): args += ["-fsanitize=address"] diff --git a/fuzzers/libfuzzer/runtime/rt.c b/fuzzers/libfuzzer/runtime/rt.c index 32e5aa4890..1fa6ef9755 100644 --- a/fuzzers/libfuzzer/runtime/rt.c +++ b/fuzzers/libfuzzer/runtime/rt.c @@ -1,4 +1,123 @@ +#include +#define MAP_SIZE 65536 + +uint8_t __lafl_dummy_map[MAP_SIZE]; + +uint8_t *__lafl_edges_map = __lafl_dummy_map; +uint8_t *__lafl_cmp_map = __lafl_dummy_map; + +uint32_t __lafl_max_edges_size = 0; + +void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { + + __lafl_edges_map[*guard]++; + +} + +void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { + + if (start == stop || *start) return; + + *(start++) = (++__lafl_max_edges_size) & (MAP_SIZE -1); + + while (start < stop) { + + *start = (++__lafl_max_edges_size) & (MAP_SIZE -1); + start++; + + } + +} + +#define MAX(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + \ + }) + +#if defined(__APPLE__) + #pragma weak __sanitizer_cov_trace_const_cmp1 = __sanitizer_cov_trace_cmp1 + #pragma weak __sanitizer_cov_trace_const_cmp2 = __sanitizer_cov_trace_cmp2 + #pragma weak __sanitizer_cov_trace_const_cmp4 = __sanitizer_cov_trace_cmp4 + #pragma weak __sanitizer_cov_trace_const_cmp8 = __sanitizer_cov_trace_cmp8 +#else +void __sanitizer_cov_trace_const_cmp1(uint8_t arg1, uint8_t arg2) __attribute__((alias("__sanitizer_cov_trace_cmp1"))); +void __sanitizer_cov_trace_const_cmp2(uint16_t arg1, uint16_t arg2) + __attribute__((alias("__sanitizer_cov_trace_cmp2"))); +void __sanitizer_cov_trace_const_cmp4(uint32_t arg1, uint32_t arg2) + __attribute__((alias("__sanitizer_cov_trace_cmp4"))); +void __sanitizer_cov_trace_const_cmp8(uint64_t arg1, uint64_t arg2) + __attribute__((alias("__sanitizer_cov_trace_cmp8"))); +#endif + +void __sanitizer_cov_trace_cmp1(uint8_t arg1, uint8_t arg2) { + + uintptr_t k = (uintptr_t)__builtin_return_address(0); + k = (k >> 4) ^ (k << 8); + k &= MAP_SIZE - 1; + __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2)))); + +} + +void __sanitizer_cov_trace_cmp2(uint16_t arg1, uint16_t arg2) { + + uintptr_t k = (uintptr_t)__builtin_return_address(0); + k = (k >> 4) ^ (k << 8); + k &= MAP_SIZE - 1; + __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2)))); + +} + +void __sanitizer_cov_trace_cmp4(uint32_t arg1, uint32_t arg2) { + + uintptr_t k = (uintptr_t)__builtin_return_address(0); + k = (k >> 4) ^ (k << 8); + k &= MAP_SIZE - 1; + __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2)))); + +} + +void __sanitizer_cov_trace_cmp8(uint64_t arg1, uint64_t arg2) { + + uintptr_t k = (uintptr_t)__builtin_return_address(0); + k = (k >> 4) ^ (k << 8); + k &= MAP_SIZE - 1; + __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcountll(~(arg1 ^ arg2)))); + +} + +void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { + + uintptr_t rt = (uintptr_t)__builtin_return_address(0); + if (cases[1] == 64) { + + for (uint64_t i = 0; i < cases[0]; i++) { + + uintptr_t k = rt + i; + k = (k >> 4) ^ (k << 8); + k &= MAP_SIZE - 1; + __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcountll(~(val ^ cases[i + 2])))); + + } + + } else { + + for (uint64_t i = 0; i < cases[0]; i++) { + + uintptr_t k = rt + i; + k = (k >> 4) ^ (k << 8); + k &= MAP_SIZE - 1; + __lafl_cmp_map[k] = MAX(__lafl_cmp_map[k], (__builtin_popcount(~(val ^ cases[i + 2])))); + + } + + } + +} __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); diff --git a/fuzzers/libfuzzer/src/lib.rs b/fuzzers/libfuzzer/src/lib.rs index a6cf977b3c..8eafca0060 100644 --- a/fuzzers/libfuzzer/src/lib.rs +++ b/fuzzers/libfuzzer/src/lib.rs @@ -1,17 +1,28 @@ use std::boxed::Box; +use std::cell::RefCell; +use std::rc::Rc; use afl::corpus::{Corpus, InMemoryCorpus, Testcase}; -use afl::engines::{DefaultEngine, DefaultState, Engine}; +use afl::engines::{DefaultEngine, DefaultState, Engine, State}; use afl::executors::inmemory::InMemoryExecutor; use afl::executors::{Executor, ExitKind}; +use afl::feedbacks::{create_history_map, MaxMapFeedback}; use afl::inputs::bytes::BytesInput; use afl::mutators::scheduled::{mutation_bitflip, ComposedByMutations, DefaultScheduledMutator}; +use afl::observers::DefaultMapObserver; use afl::stages::mutational::DefaultMutationalStage; use afl::utils::DefaultRand; +const MAP_SIZE: usize = 65536; + +#[no_mangle] extern "C" { /// int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) fn LLVMFuzzerTestOneInput(data: *const u8, size: usize) -> i32; + + static __lafl_edges_map: *mut u8; + static __lafl_cmp_map: *mut u8; + static __lafl_max_edges_size: u32; } fn harness(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { @@ -29,8 +40,17 @@ pub extern "C" fn afl_libfuzzer_main() { let testcase = Testcase::new(vec![0; 4]).into(); corpus.add(testcase); + let edges_observer = Rc::new(RefCell::new(DefaultMapObserver::new_from_ptr( + unsafe { __lafl_edges_map }, + unsafe { __lafl_max_edges_size as usize }, + ))); + let edges_history_map = create_history_map::(MAP_SIZE); + let edges_feedback = MaxMapFeedback::new(edges_observer.clone(), edges_history_map); + let executor = InMemoryExecutor::::new(harness); let mut state = DefaultState::new(corpus, executor); + state.add_observer(edges_observer); + state.add_feedback(Box::new(edges_feedback)); let mut engine = DefaultEngine::new(); let mut mutator = DefaultScheduledMutator::new(&rand); diff --git a/src/engines/mod.rs b/src/engines/mod.rs index da8528553a..d05eb759fc 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -20,29 +20,29 @@ where I: Input, { /// Get the linked observers - fn observers(&self) -> &[Box]; + fn observers(&self) -> &[Rc>]; /// Get the linked observers - fn observers_mut(&mut self) -> &mut Vec>; + fn observers_mut(&mut self) -> &mut Vec>>; /// Add a linked observer - fn add_observer(&mut self, observer: Box) { + fn add_observer(&mut self, observer: Rc>) { self.observers_mut().push(observer); } /// Reset the state of all the observes linked to this executor fn reset_observers(&mut self) -> Result<(), AflError> { - for observer in self.observers_mut() { - observer.reset()?; + for observer in self.observers() { + observer.borrow_mut().reset()?; } Ok(()) } /// Run the post exec hook for all the observes linked to this executor fn post_exec_observers(&mut self) -> Result<(), AflError> { - self.observers_mut() - .iter_mut() - .map(|x| x.post_exec()) + self.observers() + .iter() + .map(|x| x.borrow_mut().post_exec()) .fold(Ok(()), |acc, x| if x.is_err() { x } else { acc }) } @@ -101,7 +101,7 @@ where E: Executor, I: Input, { - observers: Vec>, + observers: Vec>>, feedbacks: Vec>>, corpus: C, executor: E, @@ -113,11 +113,11 @@ where E: Executor, I: Input, { - fn observers(&self) -> &[Box] { + fn observers(&self) -> &[Rc>] { &self.observers } - fn observers_mut(&mut self) -> &mut Vec> { + fn observers_mut(&mut self) -> &mut Vec>> { &mut self.observers } diff --git a/src/feedbacks/mod.rs b/src/feedbacks/mod.rs index 810af1568a..07390bc141 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -78,21 +78,21 @@ where } /// The most common AFL-like feedback type -pub struct MapFeedback<'a, T, R, O> +pub struct MapFeedback where T: Integer + Copy + 'static, R: Reducer, O: MapObserver, { /// Contains information about untouched entries - history_map: &'a RefCell>, + history_map: Rc>>, /// The observer this feedback struct observes - map_observer: &'a RefCell, + map_observer: Rc>, /// Phantom Data of Reducer phantom: PhantomData, } -impl<'a, T, R, O, I> Feedback for MapFeedback<'a, T, R, O> +impl Feedback for MapFeedback where T: Integer + Copy + 'static, R: Reducer, @@ -122,7 +122,7 @@ where } } -impl<'a, T, R, O> MapFeedback<'a, T, R, O> +impl MapFeedback where T: Integer + Copy + 'static, R: Reducer, @@ -130,7 +130,7 @@ where { /// Create new MapFeedback using a map observer, and a map. /// The map can be shared. - pub fn new(map_observer: &'a RefCell, history_map: &'a RefCell>) -> Self { + pub fn new(map_observer: Rc>, history_map: Rc>>) -> Self { MapFeedback { map_observer: map_observer, history_map: history_map, @@ -140,14 +140,14 @@ where } /// Returns a usable history map of the given size -pub fn create_history_map(map_size: usize) -> RefCell> +pub fn create_history_map(map_size: usize) -> Rc>> where T: Default + Clone, { { - RefCell::new(vec![T::default(); map_size]) + Rc::new(RefCell::new(vec![T::default(); map_size])) } } -pub type MaxMapFeedback<'a, T, O> = MapFeedback<'a, T, MaxReducer, O>; -pub type MinMapFeedback<'a, T, O> = MapFeedback<'a, T, MinReducer, O>; +pub type MaxMapFeedback = MapFeedback, O>; +pub type MinMapFeedback = MapFeedback, O>; diff --git a/src/observers/mod.rs b/src/observers/mod.rs index 7f4917dd18..5df1e17edc 100644 --- a/src/observers/mod.rs +++ b/src/observers/mod.rs @@ -1,5 +1,7 @@ extern crate num; +use alloc::rc::Rc; +use core::cell::RefCell; use core::slice::from_raw_parts_mut; use num::Integer; @@ -57,13 +59,19 @@ where initial: T, } -impl<'a, T: Integer + Copy> Observer for DefaultMapObserver<'a, T> { +impl<'a, T> Observer for DefaultMapObserver<'a, T> +where + T: Integer + Copy, +{ fn reset(&mut self) -> Result<(), AflError> { self.reset_map() } } -impl<'a, T: Integer + Copy> MapObserver for DefaultMapObserver<'a, T> { +impl<'a, T> MapObserver for DefaultMapObserver<'a, T> +where + T: Integer + Copy, +{ fn map(&self) -> &[T] { &self.map } @@ -85,7 +93,10 @@ impl<'a, T: Integer + Copy> MapObserver for DefaultMapObserver<'a, T> { } } -impl<'a, T: Integer + Copy> DefaultMapObserver<'a, T> { +impl<'a, T> DefaultMapObserver<'a, T> +where + T: Integer + Copy, +{ /// Creates a new MapObserver pub fn new(map: &'a mut [T]) -> Self { let initial = if map.len() > 0 { map[0] } else { T::zero() }; @@ -106,3 +117,12 @@ impl<'a, T: Integer + Copy> DefaultMapObserver<'a, T> { } } } + +impl<'a, T> Into>> for DefaultMapObserver<'a, T> +where + T: Integer + Copy, +{ + fn into(self) -> Rc> { + Rc::new(RefCell::new(self)) + } +}