diff --git a/fuzzers/binary_only/qemu_coverage/README.md b/fuzzers/binary_only/qemu_coverage/README.md index 49153b0dc7..322ffe126a 100644 --- a/fuzzers/binary_only/qemu_coverage/README.md +++ b/fuzzers/binary_only/qemu_coverage/README.md @@ -2,7 +2,7 @@ This folder contains an example fuzzer which runs each entry in the input corpus and collects the cumuative coverage data in drcov format. This fuzzer also distributes the test cases in -the input corupus evenly across the selected cores. +the input corpus evenly across the selected cores. The following architectures are supported: * arm diff --git a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs index df2f174561..58f6f27f39 100644 --- a/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs +++ b/fuzzers/binary_only/qemu_coverage/src/fuzzer.rs @@ -28,10 +28,8 @@ use libafl_bolts::{ AsSlice, }; use libafl_qemu::{ - elf::EasyElf, - modules::{drcov::DrCovModule, utils::filters::StdAddressFilter}, - ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor, - QemuExitReason, QemuRWError, QemuShutdownCause, Regs, + elf::EasyElf, modules::drcov::DrCovModule, ArchExtras, CallingConvention, Emulator, GuestAddr, + GuestReg, MmapPerms, Qemu, QemuExecutor, QemuExitReason, QemuRWError, QemuShutdownCause, Regs, }; #[derive(Default)] @@ -127,9 +125,14 @@ pub fn fuzz() { mut mgr: LlmpRestartingEventManager<_, _, _, _, _>, client_description: ClientDescription| { let mut cov_path = options.coverage_path.clone(); + let core_id = client_description.core_id(); + + let coverage_name = cov_path.file_stem().unwrap().to_str().unwrap(); + let coverage_extension = cov_path.extension().unwrap_or_default().to_str().unwrap(); + let core = core_id.0; + cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}")); let emulator_modules = tuple_list!(DrCovModule::builder() - .filter(StdAddressFilter::default()) .filename(cov_path.clone()) .full_trace(false) .build()); @@ -175,7 +178,7 @@ pub fn fuzz() { let stack_ptr: GuestAddr = qemu.read_reg(Regs::Sp).unwrap(); - let reset = |buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> { + let reset = |qemu: Qemu, buf: &[u8], len: GuestReg| -> Result<(), QemuRWError> { unsafe { let _ = qemu.write_mem(input_addr, buf); qemu.write_reg(Regs::Pc, test_one_input_ptr)?; @@ -197,7 +200,9 @@ pub fn fuzz() { }; let mut harness = - |_emulator: &mut Emulator<_, _, _, _, _, _, _>, _state: &mut _, input: &BytesInput| { + |emulator: &mut Emulator<_, _, _, _, _, _, _>, state: &mut _, input: &BytesInput| { + let qemu = emulator.qemu(); + let target = input.target_bytes(); let mut buf = target.as_slice(); let mut len = buf.len(); @@ -206,7 +211,13 @@ pub fn fuzz() { len = MAX_INPUT_SIZE; } let len = len as GuestReg; - reset(buf, len).unwrap(); + reset(qemu, buf, len).unwrap(); + + unsafe { + let ret = emulator.run(state, input); + log::warn!("ret = {ret:?}"); + } + ExitKind::Ok }; @@ -215,6 +226,7 @@ pub fn fuzz() { .cores .position(core_id) .expect("Failed to get core index"); + let files = corpus_files .iter() .skip(files_per_core * core_idx) @@ -245,11 +257,6 @@ pub fn fuzz() { let scheduler = QueueScheduler::new(); let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - let coverage_name = cov_path.file_stem().unwrap().to_str().unwrap(); - let coverage_extension = cov_path.extension().unwrap_or_default().to_str().unwrap(); - let core = core_id.0; - cov_path.set_file_name(format!("{coverage_name}-{core:03}.{coverage_extension}")); - let mut executor = QemuExecutor::new( emulator, &mut harness, diff --git a/libafl_qemu/src/modules/cmplog.rs b/libafl_qemu/src/modules/cmplog.rs index a69704a148..725a3708c1 100644 --- a/libafl_qemu/src/modules/cmplog.rs +++ b/libafl_qemu/src/modules/cmplog.rs @@ -207,7 +207,7 @@ where return None; } } - let state = state.expect("The gen_unique_cmp_ids hook works only for in-process fuzzing"); + let state = state.expect("The gen_unique_cmp_ids hook works only for in-process fuzzing. Is the Executor initialized?"); if state.metadata_map().get::().is_none() { state.add_metadata(QemuCmpsMapMetadata::new()); } diff --git a/libafl_qemu/src/modules/drcov.rs b/libafl_qemu/src/modules/drcov.rs index c565634399..be69ce189f 100644 --- a/libafl_qemu/src/modules/drcov.rs +++ b/libafl_qemu/src/modules/drcov.rs @@ -265,26 +265,27 @@ where I: Unpin, S: Unpin + HasMetadata, { - fn post_qemu_init(&mut self, _qemu: Qemu, emulator_modules: &mut EmulatorModules) + fn post_qemu_init(&mut self, _qemu: Qemu, _emulator_modules: &mut EmulatorModules) where ET: EmulatorModuleTuple, { - emulator_modules.blocks( - Hook::Function(gen_unique_block_ids::), - Hook::Function(gen_block_lengths::), - Hook::Function(exec_trace_block::), - ); } #[cfg(feature = "usermode")] fn first_exec( &mut self, qemu: Qemu, - _emulator_modules: &mut EmulatorModules, + emulator_modules: &mut EmulatorModules, _state: &mut S, ) where ET: EmulatorModuleTuple, { + emulator_modules.blocks( + Hook::Function(gen_unique_block_ids::), + Hook::Function(gen_block_lengths::), + Hook::Function(exec_trace_block::), + ); + if self.module_mapping.is_none() { log::info!("Auto-filling module mapping for DrCov module from QEMU mapping."); @@ -392,7 +393,7 @@ where return None; } - let state = state.expect("The gen_unique_block_ids hook works only for in-process fuzzing"); + let state = state.expect("The gen_unique_block_ids hook works only for in-process fuzzing. Is the Executor initialized?"); if state .metadata_map_mut() .get_mut::() diff --git a/libafl_qemu/src/modules/edges/helpers.rs b/libafl_qemu/src/modules/edges/helpers.rs index 5a8f58e306..e095d69c7d 100644 --- a/libafl_qemu/src/modules/edges/helpers.rs +++ b/libafl_qemu/src/modules/edges/helpers.rs @@ -133,7 +133,7 @@ mod generators { let mask: usize = get_mask::(); - let state = state.expect("The gen_unique_edge_ids hook works only for in-process fuzzing"); + let state = state.expect("The gen_unique_edge_ids hook works only for in-process fuzzing. Is the Executor initialized?"); let meta = state.metadata_or_insert_with(QemuEdgesMapMetadata::new); match meta.map.entry((src, dest)) {