@@ -13,14 +13,14 @@ use libafl::{
1313 HasExecHooksTuple , HasObservers , HasObserversHooks ,
1414 } ,
1515 feedback_or,
16- feedbacks:: { CrashFeedback , MaxMapFeedback , TimeoutFeedback } ,
16+ feedbacks:: { CrashFeedback , MapFeedbackState , MaxMapFeedback , TimeFeedback , TimeoutFeedback } ,
1717 fuzzer:: { Fuzzer , StdFuzzer } ,
1818 inputs:: { HasTargetBytes , Input } ,
1919 mutators:: scheduled:: { havoc_mutations, StdScheduledMutator } ,
2020 mutators:: token_mutations:: Tokens ,
21- observers:: { HitcountsMapObserver , ObserversTuple , StdMapObserver } ,
21+ observers:: { HitcountsMapObserver , ObserversTuple , StdMapObserver , TimeObserver } ,
2222 stages:: mutational:: StdMutationalStage ,
23- state:: { HasCorpus , HasMetadata , State } ,
23+ state:: { HasCorpus , HasMetadata , StdState } ,
2424 stats:: SimpleStats ,
2525 utils:: { current_nanos, StdRand } ,
2626 Error ,
@@ -39,14 +39,14 @@ use libafl_frida::{
3939 FridaOptions ,
4040} ;
4141
42- struct FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
42+ struct FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
4343where
4444 FH : FridaHelper < ' b > ,
4545 H : FnMut ( & [ u8 ] ) -> ExitKind ,
4646 I : Input + HasTargetBytes ,
4747 OT : ObserversTuple ,
4848{
49- base : TimeoutExecutor < InProcessExecutor < ' a , EM , H , I , OT , S > , I > ,
49+ base : TimeoutExecutor < InProcessExecutor < ' a , H , I , OT , S > , I > ,
5050 /// Frida's dynamic rewriting engine
5151 stalker : Stalker < ' a > ,
5252 /// User provided callback for instrumentation
5555 _phantom : PhantomData < & ' b u8 > ,
5656}
5757
58- impl < ' a , ' b , ' c , EM , FH , H , I , OT , S > Executor < I >
59- for FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
58+ impl < ' a , ' b , ' c , FH , H , I , OT , S > Executor < I >
59+ for FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
6060where
6161 FH : FridaHelper < ' b > ,
6262 H : FnMut ( & [ u8 ] ) -> ExitKind ,
9191 }
9292}
9393
94- impl < ' a , ' b , ' c , EM , FH , H , I , OT , S > HasExecHooks < EM , I , S >
95- for FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
94+ impl < ' a , ' b , ' c , EM , FH , H , I , OT , S , Z > HasExecHooks < EM , I , S , Z >
95+ for FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
9696where
9797 FH : FridaHelper < ' b > ,
9898 H : FnMut ( & [ u8 ] ) -> ExitKind ,
@@ -101,21 +101,33 @@ where
101101{
102102 /// Called right before exexution starts
103103 #[ inline]
104- fn pre_exec ( & mut self , state : & mut S , event_mgr : & mut EM , input : & I ) -> Result < ( ) , Error > {
104+ fn pre_exec (
105+ & mut self ,
106+ fuzzer : & mut Z ,
107+ state : & mut S ,
108+ event_mgr : & mut EM ,
109+ input : & I ,
110+ ) -> Result < ( ) , Error > {
105111 self . helper . pre_exec ( input) ;
106- self . base . pre_exec ( state, event_mgr, input)
112+ self . base . pre_exec ( fuzzer , state, event_mgr, input)
107113 }
108114
109115 /// Called right after execution finished.
110116 #[ inline]
111- fn post_exec ( & mut self , state : & mut S , event_mgr : & mut EM , input : & I ) -> Result < ( ) , Error > {
117+ fn post_exec (
118+ & mut self ,
119+ fuzzer : & mut Z ,
120+ state : & mut S ,
121+ event_mgr : & mut EM ,
122+ input : & I ,
123+ ) -> Result < ( ) , Error > {
112124 self . helper . post_exec ( input) ;
113- self . base . post_exec ( state, event_mgr, input)
125+ self . base . post_exec ( fuzzer , state, event_mgr, input)
114126 }
115127}
116128
117- impl < ' a , ' b , ' c , EM , FH , H , I , OT , S > HasObservers < OT >
118- for FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
129+ impl < ' a , ' b , ' c , FH , H , I , OT , S > HasObservers < OT >
130+ for FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
119131where
120132 FH : FridaHelper < ' b > ,
121133 H : FnMut ( & [ u8 ] ) -> ExitKind ,
@@ -133,17 +145,17 @@ where
133145 }
134146}
135147
136- impl < ' a , ' b , ' c , EM , FH , H , I , OT , S > HasObserversHooks < EM , I , OT , S >
137- for FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
148+ impl < ' a , ' b , ' c , EM , FH , H , I , OT , S , Z > HasObserversHooks < EM , I , OT , S , Z >
149+ for FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
138150where
139151 FH : FridaHelper < ' b > ,
140152 H : FnMut ( & [ u8 ] ) -> ExitKind ,
141153 I : Input + HasTargetBytes ,
142- OT : ObserversTuple + HasExecHooksTuple < EM , I , S > ,
154+ OT : ObserversTuple + HasExecHooksTuple < EM , I , S , Z > ,
143155{
144156}
145157
146- impl < ' a , ' b , ' c , EM , FH , H , I , OT , S > FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
158+ impl < ' a , ' b , ' c , FH , H , I , OT , S > FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
147159where
148160 FH : FridaHelper < ' b > ,
149161 H : FnMut ( & [ u8 ] ) -> ExitKind ,
@@ -152,7 +164,7 @@ where
152164{
153165 pub fn new (
154166 gum : & ' a Gum ,
155- base : InProcessExecutor < ' a , EM , H , I , OT , S > ,
167+ base : InProcessExecutor < ' a , H , I , OT , S > ,
156168 helper : & ' c mut FH ,
157169 timeout : Duration ,
158170 ) -> Self {
@@ -268,25 +280,45 @@ unsafe fn fuzz(
268280 MAP_SIZE ,
269281 ) ) ;
270282
283+ // Create an observation channel to keep track of the execution time
284+ let time_observer = TimeObserver :: new ( "time" ) ;
285+
286+ // Create an observation channel for ASan violations
287+ let asan_observer = AsanErrorsObserver :: new ( & ASAN_ERRORS ) ;
288+
289+ // The state of the edges feedback.
290+ let feedback_state = MapFeedbackState :: with_observer ( & edges_observer) ;
291+
292+ // Feedback to rate the interestingness of an input
293+ // This one is composed by two Feedbacks in OR
294+ let feedback = feedback_or ! (
295+ // New maximization map feedback linked to the edges observer and the feedback state
296+ MaxMapFeedback :: new_tracking( & feedback_state, & edges_observer, true , false ) ,
297+ // Time feedback, this one does not need a feedback state
298+ TimeFeedback :: new_with_observer( & time_observer)
299+ ) ;
300+
301+ // Feedbacks to recognize an input as solution
302+ let objective = feedback_or ! (
303+ CrashFeedback :: new( ) ,
304+ TimeoutFeedback :: new( ) ,
305+ AsanErrorsFeedback :: new( )
306+ ) ;
307+
271308 // If not restarting, create a State from scratch
272309 let mut state = state. unwrap_or_else ( || {
273- State :: new (
310+ StdState :: new (
274311 // RNG
275312 StdRand :: with_seed ( current_nanos ( ) ) ,
276313 // Corpus that will be evolved, we keep it in memory for performance
277314 InMemoryCorpus :: new ( ) ,
278- // Feedbacks to rate the interestingness of an input
279- MaxMapFeedback :: new_tracking_with_observer ( & edges_observer, true , false ) ,
280315 // Corpus in which we store solutions (crashes in this example),
281316 // on disk so the user can get them after stopping the fuzzer
282317 OnDiskCorpus :: new_save_meta ( objective_dir, Some ( OnDiskMetadataFormat :: JsonPretty ) )
283318 . unwrap ( ) ,
284- // Feedbacks to recognize an input as solution
285- feedback_or ! (
286- CrashFeedback :: new( ) ,
287- TimeoutFeedback :: new( ) ,
288- AsanErrorsFeedback :: new( )
289- ) ,
319+ // States of the feedbacks.
320+ // They are the data related to the feedbacks that you want to persist in the State.
321+ tuple_list ! ( feedback_state) ,
290322 )
291323 } ) ;
292324
@@ -305,11 +337,13 @@ unsafe fn fuzz(
305337
306338 // Setup a basic mutator with a mutational stage
307339 let mutator = StdScheduledMutator :: new ( havoc_mutations ( ) ) ;
308- let stage = StdMutationalStage :: new ( mutator) ;
340+ let mut stages = tuple_list ! ( StdMutationalStage :: new( mutator) ) ;
309341
310- // A fuzzer with just one stage and a minimization+queue policy to get testcasess from the corpus
342+ // A minimization+queue policy to get testcasess from the corpus
311343 let scheduler = IndexesLenTimeMinimizerCorpusScheduler :: new ( QueueCorpusScheduler :: new ( ) ) ;
312- let mut fuzzer = StdFuzzer :: new ( tuple_list ! ( stage) ) ;
344+
345+ // A fuzzer with feedbacks and a corpus scheduler
346+ let mut fuzzer = StdFuzzer :: new ( scheduler, feedback, objective) ;
313347
314348 frida_helper. register_thread ( ) ;
315349
@@ -318,7 +352,8 @@ unsafe fn fuzz(
318352 & gum,
319353 InProcessExecutor :: new (
320354 & mut frida_harness,
321- tuple_list ! ( edges_observer, AsanErrorsObserver :: new( & ASAN_ERRORS ) ) ,
355+ tuple_list ! ( edges_observer, time_observer, asan_observer) ,
356+ & mut fuzzer,
322357 & mut state,
323358 & mut restarting_mgr,
324359 ) ?,
@@ -338,15 +373,20 @@ unsafe fn fuzz(
338373 // In case the corpus is empty (on first run), reset
339374 if state. corpus ( ) . count ( ) < 1 {
340375 state
341- . load_initial_inputs ( & mut executor, & mut restarting_mgr, & scheduler, & corpus_dirs)
376+ . load_initial_inputs (
377+ & mut fuzzer,
378+ & mut executor,
379+ & mut restarting_mgr,
380+ & corpus_dirs,
381+ )
342382 . expect ( & format ! (
343383 "Failed to load initial corpus at {:?}" ,
344384 & corpus_dirs
345385 ) ) ;
346386 println ! ( "We imported {} inputs from disk." , state. corpus( ) . count( ) ) ;
347387 }
348388
349- fuzzer. fuzz_loop ( & mut state , & mut executor, & mut restarting_mgr , & scheduler ) ?;
389+ fuzzer. fuzz_loop ( & mut stages , & mut executor, & mut state , & mut restarting_mgr ) ?;
350390
351391 // Never reached
352392 Ok ( ( ) )
0 commit comments