diff --git a/fuzzers/wcet_qemu_sys/Cargo.toml b/fuzzers/wcet_qemu_sys/Cargo.toml index 868c2bc2b6..f415c52cfb 100644 --- a/fuzzers/wcet_qemu_sys/Cargo.toml +++ b/fuzzers/wcet_qemu_sys/Cargo.toml @@ -18,3 +18,4 @@ clap = { version = "3.0.0-beta.2", features = ["default"] } serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib hashbrown = { version = "0.11", features = ["serde", "ahash-compile-time-rng"], default-features=false } # A faster hashmap, nostd compatible nix = "0.23.0" +goblin = "0.4.2" diff --git a/fuzzers/wcet_qemu_sys/src/showmap.rs b/fuzzers/wcet_qemu_sys/src/showmap.rs index 74e7e3d9bf..2447256c4a 100644 --- a/fuzzers/wcet_qemu_sys/src/showmap.rs +++ b/fuzzers/wcet_qemu_sys/src/showmap.rs @@ -1,5 +1,6 @@ //! A singlethreaded QEMU fuzzer that can auto-restart. +use std::path::Path; use libafl::corpus::Corpus; use libafl::state::HasCorpus; use libafl::Fuzzer; @@ -58,12 +59,18 @@ pub fn main() { // Needed only on no_std //RegistryBuilder::register::(); - let mut args: Vec = env::args().collect(); + let args: Vec = env::args().collect(); - let res = match App::new("libafl_qemu_fuzzbench") + let res = match App::new("wcet_qemu_fuzzer") .version("0.4.0") - .author("AFLplusplus team") - .about("LibAFL-based fuzzer with QEMU for Fuzzbench") + .author("Alwin Berger") + .about("LibAFL-based fuzzer for WCET in System Kernels.") + .arg( + Arg::new("k") + .long("libafl-kernel") + .required(true) + .takes_value(true), + ) .arg( Arg::new("out") .long("libafl-out") @@ -130,43 +137,72 @@ pub fn main() { return; } - fuzz(in_dir) + let kernel = PathBuf::from(res.value_of("k").unwrap().to_string()); + + + fuzz(in_dir, kernel) .expect("An error occurred while fuzzing"); } +fn virt2phys(vaddr : u64, tab : &goblin::elf::Elf) -> u64 { + let ret; + for i in &tab.program_headers { + if i.vm_range().contains(&vaddr.try_into().expect("Can not cast u64 to usize")) { + ret = vaddr-i.p_vaddr+i.p_paddr; + return ret - (ret % 2); + } + } + ret = vaddr; + // unlike the arm-toolcahin goblin produces some off-by one errors when parsing arm + return ret - (ret % 2); +} + /// The actual fuzzer fn fuzz( seed_dir: PathBuf, + kernel: PathBuf, ) -> Result<(), Error> { //=========== Setup emulator let mut env: Vec<(String, String)> = env::vars().collect(); - let mut args2: Vec = vec![ + let mut args: Vec = vec![ "qemu-system-arm", "-machine","mps2-an385", "-monitor", "null", "-semihosting", "--semihosting-config", "enable=on,target=native", - "-kernel", "RTOSDemo.axf", + "-kernel", kernel.to_str().unwrap(), "-serial", "stdio", "-nographic", "-snapshot", "-drive", "if=none,format=qcow2,file=dummy.qcow2", "-S" ].iter().map(|x| x.to_string()).collect(); - let emu = Emulator::new(&mut args2, &mut env); + let emu = Emulator::new(&mut args, &mut env); //=========== Analyze the binary to find the target function address - // let mut elf_buffer = Vec::new(); - // let elf = EasyElf::from_file(emu::binary_path(), &mut elf_buffer)?; + let mut elf_buffer = Vec::new(); + let bin_path=Path::new("./RTOSDemo.axf"); + let elf = EasyElf::from_file(bin_path, &mut elf_buffer)?; - // let test_one_input_ptr = elf - // .resolve_symbol("LLVMFuzzerTestOneInput", 0) - // .expect("Symbol LLVMFuzzerTestOneInput not found"); - // println!("LLVMFuzzerTestOneInput @ {:#x}", test_one_input_ptr); + let test_one_input_ptr = elf + .resolve_symbol("FUZZ_INPUT", 0) + .expect("Symbol FUZZ_INPUT not found"); + let test_one_input_ptr = virt2phys(test_one_input_ptr,&elf.goblin()); + println!("FUZZ_INPUT @ {:#x}", test_one_input_ptr); + let test_length_ptr = elf + .resolve_symbol("FUZZ_LENGTH", 0) + .expect("Symbol FUZZ_LENGTH not found"); + let test_length_ptr = virt2phys(test_length_ptr,&elf.goblin()); + println!("FUZZ_LENGTH @ {:#x}", test_length_ptr); + let check_breakpoint = elf + .resolve_symbol("trigger_Qemu_break", 0) + .expect("Symbol trigger_Qemu_break not found"); + let check_breakpoint = virt2phys(check_breakpoint,&elf.goblin()); + println!("Breakpoint at {:#x}", check_breakpoint); //====== Create the input field - let input_addr = 0x00006de4+0xc; + let input_addr = test_one_input_ptr; println!("Placing input at {:#x}", input_addr); - emu.set_breakpoint(0x00004f5c); + emu.set_breakpoint(check_breakpoint); //====== Create the most simple status display and managers. @@ -221,7 +257,8 @@ fn fuzz( } unsafe { - emu.write_mem(0x00006de4+0xc,buf); + emu.write_mem(test_length_ptr,&(len as u32).to_le_bytes()); + emu.write_mem(input_addr,buf); // println!("{:#?}",edges_copy); emu.run(); diff --git a/fuzzers/wcet_qemu_sys/starter.sh b/fuzzers/wcet_qemu_sys/starter.sh index 654c6c4c91..12c56008de 100755 --- a/fuzzers/wcet_qemu_sys/starter.sh +++ b/fuzzers/wcet_qemu_sys/starter.sh @@ -1,3 +1,3 @@ mkdir -p target/test_in target/test_out [ ! -f target/test_in/test ] && echo " !test" > target/test_in/test -LD_LIBRARY_PATH=target/debug target/debug/wcet_qemu_sys $1 --libafl-out target/test_out --libafl-in target/test_in +LD_LIBRARY_PATH=target/debug target/debug/wcet_qemu_sys --libafl-kernel $1 --libafl-out target/test_out --libafl-in target/test_in