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:
s1341 2021-12-29 19:47:33 +02:00 committed by GitHub
parent e47c3be3fd
commit b5153cc525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 48 additions and 32 deletions

View File

@ -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",

View File

@ -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;

View File

@ -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(&current_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
} }

View File

@ -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.

View File

@ -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)]

View File

@ -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()
}
}

View File

@ -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()));

View File

@ -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() {