1
1
//! A libfuzzer-like fuzzer with llmp-multithreading support and restarts
2
2
//! The example harness is built for libpng.
3
+ use std:: { path:: PathBuf , ptr:: null} ;
4
+
3
5
use frida_gum:: Gum ;
4
6
use libafl:: {
5
7
corpus:: { CachedOnDiskCorpus , Corpus , OnDiskCorpus } ,
6
- Error ,
7
- events:: { EventConfig , launcher:: Launcher , llmp:: LlmpRestartingEventManager } ,
8
- executors:: { ExitKind , inprocess:: InProcessExecutor , ShadowExecutor } , feedback_or,
9
- feedback_or_fast,
8
+ events:: { launcher:: Launcher , llmp:: LlmpRestartingEventManager , EventConfig } ,
9
+ executors:: { inprocess:: InProcessExecutor , ExitKind , ShadowExecutor } ,
10
+ feedback_or, feedback_or_fast,
10
11
feedbacks:: { CrashFeedback , MaxMapFeedback , TimeFeedback , TimeoutFeedback } ,
11
12
fuzzer:: { Fuzzer , StdFuzzer } ,
12
13
inputs:: { BytesInput , HasTargetBytes } ,
13
14
monitors:: MultiMonitor ,
14
15
mutators:: {
15
- scheduled:: { havoc_mutations, StdScheduledMutator , tokens_mutations } ,
16
+ scheduled:: { havoc_mutations, tokens_mutations , StdScheduledMutator } ,
16
17
token_mutations:: { I2SRandReplace , Tokens } ,
17
18
} ,
18
- observers:: { HitcountsMapObserver , StdMapObserver , TimeObserver } ,
19
+ observers:: { HitcountsMapObserver , StdMapObserver , TimeObserver , TrackingHinted } ,
19
20
schedulers:: { IndexesLenTimeMinimizerScheduler , QueueScheduler } ,
20
21
stages:: { ShadowTracingStage , StdMutationalStage } ,
21
22
state:: { HasCorpus , HasMetadata , StdState } ,
23
+ Error ,
22
24
} ;
23
25
#[ cfg( unix) ]
24
26
use libafl:: { feedback_and_fast, feedbacks:: ConstFeedback } ;
25
27
use libafl_bolts:: {
26
- AsSlice ,
27
- cli:: { FuzzerOptions , parse_args} ,
28
+ cli:: { parse_args, FuzzerOptions } ,
28
29
current_nanos,
29
30
rands:: StdRand ,
30
31
shmem:: { ShMemProvider , StdShMemProvider } ,
31
- tuples:: { Merge , tuple_list} ,
32
+ tuples:: { tuple_list, Merge } ,
33
+ AsSlice ,
34
+ } ;
35
+ #[ cfg( unix) ]
36
+ use libafl_frida:: asan:: {
37
+ asan_rt:: AsanRuntime ,
38
+ errors:: { AsanErrorsFeedback , AsanErrorsObserver , ASAN_ERRORS } ,
32
39
} ;
33
40
use libafl_frida:: {
34
41
cmplog_rt:: CmpLogRuntime ,
35
42
coverage_rt:: { CoverageRuntime , MAP_SIZE } ,
36
43
executor:: FridaInProcessExecutor ,
37
44
helper:: FridaInstrumentationHelper ,
38
45
} ;
39
- #[ cfg( unix) ]
40
- use libafl_frida:: asan:: {
41
- asan_rt:: AsanRuntime ,
42
- errors:: { ASAN_ERRORS , AsanErrorsFeedback , AsanErrorsObserver } ,
43
- } ;
44
46
use libafl_targets:: cmplog:: CmpLogObserver ;
45
47
use mimalloc:: MiMalloc ;
46
- use std:: { path:: PathBuf , ptr:: null} ;
47
48
48
49
#[ global_allocator]
49
50
static GLOBAL : MiMalloc = MiMalloc ;
@@ -103,21 +104,22 @@ unsafe fn fuzz(
103
104
104
105
let coverage = CoverageRuntime :: new ( ) ;
105
106
#[ cfg( unix) ]
106
- let asan = AsanRuntime :: new ( & options) ;
107
+ let asan = AsanRuntime :: new ( & options) ;
107
108
108
109
#[ cfg( unix) ]
109
- let mut frida_helper =
110
+ let mut frida_helper =
110
111
FridaInstrumentationHelper :: new ( & gum, options, tuple_list ! ( coverage, asan) ) ;
111
112
#[ cfg( windows) ]
112
- let mut frida_helper =
113
+ let mut frida_helper =
113
114
FridaInstrumentationHelper :: new ( & gum, & options, tuple_list ! ( coverage) ) ;
114
115
115
116
// Create an observation channel using the coverage map
116
117
let edges_observer = HitcountsMapObserver :: new ( StdMapObserver :: from_mut_ptr (
117
118
"edges" ,
118
119
frida_helper. map_mut_ptr ( ) . unwrap ( ) ,
119
120
MAP_SIZE ,
120
- ) ) ;
121
+ ) )
122
+ . track_indices ( ) ;
121
123
122
124
// Create an observation channel to keep track of the execution time
123
125
let time_observer = TimeObserver :: new ( "time" ) ;
@@ -133,14 +135,14 @@ unsafe fn fuzz(
133
135
134
136
// Feedbacks to recognize an input as solution
135
137
#[ cfg( unix) ]
136
- let mut objective = feedback_or_fast ! (
138
+ let mut objective = feedback_or_fast ! (
137
139
CrashFeedback :: new( ) ,
138
140
TimeoutFeedback :: new( ) ,
139
141
// true enables the AsanErrorFeedback
140
142
feedback_and_fast!( ConstFeedback :: from( true ) , AsanErrorsFeedback :: new( ) )
141
143
) ;
142
144
#[ cfg( windows) ]
143
- let mut objective = feedback_or_fast ! ( CrashFeedback :: new( ) , TimeoutFeedback :: new( ) ) ;
145
+ let mut objective = feedback_or_fast ! ( CrashFeedback :: new( ) , TimeoutFeedback :: new( ) ) ;
144
146
145
147
// If not restarting, create a State from scratch
146
148
let mut state = state. unwrap_or_else ( || {
@@ -156,7 +158,7 @@ unsafe fn fuzz(
156
158
& mut feedback,
157
159
& mut objective,
158
160
)
159
- . unwrap ( )
161
+ . unwrap ( )
160
162
} ) ;
161
163
162
164
println ! ( "We're a client, let's fuzz :)" ) ;
@@ -176,19 +178,20 @@ unsafe fn fuzz(
176
178
let mutator = StdScheduledMutator :: new ( havoc_mutations ( ) . merge ( tokens_mutations ( ) ) ) ;
177
179
178
180
// A minimization+queue policy to get testcasess from the corpus
179
- let scheduler = IndexesLenTimeMinimizerScheduler :: new ( QueueScheduler :: new ( ) ) ;
181
+ let scheduler =
182
+ IndexesLenTimeMinimizerScheduler :: new ( & edges_observer, QueueScheduler :: new ( ) ) ;
180
183
181
184
// A fuzzer with feedbacks and a corpus scheduler
182
185
let mut fuzzer = StdFuzzer :: new ( scheduler, feedback, objective) ;
183
186
184
187
#[ cfg( unix) ]
185
- let observers = tuple_list ! (
188
+ let observers = tuple_list ! (
186
189
edges_observer,
187
190
time_observer,
188
191
AsanErrorsObserver :: new( & ASAN_ERRORS )
189
192
) ;
190
193
#[ cfg( windows) ]
191
- let observers = tuple_list ! ( edges_observer, time_observer) ;
194
+ let observers = tuple_list ! ( edges_observer, time_observer) ;
192
195
193
196
// Create the executor for an in-process function with just one observer for edge coverage
194
197
let mut executor = FridaInProcessExecutor :: new (
@@ -234,7 +237,8 @@ unsafe fn fuzz(
234
237
"edges" ,
235
238
frida_helper. map_mut_ptr ( ) . unwrap ( ) ,
236
239
MAP_SIZE ,
237
- ) ) ;
240
+ ) )
241
+ . track_indices ( ) ;
238
242
239
243
// Create an observation channel to keep track of the execution time
240
244
let time_observer = TimeObserver :: new ( "time" ) ;
@@ -249,13 +253,13 @@ unsafe fn fuzz(
249
253
) ;
250
254
251
255
#[ cfg( unix) ]
252
- let mut objective = feedback_or_fast ! (
256
+ let mut objective = feedback_or_fast ! (
253
257
CrashFeedback :: new( ) ,
254
258
TimeoutFeedback :: new( ) ,
255
259
feedback_and_fast!( ConstFeedback :: from( false ) , AsanErrorsFeedback :: new( ) )
256
260
) ;
257
261
#[ cfg( windows) ]
258
- let mut objective = feedback_or_fast ! ( CrashFeedback :: new( ) , TimeoutFeedback :: new( ) ) ;
262
+ let mut objective = feedback_or_fast ! ( CrashFeedback :: new( ) , TimeoutFeedback :: new( ) ) ;
259
263
260
264
// If not restarting, create a State from scratch
261
265
let mut state = state. unwrap_or_else ( || {
@@ -271,7 +275,7 @@ unsafe fn fuzz(
271
275
& mut feedback,
272
276
& mut objective,
273
277
)
274
- . unwrap ( )
278
+ . unwrap ( )
275
279
} ) ;
276
280
277
281
println ! ( "We're a client, let's fuzz :)" ) ;
@@ -291,19 +295,20 @@ unsafe fn fuzz(
291
295
let mutator = StdScheduledMutator :: new ( havoc_mutations ( ) . merge ( tokens_mutations ( ) ) ) ;
292
296
293
297
// A minimization+queue policy to get testcasess from the corpus
294
- let scheduler = IndexesLenTimeMinimizerScheduler :: new ( QueueScheduler :: new ( ) ) ;
298
+ let scheduler =
299
+ IndexesLenTimeMinimizerScheduler :: new ( & edges_observer, QueueScheduler :: new ( ) ) ;
295
300
296
301
// A fuzzer with feedbacks and a corpus scheduler
297
302
let mut fuzzer = StdFuzzer :: new ( scheduler, feedback, objective) ;
298
303
299
304
#[ cfg( unix) ]
300
- let observers = tuple_list ! (
305
+ let observers = tuple_list ! (
301
306
edges_observer,
302
307
time_observer,
303
308
AsanErrorsObserver :: new( & ASAN_ERRORS )
304
309
) ;
305
310
#[ cfg( windows) ]
306
- let observers = tuple_list ! ( edges_observer, time_observer, ) ;
311
+ let observers = tuple_list ! ( edges_observer, time_observer, ) ;
307
312
308
313
// Create the executor for an in-process function with just one observer for edge coverage
309
314
let mut executor = FridaInProcessExecutor :: new (
@@ -364,7 +369,8 @@ unsafe fn fuzz(
364
369
"edges" ,
365
370
frida_helper. map_mut_ptr ( ) . unwrap ( ) ,
366
371
MAP_SIZE ,
367
- ) ) ;
372
+ ) )
373
+ . track_indices ( ) ;
368
374
369
375
// Create an observation channel to keep track of the execution time
370
376
let time_observer = TimeObserver :: new ( "time" ) ;
@@ -379,13 +385,13 @@ unsafe fn fuzz(
379
385
) ;
380
386
381
387
#[ cfg( unix) ]
382
- let mut objective = feedback_or_fast ! (
388
+ let mut objective = feedback_or_fast ! (
383
389
CrashFeedback :: new( ) ,
384
390
TimeoutFeedback :: new( ) ,
385
391
feedback_and_fast!( ConstFeedback :: from( false ) , AsanErrorsFeedback :: new( ) )
386
392
) ;
387
393
#[ cfg( windows) ]
388
- let mut objective = feedback_or_fast ! ( CrashFeedback :: new( ) , TimeoutFeedback :: new( ) ) ;
394
+ let mut objective = feedback_or_fast ! ( CrashFeedback :: new( ) , TimeoutFeedback :: new( ) ) ;
389
395
390
396
// If not restarting, create a State from scratch
391
397
let mut state = state. unwrap_or_else ( || {
@@ -401,7 +407,7 @@ unsafe fn fuzz(
401
407
& mut feedback,
402
408
& mut objective,
403
409
)
404
- . unwrap ( )
410
+ . unwrap ( )
405
411
} ) ;
406
412
407
413
println ! ( "We're a client, let's fuzz :)" ) ;
@@ -421,19 +427,20 @@ unsafe fn fuzz(
421
427
let mutator = StdScheduledMutator :: new ( havoc_mutations ( ) . merge ( tokens_mutations ( ) ) ) ;
422
428
423
429
// A minimization+queue policy to get testcasess from the corpus
424
- let scheduler = IndexesLenTimeMinimizerScheduler :: new ( QueueScheduler :: new ( ) ) ;
430
+ let scheduler =
431
+ IndexesLenTimeMinimizerScheduler :: new ( & edges_observer, QueueScheduler :: new ( ) ) ;
425
432
426
433
// A fuzzer with feedbacks and a corpus scheduler
427
434
let mut fuzzer = StdFuzzer :: new ( scheduler, feedback, objective) ;
428
435
429
436
#[ cfg( unix) ]
430
- let observers = tuple_list ! (
437
+ let observers = tuple_list ! (
431
438
edges_observer,
432
439
time_observer,
433
440
AsanErrorsObserver :: new( & ASAN_ERRORS )
434
441
) ;
435
442
#[ cfg( windows) ]
436
- let observers = tuple_list ! ( edges_observer, time_observer, ) ;
443
+ let observers = tuple_list ! ( edges_observer, time_observer, ) ;
437
444
438
445
// Create the executor for an in-process function with just one observer for edge coverage
439
446
let mut executor = FridaInProcessExecutor :: new (
0 commit comments