From d536ddc24085bced267143b4f45102715d71693e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 15 May 2020 09:27:15 +0200 Subject: change: slaves only sync from masters --- src/afl-fuzz-init.c | 47 +++++++++++++++++++++++++++++++++++++---------- src/afl-fuzz-run.c | 18 +++++++----------- src/afl-fuzz.c | 13 +++++++++++++ 3 files changed, 57 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 613d1437..518de8af 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1315,6 +1315,36 @@ dir_cleanup_failed: } +/* If this is a -S slave, ensure a -M master is running */ + +int check_master_exists(afl_state_t *afl) { + + DIR * sd; + struct dirent *sd_ent; + u8 * fn; + sd = opendir(afl->sync_dir); + if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } + while ((sd_ent = readdir(sd))) { + + /* Skip dot files and our own output directory. */ + + if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) { + + continue; + + } + + fn = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + int res = access(fn, F_OK); + free(fn); + if (res == 0) return 1; + + } + + return 0; + +} + /* Prepare output directories and fds. */ void setup_dirs_fds(afl_state_t *afl) { @@ -1330,18 +1360,15 @@ void setup_dirs_fds(afl_state_t *afl) { } - /* - if (afl->is_master) { + if (afl->is_master) { - u8 *x = alloc_printf("%s/%s/is_master", afl->sync_dir, afl->sync_id); - int fd = open(x, O_CREAT | O_RDWR, 0644); - if (fd < 0) FATAL("cannot create %s", x); - free(x); - close(fd); - - } + u8 *x = alloc_printf("%s/%s/is_master", afl->sync_dir, afl->sync_id); + int fd = open(x, O_CREAT | O_RDWR, 0644); + if (fd < 0) FATAL("cannot create %s", x); + free(x); + close(fd); - */ + } if (mkdir(afl->out_dir, 0700)) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index bbcd9a99..3708cf1a 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -401,19 +401,15 @@ void sync_fuzzers(afl_state_t *afl) { } - /* - // a slave only syncs from a master, a master syncs from everyone - if (likely(afl->is_slave)) { + // a slave only syncs from a master, a master syncs from everyone + if (likely(afl->is_slave)) { - u8 x = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); - int res = access(x, F_OK); - free(x); - if (res != 0) - continue; + u8 *x = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + int res = access(x, F_OK); + free(x); + if (likely(res != 0)) continue; - } - - */ + } /* Skip anything that doesn't have a queue/ subdirectory. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8625c37c..9240526e 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1065,8 +1065,21 @@ int main(int argc, char **argv_orig, char **envp) { init_count_class16(); + if (afl->is_master && check_master_exists(afl) == 1) { + + WARNF("It is wasteful to run more than one master!"); + + } + setup_dirs_fds(afl); + if (afl->is_slave && check_master_exists(afl) == 0) { + + WARNF("no -M master found. You need to run one master!"); + sleep(5); + + } + setup_custom_mutators(afl); setup_cmdline_file(afl, argv + optind); -- cgit 1.4.1 From 57637ba0b0981a7e2ebd407fc04a619f4120fb62 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 15 May 2020 13:39:42 +0200 Subject: removed overlooked post_lib references, added post_lib examples to examples/custom_mutators --- docs/Changelog.md | 1 + docs/QuickStartGuide.md | 5 +- docs/life_pro_tips.md | 4 +- examples/README.md | 15 ++- examples/custom_mutators/README.md | 4 + examples/custom_mutators/post_library_gif.so.c | 159 +++++++++++++++++++++++++ examples/custom_mutators/post_library_png.so.c | 157 ++++++++++++++++++++++++ include/afl-fuzz.h | 2 - qemu_mode/README.md | 2 +- src/afl-fuzz-mutators.c | 3 - 10 files changed, 339 insertions(+), 13 deletions(-) create mode 100644 examples/custom_mutators/post_library_gif.so.c create mode 100644 examples/custom_mutators/post_library_png.so.c (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 14b7fb6c..40b841a5 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,7 @@ sending a mail to . - -S slaves now only sync from the master to increase performance, the -M master stilly syncs from everyone. Added checks that exactly one master is present + - added former post_library examples to examples/custom_mutators/ ### Version ++2.65c (release): diff --git a/docs/QuickStartGuide.md b/docs/QuickStartGuide.md index 1e1d60b7..10be409a 100644 --- a/docs/QuickStartGuide.md +++ b/docs/QuickStartGuide.md @@ -10,8 +10,9 @@ how to hit the ground running: If testing a network service, modify it to run in the foreground and read from stdin. When fuzzing a format that uses checksums, comment out the checksum verification code, too. - If this is not possible (e.g. in -Q(emu) mode) then use AFL_POST_LIBRARY - to calculate the values with your own library. + + If this is not possible (e.g. in -Q(emu) mode) then use + AFL_CUSTOM_MUTATOR_LIBRARY to calculate the values with your own library. The program must crash properly when a fault is encountered. Watch out for custom SIGSEGV or SIGABRT handlers and background processes. For tips on diff --git a/docs/life_pro_tips.md b/docs/life_pro_tips.md index 0724e83c..a5bd7286 100644 --- a/docs/life_pro_tips.md +++ b/docs/life_pro_tips.md @@ -82,8 +82,8 @@ You can find a simple solution in examples/argv_fuzzing. ## Attacking a format that uses checksums? -Remove the checksum-checking code or -use a postprocessor! See examples/post_library/ for more. +Remove the checksum-checking code or use a postprocessor! +See examples/custom_mutators/ for more. ## Dealing with a very slow target or hoping for instant results? diff --git a/examples/README.md b/examples/README.md index 3c5aa9f2..d28aadbe 100644 --- a/examples/README.md +++ b/examples/README.md @@ -2,7 +2,15 @@ Here's a quick overview of the stuff you can find in this directory: - - custom_mutators - example custom mutators in python an c + - afl_network_proxy - fuzz a target over the network: afl-fuzz on + a host, target on an embedded system. + + - afl_proxy - skeleton file example to show how to fuzz + something where you gather coverage data via + different means, e.g. hw debugger + + - afl_untracer - fuzz binary-only libraries much faster but with + less coverage than qemu_mode - argv_fuzzing - a simple wrapper to allow cmdline to be fuzzed (e.g., to test setuid programs). @@ -23,6 +31,9 @@ Here's a quick overview of the stuff you can find in this directory: - crash_triage - a very rudimentary example of how to annotate crashes with additional gdb metadata. + - custom_mutators - examples for the afl++ custom mutator interface in + C and Python + - distributed_fuzzing - a sample script for synchronizing fuzzer instances across multiple machines (see parallel_fuzzing.md). @@ -31,8 +42,6 @@ Here's a quick overview of the stuff you can find in this directory: - persistent_demo - an example of how to use the LLVM persistent process mode to speed up certain fuzzing jobs. - - post_library - an example of how to build postprocessors for AFL. - - socket_fuzzing - a LD_PRELOAD library 'redirects' a socket to stdin for fuzzing access with afl++ diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md index 99fb9da3..a81538e6 100644 --- a/examples/custom_mutators/README.md +++ b/examples/custom_mutators/README.md @@ -15,6 +15,10 @@ example.c - this is a simple example written in C and should be compiled to a example.py - this is the template you can use, the functions are there but they are empty +post_library_gif.so.c - fix a fuzz input to ensure it is valid for GIF + +post_library_png.so.c - fix a fuzz input to ensure it is valid for PNG + simple-chunk-replace.py - this is a simple example where chunks are replaced common.py - this can be used for common functions and helpers. diff --git a/examples/custom_mutators/post_library_gif.so.c b/examples/custom_mutators/post_library_gif.so.c new file mode 100644 index 00000000..9b76ead5 --- /dev/null +++ b/examples/custom_mutators/post_library_gif.so.c @@ -0,0 +1,159 @@ +/* + american fuzzy lop++ - postprocessor library example + -------------------------------------------------- + + Originally written by Michal Zalewski + Edited by Dominik Maier, 2020 + + Copyright 2015 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + Postprocessor libraries can be passed to afl-fuzz to perform final cleanup + of any mutated test cases - for example, to fix up checksums in PNG files. + + Please heed the following warnings: + + 1) In almost all cases, it is more productive to comment out checksum logic + in the targeted binary (as shown in ../libpng_no_checksum/). One possible + exception is the process of fuzzing binary-only software in QEMU mode. + + 2) The use of postprocessors for anything other than checksums is + questionable and may cause more harm than good. AFL is normally pretty good + about dealing with length fields, magic values, etc. + + 3) Postprocessors that do anything non-trivial must be extremely robust to + gracefully handle malformed data and other error conditions - otherwise, + they will crash and take afl-fuzz down with them. Be wary of reading past + *len and of integer overflows when calculating file offsets. + + In other words, THIS IS PROBABLY NOT WHAT YOU WANT - unless you really, + honestly know what you're doing =) + + With that out of the way: the postprocessor library is passed to afl-fuzz + via AFL_POST_LIBRARY. The library must be compiled with: + + gcc -shared -Wall -O3 post_library.so.c -o post_library.so + + AFL will call the afl_custom_post_process() function for every mutated output + buffer. From there, you have three choices: + + 1) If you don't want to modify the test case, simply set `*out_buf = in_buf` + and return the original `len`. + + 2) If you want to skip this test case altogether and have AFL generate a + new one, return 0 or set `*out_buf = NULL`. + Use this sparingly - it's faster than running the target program + with patently useless inputs, but still wastes CPU time. + + 3) If you want to modify the test case, allocate an appropriately-sized + buffer, move the data into that buffer, make the necessary changes, and + then return the new pointer as out_buf. Return an appropriate len + afterwards. + + Note that the buffer will *not* be freed for you. To avoid memory leaks, + you need to free it or reuse it on subsequent calls (as shown below). + + *** Feel free to reuse the original 'in_buf' BUFFER and return it. *** + + Aight. The example below shows a simple postprocessor that tries to make + sure that all input files start with "GIF89a". + + PS. If you don't like C, you can try out the unix-based wrapper from + Ben Nagy instead: https://github.com/bnagy/aflfix + + */ + +#include +#include +#include + +/* Header that must be present at the beginning of every test case: */ + +#define HEADER "GIF89a" + +typedef struct post_state { + + unsigned char *buf; + size_t size; + +} post_state_t; + +void *afl afl_custom_init(void *afl) { + + post_state_t *state = malloc(sizeof(post_state_t)); + if (!state) { + + perror("malloc"); + return NULL; + + } + + state->buf = calloc(sizeof(unsigned char), 4096); + if (!state->buf) { return NULL; } + + return state; + +} + +/* The actual postprocessor routine called by afl-fuzz: */ + +size_t afl_custom_post_process(post_state_t *data, unsigned char *in_buf, + unsigned int len, unsigned char **out_buf) { + + /* Skip execution altogether for buffers shorter than 6 bytes (just to + show how it's done). We can trust len to be sane. */ + + if (len < strlen(HEADER)) return 0; + + /* Do nothing for buffers that already start with the expected header. */ + + if (!memcmp(in_buf, HEADER, strlen(HEADER))) { + + *out_buf = in_buf; + return len; + + } + + /* Allocate memory for new buffer, reusing previous allocation if + possible. */ + + *out_buf = realloc(data->buf, len); + + /* If we're out of memory, the most graceful thing to do is to return the + original buffer and give up on modifying it. Let AFL handle OOM on its + own later on. */ + + if (!*out_buf) { + + *out_buf = in_buf; + return len; + + } + + /* Copy the original data to the new location. */ + + memcpy(*out_buf, in_buf, len); + + /* Insert the new header. */ + + memcpy(*out_buf, HEADER, strlen(HEADER)); + + /* Return the new len. It hasn't changed, so it's just len. */ + + return len; + +} + +/* Gets called afterwards */ +void afl_custom_deinit(post_state_t *data) { + + free(data->buf); + free(data); + +} + diff --git a/examples/custom_mutators/post_library_png.so.c b/examples/custom_mutators/post_library_png.so.c new file mode 100644 index 00000000..7c1ea93e --- /dev/null +++ b/examples/custom_mutators/post_library_png.so.c @@ -0,0 +1,157 @@ +/* + american fuzzy lop++ - postprocessor for PNG + ------------------------------------------ + + Originally written by Michal Zalewski + + Copyright 2015 Google Inc. All rights reserved. + Adapted to the new API, 2020 by Dominik Maier + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + See post_library.so.c for a general discussion of how to implement + postprocessors. This specific postprocessor attempts to fix up PNG + checksums, providing a slightly more complicated example than found + in post_library.so.c. + + Compile with: + + gcc -shared -Wall -O3 post_library_png.so.c -o post_library_png.so -lz + + */ + +#include +#include +#include +#include +#include + +#include + +/* A macro to round an integer up to 4 kB. */ + +#define UP4K(_i) ((((_i) >> 12) + 1) << 12) + +typedef struct post_state { + + unsigned char *buf; + size_t size; + +} post_state_t; + +void *afl_custom_init(void *afl) { + + post_state_t *state = malloc(sizeof(post_state_t)); + if (!state) { + + perror("malloc"); + return NULL; + + } + + state->buf = calloc(sizeof(unsigned char), 4096); + if (!state->buf) { return NULL; } + + return state; + +} + +size_t afl_custom_post_process(post_state_t *data, const unsigned char *in_buf, + unsigned int len, + const unsigned char **out_buf) { + + unsigned char *new_buf = (unsigned char *)in_buf; + unsigned int pos = 8; + + /* Don't do anything if there's not enough room for the PNG header + (8 bytes). */ + + if (len < 8) { + + *out_buf = in_buf; + return len; + + } + + /* Minimum size of a zero-length PNG chunk is 12 bytes; if we + don't have that, we can bail out. */ + + while (pos + 12 <= len) { + + unsigned int chunk_len, real_cksum, file_cksum; + + /* Chunk length is the first big-endian dword in the chunk. */ + + chunk_len = ntohl(*(uint32_t *)(in_buf + pos)); + + /* Bail out if chunk size is too big or goes past EOF. */ + + if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > len) break; + + /* Chunk checksum is calculated for chunk ID (dword) and the actual + payload. */ + + real_cksum = htonl(crc32(0, in_buf + pos + 4, chunk_len + 4)); + + /* The in-file checksum is the last dword past the chunk data. */ + + file_cksum = *(uint32_t *)(in_buf + pos + 8 + chunk_len); + + /* If the checksums do not match, we need to fix the file. */ + + if (real_cksum != file_cksum) { + + /* First modification? Make a copy of the input buffer. Round size + up to 4 kB to minimize the number of reallocs needed. */ + + if (new_buf == in_buf) { + + if (len <= data->size) { + + new_buf = data->buf; + + } else { + + new_buf = realloc(data->buf, UP4K(len)); + if (!new_buf) { + + *out_buf = in_buf; + return len; + + } + + data->buf = new_buf; + data->size = UP4K(len); + memcpy(new_buf, in_buf, len); + + } + + } + + *(uint32_t *)(new_buf + pos + 8 + chunk_len) = real_cksum; + + } + + /* Skip the entire chunk and move to the next one. */ + + pos += 12 + chunk_len; + + } + + *out_buf = new_buf; + return len; + +} + +/* Gets called afterwards */ +void afl_custom_deinit(post_state_t *data) { + + free(data->buf); + free(data); + +} + diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index a77c634c..6e74f824 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -547,8 +547,6 @@ typedef struct afl_state { /* afl_postprocess API - Now supported via custom mutators */ - struct custom_mutator *post_library_mutator; - /* CmpLog */ char * cmplog_binary; diff --git a/qemu_mode/README.md b/qemu_mode/README.md index 76b74e17..50d451b6 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -157,7 +157,7 @@ match. ## 10) Gotchas, feedback, bugs If you need to fix up checksums or do other cleanup on mutated test cases, see -examples/post_library/ for a viable solution. +examples/custom_mutators/ for a viable solution. Do not mix QEMU mode with ASAN, MSAN, or the likes; QEMU doesn't appreciate the "shadow VM" trick employed by the sanitizers and will probably just diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 87cb86fa..29e10d02 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -108,9 +108,6 @@ void setup_custom_mutators(afl_state_t *afl) { #endif - if (afl->post_library_mutator) - list_append(&afl->custom_mutator_list, afl->post_library_mutator); - } void destroy_custom_mutators(afl_state_t *afl) { -- cgit 1.4.1 From 9dd3e3e38a6f9643a4850099ca7e0112e5e94f14 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 17 May 2020 00:13:55 +0200 Subject: fix -M check --- src/afl-fuzz-init.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 518de8af..1a724bfb 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1315,15 +1315,18 @@ dir_cleanup_failed: } -/* If this is a -S slave, ensure a -M master is running */ +/* If this is a -S slave, ensure a -M master is running, if a master is + running when another master is started then warn */ int check_master_exists(afl_state_t *afl) { DIR * sd; struct dirent *sd_ent; u8 * fn; + sd = opendir(afl->sync_dir); - if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } + if (!sd) { return 0; } + while ((sd_ent = readdir(sd))) { /* Skip dot files and our own output directory. */ -- cgit 1.4.1 From d37a8f72d6d4d92df73a318ad02046adbc6dba29 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 17 May 2020 01:36:03 +0200 Subject: fix master creation file --- src/afl-fuzz-init.c | 20 ++++++++++---------- src/afl-fuzz.c | 3 ++- 2 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 1a724bfb..dd85a8f4 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1363,16 +1363,6 @@ void setup_dirs_fds(afl_state_t *afl) { } - if (afl->is_master) { - - u8 *x = alloc_printf("%s/%s/is_master", afl->sync_dir, afl->sync_id); - int fd = open(x, O_CREAT | O_RDWR, 0644); - if (fd < 0) FATAL("cannot create %s", x); - free(x); - close(fd); - - } - if (mkdir(afl->out_dir, 0700)) { if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); } @@ -1402,6 +1392,16 @@ void setup_dirs_fds(afl_state_t *afl) { } + if (afl->is_master) { + + u8 *x = alloc_printf("%s/is_master", afl->out_dir); + int fd = open(x, O_CREAT | O_RDWR, 0644); + if (fd < 0) FATAL("cannot create %s", x); + free(x); + close(fd); + + } + /* Queue directory for any starting & discovered paths. */ tmp = alloc_printf("%s/queue", afl->out_dir); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9240526e..94f47341 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1067,7 +1067,8 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->is_master && check_master_exists(afl) == 1) { - WARNF("It is wasteful to run more than one master!"); + WARNF("it is wasteful to run more than one master!"); + sleep(1); } -- cgit 1.4.1 From 30824bc58ef5b5f5e44fecfb3607c3ed4ad34744 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 18 May 2020 10:48:39 +0200 Subject: afl-as fast system fix --- src/afl-as.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/afl-as.c b/src/afl-as.c index 4809a731..f153c043 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -233,7 +233,7 @@ static void edit_params(int argc, char **argv) { } modified_file = - alloc_printf("%s/.afl-%u-%u.s", tmp_dir, (u32)getpid(), (u32)time(NULL)); + alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(), (u32)time(NULL), (u32)random()); wrap_things_up: @@ -531,7 +531,7 @@ static void add_instrumentation(void) { int main(int argc, char **argv) { s32 pid; - u32 rand_seed; + u32 rand_seed, i, j; int status; u8 *inst_ratio_str = getenv("AFL_INST_RATIO"); @@ -590,6 +590,10 @@ int main(int argc, char **argv) { gettimeofday(&tv, &tz); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); + // in fast systems where pids can repeat in the same seconds we need this + for (i = 1; i < argc; i++) + for (j = 0; j < strlen(argv[i]); j++) + rand_seed += argv[i][j]; srandom(rand_seed); -- cgit 1.4.1 From 25fbec663838cd23908042f4a8fca175ca77c046 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 19 May 2020 19:51:54 +0200 Subject: if no master is present a slave becomes a temporary master --- docs/Changelog.md | 2 ++ src/afl-as.c | 8 +++---- src/afl-fuzz-run.c | 67 ++++++++++++++++++++++++++++++++++-------------------- 3 files changed, 48 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 189eca69..de874d1a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,8 @@ sending a mail to . - -S slaves now only sync from the master to increase performance, the -M master stilly syncs from everyone. Added checks that exactly one master is present + - If no master is present at sync time one slave automatically becomes + a temporary master until a real master shows up - llvm_mode: - lowered minimum required llvm version to 3.4 (except LLVMInsTrim, which needs 3.8.0) diff --git a/src/afl-as.c b/src/afl-as.c index f153c043..f16d6060 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -232,8 +232,8 @@ static void edit_params(int argc, char **argv) { } - modified_file = - alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(), (u32)time(NULL), (u32)random()); + modified_file = alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(), + (u32)time(NULL), (u32)random()); wrap_things_up: @@ -592,8 +592,8 @@ int main(int argc, char **argv) { rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); // in fast systems where pids can repeat in the same seconds we need this for (i = 1; i < argc; i++) - for (j = 0; j < strlen(argv[i]); j++) - rand_seed += argv[i][j]; + for (j = 0; j < strlen(argv[i]); j++) + rand_seed += argv[i][j]; srandom(rand_seed); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 3708cf1a..bf13f1f9 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -373,7 +373,7 @@ void sync_fuzzers(afl_state_t *afl) { DIR * sd; struct dirent *sd_ent; - u32 sync_cnt = 0; + u32 sync_cnt = 0, synced = 0, entries = 0; sd = opendir(afl->sync_dir); if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } @@ -388,7 +388,7 @@ void sync_fuzzers(afl_state_t *afl) { DIR * qd; struct dirent *qd_ent; - u8 * qd_path, *qd_synced_path; + u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; u32 min_accept = 0, next_min_accept; s32 id_fd; @@ -401,31 +401,41 @@ void sync_fuzzers(afl_state_t *afl) { } + entries++; + // a slave only syncs from a master, a master syncs from everyone if (likely(afl->is_slave)) { - u8 *x = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); - int res = access(x, F_OK); - free(x); - if (likely(res != 0)) continue; + sprintf(qd_path, "%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + int res = access(qd_path, F_OK); + if (unlikely(afl->is_master)) { // an elected temporary master - } + if (likely(res == 0)) { // there is another master? downgrade. - /* Skip anything that doesn't have a queue/ subdirectory. */ + afl->is_master = 0; + sprintf(qd_path, "%s/is_master", afl->out_dir); - qd_path = alloc_printf("%s/%s/queue", afl->sync_dir, sd_ent->d_name); + } - if (!(qd = opendir(qd_path))) { + } else { - ck_free(qd_path); - continue; + if (likely(res != 0)) { continue; } + + } } + synced++; + + /* Skip anything that doesn't have a queue/ subdirectory. */ + + sprintf(qd_path, "%s/%s/queue", afl->sync_dir, sd_ent->d_name); + + if (!(qd = opendir(qd_path))) { continue; } + /* Retrieve the ID of the last seen test case. */ - qd_synced_path = - alloc_printf("%s/.synced/%s", afl->out_dir, sd_ent->d_name); + sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name); id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); @@ -452,7 +462,7 @@ void sync_fuzzers(afl_state_t *afl) { while ((qd_ent = readdir(qd))) { - u8 * path; + u8 path[PATH_MAX]; s32 fd; struct stat st; @@ -472,18 +482,13 @@ void sync_fuzzers(afl_state_t *afl) { } - path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); + alloc_printf(path, "%s/%s", qd_path, qd_ent->d_name); /* Allow this to fail in case the other fuzzer is resuming or so... */ fd = open(path, O_RDONLY); - if (fd < 0) { - - ck_free(path); - continue; - - } + if (fd < 0) { continue; } if (fstat(fd, &st)) { PFATAL("fstat() failed"); } @@ -516,7 +521,6 @@ void sync_fuzzers(afl_state_t *afl) { } - ck_free(path); close(fd); } @@ -526,13 +530,26 @@ void sync_fuzzers(afl_state_t *afl) { close_sync: close(id_fd); closedir(qd); - ck_free(qd_path); - ck_free(qd_synced_path); } closedir(sd); + // If we are a slave and no master was found to sync then become the master + if (unlikely(synced == 0) && likely(entries) && likely(afl->is_slave)) { + + // there is a small race condition here that another slave runs at the same + // time. If so, the first temporary master running again will demote + // themselves so this is not an issue + + u8 path[PATH_MAX]; + afl->is_master = 1; + sprintf(path, "%s/is_master", afl->out_dir); + int fd = open(path, O_CREAT | O_RDWR, 0644); + if (fd >= 0) { close(fd); } + + } + } /* Trim all new test cases to save cycles when doing deterministic checks. The -- cgit 1.4.1 From 0ed767fac5882c98f046cd6482f6fd4b0df1514a Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 19 May 2020 19:54:10 +0200 Subject: forgot the unlink ... --- src/afl-fuzz-run.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index bf13f1f9..331df288 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -414,6 +414,7 @@ void sync_fuzzers(afl_state_t *afl) { afl->is_master = 0; sprintf(qd_path, "%s/is_master", afl->out_dir); + unlink(qd_path); } -- cgit 1.4.1 From 982017a2abe935e7221de01150ede05e0082d9f6 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 20 May 2020 22:52:33 +0200 Subject: remove master file on exit --- src/afl-fuzz.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 94f47341..c07371a8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1366,6 +1366,14 @@ stop_fuzzing: time_spent_working / afl->fsrv.total_execs); #endif + if (afl->is_master) { + + u8 path[PATH_MAX]; + sprintf(path, "%s/is_master", afl->out_dir); + unlink(path); + + } + fclose(afl->fsrv.plot_file); destroy_queue(afl); destroy_extras(afl); -- cgit 1.4.1 From c456e20750483c8872229bf6e18f5f6a44d28bc3 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 20 May 2020 23:12:33 +0200 Subject: better sync - lesser and better imports --- src/afl-fuzz-run.c | 59 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 331df288..8a1f02a7 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -374,6 +374,7 @@ void sync_fuzzers(afl_state_t *afl) { DIR * sd; struct dirent *sd_ent; u32 sync_cnt = 0, synced = 0, entries = 0; + u8 path[PATH_MAX]; sd = opendir(afl->sync_dir); if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } @@ -386,10 +387,8 @@ void sync_fuzzers(afl_state_t *afl) { while ((sd_ent = readdir(sd))) { - DIR * qd; - struct dirent *qd_ent; - u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; - u32 min_accept = 0, next_min_accept; + u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; + u32 min_accept = 0, next_min_accept; s32 id_fd; @@ -432,7 +431,17 @@ void sync_fuzzers(afl_state_t *afl) { sprintf(qd_path, "%s/%s/queue", afl->sync_dir, sd_ent->d_name); - if (!(qd = opendir(qd_path))) { continue; } + struct dirent **namelist = NULL; + int m = 0, n, o; + + n = scandir(qd_path, &namelist, NULL, alphasort); + + if (n < 1) { + + if (namelist) free(namelist); + continue; + + } /* Retrieve the ID of the last seen test case. */ @@ -461,29 +470,34 @@ void sync_fuzzers(afl_state_t *afl) { /* For every file queued by this fuzzer, parse ID and see if we have looked at it before; exec a test case if not. */ - while ((qd_ent = readdir(qd))) { + u8 entry[12]; + sprintf(entry, "id:%06u", next_min_accept); + while (m < n) { - u8 path[PATH_MAX]; - s32 fd; - struct stat st; + if (memcmp(namelist[m]->d_name, entry, 9)) { - if (qd_ent->d_name[0] == '.' || - sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &afl->syncing_case) != 1 || - afl->syncing_case < min_accept) { + m++; - continue; + } else { + + break; } - /* OK, sounds like a new one. Let's give it a try. */ + } - if (afl->syncing_case >= next_min_accept) { + if (m >= n) { goto close_sync; } // nothing new + o = n - 1; - next_min_accept = afl->syncing_case + 1; + while (o >= m) { - } + s32 fd; + struct stat st; - alloc_printf(path, "%s/%s", qd_path, qd_ent->d_name); + sprintf(path, "%s/%s", qd_path, namelist[o]->d_name); + afl->syncing_case = next_min_accept; + next_min_accept++; + o--; /* Allow this to fail in case the other fuzzer is resuming or so... */ @@ -491,7 +505,7 @@ void sync_fuzzers(afl_state_t *afl) { if (fd < 0) { continue; } - if (fstat(fd, &st)) { PFATAL("fstat() failed"); } + if (fstat(fd, &st)) { WARNF("fstat() failed"); } /* Ignore zero-sized or oversized files. */ @@ -518,8 +532,6 @@ void sync_fuzzers(afl_state_t *afl) { munmap(mem, st.st_size); - if (!(afl->stage_cur++ % afl->stats_update_freq)) { show_stats(afl); } - } close(fd); @@ -530,7 +542,10 @@ void sync_fuzzers(afl_state_t *afl) { close_sync: close(id_fd); - closedir(qd); + if (n > 0) + for (m = 0; m < n; m++) + free(namelist[m]); + free(namelist); } -- cgit 1.4.1 From 38fe1c60666d9e8cb3d7b825e5a926111b2160d5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 22 May 2020 20:59:32 +0200 Subject: more help for LTO issues --- llvm_mode/README.lto.md | 11 +++++++++-- src/afl-forkserver.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index fa5b8665..88b1517d 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -6,8 +6,6 @@ This version requires a current llvm 11 compiled from the github master. 1. Use afl-clang-lto/afl-clang-lto++ because it is faster and gives better coverage than anything else that is out there in the AFL world - 1a. Set AFL_LLVM_INSTRUMENT=CFG if you want the InsTrimLTO version - (recommended) 2. You can use it together with llvm_mode: laf-intel and whitelisting features and can be combined with cmplog/Redqueen @@ -20,6 +18,8 @@ This version requires a current llvm 11 compiled from the github master. note that if that target uses _init functions or early constructors then also set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise +6. If you get the error `error: Invalid record` at link time you must decide + between LTO or cmplog/laf-intel ## Introduction and problem description @@ -134,6 +134,13 @@ and on some target you have to to AR=/RANLIB= even for make as the configure scr Other targets ignore environment variables and need the parameters set via `./configure --cc=... --cxx= --ranlib= ...` etc. (I am looking at you ffmpeg!). +### error: Invalid record + +This error only occurs if cmplog or laf-intel were activated. +If you see the error `error: Invalid record` at link time then an +instrumentation went wrong. You now must choose, either use afl-clang-fast +and keep cmplog/laf-intel, or drop cmplog/laf-intel and keep using afl-clang-lto. + ### compiling programs still fail afl-clang-lto is still work in progress. diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1c0ba349..076fa392 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -679,7 +679,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "Hmm, looks like the target binary terminated before we could" "complete a handshake with the injected code.\n" "If the target was compiled with afl-clang-lto then recompiling with" - "AFL_LLVM_MAP_DYNAMIC might solve your problem.\n" + " AFL_LLVM_MAP_DYNAMIC might solve your problem.\n" "Otherwise there is a horrible bug in the fuzzer.\n" "Poke for troubleshooting tips.\n"); -- cgit 1.4.1 From c64ea494320f174575206006d0ea8c098c1a71e1 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 23 May 2020 01:37:21 +0200 Subject: AFL_LLVM_LAF_ALL --- docs/Changelog.md | 1 + docs/env_variables.md | 9 +++++++-- llvm_mode/README.laf-intel.md | 3 +++ llvm_mode/afl-clang-fast.c | 17 +++++++++++++---- src/afl-common.c | 2 +- 5 files changed, 25 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 71738913..08952717 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -24,6 +24,7 @@ sending a mail to . - lowered minimum required llvm version to 3.4 (except LLVMInsTrim, which needs 3.8.0) - small change to cmplog to make it work with current llvm 11-dev + - added AFL_LLVM_LAF_ALL, sets all laf-intel settings - fixed afl-gcc/afl-as that could break on fast systems reusing pids in the same second - added lots of dictionaries from oss-fuzz, go-fuzz and Jakub Wilk diff --git a/docs/env_variables.md b/docs/env_variables.md index 2668be7d..867e937e 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -190,13 +190,18 @@ Then there are a few specific features that are only available in llvm_mode: to allow afl-fuzz to find otherwise rather impossible paths. It is not restricted to Intel CPUs ;-) - - Setting AFL_LLVM_LAF_SPLIT_SWITCHES will split switch()es - - Setting AFL_LLVM_LAF_TRANSFORM_COMPARES will split string compare functions + - Setting AFL_LLVM_LAF_SPLIT_SWITCHES will split switch()es + - Setting AFL_LLVM_LAF_SPLIT_COMPARES will split all floating point and 64, 32 and 16 bit integer CMP instructions + - Setting AFL_LLVM_LAF_SPLIT_FLOATS will split floating points, needs + AFL_LLVM_LAF_SPLIT_COMPARES to be set + + - Setting AFL_LLVM_LAF_ALL sets all of the above + See llvm_mode/README.laf-intel.md for more information. ### WHITELIST diff --git a/llvm_mode/README.laf-intel.md b/llvm_mode/README.laf-intel.md index 462c7bac..2fa4bc26 100644 --- a/llvm_mode/README.laf-intel.md +++ b/llvm_mode/README.laf-intel.md @@ -37,3 +37,6 @@ series of sign, exponent and mantissa comparisons followed by splitting each of them into 8 bit comparisons when necessary. It is activated with the `AFL_LLVM_LAF_SPLIT_FLOATS` setting, available only when `AFL_LLVM_LAF_SPLIT_COMPARES` is set. + +You can also set `AFL_LLVM_LAF_ALL` and have all of the above enabled :-) + diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 2cc40b62..2aeb0400 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -829,14 +829,14 @@ int main(int argc, char **argv, char **envp) { "AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n" "AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n" "AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n" - "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to " - "cascaded " - "comp.\n" + "AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" "AFL_LLVM_LAF_SPLIT_SWITCHES: casc. comp. in 'switch'\n" " to cascaded comparisons\n" + "AFL_LLVM_LAF_SPLIT_FLOATS: transform floating point comp. to " + "cascaded comp.\n" "AFL_LLVM_LAF_TRANSFORM_COMPARES: transform library comparison " "function calls\n" - "AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n" + "AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n" "AFL_LLVM_WHITELIST: enable whitelisting (selective " "instrumentation)\n" "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" @@ -925,6 +925,15 @@ int main(int argc, char **argv, char **envp) { check_environment_vars(envp); + if (getenv("AFL_LLVM_LAF_ALL")) { + + setenv("AFL_LLVM_LAF_SPLIT_SWITCHES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_COMPARES", "1", 1); + setenv("AFL_LLVM_LAF_SPLIT_FLOATS", "1", 1); + setenv("AFL_LLVM_LAF_TRANSFORM_COMPARES", "1", 1); + + } + cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG"); if (!be_quiet && cmplog_mode) printf("CmpLog mode by \n"); diff --git a/src/afl-common.c b/src/afl-common.c index 808c9812..1bb58a60 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -67,7 +67,7 @@ char *afl_environment_variables[] = { "AFL_LLVM_SKIPSINGLEBLOCK", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", - "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", + "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", -- cgit 1.4.1 From 0245f8438d71b07e2a2415e8880bd4bbd70b5859 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Sat, 23 May 2020 08:15:20 +0200 Subject: forkserver: missing space in message --- src/afl-forkserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 076fa392..b67aedde 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -677,7 +677,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated before we could" - "complete a handshake with the injected code.\n" + " complete a handshake with the injected code.\n" "If the target was compiled with afl-clang-lto then recompiling with" " AFL_LLVM_MAP_DYNAMIC might solve your problem.\n" "Otherwise there is a horrible bug in the fuzzer.\n" -- cgit 1.4.1 From 707145c491366825b5595eada29fbb2e87e800fd Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 25 May 2020 16:40:55 +0200 Subject: persistent mode: shared memory test case transfer --- docs/Changelog.md | 2 + examples/persistent_demo/persistent_demo.c | 14 ++- examples/persistent_demo/persistent_demo_new.c | 118 +++++++++++++++++++++++++ include/afl-fuzz.h | 1 + include/config.h | 4 + include/forkserver.h | 8 ++ include/types.h | 3 +- llvm_mode/afl-clang-fast.c | 8 ++ llvm_mode/afl-llvm-rt.o.c | 91 +++++++++++++++++-- src/afl-forkserver.c | 79 ++++++++++++----- src/afl-fuzz-init.c | 24 +++++ src/afl-fuzz-run.c | 10 +++ src/afl-fuzz.c | 8 ++ 13 files changed, 340 insertions(+), 30 deletions(-) create mode 100644 examples/persistent_demo/persistent_demo_new.c (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 6115a0cc..884de0b1 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,8 @@ sending a mail to . ### Version ++2.65d (dev) + - initial support for persistent mode shared memory testcase handover + (instead of via files/stdin) - afl-fuzz: - -S slaves now only sync from the master to increase performance, the -M master stilly syncs from everyone. Added checks that exactly diff --git a/examples/persistent_demo/persistent_demo.c b/examples/persistent_demo/persistent_demo.c index 36f12850..41cd9e38 100644 --- a/examples/persistent_demo/persistent_demo.c +++ b/examples/persistent_demo/persistent_demo.c @@ -63,7 +63,7 @@ int main(int argc, char **argv) { We just have some trivial inline code that faults on 'foo!'. */ /* do we have enough data? */ - if (len < 4) return 0; + if (len < 8) return 0; if (buf[0] == 'f') { @@ -77,7 +77,17 @@ int main(int argc, char **argv) { if (buf[3] == '!') { printf("four\n"); - abort(); + if (buf[4] == '!') { + + printf("five\n"); + if (buf[5] == '!') { + + printf("six\n"); + abort(); + + } + + } } diff --git a/examples/persistent_demo/persistent_demo_new.c b/examples/persistent_demo/persistent_demo_new.c new file mode 100644 index 00000000..fffd40b6 --- /dev/null +++ b/examples/persistent_demo/persistent_demo_new.c @@ -0,0 +1,118 @@ +/* + american fuzzy lop++ - persistent mode example + -------------------------------------------- + + Originally written by Michal Zalewski + + Copyright 2015 Google Inc. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This file demonstrates the high-performance "persistent mode" that may be + suitable for fuzzing certain fast and well-behaved libraries, provided that + they are stateless or that their internal state can be easily reset + across runs. + + To make this work, the library and this shim need to be compiled in LLVM + mode using afl-clang-fast (other compiler wrappers will *not* work). + + */ + +#include +#include +#include +#include +#include + +__AFL_FUZZ_INIT(); + +unsigned int crc32_for_byte(unsigned int r) { + + for (int j = 0; j < 8; ++j) + r = (r & 1 ? 0 : (unsigned int)0xEDB88320L) ^ r >> 1; + return r ^ (unsigned int)0xFF000000L; + +} + +unsigned int crc32(unsigned char *data, unsigned int n_bytes) { + + static unsigned char table[0x100]; + unsigned int crc = 0; + if (!*table) + for (unsigned int i = 0; i < 0x100; ++i) + table[i] = crc32_for_byte(i); + for (unsigned int i = 0; i < n_bytes; ++i) + crc = table[(unsigned char)crc ^ (data)[i]] ^ crc >> 8; + return crc; + +} + +/* Main entry point. */ + +int main(int argc, char **argv) { + + ssize_t len; /* how much input did we read? */ + unsigned char *buf; /* test case buffer pointer */ + + /* The number passed to __AFL_LOOP() controls the maximum number of + iterations before the loop exits and the program is allowed to + terminate normally. This limits the impact of accidental memory leaks + and similar hiccups. */ + + buf = __AFL_FUZZ_TESTCASE_BUF; + + while (__AFL_LOOP(1000)) { + + len = __AFL_FUZZ_TESTCASE_LEN; + + /* do we have enough data? */ + if (len < 8) return 0; + + if (buf[0] == 'f') { + + printf("one\n"); + if (buf[1] == 'o') { + + printf("two\n"); + if (buf[2] == 'o') { + + printf("three\n"); + if (buf[3] == '!') { + + printf("four\n"); + if (buf[4] == '!') { + + printf("five\n"); + if (buf[6] == '!') { + + printf("six\n"); + abort(); + + } + + } + + } + + } + + } + + } + + /*** END PLACEHOLDER CODE ***/ + + } + + /* Once the loop is exited, terminate normally - AFL will restart the process + when this happens, with a clean slate when it comes to allocated memory, + leftover file descriptors, etc. */ + + return 0; + +} + diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 6e74f824..32ae2a58 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -342,6 +342,7 @@ typedef struct afl_state { afl_forkserver_t fsrv; sharedmem_t shm; + sharedmem_t * shm_fuzz; afl_env_vars_t afl_env; char **argv; /* argv if needed */ diff --git a/include/config.h b/include/config.h index 6fde8b36..57efd0f6 100644 --- a/include/config.h +++ b/include/config.h @@ -304,6 +304,10 @@ #define SHM_ENV_VAR "__AFL_SHM_ID" +/* Environment variable used to pass SHM FUZZ ID to the called program. */ + +#define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID" + /* Other less interesting, internal-only variables. */ #define CLANG_ENV_VAR "__AFL_CLANG_MODE" diff --git a/include/forkserver.h b/include/forkserver.h index e8ac2837..00555d7e 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -73,10 +73,18 @@ typedef struct afl_forkserver { u8 last_kill_signal; /* Signal that killed the child */ + u8 use_shdmen_fuzz; /* use shared mem for test cases */ + + u8 support_shdmen_fuzz; /* set by afl-fuzz */ + u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ u8 qemu_mode; /* if running in qemu mode or not */ + u32 shdmem_fuzz_len; /* length of the fuzzing test case */ + + u8 *shdmem_fuzz; /* allocated memory for fuzzing */ + char *cmplog_binary; /* the name of the cmplog binary */ /* Function to kick off the forkserver child */ diff --git a/include/types.h b/include/types.h index f95c4be2..95ca2689 100644 --- a/include/types.h +++ b/include/types.h @@ -43,10 +43,11 @@ typedef uint32_t u32; #define FS_ERROR_MMAP 16 /* Reporting options */ -#define FS_OPT_ENABLED 0x8f000001 +#define FS_OPT_ENABLED 0x80000001 #define FS_OPT_MAPSIZE 0x40000000 #define FS_OPT_SNAPSHOT 0x20000000 #define FS_OPT_AUTODICT 0x10000000 +#define FS_OPT_SHDMEM_FUZZ 0x01000000 // FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 #define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1) #define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 8791c5ae..e8f20bb2 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -489,6 +489,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { */ + cc_params[cc_par_cnt++] = + "-D__AFL_FUZZ_INIT()=" + "int __afl_sharedmem_fuzzing = 1;" + "extern unsigned int __afl_fuzz_len;" + "extern unsigned char *__afl_fuzz_ptr;"; + cc_params[cc_par_cnt++] = "-D__AFL_FUZZ_TESTCASE_BUF=__afl_fuzz_ptr"; + cc_params[cc_par_cnt++] = "-D__AFL_FUZZ_TESTCASE_LEN=__afl_fuzz_len"; + cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)=" "({ static volatile char *_B __attribute__((used)); " diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index dac35796..a461bc03 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -76,6 +76,8 @@ u8 __afl_area_initial[MAP_SIZE]; #endif u8 *__afl_area_ptr = __afl_area_initial; u8 *__afl_dictionary; +u8 *__afl_fuzz_ptr; +u32 __afl_fuzz_len; u32 __afl_final_loc; u32 __afl_map_size = MAP_SIZE; @@ -92,6 +94,8 @@ __thread u32 __afl_prev_ctx; __thread u32 __afl_cmp_counter; #endif +int __afl_sharedmem_fuzzing __attribute__((weak)); + struct cmp_map *__afl_cmp_map; /* Running in persistent mode? */ @@ -109,6 +113,59 @@ void send_forkserver_error(int error) { } +/* SHM fuzzing setup. */ + +static void __afl_map_shm_fuzz() { + + char *id_str = getenv(SHM_FUZZ_ENV_VAR); + + if (id_str) { + +#ifdef USEMMAP + const char * shm_file_path = id_str; + int shm_fd = -1; + unsigned char *shm_base = NULL; + + /* create the shared memory segment as if it was a file */ + shm_fd = shm_open(shm_file_path, O_RDWR, 0600); + if (shm_fd == -1) { + + fprintf(stderr, "shm_open() failed for fuzz\n"); + send_forkserver_error(FS_ERROR_SHM_OPEN); + exit(1); + + } + + __afl_fuzz_ptr = mmap(0, MAX_FILE, PROT_READ, MAP_SHARED, shm_fd, 0); + +#else + u32 shm_id = atoi(id_str); + + __afl_fuzz_ptr = shmat(shm_id, NULL, 0); + +#endif + + /* Whooooops. */ + + if (__afl_fuzz_ptr == (void *)-1) { + + fprintf(stderr, "Error: could not access fuzzing shared memory\n"); + exit(1); + + } + + if (getenv("AFL_DEBUG")) + fprintf(stderr, "DEBUG: successfully got fuzzing shared memory\n"); + + } else { + + fprintf(stderr, "Error: variable for fuzzing shared memory is not set\n"); + exit(1); + + } + +} + /* SHM setup. */ static void __afl_map_shm(void) { @@ -310,17 +367,25 @@ static void __afl_start_snapshots(void) { assume we're not running in forkserver mode and just execute program. */ status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT); + if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ; if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); - if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT; + if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT; memcpy(tmp, &status, 4); if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; - if (__afl_dictionary_len > 0 && __afl_dictionary) { + if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) { if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + if ((was_killed & (0xffffffff & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ))) == + (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { + + __afl_map_shm_fuzz(); + + } + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) == (FS_OPT_ENABLED | FS_OPT_AUTODICT)) { @@ -357,7 +422,7 @@ static void __afl_start_snapshots(void) { // uh this forkserver master does not understand extended option passing // or does not want the dictionary - already_read_first = 1; + if (!__afl_fuzz_ptr) already_read_first = 1; } @@ -378,6 +443,9 @@ static void __afl_start_snapshots(void) { } + __afl_fuzz_len = (was_killed >> 8); + was_killed = (was_killed & 0xff); + /* If we stopped the child in persistent mode, but there was a race condition and afl-fuzz already issued SIGKILL, write off the old process. */ @@ -473,7 +541,8 @@ static void __afl_start_forkserver(void) { if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); - if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT; + if (__afl_dictionary_len && __afl_dictionary) status |= FS_OPT_AUTODICT; + if (__afl_sharedmem_fuzzing != 0) status |= FS_OPT_SHDMEM_FUZZ; if (status) status |= (FS_OPT_ENABLED); memcpy(tmp, &status, 4); @@ -482,10 +551,17 @@ static void __afl_start_forkserver(void) { if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; - if (__afl_dictionary_len > 0 && __afl_dictionary) { + if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) { if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) == + (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { + + __afl_map_shm_fuzz(); + + } + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) == (FS_OPT_ENABLED | FS_OPT_AUTODICT)) { @@ -522,7 +598,7 @@ static void __afl_start_forkserver(void) { // uh this forkserver master does not understand extended option passing // or does not want the dictionary - already_read_first = 1; + if (!__afl_fuzz_ptr) already_read_first = 1; } @@ -544,6 +620,9 @@ static void __afl_start_forkserver(void) { } + __afl_fuzz_len = (was_killed >> 8); + was_killed = (was_killed & 0xff); + /* If we stopped the child in persistent mode, but there was a race condition and afl-fuzz already issued SIGKILL, write off the old process. */ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index b67aedde..137a4f99 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -442,7 +442,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { - if (!be_quiet && getenv("AFL_DEBUG")) { + if (getenv("AFL_DEBUG")) { ACTF("Extended forkserver functions received (%08x).", status); @@ -455,6 +455,28 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) { + + if (fsrv->support_shdmen_fuzz) { + + fsrv->use_shdmen_fuzz = 1; + if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); } + + if ((status & FS_OPT_AUTODICT) == 0) { + + u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) { + + FATAL("Writing to forkserver failed."); + + } + + } + + } + + } + if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); @@ -490,7 +512,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) { // this is not afl-fuzz - we deny and return - status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT)); + if (fsrv->use_shdmen_fuzz) + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); + else + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { FATAL("Writing to forkserver failed."); @@ -749,39 +774,48 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) { void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { - s32 fd = fsrv->out_fd; + if (fsrv->shdmem_fuzz) { - if (fsrv->out_file) { + memcpy(fsrv->shdmem_fuzz, buf, len); + fsrv->shdmem_fuzz_len = len; - if (fsrv->no_unlink) { + } else { - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); + s32 fd = fsrv->out_fd; - } else { + if (fsrv->out_file) { - unlink(fsrv->out_file); /* Ignore errors. */ - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fsrv->no_unlink) { - } + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); } + } else { - } else { + unlink(fsrv->out_file); /* Ignore errors. */ + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - lseek(fd, 0, SEEK_SET); + } - } + if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); } - ck_write(fd, buf, len, fsrv->out_file); + } else { - if (!fsrv->out_file) { + lseek(fd, 0, SEEK_SET); - if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); } - lseek(fd, 0, SEEK_SET); + } - } else { + ck_write(fd, buf, len, fsrv->out_file); - close(fd); + if (!fsrv->out_file) { + + if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); } + lseek(fd, 0, SEEK_SET); + + } else { + + close(fd); + + } } @@ -795,6 +829,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, s32 res; u32 exec_ms; + u32 write_value = fsrv->last_run_timed_out; /* After this memset, fsrv->trace_bits[] are effectively volatile, so we must prevent any earlier operations from venturing into that @@ -804,10 +839,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, MEM_BARRIER(); + if (fsrv->shdmem_fuzz_len) write_value += (fsrv->shdmem_fuzz_len << 8); + /* we have the fork server (or faux server) up and running First, tell it if the previous run timed out. */ - if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) { + if ((res = write(fsrv->fsrv_ctl_fd, &write_value, 4)) != 4) { if (*stop_soon_p) { return 0; } RPFATAL(res, "Unable to request new process from fork server (OOM?)"); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index dd85a8f4..9349fefe 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2153,6 +2153,30 @@ void check_binary(afl_state_t *afl, u8 *fname) { OKF(cPIN "Persistent mode binary detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; + // do not fail if we can not get the fuzzing shared mem + if ((afl->shm_fuzz = calloc(1, sizeof(sharedmem_t)))) { + + // we need to set the dumb mode to not overwrite the SHM_ENV_VAR + if ((afl->fsrv.shdmem_fuzz = afl_shm_init(afl->shm_fuzz, MAX_FILE, 1))) { + +#ifdef USEMMAP + setenv(SHM_FUZZ_ENV_VAR, afl->shm_fuzz->g_shm_file_path, 1); +#else + u8 *shm_str; + shm_str = alloc_printf("%d", afl->shm_fuzz->shm_id); + setenv(SHM_FUZZ_ENV_VAR, shm_str, 1); + ck_free(shm_str); +#endif + afl->fsrv.support_shdmen_fuzz = 1; + + } else { + + free(afl->shm_fuzz); + afl->shm_fuzz = NULL; + + } + + } } else if (getenv("AFL_PERSISTENT")) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 8a1f02a7..04450363 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -231,6 +231,16 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child_output); + if (afl->fsrv.support_shdmen_fuzz && !afl->fsrv.use_shdmen_fuzz) { + + afl_shm_deinit(afl->shm_fuzz); + free(afl->shm_fuzz); + afl->shm_fuzz = NULL; + afl->fsrv.support_shdmen_fuzz = 0; + afl->fsrv.shdmem_fuzz = NULL; + + } + } if (q->exec_cksum) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c07371a8..e024e9a4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1379,6 +1379,14 @@ stop_fuzzing: destroy_extras(afl); destroy_custom_mutators(afl); afl_shm_deinit(&afl->shm); + + if (afl->shm_fuzz) { + + afl_shm_deinit(afl->shm_fuzz); + free(afl->shm_fuzz); + + } + afl_fsrv_deinit(&afl->fsrv); if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } ck_free(afl->fsrv.target_path); -- cgit 1.4.1 From dab498c3b726cf4503abfbd61b62f65f92c9a4e9 Mon Sep 17 00:00:00 2001 From: arnow117 Date: Wed, 27 May 2020 16:01:44 +0800 Subject: fix MOPT implementation flaws in core fuzzing --- src/afl-fuzz-one.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ddd15c84..5b1a2cba 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -4250,14 +4250,29 @@ pacemaker_fuzzing: u64 temp_temp_puppet = afl->queued_paths + afl->unique_crashes - temp_total_found; afl->total_puppet_find = afl->total_puppet_find + temp_temp_puppet; - for (i = 0; i < operator_num; ++i) { - if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) { + if (MOpt_globals.is_pilot_mode){ - MOpt_globals.finds_v2[i] += temp_temp_puppet; + for (i = 0; i < operator_num; ++i) { + + if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) { + + MOpt_globals.finds_v2[i] += temp_temp_puppet; + + } } + } else { + + for (i = 0; i < operator_num; i++) { + + if (afl->core_operator_cycles_puppet_v2[i] > afl->core_operator_cycles_puppet_v3[i]) + + afl->core_operator_finds_puppet_v2[i] += temp_temp_puppet; + + } + } } /* if */ @@ -4437,7 +4452,6 @@ pacemaker_fuzzing: afl->total_pacemaker_time += *MOpt_globals.pTime; *MOpt_globals.pTime = 0; - afl->temp_puppet_find = afl->total_puppet_find; new_hit_cnt = afl->queued_paths + afl->unique_crashes; if (MOpt_globals.is_pilot_mode) { @@ -4448,6 +4462,7 @@ pacemaker_fuzzing: } + afl->temp_puppet_find = afl->total_puppet_find; u64 temp_stage_finds_puppet = 0; for (i = 0; i < operator_num; ++i) { @@ -4530,6 +4545,15 @@ pacemaker_fuzzing: } else { + for (i = 0; i < operator_num; i++) + { + + afl->core_operator_finds_puppet[i] = afl->core_operator_finds_puppet_v2[i]; + afl->core_operator_cycles_puppet[i] = afl->core_operator_cycles_puppet_v2[i]; + temp_stage_finds_puppet += afl->core_operator_finds_puppet[i]; + + } + afl->key_module = 2; afl->old_hit_count = new_hit_cnt; -- cgit 1.4.1 From aace0d119228aeb847e97f9dae50b8e0738eed90 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 27 May 2020 11:28:29 +0200 Subject: code format --- docs/Changelog.md | 1 + docs/INSTALL.md | 4 ++-- src/afl-fuzz-one.c | 26 ++++++++++++++------------ 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/docs/Changelog.md b/docs/Changelog.md index 18acfba4..d95f7367 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,6 +16,7 @@ sending a mail to . exactly one master is present and warn otherwise - If no master is present at a sync one slave automatically becomes a temporary master until a real master shows up + - fix/update to MOpt (thanks to arnow117) - llvm_mode: - the default instrumentation is now PCGUARD, as it is faster and provides better coverage. The original afl instrumentation can be set via diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 0f9673ad..766f24d7 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -17,7 +17,7 @@ You can start using the fuzzer without installation, but it is also possible to install it with: ```bash -make install +sudo make install ``` There are no special dependencies to speak of; you will need GNU make and a @@ -46,7 +46,7 @@ please install it first. As on Linux, you can use the fuzzer itself without installation, or install it with: ``` -gmake install +sudo gmake install ``` Keep in mind that if you are using csh as your shell, the syntax of some of the diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 5b1a2cba..56f16b4c 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -4251,7 +4251,7 @@ pacemaker_fuzzing: afl->queued_paths + afl->unique_crashes - temp_total_found; afl->total_puppet_find = afl->total_puppet_find + temp_temp_puppet; - if (MOpt_globals.is_pilot_mode){ + if (MOpt_globals.is_pilot_mode) { for (i = 0; i < operator_num; ++i) { @@ -4265,13 +4265,14 @@ pacemaker_fuzzing: } else { - for (i = 0; i < operator_num; i++) { + for (i = 0; i < operator_num; i++) { - if (afl->core_operator_cycles_puppet_v2[i] > afl->core_operator_cycles_puppet_v3[i]) + if (afl->core_operator_cycles_puppet_v2[i] > + afl->core_operator_cycles_puppet_v3[i]) - afl->core_operator_finds_puppet_v2[i] += temp_temp_puppet; + afl->core_operator_finds_puppet_v2[i] += temp_temp_puppet; - } + } } @@ -4545,14 +4546,15 @@ pacemaker_fuzzing: } else { - for (i = 0; i < operator_num; i++) - { + for (i = 0; i < operator_num; i++) { - afl->core_operator_finds_puppet[i] = afl->core_operator_finds_puppet_v2[i]; - afl->core_operator_cycles_puppet[i] = afl->core_operator_cycles_puppet_v2[i]; - temp_stage_finds_puppet += afl->core_operator_finds_puppet[i]; - - } + afl->core_operator_finds_puppet[i] = + afl->core_operator_finds_puppet_v2[i]; + afl->core_operator_cycles_puppet[i] = + afl->core_operator_cycles_puppet_v2[i]; + temp_stage_finds_puppet += afl->core_operator_finds_puppet[i]; + + } afl->key_module = 2; -- cgit 1.4.1