From b70833f26b9df6a15d5d74c4fd26bdd11317319d Mon Sep 17 00:00:00 2001 From: Dongjia Zhang Date: Thu, 13 Jan 2022 18:45:15 +0900 Subject: [PATCH] Libafl_frida ASan shadow bit (#455) * add * debugging * remove debug code * fmt * why * writable or executable ranges * for * fmt * fix --- libafl_frida/src/alloc.rs | 101 ++++++++++++++++++------------- libafl_frida/src/asan/asan_rt.rs | 1 - 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/libafl_frida/src/alloc.rs b/libafl_frida/src/alloc.rs index e97d6fe87c..3a77e475cd 100644 --- a/libafl_frida/src/alloc.rs +++ b/libafl_frida/src/alloc.rs @@ -85,6 +85,7 @@ impl Allocator { all(target_arch = "aarch64", target_os = "android") ))] #[must_use] + #[allow(clippy::too_many_lines)] pub fn new(options: FridaOptions) -> Self { let ret = unsafe { sysconf(_SC_PAGESIZE) }; assert!( @@ -98,55 +99,73 @@ impl Allocator { // probe to find a usable shadow bit: let mut shadow_bit = 0; - #[cfg(all(target_arch = "aarch64", target_os = "android"))] - for try_shadow_bit in &[44usize, 36usize] { - let addr: usize = 1 << try_shadow_bit; - if unsafe { - mmap( - addr as *mut c_void, - page_size, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_PRIVATE - | ANONYMOUS_FLAG - | MapFlags::MAP_FIXED - | MapFlags::MAP_NORESERVE, - -1, - 0, - ) - } - .is_ok() - { - shadow_bit = *try_shadow_bit; + let mut occupied_ranges: Vec<(usize, usize)> = vec![]; + // max(userspace address) this is usually 0x8_0000_0000_0000 - 1 on x64 linux. + let mut userspace_max: usize = 0; + + for prot in [ + PageProtection::Read, + PageProtection::Write, + PageProtection::Execute, + ] { + RangeDetails::enumerate_with_prot(prot, &mut |details| { + let start = details.memory_range().base_address().0 as usize; + let end = start + details.memory_range().size(); + occupied_ranges.push((start, end)); + // println!("{:x} {:x}", start, end); + if end > userspace_max { + userspace_max = end; + } + true + }); + } + + let mut maxbit = 0; + for power in 1..64 { + let base: usize = 2; + if base.pow(power) > userspace_max { + maxbit = power; break; } } - // x86_64's userspace's up to 0x7fff-ffff-ffff so 46 is not available. (0x4000-0000-0000 - 0xc000-0000-0000) - // we'd also want to avoid 0x5555-xxxx-xxxx because programs are mapped there. so 45 is not available either (0x2000-0000-0000 - 0x6000-0000-0000). - // This memory map is for amd64 linux. - #[cfg(target_os = "linux")] { - let try_shadow_bit: usize = 44; - let addr: usize = 1 << try_shadow_bit; - if unsafe { - mmap( - addr as *mut c_void, - page_size, - ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, - MapFlags::MAP_PRIVATE - | ANONYMOUS_FLAG - | MapFlags::MAP_FIXED - | MapFlags::MAP_NORESERVE, - -1, - 0, - ) - } - .is_ok() - { - shadow_bit = try_shadow_bit; + for try_shadow_bit in &[maxbit - 4, maxbit - 3, maxbit - 2] { + let addr: usize = 1 << try_shadow_bit; + let shadow_start = addr; + let shadow_end = addr + addr + addr; + + // check if the proposed shadow bit overlaps with occupied ranges. + for (start, end) in &occupied_ranges { + if (shadow_start <= *end) && (*start <= shadow_end) { + // println!("{:x} {:x}, {:x} {:x}",shadow_start,shadow_end,start,end); + println!("shadow_bit {:x} is not suitable", try_shadow_bit); + break; + } + } + + if unsafe { + mmap( + addr as *mut c_void, + page_size, + ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, + MapFlags::MAP_PRIVATE + | ANONYMOUS_FLAG + | MapFlags::MAP_FIXED + | MapFlags::MAP_NORESERVE, + -1, + 0, + ) + } + .is_ok() + { + shadow_bit = (*try_shadow_bit).try_into().unwrap(); + break; + } } } + println!("shadow_bit {:x} is suitable", shadow_bit); assert!(shadow_bit != 0); // attempt to pre-map the entire shadow-memory space diff --git a/libafl_frida/src/asan/asan_rt.rs b/libafl_frida/src/asan/asan_rt.rs index 27fda05450..af4cc11480 100644 --- a/libafl_frida/src/asan/asan_rt.rs +++ b/libafl_frida/src/asan/asan_rt.rs @@ -2155,7 +2155,6 @@ impl AsanRuntime { .unwrap() .arch_detail() .operands(); - // Ignore lea instruction // put nop into the white-list so that instructions like // like `nop dword [rax + rax]` does not get caught.