I'm using AFL++ 4.0c to fuzz my app. It basically wraps clang compiler too instrument my code with fuzzing shenanigans. As well I provide coverage flags:
--coverage -g -fprofile-instr-generate -fcoverage-mapping
Then I try to launch my app with fuzzer
env PARAM=paramstuff \ # setup some env
afl-fuzz -x dicts/dicts -f file.txt \ # setup afl flags
-i input -o output \ # input and output for afl
-- \
./myapp --flag --flag2 --flag3 # flags for my app
It fuzzes just fine, but coverage profile is written empty.
Fuzzer works until stopped via CTRL+C. App stops the same way.
In my case AFL used fork server to fuzz parts of my app:
#ifdef __AFL_HAVE_MANUAL_CONTROL
SSH_TRACE(0, ("AFL INIT"));
__AFL_INIT();
while (__AFL_LOOP(1000)) {
#endif
/*
* regular code to fuzz goes here
*/
#ifdef __AFL_HAVE_MANUAL_CONTROL
}
#endif
So proper finalization never triggered and coverage data never dumped to profile.raw
. So to force it to dump data manually I called __llvm_profile_write_file();
right after closing bracket of afl loop in the last #ifndef
section. For gcc instrumentation exist similar function __gcov_flush()
.
Couple notes for those who fuzz things:
#ifndef
guards otherwise it will mess up with regular coverage dump when you just run app. Unless you close your forked processes with __exit()
and know what you are doing.