From fd869ba1cdaf4b39351a1b53d484996adfade0cf Mon Sep 17 00:00:00 2001 From: Toka Date: Wed, 17 Nov 2021 20:51:39 +0900 Subject: [PATCH] Frida Refactor: Frida executor (#374) * frida executor * add files * fmt & clippy * fmt * fix * fmt * fix & fmt --- fuzzers/frida_libpng/src/fuzzer.rs | 133 ++--------------------------- libafl_frida/src/executor.rs | 126 +++++++++++++++++++++++++++ libafl_frida/src/lib.rs | 3 + 3 files changed, 134 insertions(+), 128 deletions(-) create mode 100644 libafl_frida/src/executor.rs diff --git a/fuzzers/frida_libpng/src/fuzzer.rs b/fuzzers/frida_libpng/src/fuzzer.rs index 2b85d92cbf..6ae7a3ee59 100644 --- a/fuzzers/frida_libpng/src/fuzzer.rs +++ b/fuzzers/frida_libpng/src/fuzzer.rs @@ -17,43 +17,35 @@ use libafl::{ IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler, }, events::{llmp::LlmpRestartingEventManager, EventConfig}, - executors::{ - inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasObservers, - ShadowExecutor, - }, + executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor}, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes, Input}, + inputs::{BytesInput, HasTargetBytes}, monitors::MultiMonitor, mutators::{ scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, token_mutations::I2SRandReplace, token_mutations::Tokens, }, - observers::{HitcountsMapObserver, ObserversTuple, StdMapObserver, TimeObserver}, + observers::{HitcountsMapObserver, StdMapObserver, TimeObserver}, stages::{ShadowTracingStage, StdMutationalStage}, state::{HasCorpus, HasMetadata, StdState}, Error, }; -use frida_gum::{ - stalker::{NoneEventSink, Stalker}, - Gum, MemoryRange, NativePointer, -}; +use frida_gum::Gum; use std::{ env, - ffi::c_void, - marker::PhantomData, net::SocketAddr, path::{Path, PathBuf}, - time::Duration, }; use libafl_frida::{ coverage_rt::MAP_SIZE, helper::{FridaHelper, FridaInstrumentationHelper}, + executor::FridaInProcessExecutor, FridaOptions, }; @@ -62,120 +54,6 @@ use libafl_frida::asan_errors::{AsanErrorsFeedback, AsanErrorsObserver, ASAN_ERR use libafl_targets::cmplog::{CmpLogObserver, CMPLOG_MAP}; -struct FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> -where - FH: FridaHelper<'b>, - H: FnMut(&I) -> ExitKind, - I: Input + HasTargetBytes, - OT: ObserversTuple, -{ - base: TimeoutExecutor>, - /// Frida's dynamic rewriting engine - stalker: Stalker<'a>, - /// User provided callback for instrumentation - helper: &'c mut FH, - followed: bool, - _phantom: PhantomData<&'b u8>, -} - -impl<'a, 'b, 'c, EM, FH, H, I, OT, S, Z> Executor - for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> -where - FH: FridaHelper<'b>, - H: FnMut(&I) -> ExitKind, - I: Input + HasTargetBytes, - OT: ObserversTuple, -{ - /// Instruct the target about the input and run - #[inline] - fn run_target( - &mut self, - fuzzer: &mut Z, - state: &mut S, - mgr: &mut EM, - input: &I, - ) -> Result { - self.helper.pre_exec(input); - if self.helper.stalker_enabled() { - if self.followed { - self.stalker.activate(NativePointer( - self.base.inner().harness_mut() as *mut _ as *mut c_void - )) - } else { - self.followed = true; - self.stalker - .follow_me::(self.helper.transformer(), None); - } - } - let res = self.base.run_target(fuzzer, state, mgr, input); - if self.helper.stalker_enabled() { - self.stalker.deactivate(); - } - #[cfg(unix)] - if unsafe { ASAN_ERRORS.is_some() && !ASAN_ERRORS.as_ref().unwrap().is_empty() } { - println!("Crashing target as it had ASAN errors"); - unsafe { - libc::raise(libc::SIGABRT); - } - } - self.helper.post_exec(input); - res - } -} - -impl<'a, 'b, 'c, FH, H, I, OT, S> HasObservers - for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> -where - FH: FridaHelper<'b>, - H: FnMut(&I) -> ExitKind, - I: Input + HasTargetBytes, - OT: ObserversTuple, -{ - #[inline] - fn observers(&self) -> &OT { - self.base.observers() - } - - #[inline] - fn observers_mut(&mut self) -> &mut OT { - self.base.observers_mut() - } -} - -impl<'a, 'b, 'c, FH, H, I, OT, S> FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> -where - FH: FridaHelper<'b>, - H: FnMut(&I) -> ExitKind, - I: Input + HasTargetBytes, - OT: ObserversTuple, -{ - pub fn new( - gum: &'a Gum, - base: InProcessExecutor<'a, H, I, OT, S>, - helper: &'c mut FH, - timeout: Duration, - ) -> Self { - let mut stalker = Stalker::new(gum); - - #[cfg(not(all(debug_assertions, target_arch = "x86_64")))] - for range in helper.ranges().gaps(&(0..usize::MAX)) { - println!("excluding range: {:x}-{:x}", range.start, range.end); - stalker.exclude(&MemoryRange::new( - NativePointer(range.start as *mut c_void), - range.end - range.start, - )); - } - - Self { - base: TimeoutExecutor::new(base, timeout), - stalker, - helper, - followed: false, - _phantom: PhantomData, - } - } -} - /// The main fn, usually parsing parameters, and starting the fuzzer pub fn main() { // Registry the metadata types used in this fuzzer @@ -403,7 +281,6 @@ unsafe fn fuzz( &mut mgr, )?, &mut frida_helper, - Duration::new(30, 0), ); #[cfg(windows)] diff --git a/libafl_frida/src/executor.rs b/libafl_frida/src/executor.rs new file mode 100644 index 0000000000..cebf995747 --- /dev/null +++ b/libafl_frida/src/executor.rs @@ -0,0 +1,126 @@ +use crate::helper::FridaHelper; + +use std::{ffi::c_void, marker::PhantomData}; + +use frida_gum::{ + stalker::{NoneEventSink, Stalker}, + Gum, MemoryRange, NativePointer, +}; + +use libafl::{ + executors::{Executor, ExitKind, HasObservers, InProcessExecutor}, + inputs::{HasTargetBytes, Input}, + observers::ObserversTuple, + Error, +}; + +use crate::asan_errors::ASAN_ERRORS; + +pub struct FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> +where + FH: FridaHelper<'b>, + H: FnMut(&I) -> ExitKind, + I: Input + HasTargetBytes, + OT: ObserversTuple, +{ + base: InProcessExecutor<'a, H, I, OT, S>, + /// Frida's dynamic rewriting engine + stalker: Stalker<'a>, + /// User provided callback for instrumentation + helper: &'c mut FH, + followed: bool, + _phantom: PhantomData<&'b u8>, +} + +impl<'a, 'b, 'c, EM, FH, H, I, OT, S, Z> Executor + for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> +where + FH: FridaHelper<'b>, + H: FnMut(&I) -> ExitKind, + I: Input + HasTargetBytes, + OT: ObserversTuple, +{ + /// Instruct the target about the input and run + #[inline] + fn run_target( + &mut self, + fuzzer: &mut Z, + state: &mut S, + mgr: &mut EM, + input: &I, + ) -> Result { + self.helper.pre_exec(input); + if self.helper.stalker_enabled() { + if self.followed { + self.stalker.activate(NativePointer( + self.base.harness_mut() as *mut _ as *mut c_void + )); + } else { + self.followed = true; + self.stalker + .follow_me::(self.helper.transformer(), None); + } + } + let res = self.base.run_target(fuzzer, state, mgr, input); + if self.helper.stalker_enabled() { + self.stalker.deactivate(); + } + #[cfg(unix)] + if unsafe { ASAN_ERRORS.is_some() && !ASAN_ERRORS.as_ref().unwrap().is_empty() } { + println!("Crashing target as it had ASAN errors"); + unsafe { + libc::raise(libc::SIGABRT); + } + } + self.helper.post_exec(input); + res + } +} + +impl<'a, 'b, 'c, FH, H, I, OT, S> HasObservers + for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> +where + FH: FridaHelper<'b>, + H: FnMut(&I) -> ExitKind, + I: Input + HasTargetBytes, + OT: ObserversTuple, +{ + #[inline] + fn observers(&self) -> &OT { + self.base.observers() + } + + #[inline] + fn observers_mut(&mut self) -> &mut OT { + self.base.observers_mut() + } +} + +impl<'a, 'b, 'c, FH, H, I, OT, S> FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> +where + FH: FridaHelper<'b>, + H: FnMut(&I) -> ExitKind, + I: Input + HasTargetBytes, + OT: ObserversTuple, +{ + pub fn new(gum: &'a Gum, base: InProcessExecutor<'a, H, I, OT, S>, helper: &'c mut FH) -> Self { + let mut stalker = Stalker::new(gum); + + #[cfg(all(not(debug_assertions), target_arch = "x86_64"))] + for range in helper.ranges().gaps(&(0..usize::MAX)) { + println!("excluding range: {:x}-{:x}", range.start, range.end); + stalker.exclude(&MemoryRange::new( + NativePointer(range.start as *mut c_void), + range.end - range.start, + )); + } + + Self { + base, + stalker, + helper, + followed: false, + _phantom: PhantomData, + } + } +} diff --git a/libafl_frida/src/lib.rs b/libafl_frida/src/lib.rs index b96cf1e081..f2fdfe3116 100644 --- a/libafl_frida/src/lib.rs +++ b/libafl_frida/src/lib.rs @@ -22,6 +22,9 @@ pub mod cmplog_rt; /// The `LibAFL` firda helper pub mod helper; +/// The frida executor +pub mod executor; + // for parsing asan and cmplog cores use libafl::bolts::os::parse_core_bind_arg; // for getting current core_id