Various frida/ashmem fixes (#116)
* Fix incorrect encoding of and imm: use a register for now * Fix assumption regarding length of ashmem clients list * Make harness less chatty * Fix refcounting in the ashmem server * Always work around the frida allocate-near bug, not just when doing asan. * Add support for ashmem on devices which have a boot secret, but don't use it * Formatting
This commit is contained in:
parent
bfbaa7ae83
commit
533a93ddd6
@ -87,7 +87,7 @@ extern "C" int afl_libfuzzer_init() {
|
|||||||
static char * allocation = NULL;
|
static char * allocation = NULL;
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
void func3( char * alloc) {
|
void func3( char * alloc) {
|
||||||
printf("func3\n");
|
//printf("func3\n");
|
||||||
if (random() == 0) {
|
if (random() == 0) {
|
||||||
alloc[0x1ff] = 0xde;
|
alloc[0x1ff] = 0xde;
|
||||||
printf("alloc[0x200]: %d\n", alloc[0x200]);
|
printf("alloc[0x200]: %d\n", alloc[0x200]);
|
||||||
@ -96,12 +96,12 @@ void func3( char * alloc) {
|
|||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
void func2() {
|
void func2() {
|
||||||
allocation = (char*)malloc(0xff);
|
allocation = (char*)malloc(0xff);
|
||||||
printf("func2\n");
|
//printf("func2\n");
|
||||||
func3(allocation);
|
func3(allocation);
|
||||||
}
|
}
|
||||||
__attribute__((noinline))
|
__attribute__((noinline))
|
||||||
void func1() {
|
void func1() {
|
||||||
printf("func1\n");
|
//printf("func1\n");
|
||||||
func2();
|
func2();
|
||||||
}
|
}
|
||||||
// Entry point for LibFuzzer.
|
// Entry point for LibFuzzer.
|
||||||
|
@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
rc::Rc,
|
rc::{Rc, Weak},
|
||||||
sync::{Arc, Condvar, Mutex},
|
sync::{Arc, Condvar, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,8 +167,8 @@ impl ShMemProvider for ServedShMemProvider {
|
|||||||
fn release_map(&mut self, map: &mut Self::Mem) {
|
fn release_map(&mut self, map: &mut Self::Mem) {
|
||||||
let (refcount, _) = self
|
let (refcount, _) = self
|
||||||
.send_receive(AshmemRequest::Deregister(map.server_fd))
|
.send_receive(AshmemRequest::Deregister(map.server_fd))
|
||||||
.expect("Could not communicate to AshMem server!");
|
.expect("Could not communicate with AshMem server!");
|
||||||
if refcount == 0 {
|
if refcount == 1 {
|
||||||
unsafe {
|
unsafe {
|
||||||
ManuallyDrop::drop(&mut map.inner);
|
ManuallyDrop::drop(&mut map.inner);
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ impl AshmemClient {
|
|||||||
pub struct AshmemService {
|
pub struct AshmemService {
|
||||||
provider: AshmemShMemProvider,
|
provider: AshmemShMemProvider,
|
||||||
clients: HashMap<RawFd, AshmemClient>,
|
clients: HashMap<RawFd, AshmemClient>,
|
||||||
all_maps: HashMap<i32, Rc<RefCell<AshmemShMem>>>,
|
all_maps: HashMap<i32, Weak<RefCell<AshmemShMem>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -252,9 +252,14 @@ impl AshmemService {
|
|||||||
};
|
};
|
||||||
Ok(AshmemResponse::Id(client_id))
|
Ok(AshmemResponse::Id(client_id))
|
||||||
}
|
}
|
||||||
AshmemRequest::NewMap(map_size) => Ok(AshmemResponse::Mapping(Rc::new(RefCell::new(
|
AshmemRequest::NewMap(map_size) => {
|
||||||
self.provider.new_map(map_size)?,
|
let new_map = self.provider.new_map(map_size)?;
|
||||||
)))),
|
let description = new_map.description();
|
||||||
|
let new_rc = Rc::new(RefCell::new(new_map));
|
||||||
|
self.all_maps
|
||||||
|
.insert(description.id.to_int(), Rc::downgrade(&new_rc));
|
||||||
|
Ok(AshmemResponse::Mapping(new_rc))
|
||||||
|
}
|
||||||
AshmemRequest::ExistingMap(description) => {
|
AshmemRequest::ExistingMap(description) => {
|
||||||
let client = self.clients.get_mut(&client_id).unwrap();
|
let client = self.clients.get_mut(&client_id).unwrap();
|
||||||
if client.maps.contains_key(&description.id.to_int()) {
|
if client.maps.contains_key(&description.id.to_int()) {
|
||||||
@ -269,25 +274,27 @@ impl AshmemService {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.clone(),
|
.clone(),
|
||||||
))
|
))
|
||||||
} else if self.all_maps.contains_key(&description.id.to_int()) {
|
} else {
|
||||||
Ok(AshmemResponse::Mapping(
|
Ok(AshmemResponse::Mapping(
|
||||||
self.all_maps
|
self.all_maps
|
||||||
.get_mut(&description.id.to_int())
|
.get_mut(&description.id.to_int())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone(),
|
.clone()
|
||||||
|
.upgrade()
|
||||||
|
.unwrap(),
|
||||||
))
|
))
|
||||||
} else {
|
|
||||||
let new_rc =
|
|
||||||
Rc::new(RefCell::new(self.provider.from_description(description)?));
|
|
||||||
self.all_maps
|
|
||||||
.insert(description.id.to_int(), new_rc.clone());
|
|
||||||
Ok(AshmemResponse::Mapping(new_rc))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AshmemRequest::Deregister(map_id) => {
|
AshmemRequest::Deregister(map_id) => {
|
||||||
let client = self.clients.get_mut(&client_id).unwrap();
|
let client = self.clients.get_mut(&client_id).unwrap();
|
||||||
let map = client.maps.entry(map_id).or_default().pop().unwrap();
|
let maps = client.maps.entry(map_id).or_default();
|
||||||
Ok(AshmemResponse::RefCount(Rc::strong_count(&map) as u32))
|
if maps.is_empty() {
|
||||||
|
Ok(AshmemResponse::RefCount(0u32))
|
||||||
|
} else {
|
||||||
|
Ok(AshmemResponse::RefCount(
|
||||||
|
Rc::strong_count(&maps.pop().unwrap()) as u32,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//println!("send ashmem client: {}, response: {:?}", client_id, &response);
|
//println!("send ashmem client: {}, response: {:?}", client_id, &response);
|
||||||
|
@ -656,7 +656,13 @@ pub mod unix_shmem {
|
|||||||
if let Ok(boot_id) =
|
if let Ok(boot_id) =
|
||||||
std::fs::read_to_string("/proc/sys/kernel/random/boot_id")
|
std::fs::read_to_string("/proc/sys/kernel/random/boot_id")
|
||||||
{
|
{
|
||||||
format!("{}{}", "/dev/ashmem", boot_id).trim().to_string()
|
let path_str =
|
||||||
|
format!("{}{}", "/dev/ashmem", boot_id).trim().to_string();
|
||||||
|
if std::path::Path::new(&path_str).exists() {
|
||||||
|
path_str
|
||||||
|
} else {
|
||||||
|
"/dev/ashmem".to_string()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
"/dev/ashmem".to_string()
|
"/dev/ashmem".to_string()
|
||||||
},
|
},
|
||||||
|
@ -745,30 +745,6 @@ impl AsanRuntime {
|
|||||||
/// instance after this function has been called, as the generated blobs would become
|
/// instance after this function has been called, as the generated blobs would become
|
||||||
/// invalid!
|
/// invalid!
|
||||||
pub fn init(&mut self, modules_to_instrument: &[PathBuf]) {
|
pub fn init(&mut self, modules_to_instrument: &[PathBuf]) {
|
||||||
// workaround frida's frida-gum-allocate-near bug:
|
|
||||||
unsafe {
|
|
||||||
for _ in 0..512 {
|
|
||||||
mmap(
|
|
||||||
std::ptr::null_mut(),
|
|
||||||
128 * 1024,
|
|
||||||
ProtFlags::PROT_NONE,
|
|
||||||
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.expect("Failed to map dummy regions for frida workaround");
|
|
||||||
mmap(
|
|
||||||
std::ptr::null_mut(),
|
|
||||||
4 * 1024 * 1024,
|
|
||||||
ProtFlags::PROT_NONE,
|
|
||||||
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
|
|
||||||
-1,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.expect("Failed to map dummy regions for frida workaround");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ASAN_ERRORS = Some(AsanErrors::new());
|
ASAN_ERRORS = Some(AsanErrors::new());
|
||||||
}
|
}
|
||||||
@ -1443,7 +1419,7 @@ impl AsanRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
fn generate_shadow_check_exact_blob(&mut self, val: u32) -> Box<[u8]> {
|
fn generate_shadow_check_exact_blob(&mut self, val: u64) -> Box<[u8]> {
|
||||||
let shadow_bit = Allocator::get().shadow_bit as u32;
|
let shadow_bit = Allocator::get().shadow_bit as u32;
|
||||||
macro_rules! shadow_check_exact {
|
macro_rules! shadow_check_exact {
|
||||||
($ops:ident, $val:expr) => {dynasm!($ops
|
($ops:ident, $val:expr) => {dynasm!($ops
|
||||||
@ -1460,9 +1436,11 @@ impl AsanRuntime {
|
|||||||
; lsr x1, x1, #16
|
; lsr x1, x1, #16
|
||||||
; lsr x1, x1, x0
|
; lsr x1, x1, x0
|
||||||
; .dword -717536768 // 0xd53b4200 //mrs x0, NZCV
|
; .dword -717536768 // 0xd53b4200 //mrs x0, NZCV
|
||||||
; and x1, x1, #$val as u64
|
; stp x2, x3, [sp, #-0x10]!
|
||||||
; cmp x1, #$val
|
; mov x2, $val
|
||||||
; b.eq >done
|
; ands x1, x1, x2
|
||||||
|
; ldp x2, x3, [sp], 0x10
|
||||||
|
; b.ne >done
|
||||||
|
|
||||||
; adr x1, >done
|
; adr x1, >done
|
||||||
; nop // will be replaced by b to report
|
; nop // will be replaced by b to report
|
||||||
|
@ -36,6 +36,8 @@ use num_traits::cast::FromPrimitive;
|
|||||||
use rangemap::RangeMap;
|
use rangemap::RangeMap;
|
||||||
use std::{path::PathBuf, rc::Rc};
|
use std::{path::PathBuf, rc::Rc};
|
||||||
|
|
||||||
|
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
|
||||||
|
|
||||||
use crate::{asan_rt::AsanRuntime, FridaOptions};
|
use crate::{asan_rt::AsanRuntime, FridaOptions};
|
||||||
|
|
||||||
/// An helper that feeds [`FridaInProcessExecutor`] with user-supplied instrumentation
|
/// An helper that feeds [`FridaInProcessExecutor`] with user-supplied instrumentation
|
||||||
@ -216,6 +218,30 @@ impl<'a> FridaInstrumentationHelper<'a> {
|
|||||||
_harness_module_name: &str,
|
_harness_module_name: &str,
|
||||||
modules_to_instrument: &'a [PathBuf],
|
modules_to_instrument: &'a [PathBuf],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
// workaround frida's frida-gum-allocate-near bug:
|
||||||
|
unsafe {
|
||||||
|
for _ in 0..512 {
|
||||||
|
mmap(
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
128 * 1024,
|
||||||
|
ProtFlags::PROT_NONE,
|
||||||
|
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE | MapFlags::MAP_NORESERVE,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.expect("Failed to map dummy regions for frida workaround");
|
||||||
|
mmap(
|
||||||
|
std::ptr::null_mut(),
|
||||||
|
4 * 1024 * 1024,
|
||||||
|
ProtFlags::PROT_NONE,
|
||||||
|
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE | MapFlags::MAP_NORESERVE,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.expect("Failed to map dummy regions for frida workaround");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut helper = Self {
|
let mut helper = Self {
|
||||||
map: [0u8; MAP_SIZE],
|
map: [0u8; MAP_SIZE],
|
||||||
previous_pc: [0u64; 1],
|
previous_pc: [0u64; 1],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user