Frida Refactor: Frida executor (#374)
* frida executor * add files * fmt & clippy * fmt * fix * fmt * fix & fmt
This commit is contained in:
parent
ba969108e3
commit
fd869ba1cd
@ -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)]
|
||||||
|
126
libafl_frida/src/executor.rs
Normal file
126
libafl_frida/src/executor.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user