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")
))]
#[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

View File

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