fix edge fuzzing

This commit is contained in:
Alwin Berger 2025-01-06 15:52:48 +01:00
parent 79d3f89254
commit cc2a2e6422
5 changed files with 28 additions and 22 deletions

View File

@ -62,6 +62,7 @@ debug = true
[dependencies]
libafl = { path = "../../libafl/", features = ["multipart_inputs", "prelude"] }
libafl_bolts = { path = "../../libafl_bolts/" }
libafl_targets = { path = "../../libafl_targets/" }
libafl_qemu = { path = "../../libafl_qemu/", features = ["arm", "systemmode"], default-features = false }
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

View File

@ -10,8 +10,9 @@ use libafl::{
common::{HasMetadata, HasNamedMetadata}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::ExitKind, feedback_or, feedback_or_fast, feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback}, fuzzer::{Fuzzer, StdFuzzer}, inputs::{multi::MultipartInput, BytesInput, HasTargetBytes, Input}, monitors::MultiMonitor, observers::{CanTrack, VariableMapObserver}, prelude::{havoc_mutations, minimizer::TopRatedsMetadata, CorpusId, Generator, HitcountsMapObserver, RandBytesGenerator, SimpleEventManager, SimpleMonitor, SimplePrintingMonitor, SimpleRestartingEventManager, StdScheduledMutator}, schedulers::QueueScheduler, stages::StdMutationalStage, state::{HasCorpus, StdState}, Error, Evaluator
};
use libafl_qemu::{
elf::EasyElf, emu::Emulator, modules::{edges::{self}, FilterList}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuExitReason, QemuHooks, Regs
elf::EasyElf, emu::Emulator, modules::{edges::{self}, EdgeCoverageModule, FilterList, StdAddressFilter, StdEdgeCoverageModule}, GuestAddr, GuestPhysAddr, QemuExecutor, QemuExitReason, QemuHooks, Regs
};
use libafl_targets::{edges_map_mut_ptr, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND};
use rand::{SeedableRng, StdRng, Rng};
use crate::{
config::{get_target_ranges, get_target_symbols}, systemstate::{self, feedbacks::{DumpSystraceFeedback, SystraceErrorFeedback}, helpers::{get_function_range, load_symbol, try_load_symbol}, mutational::{input_bytes_to_interrupt_times, InterruptShiftStage, STGSnippetStage}, observers::QemuSystemStateObserver, schedulers::{GenerationScheduler, LongestTraceScheduler}, stg::{stg_map_mut_slice, GraphMaximizerCorpusScheduler, STGEdge, STGNode, StgFeedback, MAX_STG_NUM}, target_os::freertos::{config::get_range_groups, qemu_module::FreeRTOSSystemStateHelper, FreeRTOSSystem}}, time::{
@ -199,7 +200,7 @@ if let Ok(seed) = env::var("SEED_RANDOM") {
let denylist: Vec<_> = TARGET_GROUPS["ISR_FN"].values().map(|x| x.clone()).collect();
let denylist = FilterList::DenyList(denylist); // do not count isr jumps, which are useless
let denylist = StdAddressFilter::deny_list(denylist); // do not count isr jumps, which are useless
/// Setup the interrupt inputs. Noop if interrupts are not fuzzed
fn setup_interrupt_inputs(mut input : MultipartInput<BytesInput>, interrupt_config : &Vec<(usize,u32)>, mut random: Option<&mut StdRng>) -> MultipartInput<BytesInput> {
@ -325,13 +326,15 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
// Create an observation channel using the coverage map
#[cfg(feature = "observe_edges")]
let edges_observer = unsafe { VariableMapObserver::from_mut_slice(
let mut edges_observer = unsafe { VariableMapObserver::from_mut_slice(
"edges",
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_SIZE_IN_USE),
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_DEFAULT_SIZE),
addr_of_mut!(MAX_EDGES_FOUND),
)}.track_indices();
)};
#[cfg(feature = "observe_hitcounts")]
let edges_observer = HitcountsMapObserver::new(edges_observer).track_indices();
let mut edges_observer = HitcountsMapObserver::new(edges_observer);
#[cfg(feature = "observe_edges")]
let mut edges_observer = edges_observer.track_indices();
#[cfg(feature = "observe_systemstate")]
let stg_coverage_observer = unsafe { VariableMapObserver::from_mut_slice(
@ -370,7 +373,7 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
#[cfg(all(feature = "observe_systemstate"))]
let mut feedback = feedback_or!(
feedback,
DumpSystraceFeedback::<FreeRTOSSystem>::with_dump(if cli.dump_traces {cli.dump_name.clone().map(|x| x.with_extension("trace.ron"))} else {None})
DumpSystraceFeedback::<FreeRTOSSystem>::with_dump(if cli.dump_traces {cli.dump_name.clone().map(|x| x.with_extension("trace.ron"))} else {None}, &cli.select_task)
);
#[cfg(feature = "trace_stg")]
let mut feedback = feedback_or!(
@ -426,7 +429,12 @@ let run_client = |state: Option<_>, mut mgr, _core_id| {
#[cfg(feature = "observe_systemstate")]
let qhelpers = (FreeRTOSSystemStateHelper::new(&TARGET_SYMBOLS,&TARGET_RANGES,&TARGET_GROUPS), qhelpers);
#[cfg(feature = "observe_edges")]
let qhelpers = (QemuEdgeCoverageHelper::new(denylist, QemuFilterList::None), qhelpers);
let qhelpers = (
StdEdgeCoverageModule::builder()
.map_observer(edges_observer.as_mut())
.address_filter(denylist)
.build()
.unwrap(), qhelpers);//StdEdgeCoverageModule::new(denylist, FilterList::None), qhelpers);
let qhelpers = (QemuStateRestoreHelper::with_fast(initial_snap), qhelpers);
let emulator = Emulator::empty().qemu(qemu).modules(qhelpers).build().unwrap();

View File

@ -350,13 +350,13 @@ where
}
}
#[allow(unused)]
pub fn with_dump(dumpfile: Option<PathBuf>) -> Self {
pub fn with_dump(dumpfile: Option<PathBuf>, select_task: &Option<String>) -> Self {
Self {
name: Cow::from("Dumpsystemstate".to_string()),
dumpfile: dumpfile,
dump_metadata: false,
phantom: PhantomData,
select_task: None,
select_task: select_task.clone(),
}
}
#[allow(unused)]

View File

@ -322,8 +322,8 @@ impl HasRefCnt for STGNodeMetadata {
libafl_bolts::impl_serdeany!(STGNodeMetadata);
pub type GraphMaximizerCorpusScheduler<CS, S, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<S>,STGNodeMetadata,O>;
pub type GraphMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor,STGNodeMetadata,O>;
// AI generated, human verified
/// Count the occurrences of each element in a vector, assumes the vector is sorted

View File

@ -45,21 +45,18 @@ use std::borrow::Cow;
//=========================== Scheduler
pub type TimeMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
MinimizerScheduler<CS, MaxTimeFavFactor, MapIndexesMetadata, O>;
/// Multiply the testcase size with the execution time.
/// This favors small and quick testcases.
#[derive(Debug, Clone)]
pub struct MaxTimeFavFactor<S>
where
S: HasCorpus + HasMetadata,
pub struct MaxTimeFavFactor
{
phantom: PhantomData<S>,
}
impl<S> TestcaseScore<S> for MaxTimeFavFactor<S>
impl<S> TestcaseScore<S> for MaxTimeFavFactor
where
S: HasCorpus + HasMetadata,
S: HasCorpus,
{
fn compute(state: &S, entry: &mut Testcase<<S::Corpus as Corpus>::Input> ) -> Result<f64, Error> {
// TODO maybe enforce entry.exec_time().is_some()
@ -73,7 +70,7 @@ pub type LenTimeMaximizerCorpusScheduler<CS, O> =
MinimizerScheduler<CS, MaxExecsLenFavFactor<<CS as UsesState>::State>, MapIndexesMetadata, O>;
pub type TimeStateMaximizerCorpusScheduler<CS, O, SYS> =
MinimizerScheduler<CS, MaxTimeFavFactor<<CS as UsesState>::State>, <SYS as TargetSystem>::TraceData, O>;
MinimizerScheduler<CS, MaxTimeFavFactor, <SYS as TargetSystem>::TraceData, O>;
/// Multiply the testcase size with the execution time.
/// This favors small and quick testcases.
@ -433,7 +430,7 @@ pub type TimeProbMassScheduler<S> =
#[derive(Debug, Clone)]
pub struct TimeProbFactor<S>
where
S: HasCorpus + HasMetadata,
S: HasCorpus,
{
phantom: PhantomData<S>,
}
@ -444,7 +441,7 @@ where
impl<S> TestcaseScore<S> for TimeProbFactor<S>
where
S: HasCorpus + HasMetadata,
S: HasCorpus,
{
fn compute(_state: &S, entry: &mut Testcase<<S::Corpus as Corpus>::Input>) -> Result<f64, Error> {
// TODO maybe enforce entry.exec_time().is_some()