Frida various fixes (#436)
* Make drcov post_exec dependent on whether drcov is enabled * Fix find_smallest_fit algorithm * Fix missing ? * fix warnings * fix * todo for non-linux/android shadow, clippy * typo * removed unsupposted eq * cleanup, docu * libafl::Error * fixed import Co-authored-by: tokatoka <tokazerkje@outlook.com> Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
parent
e47c3be3fd
commit
b5153cc525
@ -110,6 +110,7 @@ struct Opt {
|
|||||||
)]
|
)]
|
||||||
output: PathBuf,
|
output: PathBuf,
|
||||||
|
|
||||||
|
/*
|
||||||
#[structopt(
|
#[structopt(
|
||||||
parse(try_from_str = timeout_from_millis_str),
|
parse(try_from_str = timeout_from_millis_str),
|
||||||
short,
|
short,
|
||||||
@ -129,7 +130,7 @@ struct Opt {
|
|||||||
multiple = true
|
multiple = true
|
||||||
)]
|
)]
|
||||||
tokens: Vec<PathBuf>,
|
tokens: Vec<PathBuf>,
|
||||||
|
*/
|
||||||
#[structopt(
|
#[structopt(
|
||||||
long,
|
long,
|
||||||
help = "The configuration this fuzzer runs with, for multiprocessing",
|
help = "The configuration this fuzzer runs with, for multiprocessing",
|
||||||
|
@ -112,11 +112,9 @@ where
|
|||||||
println!("spawning on cores: {:?}", self.cores);
|
println!("spawning on cores: {:?}", self.cores);
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
let stdout_file = if let Some(filename) = self.stdout_file {
|
let stdout_file = self
|
||||||
Some(File::create(filename).unwrap())
|
.stdout_file
|
||||||
} else {
|
.map(|filename| File::create(filename).unwrap());
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spawn clients
|
// Spawn clients
|
||||||
let mut index = 0_u64;
|
let mut index = 0_u64;
|
||||||
|
@ -10,7 +10,7 @@ use backtrace::Backtrace;
|
|||||||
use libc::{sysconf, _SC_PAGESIZE};
|
use libc::{sysconf, _SC_PAGESIZE};
|
||||||
use rangemap::RangeSet;
|
use rangemap::RangeSet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{ffi::c_void, io};
|
use std::{collections::BTreeMap, ffi::c_void, io};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
asan::errors::{AsanError, AsanErrors},
|
asan::errors::{AsanError, AsanErrors},
|
||||||
@ -26,7 +26,7 @@ pub struct Allocator {
|
|||||||
pre_allocated_shadow: bool,
|
pre_allocated_shadow: bool,
|
||||||
allocations: HashMap<usize, AllocationMetadata>,
|
allocations: HashMap<usize, AllocationMetadata>,
|
||||||
shadow_pages: RangeSet<usize>,
|
shadow_pages: RangeSet<usize>,
|
||||||
allocation_queue: HashMap<usize, Vec<AllocationMetadata>>,
|
allocation_queue: BTreeMap<usize, Vec<AllocationMetadata>>,
|
||||||
largest_allocation: usize,
|
largest_allocation: usize,
|
||||||
total_allocation_size: usize,
|
total_allocation_size: usize,
|
||||||
base_mapping_addr: usize,
|
base_mapping_addr: usize,
|
||||||
@ -118,8 +118,13 @@ impl Allocator {
|
|||||||
shadow_bit = try_shadow_bit;
|
shadow_bit = try_shadow_bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(shadow_bit != 0);
|
#[cfg(not(any(
|
||||||
|
target_os = "linux",
|
||||||
|
all(target_arch = "aarch64", target_os = "android")
|
||||||
|
)))]
|
||||||
|
todo!("Shadow region not yet supported for this platform!");
|
||||||
|
|
||||||
|
assert!(shadow_bit != 0);
|
||||||
// attempt to pre-map the entire shadow-memory space
|
// attempt to pre-map the entire shadow-memory space
|
||||||
|
|
||||||
let addr: usize = 1 << shadow_bit;
|
let addr: usize = 1 << shadow_bit;
|
||||||
@ -146,7 +151,7 @@ impl Allocator {
|
|||||||
shadow_bit,
|
shadow_bit,
|
||||||
allocations: HashMap::new(),
|
allocations: HashMap::new(),
|
||||||
shadow_pages: RangeSet::new(),
|
shadow_pages: RangeSet::new(),
|
||||||
allocation_queue: HashMap::new(),
|
allocation_queue: BTreeMap::new(),
|
||||||
largest_allocation: 0,
|
largest_allocation: 0,
|
||||||
total_allocation_size: 0,
|
total_allocation_size: 0,
|
||||||
base_mapping_addr: addr + addr + addr,
|
base_mapping_addr: addr + addr + addr,
|
||||||
@ -173,15 +178,12 @@ impl Allocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn find_smallest_fit(&mut self, size: usize) -> Option<AllocationMetadata> {
|
fn find_smallest_fit(&mut self, size: usize) -> Option<AllocationMetadata> {
|
||||||
let mut current_size = size;
|
for (current_size, list) in &mut self.allocation_queue {
|
||||||
while current_size <= self.largest_allocation {
|
if *current_size >= size {
|
||||||
if self.allocation_queue.contains_key(¤t_size) {
|
if let Some(metadata) = list.pop() {
|
||||||
if let Some(metadata) = self.allocation_queue.entry(current_size).or_default().pop()
|
|
||||||
{
|
|
||||||
return Some(metadata);
|
return Some(metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_size *= 2;
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,10 @@ even if the target would not have crashed under normal conditions.
|
|||||||
this helps finding mem errors early.
|
this helps finding mem errors early.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use frida_gum::NativePointer;
|
|
||||||
use frida_gum::{ModuleDetails, RangeDetails};
|
|
||||||
use hashbrown::HashMap;
|
|
||||||
|
|
||||||
use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
|
|
||||||
|
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
|
use frida_gum::{ModuleDetails, NativePointer, RangeDetails};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
|
||||||
|
|
||||||
use crate::helper::FridaInstrumentationHelper;
|
use crate::helper::FridaInstrumentationHelper;
|
||||||
|
|
||||||
@ -182,10 +179,9 @@ impl AsanRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.hook_functions(_gum);
|
self.hook_functions(_gum);
|
||||||
|
/*
|
||||||
unsafe {
|
unsafe {
|
||||||
let mem = self.allocator.alloc(0xac + 2, 8);
|
let mem = self.allocator.alloc(0xac + 2, 8);
|
||||||
unsafe {
|
|
||||||
mprotect(
|
mprotect(
|
||||||
(self.shadow_check_func.unwrap() as usize & 0xffffffffffff000) as *mut c_void,
|
(self.shadow_check_func.unwrap() as usize & 0xffffffffffff000) as *mut c_void,
|
||||||
0x1000,
|
0x1000,
|
||||||
@ -256,6 +252,7 @@ impl AsanRuntime {
|
|||||||
}
|
}
|
||||||
// assert!((self.shadow_check_func.unwrap())(((mem2 as usize) + 8875) as *const c_void, 4));
|
// assert!((self.shadow_check_func.unwrap())(((mem2 as usize) + 8875) as *const c_void, 4));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset all allocations so that they can be reused for new allocation requests.
|
/// Reset all allocations so that they can be reused for new allocation requests.
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
use crate::asan::asan_rt::ASAN_SAVE_REGISTER_NAMES;
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
use capstone::{arch::BuildsCapstone, Capstone};
|
use capstone::{arch::BuildsCapstone, Capstone};
|
||||||
use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity};
|
use color_backtrace::{default_output_stream, BacktracePrinter, Verbosity};
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use frida_gum::interceptor::Interceptor;
|
use frida_gum::interceptor::Interceptor;
|
||||||
use frida_gum::ModuleDetails;
|
use frida_gum::ModuleDetails;
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{ownedref::OwnedPtr, tuples::Named},
|
bolts::{ownedref::OwnedPtr, tuples::Named},
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
@ -20,9 +21,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use termcolor::{Color, ColorSpec, WriteColor};
|
use termcolor::{Color, ColorSpec, WriteColor};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use crate::asan::asan_rt::ASAN_SAVE_REGISTER_NAMES;
|
|
||||||
|
|
||||||
use crate::{alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT, FridaOptions};
|
use crate::{alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT, FridaOptions};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
@ -1,16 +1,24 @@
|
|||||||
|
//! Generates `DrCov` traces
|
||||||
use ahash::AHasher;
|
use ahash::AHasher;
|
||||||
use libafl::inputs::{HasTargetBytes, Input};
|
use libafl::{
|
||||||
use libafl::Error;
|
inputs::{HasTargetBytes, Input},
|
||||||
|
Error,
|
||||||
|
};
|
||||||
use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter};
|
use libafl_targets::drcov::{DrCovBasicBlock, DrCovWriter};
|
||||||
use rangemap::RangeMap;
|
use rangemap::RangeMap;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
|
|
||||||
|
/// Generates `DrCov` traces
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct DrCovRuntime {
|
pub struct DrCovRuntime {
|
||||||
|
/// The basic blocks of this execution
|
||||||
pub drcov_basic_blocks: Vec<DrCovBasicBlock>,
|
pub drcov_basic_blocks: Vec<DrCovBasicBlock>,
|
||||||
|
/// The memory ragnes of this target
|
||||||
ranges: RangeMap<usize, (u16, String)>,
|
ranges: RangeMap<usize, (u16, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DrCovRuntime {
|
impl DrCovRuntime {
|
||||||
|
/// Creates a new [`DrCovRuntime`]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -19,15 +27,19 @@ impl DrCovRuntime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// initializes this runtime wiith the given `ranges`
|
||||||
pub fn init(&mut self, ranges: &RangeMap<usize, (u16, String)>) {
|
pub fn init(&mut self, ranges: &RangeMap<usize, (u16, String)>) {
|
||||||
self.ranges = ranges.clone();
|
self.ranges = ranges.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called before execution, does nothing
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
pub fn pre_exec<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
pub fn pre_exec<I: Input + HasTargetBytes>(&mut self, _input: &I) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called after execution, writes the trace to a unique `DrCov` file for this trace
|
||||||
|
/// into `./coverage/<trace_hash>.drcov`
|
||||||
pub fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
pub fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||||
let mut hasher = AHasher::new_with_keys(0, 0);
|
let mut hasher = AHasher::new_with_keys(0, 0);
|
||||||
hasher.write(input.target_bytes().as_slice());
|
hasher.write(input.target_bytes().as_slice());
|
||||||
@ -39,3 +51,9 @@ impl DrCovRuntime {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for DrCovRuntime {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -55,7 +55,7 @@ where
|
|||||||
mgr: &mut EM,
|
mgr: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
self.helper.pre_exec(input);
|
self.helper.pre_exec(input)?;
|
||||||
if self.helper.stalker_enabled() {
|
if self.helper.stalker_enabled() {
|
||||||
if self.followed {
|
if self.followed {
|
||||||
self.stalker.activate(NativePointer(core::ptr::null_mut()));
|
self.stalker.activate(NativePointer(core::ptr::null_mut()));
|
||||||
|
@ -125,7 +125,9 @@ impl<'a> FridaHelper<'a> for FridaInstrumentationHelper<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
fn post_exec<I: Input + HasTargetBytes>(&mut self, input: &I) -> Result<(), Error> {
|
||||||
self.drcov_runtime.post_exec(input)?;
|
if self.options().enable_drcov {
|
||||||
|
self.drcov_runtime.post_exec(input)?;
|
||||||
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if self.options.asan_enabled() {
|
if self.options.asan_enabled() {
|
||||||
if self.options.asan_detect_leaks() {
|
if self.options.asan_detect_leaks() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user