Make FridaInProcessExecutor compatible with TargetBytesConverter, decouple input type from FridaRuntime trait (#2741)
* decouple input type from FridaRuntime trait * fmt * fmt2 * remove HasTargetBytes requirement from FridaInProcessExecutor * fmt * restore comment * fix clippy comment error
This commit is contained in:
parent
ffbb7a0f42
commit
1809c31a46
@ -27,7 +27,7 @@ use frida_gum::{
|
||||
};
|
||||
use frida_gum_sys::Insn;
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{cli::FuzzerOptions, AsSlice};
|
||||
use libafl_bolts::cli::FuzzerOptions;
|
||||
use libc::wchar_t;
|
||||
use rangemap::RangeMap;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@ -190,33 +190,22 @@ impl FridaRuntime for AsanRuntime {
|
||||
self.deregister_hooks(gum);
|
||||
}
|
||||
|
||||
fn pre_exec<I: libafl::inputs::Input + libafl::inputs::HasTargetBytes>(
|
||||
&mut self,
|
||||
input: &I,
|
||||
) -> Result<(), libafl::Error> {
|
||||
let target_bytes = input.target_bytes();
|
||||
let slice = target_bytes.as_slice();
|
||||
|
||||
self.unpoison(slice.as_ptr() as usize, slice.len());
|
||||
fn pre_exec(&mut self, input_bytes: &[u8]) -> Result<(), libafl::Error> {
|
||||
self.unpoison(input_bytes.as_ptr() as usize, input_bytes.len());
|
||||
self.enable_hooks();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn post_exec<I: libafl::inputs::Input + libafl::inputs::HasTargetBytes>(
|
||||
&mut self,
|
||||
input: &I,
|
||||
) -> Result<(), libafl::Error> {
|
||||
fn post_exec(&mut self, input_bytes: &[u8]) -> Result<(), libafl::Error> {
|
||||
self.disable_hooks();
|
||||
if self.check_for_leaks_enabled {
|
||||
self.check_for_leaks();
|
||||
}
|
||||
|
||||
let target_bytes = input.target_bytes();
|
||||
let slice = target_bytes.as_slice();
|
||||
// # Safety
|
||||
// The ptr and length are correct.
|
||||
unsafe {
|
||||
self.poison(slice.as_ptr() as usize, slice.len());
|
||||
self.poison(input_bytes.as_ptr() as usize, input_bytes.len());
|
||||
}
|
||||
self.reset_allocations();
|
||||
|
||||
|
@ -29,10 +29,7 @@ use iced_x86::{
|
||||
BlockEncoder, Code, DecoderOptions, Instruction, InstructionBlock, MemoryOperand, MemorySize,
|
||||
OpKind, Register,
|
||||
};
|
||||
use libafl::{
|
||||
inputs::{HasTargetBytes, Input},
|
||||
Error,
|
||||
};
|
||||
use libafl::Error;
|
||||
use libafl_targets::{cmps::__libafl_targets_cmplog_instructions, CMPLOG_MAP_W};
|
||||
use rangemap::RangeMap;
|
||||
|
||||
@ -132,11 +129,11 @@ impl FridaRuntime for CmpLogRuntime {
|
||||
|
||||
fn deinit(&mut self, _gum: &frida_gum::Gum) {}
|
||||
|
||||
fn pre_exec<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
||||
fn pre_exec(&mut self, _input_bytes: &[u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn post_exec<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
||||
fn post_exec(&mut self, _input_bytes: &[u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -44,17 +44,11 @@ impl FridaRuntime for CoverageRuntime {
|
||||
|
||||
fn deinit(&mut self, _gum: &frida_gum::Gum) {}
|
||||
|
||||
fn pre_exec<I: libafl::inputs::Input + libafl::inputs::HasTargetBytes>(
|
||||
&mut self,
|
||||
_input: &I,
|
||||
) -> Result<(), libafl::Error> {
|
||||
fn pre_exec(&mut self, _input_bytes: &[u8]) -> Result<(), libafl::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn post_exec<I: libafl::inputs::Input + libafl::inputs::HasTargetBytes>(
|
||||
&mut self,
|
||||
_input: &I,
|
||||
) -> Result<(), libafl::Error> {
|
||||
fn post_exec(&mut self, _input_bytes: &[u8]) -> Result<(), libafl::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,7 @@ use std::{
|
||||
|
||||
use ahash::RandomState;
|
||||
use frida_gum::ModuleMap;
|
||||
use libafl::{
|
||||
inputs::{HasTargetBytes, Input},
|
||||
Error,
|
||||
};
|
||||
use libafl_bolts::AsSlice;
|
||||
use libafl::Error;
|
||||
use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter};
|
||||
use rangemap::RangeMap;
|
||||
|
||||
@ -43,20 +39,20 @@ impl FridaRuntime for DrCovRuntime {
|
||||
fn deinit(&mut self, _gum: &frida_gum::Gum) {}
|
||||
|
||||
/// Called before execution, does nothing
|
||||
fn pre_exec<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
||||
fn pre_exec(&mut self, _input_bytes: &[u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Called after execution, writes the trace to a unique `DrCov` file for this trace
|
||||
/// into `./coverage/<input_hash>_<coverage_hash>.drcov`. Empty coverages will be skipped.
|
||||
fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||
fn post_exec(&mut self, input_bytes: &[u8]) -> Result<(), Error> {
|
||||
// We don't need empty coverage files
|
||||
if self.drcov_basic_blocks.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut input_hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
|
||||
input_hasher.write(input.target_bytes().as_slice());
|
||||
input_hasher.write(input_bytes);
|
||||
let input_hash = input_hasher.finish();
|
||||
|
||||
let mut coverage_hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
|
||||
|
@ -15,12 +15,12 @@ use libafl::{
|
||||
};
|
||||
use libafl::{
|
||||
executors::{Executor, ExitKind, HasObservers, InProcessExecutor},
|
||||
inputs::HasTargetBytes,
|
||||
inputs::{HasTargetBytes, NopTargetBytesConverter, TargetBytesConverter},
|
||||
observers::ObserversTuple,
|
||||
state::{HasExecutions, State, UsesState},
|
||||
Error,
|
||||
};
|
||||
use libafl_bolts::tuples::RefIndexable;
|
||||
use libafl_bolts::{tuples::RefIndexable, AsSlice};
|
||||
|
||||
#[cfg(not(test))]
|
||||
use crate::asan::errors::AsanErrors;
|
||||
@ -29,30 +29,31 @@ use crate::helper::{FridaInstrumentationHelper, FridaRuntimeTuple};
|
||||
use crate::windows_hooks::initialize;
|
||||
|
||||
/// The [`FridaInProcessExecutor`] is an [`Executor`] that executes the target in the same process, usinig [`frida`](https://frida.re/) for binary-only instrumentation.
|
||||
pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S>
|
||||
pub struct FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S::Input: HasTargetBytes,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
'b: 'a,
|
||||
{
|
||||
base: InProcessExecutor<'a, H, OT, S>,
|
||||
// thread_id for the Stalker
|
||||
/// `thread_id` for the Stalker
|
||||
thread_id: Option<u32>,
|
||||
/// Frida's dynamic rewriting engine
|
||||
stalker: Stalker,
|
||||
/// User provided callback for instrumentation
|
||||
helper: &'c mut FridaInstrumentationHelper<'b, RT>,
|
||||
target_bytes_converter: TC,
|
||||
followed: bool,
|
||||
_phantom: PhantomData<&'b u8>,
|
||||
}
|
||||
|
||||
impl<H, OT, RT, S> Debug for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S>
|
||||
impl<H, OT, RT, S, TC> Debug for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State,
|
||||
S::Input: HasTargetBytes,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S> + Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
@ -64,12 +65,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<EM, H, OT, RT, S, Z> Executor<EM, Z> for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S>
|
||||
impl<EM, H, OT, RT, S, TC, Z> Executor<EM, Z>
|
||||
for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
EM: UsesState<State = S>,
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State + HasExecutions,
|
||||
S::Input: HasTargetBytes,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
Z: UsesState<State = S>,
|
||||
@ -83,7 +85,8 @@ where
|
||||
mgr: &mut EM,
|
||||
input: &Self::Input,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.helper.pre_exec(input)?;
|
||||
let target_bytes = self.target_bytes_converter.to_target_bytes(input);
|
||||
self.helper.pre_exec(target_bytes.as_slice())?;
|
||||
if self.helper.stalker_enabled() {
|
||||
if self.followed {
|
||||
self.stalker.activate(NativePointer(core::ptr::null_mut()));
|
||||
@ -115,25 +118,25 @@ where
|
||||
abort();
|
||||
}
|
||||
}
|
||||
self.helper.post_exec(input)?;
|
||||
self.helper.post_exec(target_bytes.as_slice())?;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl<H, OT, RT, S> UsesState for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S>
|
||||
impl<H, OT, RT, S, TC> UsesState for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
S: State,
|
||||
S::Input: HasTargetBytes,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
{
|
||||
type State = S;
|
||||
}
|
||||
|
||||
impl<H, OT, RT, S> HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S>
|
||||
impl<H, OT, RT, S, TC> HasObservers for FridaInProcessExecutor<'_, '_, '_, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S::Input: HasTargetBytes,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
S: State,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
{
|
||||
@ -149,7 +152,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, H, OT, S, RT> FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S>
|
||||
impl<'a, 'b, 'c, H, OT, RT, S>
|
||||
FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, NopTargetBytesConverter<S::Input>>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State,
|
||||
@ -163,7 +167,13 @@ where
|
||||
base: InProcessExecutor<'a, H, OT, S>,
|
||||
helper: &'c mut FridaInstrumentationHelper<'b, RT>,
|
||||
) -> Self {
|
||||
Self::_on_thread(gum, base, helper, None)
|
||||
FridaInProcessExecutor::with_target_bytes_converter(
|
||||
gum,
|
||||
base,
|
||||
helper,
|
||||
None,
|
||||
NopTargetBytesConverter::new(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Creates a new [`FridaInProcessExecutor`] tracking the given `thread_id`.
|
||||
@ -173,23 +183,40 @@ where
|
||||
helper: &'c mut FridaInstrumentationHelper<'b, RT>,
|
||||
thread_id: u32,
|
||||
) -> Self {
|
||||
Self::_on_thread(gum, base, helper, Some(thread_id))
|
||||
FridaInProcessExecutor::with_target_bytes_converter(
|
||||
gum,
|
||||
base,
|
||||
helper,
|
||||
Some(thread_id),
|
||||
NopTargetBytesConverter::new(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new [`FridaInProcessExecutor`] tracking the given `thread_id`, of `thread_id` is provided.
|
||||
fn _on_thread(
|
||||
impl<'a, 'b, 'c, H, OT, RT, S, TC> FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
{
|
||||
/// Creates a new [`FridaInProcessExecutor`].
|
||||
pub fn with_target_bytes_converter(
|
||||
gum: &'a Gum,
|
||||
base: InProcessExecutor<'a, H, OT, S>,
|
||||
helper: &'c mut FridaInstrumentationHelper<'b, RT>,
|
||||
thread_id: Option<u32>,
|
||||
target_bytes_converter: TC,
|
||||
) -> Self {
|
||||
let mut stalker = Stalker::new(gum);
|
||||
// Include the current module (the fuzzer) in stalked ranges. We clone the ranges so that
|
||||
// we don't add it to the INSTRUMENTED ranges.
|
||||
let mut ranges = helper.ranges().clone();
|
||||
for module in frida_gum::Module::obtain(gum).enumerate_modules() {
|
||||
if module.base_address < Self::new as usize
|
||||
&& (Self::new as usize as u64) < module.base_address as u64 + module.size as u64
|
||||
if module.base_address < Self::with_target_bytes_converter as usize
|
||||
&& (Self::with_target_bytes_converter as usize as u64)
|
||||
< module.base_address as u64 + module.size as u64
|
||||
{
|
||||
ranges.insert(
|
||||
module.base_address as u64..(module.base_address as u64 + module.size as u64),
|
||||
@ -220,6 +247,7 @@ where
|
||||
thread_id,
|
||||
stalker,
|
||||
helper,
|
||||
target_bytes_converter,
|
||||
followed: false,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
@ -227,12 +255,12 @@ where
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl<'a, 'b, 'c, H, OT, RT, S> HasInProcessHooks<S>
|
||||
for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S>
|
||||
impl<'a, 'b, 'c, H, OT, RT, S, TC> HasInProcessHooks<S>
|
||||
for FridaInProcessExecutor<'a, 'b, 'c, H, OT, RT, S, TC>
|
||||
where
|
||||
H: FnMut(&S::Input) -> ExitKind,
|
||||
S: State + HasSolutions + HasCorpus + HasExecutions,
|
||||
S::Input: HasTargetBytes,
|
||||
TC: TargetBytesConverter<Input = S::Input>,
|
||||
OT: ObserversTuple<S::Input, S>,
|
||||
RT: FridaRuntimeTuple,
|
||||
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
|
@ -13,10 +13,7 @@ use frida_gum::{
|
||||
Backend, Gum, ModuleDetails, ModuleMap, Script,
|
||||
};
|
||||
use frida_gum_sys::gchar;
|
||||
use libafl::{
|
||||
inputs::{HasTargetBytes, Input},
|
||||
Error,
|
||||
};
|
||||
use libafl::Error;
|
||||
use libafl_bolts::{
|
||||
cli::{FridaScriptBackend, FuzzerOptions},
|
||||
tuples::MatchFirstType,
|
||||
@ -49,10 +46,10 @@ pub trait FridaRuntime: 'static + Debug {
|
||||
fn deinit(&mut self, gum: &Gum);
|
||||
|
||||
/// Method called before execution
|
||||
fn pre_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error>;
|
||||
fn pre_exec(&mut self, input_bytes: &[u8]) -> Result<(), Error>;
|
||||
|
||||
/// Method called after execution
|
||||
fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error>;
|
||||
fn post_exec(&mut self, input_bytes: &[u8]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// The tuple for Frida Runtime
|
||||
@ -69,10 +66,10 @@ pub trait FridaRuntimeTuple: MatchFirstType + Debug {
|
||||
fn deinit_all(&mut self, gum: &Gum);
|
||||
|
||||
/// Method called before execution
|
||||
fn pre_exec_all<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error>;
|
||||
fn pre_exec_all(&mut self, input_bytes: &[u8]) -> Result<(), Error>;
|
||||
|
||||
/// Method called after execution
|
||||
fn post_exec_all<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error>;
|
||||
fn post_exec_all(&mut self, input_bytes: &[u8]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
impl FridaRuntimeTuple for () {
|
||||
@ -85,10 +82,10 @@ impl FridaRuntimeTuple for () {
|
||||
}
|
||||
fn deinit_all(&mut self, _gum: &Gum) {}
|
||||
|
||||
fn pre_exec_all<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
||||
fn pre_exec_all(&mut self, _input_bytes: &[u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
fn post_exec_all<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
||||
fn post_exec_all(&mut self, _input_bytes: &[u8]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -113,14 +110,14 @@ where
|
||||
self.1.deinit_all(gum);
|
||||
}
|
||||
|
||||
fn pre_exec_all<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||
self.0.pre_exec(input)?;
|
||||
self.1.pre_exec_all(input)
|
||||
fn pre_exec_all(&mut self, input_bytes: &[u8]) -> Result<(), Error> {
|
||||
self.0.pre_exec(input_bytes)?;
|
||||
self.1.pre_exec_all(input_bytes)
|
||||
}
|
||||
|
||||
fn post_exec_all<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||
self.0.post_exec(input)?;
|
||||
self.1.post_exec_all(input)
|
||||
fn post_exec_all(&mut self, input_bytes: &[u8]) -> Result<(), Error> {
|
||||
self.0.post_exec(input_bytes)?;
|
||||
self.1.post_exec_all(input_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@ -709,13 +706,13 @@ where
|
||||
}
|
||||
|
||||
/// Method called before execution
|
||||
pub fn pre_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||
(*self.runtimes).borrow_mut().pre_exec_all(input)
|
||||
pub fn pre_exec(&mut self, input_bytes: &[u8]) -> Result<(), Error> {
|
||||
(*self.runtimes).borrow_mut().pre_exec_all(input_bytes)
|
||||
}
|
||||
|
||||
/// Method called after execution
|
||||
pub fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||
(*self.runtimes).borrow_mut().post_exec_all(input)
|
||||
pub fn post_exec(&mut self, input_bytes: &[u8]) -> Result<(), Error> {
|
||||
(*self.runtimes).borrow_mut().post_exec_all(input_bytes)
|
||||
}
|
||||
|
||||
/// If stalker is enabled
|
||||
|
Loading…
x
Reference in New Issue
Block a user