diff --git a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml index d7e86848a7..cf0c414636 100644 --- a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml +++ b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/Cargo.toml @@ -18,6 +18,7 @@ debug = true [dependencies] libafl = { path = "../../../libafl/", features = ["concolic_mutation"] } libafl_targets = { path = "../../../libafl_targets/", features = ["sancov_pcguard_edges", "sancov_cmplog", "libfuzzer"] } +structopt = "0.3.21" [build-dependencies] cc = { version = "1.0", features = ["parallel"] } diff --git a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs index cd34a48a0b..e6a39d088a 100644 --- a/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs +++ b/fuzzers/libfuzzer_stb_image_concolic/fuzzer/src/main.rs @@ -28,7 +28,7 @@ use libafl::{ }, observers::{ concolic::{ - serialization_format::shared_memory::{DEFAULT_ENV_NAME, DEFAULT_SIZE}, + serialization_format::{DEFAULT_ENV_NAME, DEFAULT_SIZE}, ConcolicObserver, }, StdMapObserver, TimeObserver, @@ -47,11 +47,22 @@ use libafl_targets::{ MAX_EDGES_NUM, }; +use structopt::StructOpt; + +#[derive(Debug, StructOpt)] +struct Opt { + /// This node should do concolic tracing + solving instead of traditional fuzzing + #[structopt(short, long)] + concolic: bool, +} + pub fn main() { // Registry the metadata types used in this fuzzer // Needed only on no_std //RegistryBuilder::register::(); + let opt = Opt::from_args(); + println!( "Workdir: {:?}", env::current_dir().unwrap().to_string_lossy().to_string() @@ -60,12 +71,18 @@ pub fn main() { &[PathBuf::from("./corpus")], PathBuf::from("./crashes"), 1337, + opt.concolic, ) .expect("An error occurred while fuzzing"); } /// The actual fuzzer -fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> { +fn fuzz( + corpus_dirs: &[PathBuf], + objective_dir: PathBuf, + broker_port: u16, + concolic: bool, +) -> Result<(), Error> { // 'While the stats are state, they are usually used in the broker - which is likely never restarted let stats = MultiStats::new(|s| println!("{}", s)); @@ -183,35 +200,40 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re let mutator = StdScheduledMutator::new(havoc_mutations()); let mutational = StdMutationalStage::new(mutator); - // The shared memory for the concolic runtime to write its trace to - let mut concolic_shmem = StdShMemProvider::new() - .unwrap() - .new_map(DEFAULT_SIZE) - .unwrap(); - concolic_shmem.write_to_env(DEFAULT_ENV_NAME).unwrap(); + if concolic { + // The shared memory for the concolic runtime to write its trace to + let mut concolic_shmem = StdShMemProvider::new() + .unwrap() + .new_map(DEFAULT_SIZE) + .unwrap(); + concolic_shmem.write_to_env(DEFAULT_ENV_NAME).unwrap(); - // The concolic observer observers the concolic shared memory map. - let concolic_observer = ConcolicObserver::new("concolic".to_string(), concolic_shmem.map_mut()); + // The concolic observer observers the concolic shared memory map. + let concolic_observer = + ConcolicObserver::new("concolic".to_string(), concolic_shmem.map_mut()); - let concolic_observer_name = concolic_observer.name().to_string(); + let concolic_observer_name = concolic_observer.name().to_string(); - // The order of the stages matter! - let mut stages = tuple_list!( - // Create a concolic trace - ConcolicTracingStage::new( - TracingStage::new( - MyCommandConfigurator::default().into_executor(tuple_list!(concolic_observer)) + // The order of the stages matter! + let mut stages = tuple_list!( + // Create a concolic trace + ConcolicTracingStage::new( + TracingStage::new( + MyCommandConfigurator::default().into_executor(tuple_list!(concolic_observer)) + ), + concolic_observer_name, ), - concolic_observer_name, - ), - // Use the concolic trace for z3-based solving - SimpleConcolicMutationalStage::default(), - tracing, - i2s, - mutational - ); + // Use the concolic trace for z3-based solving + SimpleConcolicMutationalStage::default(), + ); - fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut restarting_mgr)?; + fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut restarting_mgr)?; + } else { + // The order of the stages matter! + let mut stages = tuple_list!(tracing, i2s, mutational); + + fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut restarting_mgr)?; + } // Never reached Ok(()) @@ -240,6 +262,7 @@ where .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) + .env("SYMCC_INPUT_FILE", "cur_input") .spawn() .expect("failed to start process")) } diff --git a/fuzzers/libfuzzer_stb_image_concolic/runtime/src/lib.rs b/fuzzers/libfuzzer_stb_image_concolic/runtime/src/lib.rs index 24440463e8..5d1d14108a 100644 --- a/fuzzers/libfuzzer_stb_image_concolic/runtime/src/lib.rs +++ b/fuzzers/libfuzzer_stb_image_concolic/runtime/src/lib.rs @@ -1,17 +1,18 @@ -use symcc_runtime::{ - export_runtime, - filter::NoFloat, - tracing::{self, StdShMemMessageFileWriter}, - Runtime, -}; - //! This is a basic SymCC runtime. //! It traces the execution to the shared memory region that should be passed through the environment by the fuzzer process. //! Additionally, it concretizes all floating point operations for simplicity. //! Refer to the `symcc_runtime` crate documentation for building your own runtime. +use symcc_runtime::{ + export_runtime, + filter::{NoFloat, CallStackCoverage}, + tracing::{self, StdShMemMessageFileWriter}, + Runtime, +}; + export_runtime!( NoFloat => NoFloat; + CallStackCoverage::default() => CallStackCoverage; // QSym-style expression pruning tracing::TracingRuntime::new( StdShMemMessageFileWriter::from_stdshmem_default_env() .expect("unable to construct tracing runtime writer. (missing env?)") diff --git a/libafl/src/stages/concolic.rs b/libafl/src/stages/concolic.rs index 10e79cd99a..eaf5b1d38f 100644 --- a/libafl/src/stages/concolic.rs +++ b/libafl/src/stages/concolic.rs @@ -134,7 +134,9 @@ fn generate_mutations(iter: impl Iterator) -> Vec< let mut res = Vec::new(); - let ctx = Context::new(&Config::new()); + let mut cfg = Config::new(); + cfg.set_timeout_msec(10_000); + let ctx = Context::new(&cfg); let solver = Solver::new(&ctx); let mut translation = HashMap::::new(); @@ -305,7 +307,6 @@ fn generate_mutations(iter: impl Iterator) -> Vec< } z3::SatResult::Unknown => { // we've got a problem. ignore - solver.pop(1); } z3::SatResult::Sat => { let model = solver.get_model().unwrap();