diff --git a/fuzzers/full_system/unicorn/Justfile b/fuzzers/full_system/unicorn/Justfile index cb4f80af4e..ebaea03392 100644 --- a/fuzzers/full_system/unicorn/Justfile +++ b/fuzzers/full_system/unicorn/Justfile @@ -27,7 +27,7 @@ test_single arch="arm": #!/bin/bash echo "Testing {{arch}}" - RUST_LOG="debug" timeout 10s {{FUZZER}} {{arch}} 2>&1 | tee fuzz_stdout.log || true + RUST_LOG="debug" timeout 30s {{FUZZER}} {{arch}} 2>&1 | tee fuzz_stdout.log || true if grep -qa "objectives: 1" fuzz_stdout.log; then echo "Fuzzer is working" else diff --git a/fuzzers/full_system/unicorn/src/main.rs b/fuzzers/full_system/unicorn/src/main.rs index e01fd39192..0f0294142e 100644 --- a/fuzzers/full_system/unicorn/src/main.rs +++ b/fuzzers/full_system/unicorn/src/main.rs @@ -26,14 +26,17 @@ use libafl_bolts::{ }; use libafl_targets::EDGES_MAP_DEFAULT_SIZE; pub use libafl_targets::EDGES_MAP_PTR; +#[cfg(feature = "code_hook")] +use libafl_unicorn::helper::get_stack_pointer; use libafl_unicorn::{ emu::{debug_print, memory_dump}, - helper::get_stack_pointer, hooks::set_coverage_hook, }; +#[cfg(feature = "mem_hook")] +use unicorn_engine::{unicorn_const::MemType, HookType}; use unicorn_engine::{ - unicorn_const::{Arch, MemType, SECOND_SCALE}, - HookType, Mode, Permission, RegisterARM, RegisterARM64, RegisterX86, Unicorn, + unicorn_const::{Arch, SECOND_SCALE}, + Mode, Permission, RegisterARM, RegisterARM64, RegisterX86, Unicorn, }; pub const CODE_ADDRESS: u64 = 0x9000; @@ -223,7 +226,7 @@ fn fuzzer(should_emulate: bool, arch: Arch) { log::error!("Error: {:?}", err); memory_dump(&emu, 2); - debug_print(&emu); + debug_print(&emu, true); } } @@ -323,6 +326,7 @@ fn unicorn_map_and_load_code(emu: &mut Unicorn<()>, address: u64, size: usize, p buffer.len() as u64 } +#[cfg(feature = "code_hook")] fn add_code_hook(emu: &mut Unicorn<()>) { emu.add_code_hook(0x0, !0x0_u64, |emu, pc, _| { let sp = get_stack_pointer(emu); @@ -330,6 +334,8 @@ fn add_code_hook(emu: &mut Unicorn<()>) { }) .unwrap(); } + +#[cfg(feature = "mem_hook")] fn mem_callback( emu: &mut unicorn_engine::Unicorn<()>, mem: MemType, diff --git a/libafl/src/events/launcher.rs b/libafl/src/events/launcher.rs index 4bb3238b46..67c9cf0c18 100644 --- a/libafl/src/events/launcher.rs +++ b/libafl/src/events/launcher.rs @@ -461,7 +461,7 @@ where if self.stdout_file.is_some() || self.stderr_file.is_some() { stdout = Stdio::inherit(); stderr = Stdio::inherit(); - }; + } } std::thread::sleep(Duration::from_millis( diff --git a/libafl_unicorn/src/emu.rs b/libafl_unicorn/src/emu.rs index 687d53972f..ade935fe29 100644 --- a/libafl_unicorn/src/emu.rs +++ b/libafl_unicorn/src/emu.rs @@ -33,7 +33,9 @@ pub fn memory_dump(emu: &Unicorn<()>, len: u64) { } } -pub fn debug_print(emu: &Unicorn<()>) { +// Display some register values and disassemble the instructions around the program counter +// address. The thumb_mode parameter is only taken into account when the architecture used is ARM. +pub fn debug_print(emu: &Unicorn<()>, thumb_mode: bool) { log::debug!("Status when crash happened:"); let pc = emu.pc_read().unwrap(); @@ -68,54 +70,55 @@ pub fn debug_print(emu: &Unicorn<()>) { // Provide disassembly at instant of crash let regions = emu.mem_regions().expect("Could not get memory regions"); - for i in 0..regions.len() { - if regions[i].perms.contains(Permission::EXEC) { - if pc >= regions[i].begin && pc <= regions[i].end { - let mut begin = pc - 32; - let mut end = pc + 32; - if begin < regions[i].begin { - begin = regions[i].begin; - } - if end > regions[i].end { - end = regions[i].end; - } + for region in regions { + if region.perms.contains(Permission::EXEC) && pc >= region.begin && pc <= region.end { + let mut begin = pc - 32; + let mut end = pc + 32; + if begin < region.begin { + begin = region.begin; + } + if end > region.end { + end = region.end; + } - let bytes = emu - .mem_read_as_vec(begin, (end - begin) as usize) - .expect("Could not get program code"); - let cs = match emu.get_arch() { - Arch::ARM => Capstone::new() - .arm() - .mode(arch::arm::ArchMode::Thumb) - .detail(true) - .build() - .expect("Failed to create Capstone object"), - Arch::ARM64 => Capstone::new() - .arm64() - .mode(arch::arm64::ArchMode::Arm) - .detail(true) - .build() - .expect("Failed to create Capstone object"), + let bytes = emu + .mem_read_as_vec(begin, (end - begin) as usize) + .expect("Could not get program code"); + let cs = match emu.get_arch() { + Arch::ARM => Capstone::new() + .arm() + .mode(match thumb_mode { + true => arch::arm::ArchMode::Thumb, + false => arch::arm::ArchMode::Arm, + }) + .detail(true) + .build() + .expect("Failed to create Capstone object"), + Arch::ARM64 => Capstone::new() + .arm64() + .mode(arch::arm64::ArchMode::Arm) + .detail(true) + .build() + .expect("Failed to create Capstone object"), - _ => Capstone::new() - .x86() - .mode(arch::x86::ArchMode::Mode64) - .syntax(arch::x86::ArchSyntax::Intel) - .detail(true) - .build() - .expect("Failed to create Capstone object"), - }; - let insns = cs.disasm_all(&bytes, begin).expect("Failed to disassemble"); + _ => Capstone::new() + .x86() + .mode(arch::x86::ArchMode::Mode64) + .syntax(arch::x86::ArchSyntax::Intel) + .detail(true) + .build() + .expect("Failed to create Capstone object"), + }; + let insns = cs.disasm_all(&bytes, begin).expect("Failed to disassemble"); - if !insns.is_empty() { - log::debug!("Code dump: [0x{begin:x} -> 0x{end:x}]"); - } else { - log::debug!("No disassembly available at PC: 0x{pc:x}"); - } + if !insns.is_empty() { + log::debug!("Code dump: [0x{begin:x} -> 0x{end:x}]"); + } else { + log::debug!("No disassembly available at PC: 0x{pc:x}"); + } - for i in insns.as_ref() { - log::debug!("{}", i); - } + for i in insns.as_ref() { + log::debug!("{}", i); } } } diff --git a/libafl_unicorn/src/helper.rs b/libafl_unicorn/src/helper.rs index d365b33ebb..3fbe8fa6c1 100644 --- a/libafl_unicorn/src/helper.rs +++ b/libafl_unicorn/src/helper.rs @@ -1,11 +1,10 @@ use unicorn_engine::{unicorn_const::Arch, RegisterARM, RegisterARM64, RegisterX86}; pub fn get_stack_pointer(emu: &unicorn_engine::Unicorn<()>) -> u64 { - let sp = match emu.get_arch() { + match emu.get_arch() { Arch::ARM => emu.reg_read(RegisterARM::SP).unwrap(), Arch::ARM64 => emu.reg_read(RegisterARM64::SP).unwrap(), Arch::X86 => emu.reg_read(RegisterX86::ESP).unwrap(), _ => 0, - }; - sp + } }