Resolve symbols in PIC binaries in libafl_qemu (#216)

* empty libafl_qemu crate

* fuzzbench qemu fuzzer skeleton

* emu.run() works without bp

* working emu loop

* resolve elf symbols

* running Qemu fuzzer without coverage

* qemu fuzzer with edge coverage

* merge into inprocess::GLOBAL_STATE

* create QemuExecutor and remove QemuEmulator

* qemu hooks and persist edges mapping storing them in State

* windows fix

* add libafl_qemu to workspace

* windows fix

* some clippy

* clippy

* fix fuzzbench_qemu

* fix fuzzbench_qemu makefile

* fuck you macos

* resolve PIC symbols
This commit is contained in:
Andrea Fioraldi 2021-07-09 15:17:57 +02:00 committed by GitHub
parent 4af9af784f
commit badf3f0e6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 4 deletions

View File

@ -153,7 +153,9 @@ fn fuzz(
let mut elf_buffer = Vec::new(); let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(emu::binary_path(), &mut elf_buffer)?; let elf = EasyElf::from_file(emu::binary_path(), &mut elf_buffer)?;
let test_one_input_ptr = elf.resolve_symbol("LLVMFuzzerTestOneInput").unwrap(); let test_one_input_ptr = elf
.resolve_symbol("LLVMFuzzerTestOneInput", emu::load_addr())
.expect("Symbol LLVMFuzzerTestOneInput not found".into());
println!("LLVMFuzzerTestOneInput @ {:#x}", test_one_input_ptr); println!("LLVMFuzzerTestOneInput @ {:#x}", test_one_input_ptr);
emu::set_breakpoint(test_one_input_ptr); // LLVMFuzzerTestOneInput emu::set_breakpoint(test_one_input_ptr); // LLVMFuzzerTestOneInput

View File

@ -1,6 +1,6 @@
//! Utilities to parse and process ELFs //! Utilities to parse and process ELFs
use goblin::elf::Elf; use goblin::elf::{header::ET_DYN, Elf};
use std::{convert::AsRef, fs::File, io::Read, path::Path, str}; use std::{convert::AsRef, fs::File, io::Read, path::Path, str};
use libafl::Error; use libafl::Error;
@ -38,18 +38,26 @@ impl<'a> EasyElf<'a> {
} }
#[must_use] #[must_use]
pub fn resolve_symbol(&self, name: &str) -> Option<u64> { pub fn resolve_symbol(&self, name: &str, load_addr: u64) -> Option<u64> {
for sym in self.elf.syms.iter() { for sym in self.elf.syms.iter() {
if let Some(sym_name) = self.elf.strtab.get_at(sym.st_name) { if let Some(sym_name) = self.elf.strtab.get_at(sym.st_name) {
if sym_name == name { if sym_name == name {
return if sym.st_value == 0 { return if sym.st_value == 0 {
None None
} else { } else {
Some(sym.st_value) if self.is_pic() {
Some(sym.st_value + load_addr)
} else {
Some(sym.st_value)
}
}; };
} }
} }
} }
None None
} }
fn is_pic(&self) -> bool {
self.elf.header.e_type == ET_DYN
}
} }

View File

@ -14,6 +14,7 @@ extern "C" {
fn libafl_qemu_set_breakpoint(addr: u64) -> i32; fn libafl_qemu_set_breakpoint(addr: u64) -> i32;
fn libafl_qemu_remove_breakpoint(addr: u64) -> i32; fn libafl_qemu_remove_breakpoint(addr: u64) -> i32;
fn libafl_qemu_run() -> i32; fn libafl_qemu_run() -> i32;
fn libafl_load_addr() -> u64;
fn strlen(s: *const u8) -> usize; fn strlen(s: *const u8) -> usize;
@ -129,6 +130,11 @@ pub fn binary_path<'a>() -> &'a str {
unsafe { from_utf8_unchecked(from_raw_parts(exec_path, strlen(exec_path))) } unsafe { from_utf8_unchecked(from_raw_parts(exec_path, strlen(exec_path))) }
} }
#[must_use]
pub fn load_addr() -> u64 {
unsafe { libafl_load_addr() }
}
pub fn map_private(addr: u64, size: usize, perms: MmapPerms) -> Result<u64, String> { pub fn map_private(addr: u64, size: usize, perms: MmapPerms) -> Result<u64, String> {
let res = unsafe { let res = unsafe {
target_mmap( target_mmap(