Frida Refactor: Frida executor (#374)

* frida executor

* add files

* fmt & clippy

* fmt

* fix

* fmt

* fix & fmt
This commit is contained in:
Toka 2021-11-17 20:51:39 +09:00 committed by GitHub
parent ba969108e3
commit fd869ba1cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 134 additions and 128 deletions

View File

@ -17,43 +17,35 @@ use libafl::{
IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler,
}, },
events::{llmp::LlmpRestartingEventManager, EventConfig}, events::{llmp::LlmpRestartingEventManager, EventConfig},
executors::{ executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasObservers,
ShadowExecutor,
},
feedback_or, feedback_or_fast, feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes, Input}, inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor, monitors::MultiMonitor,
mutators::{ mutators::{
scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator}, scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
token_mutations::I2SRandReplace, token_mutations::I2SRandReplace,
token_mutations::Tokens, token_mutations::Tokens,
}, },
observers::{HitcountsMapObserver, ObserversTuple, StdMapObserver, TimeObserver}, observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
stages::{ShadowTracingStage, StdMutationalStage}, stages::{ShadowTracingStage, StdMutationalStage},
state::{HasCorpus, HasMetadata, StdState}, state::{HasCorpus, HasMetadata, StdState},
Error, Error,
}; };
use frida_gum::{ use frida_gum::Gum;
stalker::{NoneEventSink, Stalker},
Gum, MemoryRange, NativePointer,
};
use std::{ use std::{
env, env,
ffi::c_void,
marker::PhantomData,
net::SocketAddr, net::SocketAddr,
path::{Path, PathBuf}, path::{Path, PathBuf},
time::Duration,
}; };
use libafl_frida::{ use libafl_frida::{
coverage_rt::MAP_SIZE, coverage_rt::MAP_SIZE,
helper::{FridaHelper, FridaInstrumentationHelper}, helper::{FridaHelper, FridaInstrumentationHelper},
executor::FridaInProcessExecutor,
FridaOptions, FridaOptions,
}; };
@ -62,120 +54,6 @@ use libafl_frida::asan_errors::{AsanErrorsFeedback, AsanErrorsObserver, ASAN_ERR
use libafl_targets::cmplog::{CmpLogObserver, CMPLOG_MAP}; 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<I, S>,
{
base: TimeoutExecutor<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<EM, I, S, Z>
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
where
FH: FridaHelper<'b>,
H: FnMut(&I) -> ExitKind,
I: Input + HasTargetBytes,
OT: ObserversTuple<I, S>,
{
/// 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<ExitKind, Error> {
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::<NoneEventSink>(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<I, OT, S>
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
where
FH: FridaHelper<'b>,
H: FnMut(&I) -> ExitKind,
I: Input + HasTargetBytes,
OT: ObserversTuple<I, S>,
{
#[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<I, S>,
{
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 /// The main fn, usually parsing parameters, and starting the fuzzer
pub fn main() { pub fn main() {
// Registry the metadata types used in this fuzzer // Registry the metadata types used in this fuzzer
@ -403,7 +281,6 @@ unsafe fn fuzz(
&mut mgr, &mut mgr,
)?, )?,
&mut frida_helper, &mut frida_helper,
Duration::new(30, 0),
); );
#[cfg(windows)] #[cfg(windows)]

View File

@ -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<I, S>,
{
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<EM, I, S, Z>
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
where
FH: FridaHelper<'b>,
H: FnMut(&I) -> ExitKind,
I: Input + HasTargetBytes,
OT: ObserversTuple<I, S>,
{
/// 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<ExitKind, Error> {
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::<NoneEventSink>(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<I, OT, S>
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
where
FH: FridaHelper<'b>,
H: FnMut(&I) -> ExitKind,
I: Input + HasTargetBytes,
OT: ObserversTuple<I, S>,
{
#[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<I, S>,
{
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,
}
}
}

View File

@ -22,6 +22,9 @@ pub mod cmplog_rt;
/// The `LibAFL` firda helper /// The `LibAFL` firda helper
pub mod helper; pub mod helper;
/// The frida executor
pub mod executor;
// for parsing asan and cmplog cores // for parsing asan and cmplog cores
use libafl::bolts::os::parse_core_bind_arg; use libafl::bolts::os::parse_core_bind_arg;
// for getting current core_id // for getting current core_id