Libafl_frida ASan shadow bit (#455)

* add

* debugging

* remove debug code

* fmt

* why

* writable or executable ranges

* for

* fmt

* fix
This commit is contained in:
Dongjia Zhang 2022-01-13 18:45:15 +09:00 committed by GitHub
parent 906bb4e653
commit b70833f26b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 42 deletions

View File

@ -85,6 +85,7 @@ impl Allocator {
all(target_arch = "aarch64", target_os = "android") all(target_arch = "aarch64", target_os = "android")
))] ))]
#[must_use] #[must_use]
#[allow(clippy::too_many_lines)]
pub fn new(options: FridaOptions) -> Self { pub fn new(options: FridaOptions) -> Self {
let ret = unsafe { sysconf(_SC_PAGESIZE) }; let ret = unsafe { sysconf(_SC_PAGESIZE) };
assert!( assert!(
@ -98,55 +99,73 @@ impl Allocator {
// probe to find a usable shadow bit: // probe to find a usable shadow bit:
let mut shadow_bit = 0; let mut shadow_bit = 0;
#[cfg(all(target_arch = "aarch64", target_os = "android"))] let mut occupied_ranges: Vec<(usize, usize)> = vec![];
for try_shadow_bit in &[44usize, 36usize] { // max(userspace address) this is usually 0x8_0000_0000_0000 - 1 on x64 linux.
let addr: usize = 1 << try_shadow_bit; let mut userspace_max: usize = 0;
if unsafe {
mmap( for prot in [
addr as *mut c_void, PageProtection::Read,
page_size, PageProtection::Write,
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, PageProtection::Execute,
MapFlags::MAP_PRIVATE ] {
| ANONYMOUS_FLAG RangeDetails::enumerate_with_prot(prot, &mut |details| {
| MapFlags::MAP_FIXED let start = details.memory_range().base_address().0 as usize;
| MapFlags::MAP_NORESERVE, let end = start + details.memory_range().size();
-1, occupied_ranges.push((start, end));
0, // println!("{:x} {:x}", start, end);
) if end > userspace_max {
} userspace_max = end;
.is_ok() }
{ true
shadow_bit = *try_shadow_bit; });
}
let mut maxbit = 0;
for power in 1..64 {
let base: usize = 2;
if base.pow(power) > userspace_max {
maxbit = power;
break; 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; for try_shadow_bit in &[maxbit - 4, maxbit - 3, maxbit - 2] {
let addr: usize = 1 << try_shadow_bit; let addr: usize = 1 << try_shadow_bit;
if unsafe { let shadow_start = addr;
mmap( let shadow_end = addr + addr + addr;
addr as *mut c_void,
page_size, // check if the proposed shadow bit overlaps with occupied ranges.
ProtFlags::PROT_READ | ProtFlags::PROT_WRITE, for (start, end) in &occupied_ranges {
MapFlags::MAP_PRIVATE if (shadow_start <= *end) && (*start <= shadow_end) {
| ANONYMOUS_FLAG // println!("{:x} {:x}, {:x} {:x}",shadow_start,shadow_end,start,end);
| MapFlags::MAP_FIXED println!("shadow_bit {:x} is not suitable", try_shadow_bit);
| MapFlags::MAP_NORESERVE, break;
-1, }
0, }
)
} if unsafe {
.is_ok() mmap(
{ addr as *mut c_void,
shadow_bit = try_shadow_bit; 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); assert!(shadow_bit != 0);
// attempt to pre-map the entire shadow-memory space // attempt to pre-map the entire shadow-memory space

View File

@ -2155,7 +2155,6 @@ impl AsanRuntime {
.unwrap() .unwrap()
.arch_detail() .arch_detail()
.operands(); .operands();
// Ignore lea instruction // Ignore lea instruction
// put nop into the white-list so that instructions like // put nop into the white-list so that instructions like
// like `nop dword [rax + rax]` does not get caught. // like `nop dword [rax + rax]` does not get caught.