@@ -13,14 +13,14 @@ use libafl::{
13
13
HasExecHooksTuple , HasObservers , HasObserversHooks ,
14
14
} ,
15
15
feedback_or,
16
- feedbacks:: { CrashFeedback , MaxMapFeedback , TimeoutFeedback } ,
16
+ feedbacks:: { CrashFeedback , MapFeedbackState , MaxMapFeedback , TimeFeedback , TimeoutFeedback } ,
17
17
fuzzer:: { Fuzzer , StdFuzzer } ,
18
18
inputs:: { HasTargetBytes , Input } ,
19
19
mutators:: scheduled:: { havoc_mutations, StdScheduledMutator } ,
20
20
mutators:: token_mutations:: Tokens ,
21
- observers:: { HitcountsMapObserver , ObserversTuple , StdMapObserver } ,
21
+ observers:: { HitcountsMapObserver , ObserversTuple , StdMapObserver , TimeObserver } ,
22
22
stages:: mutational:: StdMutationalStage ,
23
- state:: { HasCorpus , HasMetadata , State } ,
23
+ state:: { HasCorpus , HasMetadata , StdState } ,
24
24
stats:: SimpleStats ,
25
25
utils:: { current_nanos, StdRand } ,
26
26
Error ,
@@ -39,14 +39,14 @@ use libafl_frida::{
39
39
FridaOptions ,
40
40
} ;
41
41
42
- struct FridaInProcessExecutor < ' a , ' b , ' c , EM , FH , H , I , OT , S >
42
+ struct FridaInProcessExecutor < ' a , ' b , ' c , FH , H , I , OT , S >
43
43
where
44
44
FH : FridaHelper < ' b > ,
45
45
H : FnMut ( & [ u8 ] ) -> ExitKind ,
46
46
I : Input + HasTargetBytes ,
47
47
OT : ObserversTuple ,
48
48
{
49
- base : TimeoutExecutor < InProcessExecutor < ' a , EM , H , I , OT , S > , I > ,
49
+ base : TimeoutExecutor < InProcessExecutor < ' a , H , I , OT , S > , I > ,
50
50
/// Frida's dynamic rewriting engine
51
51
stalker : Stalker < ' a > ,
52
52
/// User provided callback for instrumentation
55
55
_phantom : PhantomData < & ' b u8 > ,
56
56
}
57
57
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 >
60
60
where
61
61
FH : FridaHelper < ' b > ,
62
62
H : FnMut ( & [ u8 ] ) -> ExitKind ,
91
91
}
92
92
}
93
93
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 >
96
96
where
97
97
FH : FridaHelper < ' b > ,
98
98
H : FnMut ( & [ u8 ] ) -> ExitKind ,
@@ -101,21 +101,33 @@ where
101
101
{
102
102
/// Called right before exexution starts
103
103
#[ 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 > {
105
111
self . helper . pre_exec ( input) ;
106
- self . base . pre_exec ( state, event_mgr, input)
112
+ self . base . pre_exec ( fuzzer , state, event_mgr, input)
107
113
}
108
114
109
115
/// Called right after execution finished.
110
116
#[ 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 > {
112
124
self . helper . post_exec ( input) ;
113
- self . base . post_exec ( state, event_mgr, input)
125
+ self . base . post_exec ( fuzzer , state, event_mgr, input)
114
126
}
115
127
}
116
128
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 >
119
131
where
120
132
FH : FridaHelper < ' b > ,
121
133
H : FnMut ( & [ u8 ] ) -> ExitKind ,
@@ -133,17 +145,17 @@ where
133
145
}
134
146
}
135
147
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 >
138
150
where
139
151
FH : FridaHelper < ' b > ,
140
152
H : FnMut ( & [ u8 ] ) -> ExitKind ,
141
153
I : Input + HasTargetBytes ,
142
- OT : ObserversTuple + HasExecHooksTuple < EM , I , S > ,
154
+ OT : ObserversTuple + HasExecHooksTuple < EM , I , S , Z > ,
143
155
{
144
156
}
145
157
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 >
147
159
where
148
160
FH : FridaHelper < ' b > ,
149
161
H : FnMut ( & [ u8 ] ) -> ExitKind ,
@@ -152,7 +164,7 @@ where
152
164
{
153
165
pub fn new (
154
166
gum : & ' a Gum ,
155
- base : InProcessExecutor < ' a , EM , H , I , OT , S > ,
167
+ base : InProcessExecutor < ' a , H , I , OT , S > ,
156
168
helper : & ' c mut FH ,
157
169
timeout : Duration ,
158
170
) -> Self {
@@ -268,25 +280,45 @@ unsafe fn fuzz(
268
280
MAP_SIZE ,
269
281
) ) ;
270
282
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
+
271
308
// If not restarting, create a State from scratch
272
309
let mut state = state. unwrap_or_else ( || {
273
- State :: new (
310
+ StdState :: new (
274
311
// RNG
275
312
StdRand :: with_seed ( current_nanos ( ) ) ,
276
313
// Corpus that will be evolved, we keep it in memory for performance
277
314
InMemoryCorpus :: new ( ) ,
278
- // Feedbacks to rate the interestingness of an input
279
- MaxMapFeedback :: new_tracking_with_observer ( & edges_observer, true , false ) ,
280
315
// Corpus in which we store solutions (crashes in this example),
281
316
// on disk so the user can get them after stopping the fuzzer
282
317
OnDiskCorpus :: new_save_meta ( objective_dir, Some ( OnDiskMetadataFormat :: JsonPretty ) )
283
318
. 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) ,
290
322
)
291
323
} ) ;
292
324
@@ -305,11 +337,13 @@ unsafe fn fuzz(
305
337
306
338
// Setup a basic mutator with a mutational stage
307
339
let mutator = StdScheduledMutator :: new ( havoc_mutations ( ) ) ;
308
- let stage = StdMutationalStage :: new ( mutator) ;
340
+ let mut stages = tuple_list ! ( StdMutationalStage :: new( mutator) ) ;
309
341
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
311
343
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) ;
313
347
314
348
frida_helper. register_thread ( ) ;
315
349
@@ -318,7 +352,8 @@ unsafe fn fuzz(
318
352
& gum,
319
353
InProcessExecutor :: new (
320
354
& mut frida_harness,
321
- tuple_list ! ( edges_observer, AsanErrorsObserver :: new( & ASAN_ERRORS ) ) ,
355
+ tuple_list ! ( edges_observer, time_observer, asan_observer) ,
356
+ & mut fuzzer,
322
357
& mut state,
323
358
& mut restarting_mgr,
324
359
) ?,
@@ -338,15 +373,20 @@ unsafe fn fuzz(
338
373
// In case the corpus is empty (on first run), reset
339
374
if state. corpus ( ) . count ( ) < 1 {
340
375
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
+ )
342
382
. expect ( & format ! (
343
383
"Failed to load initial corpus at {:?}" ,
344
384
& corpus_dirs
345
385
) ) ;
346
386
println ! ( "We imported {} inputs from disk." , state. corpus( ) . count( ) ) ;
347
387
}
348
388
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 ) ?;
350
390
351
391
// Never reached
352
392
Ok ( ( ) )
0 commit comments