From bd4ecd83b1e4126300475d5beb09b4a8327b045a Mon Sep 17 00:00:00 2001 From: llzmb <46303940+llzmb@users.noreply.github.com> Date: Fri, 10 Sep 2021 15:35:29 +0200 Subject: [PATCH 01/44] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index db6a70b5..eb99d9bd 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ You are free to copy, modify, and distribute AFL++ with attribution under the te Here is some information to get you started: -* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [major behaviour changes in AFL++](docs/behaviour_changes.md). +* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [important behaviour changes in AFL++](docs/important_changes.md). * If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website. * To cite our work, look at the [Cite](#cite) section. * For comparisons, use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus). @@ -66,7 +66,7 @@ A common way to do this would be: make clean all 2. Get a small but valid input file that makes sense to the program. -When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in [dictionaries/README.md](../dictionaries/README.md), too. +When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in [dictionaries/README.md](dictionaries/README.md), too. 3. If the program reads from stdin, run `afl-fuzz` like so: @@ -82,7 +82,7 @@ When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described i Questions? Concerns? Bug reports? * The contributors can be reached via [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). -* Take a look at our [FAQ](docs/faq.md). If you find an interesting or important question missing, submit it via +* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important question missing, submit it via [https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions). * There is a mailing list for the AFL/AFL++ project ([browse archive](https://groups.google.com/group/afl-users)). To compare notes with other users or to get notified about major new features, send an email to . * Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server. From 82ef4a90b0ff12a297e1bc3f1c8256ae9ace4f25 Mon Sep 17 00:00:00 2001 From: llzmb <46303940+llzmb@users.noreply.github.com> Date: Fri, 10 Sep 2021 21:37:55 +0200 Subject: [PATCH 02/44] Fix links --- README.md | 2 +- docs/best_practices.md | 2 +- docs/branches.md | 2 +- docs/fuzzing_expert.md | 2 +- docs/interpreting_output.md | 2 +- docs/known_limitations.md | 2 +- docs/life_pro_tips.md | 20 ++++++++++---------- docs/rpc_statsd.md | 2 +- docs/triaging_crashes.md | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index eb99d9bd..25e47ef2 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ You are free to copy, modify, and distribute AFL++ with attribution under the te Here is some information to get you started: -* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [important behaviour changes in AFL++](docs/important_changes.md). +* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [important changes in AFL++](docs/important_changes.md). * If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website. * To cite our work, look at the [Cite](#cite) section. * For comparisons, use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus). diff --git a/docs/best_practices.md b/docs/best_practices.md index 23fa237d..1521748a 100644 --- a/docs/best_practices.md +++ b/docs/best_practices.md @@ -59,7 +59,7 @@ which allows you to define network state with different type of data packets. 1. Use [llvm_mode](../instrumentation/README.llvm.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended). 2. Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20 speed increase). 3. Use the [AFL++ snapshot module](https://github.com/AFLplusplus/AFL-Snapshot-LKM) (x2 speed increase). -4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input file directory on a tempfs location, see [docs/env_variables.md](docs/env_variables.md). +4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input file directory on a tempfs location, see [env_variables.md](env_variables.md). 5. Improve Linux kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system less secure). 6. Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem. 7. Use your cores! [README.md:3.b) Using multiple cores/threads](../README.md#b-using-multiple-coresthreads). diff --git a/docs/branches.md b/docs/branches.md index 1e4ebbb2..81c73a0f 100644 --- a/docs/branches.md +++ b/docs/branches.md @@ -7,4 +7,4 @@ The following branches exist: * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state of AFL++ - bleeding edge and you might catch a checkout which does not compile or has a bug. *We only accept PRs in dev!!* * (any other): experimental branches to work on specific features or testing new functionality or changes. -For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab. Also take a look at the list of [major behaviour changes in AFL++](behaviour_changes.md). \ No newline at end of file +For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab. Also take a look at the list of [important changes in AFL++](important_changes.md). \ No newline at end of file diff --git a/docs/fuzzing_expert.md b/docs/fuzzing_expert.md index 23b24ad0..37ab8e2f 100644 --- a/docs/fuzzing_expert.md +++ b/docs/fuzzing_expert.md @@ -620,4 +620,4 @@ This is basically all you need to know to professionally run fuzzing campaigns. If you want to know more, the tons of texts in [docs/](./) will have you covered. Note that there are also a lot of tools out there that help fuzzing with AFL++ -(some might be deprecated or unsupported), see [links_tools.md](links_tools.md). \ No newline at end of file +(some might be deprecated or unsupported), see [tools.md](tools.md). \ No newline at end of file diff --git a/docs/interpreting_output.md b/docs/interpreting_output.md index 54ad76df..364d2cf4 100644 --- a/docs/interpreting_output.md +++ b/docs/interpreting_output.md @@ -1,6 +1,6 @@ # Interpreting output -See the [docs/status_screen.md](docs/status_screen.md) file for information on +See the [status_screen.md](status_screen.md) file for information on how to interpret the displayed stats and monitor the health of the process. Be sure to consult this file especially if any UI elements are highlighted in red. diff --git a/docs/known_limitations.md b/docs/known_limitations.md index deb539e2..b5fc8446 100644 --- a/docs/known_limitations.md +++ b/docs/known_limitations.md @@ -15,7 +15,7 @@ Here are some of the most important caveats for AFL: To work around this, you can comment out the relevant checks (see utils/libpng_no_checksum/ for inspiration); if this is not possible, you can also write a postprocessor, one of the hooks of custom mutators. - See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use + See [custom_mutators.md](custom_mutators.md) on how to use `AFL_CUSTOM_MUTATOR_LIBRARY` - There are some unfortunate trade-offs with ASAN and 64-bit binaries. This diff --git a/docs/life_pro_tips.md b/docs/life_pro_tips.md index 13ffcea0..e79bcafa 100644 --- a/docs/life_pro_tips.md +++ b/docs/life_pro_tips.md @@ -27,16 +27,16 @@ Run the bundled `afl-plot` utility to generate browser-friendly graphs. Check out the `fuzzer_stats` file in the AFL output dir or try `afl-whatsup`. ## Puzzled by something showing up in red or purple in the AFL UI? -It could be important - consult docs/status_screen.md right away! +It could be important - consult [status_screen.md](status_screen.md) right away! ## Know your target? Convert it to persistent mode for a huge performance gain! -Consult section #5 in README.llvm.md for tips. +Consult section #5 in [instrumentation/README.llvm.md](../instrumentation/README.llvm.md) for tips. ## Using clang? -Check out instrumentation/ for a faster alternative to afl-gcc! +Check out [instrumentation/](../instrumentation/) for a faster alternative to afl-gcc! ## Did you know that AFL can fuzz closed-source or cross-platform binaries? -Check out qemu_mode/README.md and unicorn_mode/README.md for more. +Check out [qemu_mode/README.md](../qemu_mode/README.md) and [unicorn_mode/README.md](../unicorn_mode/README.md) for more. ## Did you know that afl-fuzz can minimize any test case for you? Try the bundled `afl-tmin` tool - and get small repro files fast! @@ -46,7 +46,7 @@ Try the bundled `afl-tmin` tool - and get small repro files fast! ## Trouble dealing with a machine uprising? Relax, we've all been there. -Find essential survival tips at http://lcamtuf.coredump.cx/prep/. +Find essential survival tips at [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/). ## Want to automatically spot non-crashing memory handling bugs? @@ -54,7 +54,7 @@ Try running an AFL-generated corpus through ASAN, MSAN, or Valgrind. ## Good selection of input files is critical to a successful fuzzing job. -See docs/perf_tips.md for pro tips. +See [perf_tips.md](perf_tips.md) for pro tips. ## You can improve the odds of automatically spotting stack corruption issues. @@ -70,18 +70,18 @@ sanity-checking `assert()` / `abort()` statements to effortlessly catch logic bu ## Hey kid... pssst... want to figure out how AFL really works? -Check out docs/technical_details.md for all the gory details in one place! +Check out [technical_details.md](technical_details.md) for all the gory details in one place! ## There's a ton of third-party helper tools designed to work with AFL! -Be sure to check out docs/sister_projects.md before writing your own. +Be sure to check out [sister_projects.md](sister_projects.md) before writing your own. ## Need to fuzz the command-line arguments of a particular program? -You can find a simple solution in utils/argv_fuzzing. +You can find a simple solution in [utils/argv_fuzzing](../utils/argv_fuzzing/). ## Attacking a format that uses checksums? Remove the checksum-checking code or use a postprocessor! -See `afl_custom_post_process` in custom_mutators/examples/example.c for more. +See `afl_custom_post_process` in [custom_mutators/examples/example.c](../custom_mutators/examples/example.c) for more. diff --git a/docs/rpc_statsd.md b/docs/rpc_statsd.md index 898ad099..efbd550b 100644 --- a/docs/rpc_statsd.md +++ b/docs/rpc_statsd.md @@ -41,7 +41,7 @@ To enable the StatsD reporting on your fuzzer instances, you need to set the env Setting `AFL_STATSD_TAGS_FLAVOR` to the provider of your choice will assign tags / labels to each metric based on their format. The possible values are `dogstatsd`, `librato`, `signalfx` or `influxdb`. -For more information on these env vars, check out `docs/env_variables.md`. +For more information on these env vars, check out [env_variables.md](env_variables.md). The simplest way of using this feature is to use any metric provider and change the host/port of your StatsD daemon, with `AFL_STATSD_HOST` and `AFL_STATSD_PORT`, if required (defaults are `localhost` and port `8125`). diff --git a/docs/triaging_crashes.md b/docs/triaging_crashes.md index 1857c4b1..21ccecaa 100644 --- a/docs/triaging_crashes.md +++ b/docs/triaging_crashes.md @@ -43,4 +43,4 @@ file, attempts to sequentially flip bytes, and observes the behavior of the tested program. It then color-codes the input based on which sections appear to be critical, and which are not; while not bulletproof, it can often offer quick insights into complex file formats. More info about its operation can be found -near the end of [docs/technical_details.md](docs/technical_details.md). \ No newline at end of file +near the end of [technical_details.md](technical_details.md). \ No newline at end of file From 228f6c5dad1a593b4113006e587e9885459a53c2 Mon Sep 17 00:00:00 2001 From: llzmb <46303940+llzmb@users.noreply.github.com> Date: Sun, 10 Oct 2021 16:00:21 +0200 Subject: [PATCH 03/44] Update fuzzing_binary-only_targets.md --- docs/fuzzing_binary-only_targets.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md index a39e40a0..d568b976 100644 --- a/docs/fuzzing_binary-only_targets.md +++ b/docs/fuzzing_binary-only_targets.md @@ -71,7 +71,7 @@ cd unicorn_mode If the goal is to fuzz a dynamic library then there are two options available. For both you need to write a small harness that loads and calls the library. -Faster is the frida solution: [utils/afl_frida/README.md](../utils/afl_frida/README.md) +Faster is the frida solution: [frida_mode/README.md](../frida_mode/README.md) Another, less precise and slower option is using ptrace with debugger interrupt instrumentation: [utils/afl_untracer/README.md](../utils/afl_untracer/README.md). From 8bc2b52f6579ab44f536d1ccb818acf37b047ec7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 17 Oct 2021 13:03:01 +0200 Subject: [PATCH 04/44] format --- src/afl-showmap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/afl-showmap.c b/src/afl-showmap.c index a04c1f5b..5df07bf2 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -243,10 +243,13 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) { if (strcmp(outfile, "-")) { + // create empty file to prevent error messages in afl-cmin fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); close(fd); + } + return ret; } From 65c94d914db9930eaae50c6d36bdcb4ed16ea908 Mon Sep 17 00:00:00 2001 From: llzmb <46303940+llzmb@users.noreply.github.com> Date: Sun, 17 Oct 2021 20:29:24 +0200 Subject: [PATCH 05/44] Change line length to max. 80 characters --- README.md | 109 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 9fe1da7e..575a6a1a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases) GitHub version: 3.15a -Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) +Repository: +[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) AFL++ is maintained by: @@ -17,56 +18,74 @@ AFL++ is maintained by: Originally developed by Michał "lcamtuf" Zalewski. -AFL++ is a superior fork to Google's AFL - more speed, more and better mutations, more and better instrumentation, custom module support, etc. +AFL++ is a superior fork to Google's AFL - more speed, more and better +mutations, more and better instrumentation, custom module support, etc. -You are free to copy, modify, and distribute AFL++ with attribution under the terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details. +You are free to copy, modify, and distribute AFL++ with attribution under the +terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details. ## Getting started Here is some information to get you started: -* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [important changes in AFL++](docs/important_changes.md). -* If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website. +* For releases, please see the + [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and + [branches](docs/branches.md). Also take a look at the list of + [important changes in AFL++](docs/important_changes.md). +* If you want to use AFL++ for your academic work, check the + [papers page](https://aflplus.plus/papers/) on the website. * To cite our work, look at the [Cite](#cite) section. -* For comparisons, use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus). -* To get you started with tutorials, go to [docs/tutorials.md](docs/tutorials.md). +* For comparisons, use the fuzzbench `aflplusplus` setup, or use + `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` + default configuration on Google's + [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus). +* To get you started with tutorials, go to + [docs/tutorials.md](docs/tutorials.md). ## Building and installing AFL++ -To have AFL++ easily available with everything compiled, pull the image directly from the Docker Hub: +To have AFL++ easily available with everything compiled, pull the image +directly from the Docker Hub: ```shell docker pull aflplusplus/aflplusplus docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus ``` -This image is automatically generated when a push to the stable repo happens (see [docs/branches.md](docs/branches.md)). -You will find your target source code in `/src` in the container. +This image is automatically generated when a push to the stable repo happens +(see [docs/branches.md](docs/branches.md)). You will find your target source +code in `/src` in the container. To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md). ## Quick start: Fuzzing with AFL++ -*NOTE: Before you start, please read about the [common sense risks of fuzzing](docs/common_sense_risks.md).* +*NOTE: Before you start, please read about the [common sense risks of +fuzzing](docs/common_sense_risks.md).* -This is a quick start for fuzzing targets with the source code available. -To read about the process in detail, see [docs/fuzzing_expert.md](docs/fuzzing_expert.md). +This is a quick start for fuzzing targets with the source code available. To +read about the process in detail, see +[docs/fuzzing_expert.md](docs/fuzzing_expert.md). To learn about fuzzing other targets, see: -* Binary-only targets: [docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md) -* Network services: [docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service) -* GUI programs: [docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program) +* Binary-only targets: + [docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md) +* Network services: + [docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service) +* GUI programs: + [docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program) Step-by-step quick start: -1. Compile the program or library to be fuzzed using `afl-cc`. -A common way to do this would be: +1. Compile the program or library to be fuzzed using `afl-cc`. A common way to + do this would be: CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared make clean all -2. Get a small but valid input file that makes sense to the program. -When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in [dictionaries/README.md](dictionaries/README.md), too. +2. Get a small but valid input file that makes sense to the program. When + fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in + [dictionaries/README.md](dictionaries/README.md), too. 3. If the program reads from stdin, run `afl-fuzz` like so: @@ -77,42 +96,52 @@ When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described i To add a dictionary, add `-x /path/to/dictionary.txt` to afl-fuzz. - If the program takes input from a file, you can put `@@` in the program's + If the program takes input from a file, you can put `@@` in the program's command line; AFL will put an auto-generated file name in there for you. -4. Investigate anything shown in red in the fuzzer UI by promptly consulting [docs/status_screen.md](docs/status_screen.md). +4. Investigate anything shown in red in the fuzzer UI by promptly consulting + [docs/status_screen.md](docs/status_screen.md). -5. You will find found crashes and hangs in the subdirectories `crashes/` and - `hangs/` in the `-o output_dir` directory. You can replay the crashes by - feeding them to the target, e.g.: - `cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]` - You can generate cores or use gdb directly to follow up the crashes. +5. You will find found crashes and hangs in the subdirectories `crashes/` and + `hangs/` in the `-o output_dir` directory. You can replay the crashes by + feeding them to the target, e.g.: `cat output_dir/crashes/id:000000,* | + /path/to/tested/program [...program's cmdline...]` You can generate cores or + use gdb directly to follow up the crashes. ## Contact Questions? Concerns? Bug reports? -* The contributors can be reached via [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). -* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important question missing, submit it via -[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions). -* There is a mailing list for the AFL/AFL++ project ([browse archive](https://groups.google.com/group/afl-users)). To compare notes with other users or to get notified about major new features, send an email to . +* The contributors can be reached via + [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). +* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or + important question missing, submit it via + [https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions). +* There is a mailing list for the AFL/AFL++ project + ([browse archive](https://groups.google.com/group/afl-users)). To compare + notes with other users or to get notified about major new features, send an + email to . * Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server. ## Help wanted -We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it even better. -However, we already work on so many things that we do not have the time for all the big ideas. +We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it +even better. However, we already work on so many things that we do not have the +time for all the big ideas. -This can be your way to support and contribute to AFL++ - extend it to do something cool. +This can be your way to support and contribute to AFL++ - extend it to do +something cool. -For everyone who wants to contribute (and send pull requests), please read our [contributing guidelines](CONTRIBUTING.md) before your submit. +For everyone who wants to contribute (and send pull requests), please read our +[contributing guidelines](CONTRIBUTING.md) before your submit. ## Special thanks -Many of the improvements to the original AFL and AFL++ wouldn't be possible without feedback, bug reports, or patches from our contributors. +Many of the improvements to the original AFL and AFL++ wouldn't be possible +without feedback, bug reports, or patches from our contributors. -Thank you! -(For people sending pull requests - please add yourself to this list :-) +Thank you! (For people sending pull requests - please add yourself to this list +:-)
@@ -171,7 +200,9 @@ Thank you! ## Cite -If you use AFL++ in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20: +If you use AFL++ in scientific work, consider citing +[our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) +presented at WOOT'20: Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020. From 7cd98f565ffdf3e0c0ccd34c04ed2f3126ab4189 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 18 Oct 2021 12:16:58 +0200 Subject: [PATCH 06/44] lto and llvm14-dev --- docs/Changelog.md | 2 +- instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 -- instrumentation/afl-llvm-lto-instrumentation.so.cc | 4 ++++ instrumentation/afl-llvm-lto-instrumentlist.so.cc | 5 +++++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index d8dac557..6db013cf 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -24,7 +24,7 @@ sending a mail to . afl-showmap and other tools. - afl-cc: - fix for shared linking on MacOS - - llvm and LTO mode verified to work with new llvm 14-dev + - llvm and LTO mode modified to work with new llvm 14-dev (again) - added the very good grammar mutator "GramaTron" to the custom_mutators - added optimin, a faster and better corpus minimizer by diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 48ad2d02..013492f9 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -881,8 +881,6 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls( Function &F, ArrayRef IndirCalls) { if (IndirCalls.empty()) return; - assert(Options.TracePC || Options.TracePCGuard || - Options.Inline8bitCounters /*|| Options.InlineBoolFlag*/); for (auto I : IndirCalls) { IRBuilder<> IRB(I); diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index 73e41f60..4eb8424f 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -244,7 +244,11 @@ bool AFLLTOPass::runOnModule(Module &M) { // the instrument file list check AttributeList Attrs = F.getAttributes(); +#if LLVM_VERSION_MAJOR < 14 if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) { +#else + if (Attrs.hasFnAttr(StringRef("skipinstrument"))) { +#endif if (debug) fprintf(stderr, diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 416dbb88..0ec0e427 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -116,10 +116,15 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) { auto & Ctx = F.getContext(); AttributeList Attrs = F.getAttributes(); +#if LLVM_VERSION_MAJOR < 14 AttrBuilder NewAttrs; NewAttrs.addAttribute("skipinstrument"); F.setAttributes( Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs)); +#else + AttributeList NewAttrs = Attrs.addFnAttribute(Ctx, "skipinstrument"); + F.setAttributes(NewAttrs); +#endif } From 45d668a671316821c3f9793381cb54956b535491 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 18 Oct 2021 13:17:07 +0200 Subject: [PATCH 07/44] better ui banner --- docs/Changelog.md | 1 + include/afl-fuzz.h | 1 - src/afl-fuzz-init.c | 37 --------------------------------- src/afl-fuzz-stats.c | 49 ++++++++++++++++++++++++++------------------ src/afl-fuzz.c | 17 +++++++++++---- 5 files changed, 43 insertions(+), 62 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 6db013cf..63896622 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -17,6 +17,7 @@ sending a mail to . coverage being detected. thanks to Collin May for reporting! - fix -n dumb mode (nobody should use this) - fix stability issue with LTO and cmplog + - better banner - frida_mode: David Carlier added Android support :) - afl-showmap, afl-tmin and afl-analyze now honor persistent mode for more speed. thanks to dloffre-snl for reporting! diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 4b19e698..eaf55fb8 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1130,7 +1130,6 @@ void get_core_count(afl_state_t *); void fix_up_sync(afl_state_t *); void check_asan_opts(afl_state_t *); void check_binary(afl_state_t *, u8 *); -void fix_up_banner(afl_state_t *, u8 *); void check_if_tty(afl_state_t *); void setup_signal_handlers(void); void save_cmdline(afl_state_t *, u32, char **); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 9bb25785..9c45f08a 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2815,43 +2815,6 @@ void check_binary(afl_state_t *afl, u8 *fname) { } -/* Trim and possibly create a banner for the run. */ - -void fix_up_banner(afl_state_t *afl, u8 *name) { - - if (!afl->use_banner) { - - if (afl->sync_id) { - - afl->use_banner = afl->sync_id; - - } else { - - u8 *trim = strrchr(name, '/'); - if (!trim) { - - afl->use_banner = name; - - } else { - - afl->use_banner = trim + 1; - - } - - } - - } - - if (strlen(afl->use_banner) > 32) { - - u8 *tmp = ck_alloc(36); - sprintf(tmp, "%.32s...", afl->use_banner); - afl->use_banner = tmp; - - } - -} - /* Check if we're on TTY. */ void check_if_tty(afl_state_t *afl) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 870ba69a..0c06232b 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -441,9 +441,10 @@ void show_stats(afl_state_t *afl) { u64 cur_ms; u32 t_bytes, t_bits; - u32 banner_len, banner_pad; - u8 tmp[256]; - u8 time_tmp[64]; + static u8 banner[128]; + u32 banner_len, banner_pad; + u8 tmp[256]; + u8 time_tmp[64]; u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX]; #define IB(i) (val_buf[(i)]) @@ -656,26 +657,34 @@ void show_stats(afl_state_t *afl) { } /* Let's start by drawing a centered banner. */ + if (unlikely(!banner[0])) { - banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) + - strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5; - banner_pad = (79 - banner_len) / 2; - memset(tmp, ' ', banner_pad); + char *si = ""; + if (afl->sync_id) { si = afl->sync_id; } + memset(banner, 0, sizeof(banner)); + banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) + + strlen(afl->power_name) + 4 + 6; -#ifdef HAVE_AFFINITY - sprintf( - tmp + banner_pad, - "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}", - afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", - afl->use_banner, afl->power_name, afl->cpu_aff); -#else - sprintf( - tmp + banner_pad, "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", - afl->use_banner, afl->power_name); -#endif /* HAVE_AFFINITY */ + if (strlen(afl->use_banner) + banner_len > 75) { - SAYF("\n%s\n", tmp); + afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76; + memset(afl->use_banner, '.', 3); + + } + + banner_len += strlen(afl->use_banner); + banner_pad = (79 - banner_len) / 2; + memset(banner, ' ', banner_pad); + + sprintf(banner + banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN "peruvian were-rabbit" + : cYEL "american fuzzy lop", + si, afl->use_banner, afl->power_name); + + } + + SAYF("\n%s\n", banner); /* "Handy" shortcuts for drawing boxes... */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 92a37697..26886a4f 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1189,7 +1189,17 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->sync_id) { fix_up_sync(afl); } + if (afl->sync_id) { + + if (strlen(afl->sync_id) > 24) { + + FATAL("sync_id max length is 24 characters"); + + } + + fix_up_sync(afl); + + } if (!strcmp(afl->in_dir, afl->out_dir)) { @@ -1218,6 +1228,8 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); } + if (!afl->use_banner) { afl->use_banner = argv[optind]; } + if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { WARNF(cLRD @@ -1486,9 +1498,6 @@ int main(int argc, char **argv_orig, char **envp) { } save_cmdline(afl, argc, argv); - - fix_up_banner(afl, argv[optind]); - check_if_tty(afl); if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } From fd43daee6a2146e95059b7ea670c6bf24b3704ed Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 18 Oct 2021 17:21:26 +0200 Subject: [PATCH 08/44] md url --- utils/socket_fuzzing/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/socket_fuzzing/README.md b/utils/socket_fuzzing/README.md index 84398a71..2805fa22 100644 --- a/utils/socket_fuzzing/README.md +++ b/utils/socket_fuzzing/README.md @@ -6,6 +6,6 @@ for sending input to stdin which the target binary will think is coming from a network socket. This is desock_dup.c from the amazing preeny project -https://github.com/zardus/preeny +[https://github.com/zardus/preeny](https://github.com/zardus/preeny) It is packaged in AFL++ to have it at hand if needed From bb8a4d71da8f2b748a78ccc4416df6bffb393d80 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 18 Oct 2021 20:53:54 +0200 Subject: [PATCH 09/44] format and remove warning --- instrumentation/SanitizerCoverageLTO.so.cc | 8 ++++---- instrumentation/afl-llvm-dict2file.so.cc | 7 ++++--- instrumentation/afl-llvm-lto-instrumentation.so.cc | 11 +++++++---- instrumentation/afl-llvm-lto-instrumentlist.so.cc | 2 +- instrumentation/split-compares-pass.so.cc | 10 +++++----- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 960eb783..d90fa867 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -447,8 +447,7 @@ bool ModuleSanitizerCoverage::instrumentModule( if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) { dFile.open(ptr, std::ofstream::out | std::ofstream::app); - if (dFile.is_open()) - WARNF("Cannot access document file %s", ptr); + if (dFile.is_open()) WARNF("Cannot access document file %s", ptr); } @@ -1084,7 +1083,7 @@ bool ModuleSanitizerCoverage::instrumentModule( if (count) { - auto ptrhld = std::unique_ptr(new char[memlen + count]); + auto ptrhld = std::unique_ptr(new char[memlen + count]); count = 0; @@ -1502,7 +1501,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, unsigned long long int moduleID = (((unsigned long long int)(rand() & 0xffffffff)) << 32) | getpid(); - dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str() << " edgeID=" << afl_global_id << "\n"; + dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str() + << " edgeID=" << afl_global_id << "\n"; } diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index c4ad1783..0a3e74b9 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -65,8 +65,10 @@ using namespace llvm; namespace { class AFLdict2filePass : public ModulePass { + std::ofstream of; - void dict2file(u8 *, u32); + void dict2file(u8 *, u32); + public: static char ID; @@ -147,8 +149,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr); of.open(ptr, std::ofstream::out | std::ofstream::app); - if (!of.is_open()) - PFATAL("Could not open/create %s.", ptr); + if (!of.is_open()) PFATAL("Could not open/create %s.", ptr); /* Instrument all the things! */ diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index 4eb8424f..c2f61d34 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -138,8 +138,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) { dFile.open(ptr, std::ofstream::out | std::ofstream::app); - if (!dFile.is_open()) - WARNF("Cannot access document file %s", ptr); + if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr); } @@ -246,8 +245,10 @@ bool AFLLTOPass::runOnModule(Module &M) { AttributeList Attrs = F.getAttributes(); #if LLVM_VERSION_MAJOR < 14 if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) { + #else if (Attrs.hasFnAttr(StringRef("skipinstrument"))) { + #endif if (debug) @@ -852,7 +853,9 @@ bool AFLLTOPass::runOnModule(Module &M) { if (dFile.is_open()) { - dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str() << " edgeID=" << afl_global_id << "\n"; + dFile << "ModuleID=" << moduleID + << " Function=" << F.getName().str() + << " edgeID=" << afl_global_id << "\n"; } @@ -1019,7 +1022,7 @@ bool AFLLTOPass::runOnModule(Module &M) { if (count) { - auto ptrhld = std::unique_ptr(new char[memlen + count]); + auto ptrhld = std::unique_ptr(new char[memlen + count]); count = 0; diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index 0ec0e427..ee2e5dd3 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -117,7 +117,7 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) { auto & Ctx = F.getContext(); AttributeList Attrs = F.getAttributes(); #if LLVM_VERSION_MAJOR < 14 - AttrBuilder NewAttrs; + AttrBuilder NewAttrs; NewAttrs.addAttribute("skipinstrument"); F.setAttributes( Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs)); diff --git a/instrumentation/split-compares-pass.so.cc b/instrumentation/split-compares-pass.so.cc index 13f45b69..e63be98c 100644 --- a/instrumentation/split-compares-pass.so.cc +++ b/instrumentation/split-compares-pass.so.cc @@ -578,16 +578,16 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M, /* dependent on the cmp of the high parts go to the end or go on with * the comparison */ - auto term = bb->getTerminator(); - BranchInst *br = nullptr; + auto term = bb->getTerminator(); + if (pred == CmpInst::ICMP_EQ) { - br = BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb); + BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb); } else { - /* CmpInst::ICMP_NE */ - br = BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb); + // CmpInst::ICMP_NE + BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb); } From 77a63d8ccfd4b409c35227e174f1d6e809256e41 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Tue, 19 Oct 2021 13:59:31 +0200 Subject: [PATCH 10/44] execs field in filenames --- src/afl-fuzz-bitmap.c | 5 +++-- src/afl-fuzz-init.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0ae4d607..316067e4 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -317,8 +317,9 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) { } - sprintf(ret + strlen(ret), ",time:%llu", - get_cur_time() + afl->prev_run_time - afl->start_time); + sprintf(ret + strlen(ret), ",time:%llu,execs:%llu", + get_cur_time() + afl->prev_run_time - afl->start_time, + afl->fsrv.total_execs); if (afl->current_custom_fuzz && afl->current_custom_fuzz->afl_custom_describe) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 9bb25785..0fa8e6ec 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1325,8 +1325,8 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", afl->out_dir, id, - use_name); + nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s", afl->out_dir, id, + afl->fsrv.total_execs, use_name); #else From 0bc3367b55b2f08c7c2588576af27567044dc0b6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 19 Oct 2021 14:46:15 +0200 Subject: [PATCH 11/44] remove race condition --- src/afl-forkserver.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 54f510c4..94ca3009 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -610,12 +610,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!time_ms) { - if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); } + s32 tmp_pid = fsrv->fsrv_pid; + if (tmp_pid > 0) { + + kill(tmp_pid, fsrv->kill_signal); + fsrv->fsrv_pid = 1; + + } } else if (time_ms > fsrv->init_tmout) { fsrv->last_run_timed_out = 1; - if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); } + s32 tmp_pid = fsrv->fsrv_pid; + if (tmp_pid > 0) { + + kill(tmp_pid, fsrv->kill_signal); + fsrv->fsrv_pid = 1; + + } } else { @@ -1248,7 +1260,14 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ - if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); } + s32 tmp_pid = srv->child_pid; + if (tmp_pid > 0) { + + kill(tmp_pid, fsrv->kill_signal); + fsrv->child_pid = -1 + + } + fsrv->last_run_timed_out = 1; if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; } From 90786e2ce9970c52e661c0fe290cb78a1a063004 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 19 Oct 2021 15:20:59 +0200 Subject: [PATCH 12/44] fix --- src/afl-forkserver.c | 4 ++-- test/test-pre.sh | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 94ca3009..71667262 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1260,11 +1260,11 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ - s32 tmp_pid = srv->child_pid; + s32 tmp_pid = fsrv->child_pid; if (tmp_pid > 0) { kill(tmp_pid, fsrv->kill_signal); - fsrv->child_pid = -1 + fsrv->child_pid = -1; } diff --git a/test/test-pre.sh b/test/test-pre.sh index 7819da47..e12d95be 100755 --- a/test/test-pre.sh +++ b/test/test-pre.sh @@ -88,6 +88,8 @@ unset AFL_QEMU_PERSISTENT_GPR unset AFL_QEMU_PERSISTENT_RET unset AFL_QEMU_PERSISTENT_HOOK unset AFL_QEMU_PERSISTENT_CNT +unset AFL_QEMU_PERSISTENT_MEM +unset AFL_QEMU_PERSISTENT_EXITS unset AFL_CUSTOM_MUTATOR_LIBRARY unset AFL_PYTHON_MODULE unset AFL_PRELOAD From 47a333af4d7c64209570e7459b1bd5259c207dc9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 19 Oct 2021 15:42:26 +0200 Subject: [PATCH 13/44] add ninja to apt install readme --- docs/INSTALL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index b60a7048..960de1af 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -22,6 +22,7 @@ sudo apt-get install -y build-essential python3-dev automake git flex bison libg # try to install llvm 11 and install the distro default if that fails sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev +sudo apt-get install -y ninja-build # for qemu_mode git clone https://github.com/AFLplusplus/AFLplusplus cd AFLplusplus make distrib From 4e3fec2666c3d317db275f4af8875b56009621e1 Mon Sep 17 00:00:00 2001 From: Stefan Nagy Date: Wed, 20 Oct 2021 17:09:18 -0400 Subject: [PATCH 14/44] Update binaryonly_fuzzing.md with zafl --- docs/binaryonly_fuzzing.md | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/binaryonly_fuzzing.md b/docs/binaryonly_fuzzing.md index 90ea3b66..903afb70 100644 --- a/docs/binaryonly_fuzzing.md +++ b/docs/binaryonly_fuzzing.md @@ -95,13 +95,28 @@ utils/afl_untracer/, use afl-untracer.c as a template. It is slower than AFL FRIDA (see above). +## ZAFL + ZAFL is a static rewriting platform for fast, space-efficient, and inlined + binary fuzzing instrumentation. It currently supports x86-64 C and C++, + stripped and unstripped, and PIE and non-PIE binaries of all sizes and complexity. + + Beyond conventional instrumentation, ZAFL's API enables transformation passes + for more effective/efficient fuzzing. Some built-in transformations include + laf-Intel-style constraint unrolling, Angora-style context sensitivity, and + InsTrim-style CFG optimizations. + + ZAFL's baseline instrumentation speed averages about 90-95% that of afl-clang-fast's + conventional LLVM instrumentation (but is even faster when enabling CFG optimizations). + + [https://git.zephyr-software.com/opensrc/zafl](https://git.zephyr-software.com/opensrc/zafl) + ## DYNINST Dyninst is a binary instrumentation framework similar to Pintool and Dynamorio (see far below). However whereas Pintool and Dynamorio work at runtime, dyninst instruments the target at load time, and then let it run - - or save the binary with the changes. + or save the binary with the changes. This is great for some things, e.g. fuzzing, and not so effective for others, e.g. malware analysis. @@ -116,13 +131,10 @@ The speed decrease is about 15-35%, depending on the optimization options used with afl-dyninst. - So if Dyninst works, it is the best option available. Otherwise it just - doesn't work well. - [https://github.com/vanhauser-thc/afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) -## RETROWRITE, ZAFL, ... other binary rewriter +## RETROWRITE If you have an x86/x86_64 binary that still has its symbols, is compiled with position independant code (PIC/PIE) and does not use most of the C++ @@ -131,7 +143,6 @@ It is at about 80-85% performance. - [https://git.zephyr-software.com/opensrc/zafl](https://git.zephyr-software.com/opensrc/zafl) [https://github.com/HexHive/retrowrite](https://github.com/HexHive/retrowrite) From e637ca216e4559960feec6b7f887571efde4f0ba Mon Sep 17 00:00:00 2001 From: Stefan Nagy Date: Thu, 21 Oct 2021 04:52:38 -0400 Subject: [PATCH 15/44] Tidy-up zafl info --- docs/binaryonly_fuzzing.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/docs/binaryonly_fuzzing.md b/docs/binaryonly_fuzzing.md index 903afb70..de360543 100644 --- a/docs/binaryonly_fuzzing.md +++ b/docs/binaryonly_fuzzing.md @@ -95,18 +95,13 @@ utils/afl_untracer/, use afl-untracer.c as a template. It is slower than AFL FRIDA (see above). + ## ZAFL - ZAFL is a static rewriting platform for fast, space-efficient, and inlined - binary fuzzing instrumentation. It currently supports x86-64 C and C++, - stripped and unstripped, and PIE and non-PIE binaries of all sizes and complexity. - - Beyond conventional instrumentation, ZAFL's API enables transformation passes - for more effective/efficient fuzzing. Some built-in transformations include - laf-Intel-style constraint unrolling, Angora-style context sensitivity, and - InsTrim-style CFG optimizations. - - ZAFL's baseline instrumentation speed averages about 90-95% that of afl-clang-fast's - conventional LLVM instrumentation (but is even faster when enabling CFG optimizations). + ZAFL is a static rewriting platform supporting x86-64 C/C++, stripped/unstripped, + and PIE/non-PIE binaries. Beyond conventional instrumentation, ZAFL's API enables + transformation passes (e.g., laf-Intel, context sensitivity, InsTrim, etc.). + + Its baseline instrumentation speed typically averages 90-95% of afl-clang-fast's. [https://git.zephyr-software.com/opensrc/zafl](https://git.zephyr-software.com/opensrc/zafl) From e03897a0703673aa0de7772185a5b5230641cb6a Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 23 Oct 2021 20:54:24 +0200 Subject: [PATCH 16/44] fix timeout bug in afl tools --- docs/Changelog.md | 6 ++++-- src/afl-analyze.c | 12 ++++++++++++ src/afl-fuzz-init.c | 4 ++-- src/afl-showmap.c | 13 +++++++++++++ src/afl-tmin.c | 12 ++++++++++++ 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 63896622..04b2fb2e 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -19,8 +19,10 @@ sending a mail to . - fix stability issue with LTO and cmplog - better banner - frida_mode: David Carlier added Android support :) - - afl-showmap, afl-tmin and afl-analyze now honor persistent mode - for more speed. thanks to dloffre-snl for reporting! + - afl-showmap, afl-tmin and afl-analyze: + - honor persistent mode for more speed. thanks to dloffre-snl for + reporting! + - fix bug where targets are not killed on timeouts - Prevent accidently killing non-afl/fuzz services when aborting afl-showmap and other tools. - afl-cc: diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 8295488d..09b01541 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -120,6 +120,17 @@ static u8 count_class_lookup[256] = { #undef TIMES8 #undef TIMES4 +static void kill_child() { + + if (fsrv.child_pid > 0) { + + kill(fsrv.child_pid, fsrv.kill_signal); + fsrv.child_pid = -1; + + } + +} + static void classify_counts(u8 *mem) { u32 i = map_size; @@ -1053,6 +1064,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv.target_path = find_binary(argv[optind]); fsrv.trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, fsrv.out_file, &use_stdin); + signal(SIGALRM, kill_child); if (qemu_mode) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index f0e1a80d..1170715f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1325,8 +1325,8 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s", afl->out_dir, id, - afl->fsrv.total_execs, use_name); + nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s", + afl->out_dir, id, afl->fsrv.total_execs, use_name); #else diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 5df07bf2..3a244c04 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -146,6 +146,17 @@ static const u8 count_class_binary[256] = { #undef TIMES8 #undef TIMES4 +static void kill_child() { + + if (fsrv->child_pid > 0) { + + kill(fsrv->child_pid, fsrv->kill_signal); + fsrv->child_pid = -1; + + } + +} + static void classify_counts(afl_forkserver_t *fsrv) { u8 * mem = fsrv->trace_bits; @@ -526,6 +537,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { } + signal(SIGALRM, kill_child); + setitimer(ITIMER_REAL, &it, NULL); if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); } diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 4f3a6b80..ce2a0b8f 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -120,6 +120,17 @@ static const u8 count_class_lookup[256] = { #undef TIMES8 #undef TIMES4 +static void kill_child() { + + if (fsrv->child_pid > 0) { + + kill(fsrv->child_pid, fsrv->kill_signal); + fsrv->child_pid = -1; + + } + +} + static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv, sharedmem_t * shm_fuzz) { @@ -1125,6 +1136,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->target_path = find_binary(argv[optind]); fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, out_file, &fsrv->use_stdin); + signal(SIGALRM, kill_child); if (fsrv->qemu_mode) { From f68b9f5110f75068b65be35bd73d458f048f3fa1 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sat, 23 Oct 2021 20:09:36 +0100 Subject: [PATCH 17/44] frida mode display command line on mac --- frida_mode/src/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index c0de9c6b..c8183d8f 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -6,6 +6,7 @@ #ifdef __APPLE__ #include #include + #include #else #include #include @@ -90,6 +91,7 @@ static void embedded_init(void) { static void afl_print_cmdline(void) { +#if defined(__linux__) char * buffer = g_malloc0(PROC_MAX); gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid()); int fd = open(fname, O_RDONLY); @@ -123,6 +125,17 @@ static void afl_print_cmdline(void) { close(fd); g_free(fname); g_free(buffer); +#elif defined(__APPLE__) + int idx; + char **argv = *_NSGetArgv(); + int nargv = *_NSGetArgc(); + + for (idx = 0; idx < nargv; idx ++) { + + OKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]); + + } +#endif } From b12864b0beb04a3cc75f341ec96050644a252ce0 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 23 Oct 2021 22:20:40 +0200 Subject: [PATCH 18/44] updated unicorn bindings --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index cc8d5b34..e03b60c7 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -d4915053d477dd827b3fe4b494173d3fbf9f456e +c347275f5c720aa7cba40fdd6b3b095f65901b76 diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index d4915053..c347275f 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit d4915053d477dd827b3fe4b494173d3fbf9f456e +Subproject commit c347275f5c720aa7cba40fdd6b3b095f65901b76 From 4dfb7bfe4f0055683d8c0c31ac823537bb5367c8 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 23 Oct 2021 23:11:33 +0200 Subject: [PATCH 19/44] updated uc dependencies --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index e03b60c7..d6acbf91 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -c347275f5c720aa7cba40fdd6b3b095f65901b76 +94617f5b diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index c347275f..94617f5b 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit c347275f5c720aa7cba40fdd6b3b095f65901b76 +Subproject commit 94617f5bee0c08a5cbd1a1aa73f59cd973dfb17f From a7ee11a1747347847b06a4226f2800dd780f7c16 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 24 Oct 2021 19:35:58 +0200 Subject: [PATCH 20/44] fix --- src/afl-forkserver.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 71667262..c570a2bb 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -603,7 +603,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* Wait for the fork server to come up, but don't wait too long. */ rlen = 0; - if (fsrv->exec_tmout) { + if (fsrv->init_tmout) { u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout, stop_soon_p); @@ -614,7 +614,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (tmp_pid > 0) { kill(tmp_pid, fsrv->kill_signal); - fsrv->fsrv_pid = 1; + fsrv->fsrv_pid = -1; } @@ -625,7 +625,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (tmp_pid > 0) { kill(tmp_pid, fsrv->kill_signal); - fsrv->fsrv_pid = 1; + fsrv->fsrv_pid = -1; } @@ -1301,7 +1301,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = 0; } + if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = -1 ; } fsrv->total_execs++; From 0f49463edec0c019bd098659fa74c58a2d28c439 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 24 Oct 2021 19:41:06 +0200 Subject: [PATCH 21/44] fix --- src/afl-forkserver.c | 2 +- src/afl-showmap.c | 9 ++++++--- unicorn_mode/unicornafl | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index c570a2bb..80b295e0 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -1301,7 +1301,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = -1 ; } + if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = -1; } fsrv->total_execs++; diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 3a244c04..3826e385 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -77,7 +77,7 @@ static u32 tcnt, highest; /* tuple content information */ static u32 in_len; /* Input data length */ -static u32 map_size = MAP_SIZE; +static u32 map_size = MAP_SIZE, timed_out = 0; static bool quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ @@ -148,6 +148,7 @@ static const u8 count_class_binary[256] = { static void kill_child() { + timed_out = 1; if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); @@ -373,9 +374,10 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, if (!quiet_mode) { - if (fsrv->last_run_timed_out) { + if (timed_out || fsrv->last_run_timed_out) { SAYF(cLRD "\n+++ Program timed off +++\n" cRST); + timed_out = 0; } else if (stop_soon) { @@ -581,9 +583,10 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { if (!quiet_mode) { - if (fsrv->last_run_timed_out) { + if (timed_out || fsrv->last_run_timed_out) { SAYF(cLRD "\n+++ Program timed off +++\n" cRST); + timed_out = 0; } else if (stop_soon) { diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 94617f5b..d4915053 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 94617f5bee0c08a5cbd1a1aa73f59cd973dfb17f +Subproject commit d4915053d477dd827b3fe4b494173d3fbf9f456e From 0348ede4bc47264473efdac86415b9c805bdda40 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 24 Oct 2021 19:53:07 +0200 Subject: [PATCH 22/44] fix gcc warning --- src/afl-cc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/afl-cc.c b/src/afl-cc.c index e49addc4..77407a98 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1007,7 +1007,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } // prevent unnecessary build errors - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) { + + cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + + } if (preprocessor_only || have_c) { From 85ca0df98988cdb235e1d0cb9b156affc5afc80e Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 25 Oct 2021 06:53:45 +0100 Subject: [PATCH 23/44] frida mode musl build fix --- frida_mode/GNUmakefile | 3 +++ frida_mode/src/seccomp/seccomp_callback.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index ed35c9f6..b5fee7a6 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -78,6 +78,9 @@ endif ifeq "$(shell uname)" "Linux" OS:=linux + ifneq "$(findstring musl, $(shell ldd --version 2>&1 | head -n 1))" "" + CFLAGS+= -D__MUSL__ + endif endif ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" "" diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c index a88196ac..bc488489 100644 --- a/frida_mode/src/seccomp/seccomp_callback.c +++ b/frida_mode/src/seccomp/seccomp_callback.c @@ -1,6 +1,8 @@ #if defined(__linux__) && !defined(__ANDROID__) +#if !defined(__MUSL__) #include +#endif #include #include "seccomp.h" @@ -29,6 +31,7 @@ static void seccomp_callback_filter(struct seccomp_notif * req, req->data.args[0], req->data.args[1], req->data.args[2], req->data.args[3], req->data.args[4], req->data.args[5]); +#if !defined(__MUSL__) seccomp_print("FRAMES: (%u)\n", frames->len); char **syms = backtrace_symbols(frames->items, frames->len); if (syms == NULL) { FATAL("Failed to get symbols"); } @@ -49,6 +52,7 @@ static void seccomp_callback_filter(struct seccomp_notif * req, } free(syms); +#endif resp->error = 0; resp->val = 0; From 7407e2fb11675261173c625c3010ce9571a7d6f6 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 25 Oct 2021 09:37:51 +0100 Subject: [PATCH 24/44] frida mode musl further changes display stack trace --- frida_mode/src/seccomp/seccomp_callback.c | 16 ++++++++++++++++ frida_mode/src/seccomp/seccomp_filter.c | 2 ++ 2 files changed, 18 insertions(+) diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c index bc488489..4232d842 100644 --- a/frida_mode/src/seccomp/seccomp_callback.c +++ b/frida_mode/src/seccomp/seccomp_callback.c @@ -52,6 +52,22 @@ static void seccomp_callback_filter(struct seccomp_notif * req, } free(syms); +#else + void **syms = (void **)__builtin_frame_address(0); + void *framep = __builtin_frame_address(1); + int i = 0; + + syms = framep; + while (syms) { + + framep = *syms; + syms = framep; + + if (!syms) break; + + seccomp_print("\%3d. %s\n", i ++, (char *)framep); + + } #endif resp->error = 0; diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c index 8d56c367..7ee5ead1 100644 --- a/frida_mode/src/seccomp/seccomp_filter.c +++ b/frida_mode/src/seccomp/seccomp_filter.c @@ -2,7 +2,9 @@ #include #include +#if !defined(__MUSL__) #include +#endif #include #include #include From efec2b5a99d8f229eec4123e28c79a15389fe6bb Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 16:05:58 +0200 Subject: [PATCH 25/44] Update real_map_size when doing a realloc --- src/afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 26886a4f..34f3377b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1706,7 +1706,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode || afl->unicorn_mode) { - map_size = afl->fsrv.map_size = MAP_SIZE; + map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE; afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size); From f14b3bd9de4570a30c0f89bac2879ee3a7cfbcae Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 26 Oct 2021 18:48:13 +0100 Subject: [PATCH 26/44] Fix issues with Yama restrictions in FRIDA mode --- frida_mode/README.md | 6 ++++++ frida_mode/frida.map | 1 + frida_mode/include/entry.h | 3 +++ frida_mode/src/entry.c | 32 ++++++++++++++++++++++++++++++++ frida_mode/src/js/api.js | 7 +++++++ frida_mode/src/js/js_api.c | 6 ++++++ frida_mode/ts/lib/afl.ts | 12 ++++++++++++ include/envs.h | 1 + 8 files changed, 68 insertions(+) diff --git a/frida_mode/README.md b/frida_mode/README.md index df40c771..bb194080 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -288,6 +288,12 @@ ucomisd 2 ( 0.86%) * `AFL_FRIDA_STATS_INTERVAL` - The maximum frequency to output statistics information. Stats will be written whenever they are updated if the given interval has elapsed since last time they were written. +* `AFL_FRIDA_TRACEABLE` - Set the child process to be traceable by any process +to aid debugging and overcome the restrictions imposed by YAMA. Supported on +Linux only. Permits a non-root user to use `gcore` or similar to collect a core +dump of the instrumented target. Note that in order to capture the core dump you +must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` killing the +process whilst it is being dumped. ## FASAN - Frida Address Sanitizer Mode Frida mode also supports FASAN. The design of this is actually quite simple and diff --git a/frida_mode/frida.map b/frida_mode/frida.map index 0fc48aa6..e2ae87a7 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -33,6 +33,7 @@ js_api_set_stats_interval; js_api_set_stderr; js_api_set_stdout; + js_api_set_traceable; local: *; diff --git a/frida_mode/include/entry.h b/frida_mode/include/entry.h index 3f0a4ecc..edc41467 100644 --- a/frida_mode/include/entry.h +++ b/frida_mode/include/entry.h @@ -4,6 +4,7 @@ #include "frida-gumjs.h" extern guint64 entry_point; +extern gboolean traceable; extern gboolean entry_compiled; extern gboolean entry_run; @@ -15,5 +16,7 @@ void entry_start(void); void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output); +void entry_on_fork(void); + #endif diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index 186ddd3a..0ce2f3c3 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -1,5 +1,9 @@ #include +#if defined(__linux__) && !defined(__ANDROID__) + #include +#endif + #include "frida-gumjs.h" #include "debug.h" @@ -16,6 +20,7 @@ extern void __afl_manual_init(); guint64 entry_point = 0; +gboolean traceable = FALSE; gboolean entry_compiled = FALSE; gboolean entry_run = FALSE; @@ -26,21 +31,48 @@ static void entry_launch(void) { /* Child here */ entry_run = TRUE; + entry_on_fork(); instrument_on_fork(); seccomp_on_fork(); stats_on_fork(); } +#if defined(__linux__) && !defined(__ANDROID__) +void entry_on_fork(void) { + + if (traceable) { + + if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) < 0) { + + FATAL("Failed to PR_SET_PTRACER"); + + } + + } + +} + +#else +void entry_on_fork(void) { + + if (set_dumpable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); } + +} + +#endif + void entry_config(void) { entry_point = util_read_address("AFL_ENTRYPOINT"); + if (getenv("AFL_FRIDA_TRACEABLE") != NULL) { traceable = TRUE; } } void entry_init(void) { OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point); + OKF("dumpable: [%c]", traceable ? 'X' : ' '); if (dlopen(NULL, RTLD_NOW) == NULL) { FATAL("Failed to dlopen: %d", errno); } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 40bb4a16..6f9f05d8 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -243,6 +243,12 @@ class Afl { const buf = Memory.allocUtf8String(file); Afl.jsApiSetStdOut(buf); } + /** + * See `AFL_FRIDA_TRACEABLE`. + */ + static setTraceable() { + Afl.jsApiSetTraceable(); + } static jsApiGetFunction(name, retType, argTypes) { const addr = Afl.module.getExportByName(name); return new NativeFunction(addr, retType, argTypes); @@ -286,6 +292,7 @@ Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", [" Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]); Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]); Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]); +Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []); Afl.jsApiWrite = new NativeFunction( /* tslint:disable-next-line:no-null-keyword */ Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 9dba79aa..f3d81a32 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -231,3 +231,9 @@ __attribute__((visibility("default"))) void js_api_set_stalker_ic_entries( } +__attribute__((visibility("default"))) void js_api_set_traceable(void) { + + traceable = TRUE; + +} + diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 8a1ebf1b..538d9b70 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -284,6 +284,13 @@ class Afl { Afl.jsApiSetStdOut(buf); } + /** + * See `AFL_FRIDA_TRACEABLE`. + */ + public static setTraceable(): void { + Afl.jsApiSetTraceable(); + } + private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction( "js_api_add_exclude_range", "void", @@ -431,6 +438,11 @@ class Afl { "void", ["pointer"]); + private static readonly jsApiSetTraceable = Afl.jsApiGetFunction( + "js_api_set_traceable", + "void", + []); + private static readonly jsApiWrite = new NativeFunction( /* tslint:disable-next-line:no-null-keyword */ Module.getExportByName(null, "write"), diff --git a/include/envs.h b/include/envs.h index e3957147..61267a0d 100644 --- a/include/envs.h +++ b/include/envs.h @@ -76,6 +76,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", + "AFL_FRIDA_TRACEABLE", "AFL_FUZZER_ARGS", // oss-fuzz "AFL_GDB", "AFL_GCC_ALLOWLIST", From d85f5d4d62d2ca986b077aef06e8cb32148d9361 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 26 Oct 2021 22:30:44 +0100 Subject: [PATCH 27/44] frida mode macOs build fix proposal --- frida_mode/src/entry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index 0ce2f3c3..c51e202f 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -56,7 +56,7 @@ void entry_on_fork(void) { #else void entry_on_fork(void) { - if (set_dumpable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); } + if (traceable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); } } From 69d82cf9d7e007ed9508034d2c0acaeb027d2b47 Mon Sep 17 00:00:00 2001 From: Adrian Herrera Date: Wed, 27 Oct 2021 10:16:24 +0000 Subject: [PATCH 28/44] optimin: fix cmake flags Disable RTTI. Fixes issue #1133 --- utils/optimin/src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/optimin/src/CMakeLists.txt b/utils/optimin/src/CMakeLists.txt index f31ceeaf..693f63f2 100644 --- a/utils/optimin/src/CMakeLists.txt +++ b/utils/optimin/src/CMakeLists.txt @@ -1,4 +1,5 @@ add_executable(optimin OptiMin.cpp) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") foreach(LIB MaLib EvalMaxSAT glucose) target_include_directories(optimin PRIVATE From 45b8e057934b5f565013f29f4f461aaca051a56d Mon Sep 17 00:00:00 2001 From: Kuang-che Wu Date: Sat, 30 Oct 2021 22:27:49 +0800 Subject: [PATCH 29/44] fix off by one bug of PCGUARD instrumentation fix bug #1120 --- instrumentation/SanitizerCoverageLTO.so.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index d90fa867..7a3d8c4d 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1049,7 +1049,7 @@ bool ModuleSanitizerCoverage::instrumentModule( uint32_t write_loc = afl_global_id; - if (afl_global_id % 8) write_loc = (((afl_global_id + 8) >> 3) << 3); + write_loc = (((afl_global_id + 8) >> 3) << 3); GlobalVariable *AFLFinalLoc = new GlobalVariable(M, Int32Tyi, true, GlobalValue::ExternalLinkage, 0, From 36d8f979724de64ad986acd3b9fe8933e99950c4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Thu, 28 Oct 2021 15:38:50 +0200 Subject: [PATCH 30/44] gcc instrumentation opt --- src/afl-cc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/afl-cc.c b/src/afl-cc.c index 77407a98..ed6390ce 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -423,6 +423,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path); cc_params[cc_par_cnt++] = fplugin_arg; + cc_params[cc_par_cnt++] = "-fno-if-conversion"; + cc_params[cc_par_cnt++] = "-fno-if-conversion2"; } From c64735df9e87f2ee15ea32208be85e481c78814b Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 31 Oct 2021 11:55:36 +0100 Subject: [PATCH 31/44] help gcc --- src/afl-cc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/afl-cc.c b/src/afl-cc.c index ed6390ce..e7f08aac 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -737,6 +737,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) && + !strncmp(cur, "-stdlib=", 8)) { + + if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); } + continue; + + } + if ((!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) || !strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) && (strncmp(cur, "sanitize-coverage-allow", From d918a9e85b3b73127bbf7e0e14e63104537ab1d6 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sun, 31 Oct 2021 13:25:27 +0100 Subject: [PATCH 32/44] insert select instrumentation --- .../SanitizerCoveragePCGUARD.so.cc | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 013492f9..d6098897 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -203,7 +203,7 @@ class ModuleSanitizerCoverage { SanitizerCoverageOptions Options; - uint32_t instr = 0; + uint32_t instr = 0, selects = 0; GlobalVariable *AFLMapPtr = NULL; ConstantInt * One = NULL; ConstantInt * Zero = NULL; @@ -553,8 +553,9 @@ bool ModuleSanitizerCoverage::instrumentModule( getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); - OKF("Instrumented %u locations with no collisions (%s mode).", instr, - modeline); + OKF("Instrumented %u locations with no collisions (%s mode) and %u " + "selects.", + instr, modeline, selects); } @@ -836,6 +837,8 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (AllBlocks.empty()) return false; uint32_t special = 0; + uint32_t skip_next = 0; + for (auto &BB : F) { for (auto &IN : BB) { @@ -856,6 +859,64 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } + SelectInst *selectInst = nullptr; + + if (!skip_next && (selectInst = dyn_cast(&IN))) { + + selects++; + uint32_t id1 = 1 + instr + (uint32_t)AllBlocks.size() + special++; + uint32_t id2 = 1 + instr + (uint32_t)AllBlocks.size() + special++; + Value * val1 = ConstantInt::get(Int32Ty, id1); + Value * val2 = ConstantInt::get(Int32Ty, id2); + auto cond = selectInst->getCondition(); + IRBuilder<> IRB(selectInst->getNextNode()); + auto result = IRB.CreateSelect(cond, val1, val2); + + /* Get CurLoc */ + + /* Load SHM pointer */ + + LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + + /* Load counter for CurLoc */ + + Value *MapPtrIdx = IRB.CreateGEP(MapPtr, result); + + if (use_threadsafe_counters) { + + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, +#if LLVM_VERSION_MAJOR >= 13 + llvm::MaybeAlign(1), +#endif + llvm::AtomicOrdering::Monotonic); + + } else { + + LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + /* Update bitmap */ + + Value *Incr = IRB.CreateAdd(Counter, One); + + if (skip_nozero == NULL) { + + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); + + } + + IRB.CreateStore(Incr, MapPtrIdx); + + } + + skip_next = 1; + + } else { + + skip_next = 0; + + } + } } From 0cbb406451a77b7b293cd317ad116531a9cb46bf Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Nov 2021 00:30:56 +0100 Subject: [PATCH 33/44] fix --- .../SanitizerCoveragePCGUARD.so.cc | 90 +++++++++++++++---- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index d6098897..cfb777ce 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -834,10 +834,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, ArrayRef AllBlocks, bool IsLeafFunc) { - if (AllBlocks.empty()) return false; - - uint32_t special = 0; - uint32_t skip_next = 0; + uint32_t cnt_cov = 0, cnt_sel = 0; for (auto &BB : F) { @@ -853,9 +850,46 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, StringRef FuncName = Callee->getName(); if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; - uint32_t id = 1 + instr + (uint32_t)AllBlocks.size() + special++; - Value * val = ConstantInt::get(Int32Ty, id); - callInst->setOperand(1, val); + cnt_cov++; + + } + + SelectInst *selectInst = nullptr; + + if ((selectInst = dyn_cast(&IN))) { cnt_sel++; } + + } + + } + + /* Create PCGUARD array */ + CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel * 2); + selects += cnt_sel; + + uint32_t special = 0, local_selects = 0, skip_next = 0; + + for (auto &BB : F) { + + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + + if ((callInst = dyn_cast(&IN))) { + + Function *Callee = callInst->getCalledFunction(); + if (!Callee) continue; + if (callInst->getCallingConv() != llvm::CallingConv::C) continue; + StringRef FuncName = Callee->getName(); + if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; + + IRBuilder<> IRB(callInst); + Value * GuardPtr = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (++special + AllBlocks.size()) * 4)), + Int32PtrTy); + + callInst->setOperand(1, GuardPtr); } @@ -863,24 +897,40 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (!skip_next && (selectInst = dyn_cast(&IN))) { - selects++; - uint32_t id1 = 1 + instr + (uint32_t)AllBlocks.size() + special++; - uint32_t id2 = 1 + instr + (uint32_t)AllBlocks.size() + special++; - Value * val1 = ConstantInt::get(Int32Ty, id1); - Value * val2 = ConstantInt::get(Int32Ty, id2); - auto cond = selectInst->getCondition(); IRBuilder<> IRB(selectInst->getNextNode()); - auto result = IRB.CreateSelect(cond, val1, val2); + + Value *GuardPtr1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + local_selects * 2 + 1 + AllBlocks.size()) * 4)), + Int32PtrTy); + + Value *GuardPtr2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + local_selects * 2 + 2 + AllBlocks.size()) * 4)), + Int32PtrTy); + + local_selects++; + + auto cond = selectInst->getCondition(); + auto result = IRB.CreateSelect(cond, GuardPtr1, GuardPtr2); /* Get CurLoc */ + LoadInst *CurLoc = IRB.CreateLoad(result); + /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); /* Load counter for CurLoc */ - Value *MapPtrIdx = IRB.CreateGEP(MapPtr, result); + Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); if (use_threadsafe_counters) { @@ -893,6 +943,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + /* Update bitmap */ Value *Incr = IRB.CreateAdd(Counter, One); @@ -910,6 +961,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } skip_next = 1; + instr += 2; } else { @@ -921,11 +973,11 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } - CreateFunctionLocalArrays(F, AllBlocks, special); - for (size_t i = 0, N = AllBlocks.size(); i < N; i++) - InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); + if (AllBlocks.empty() && !special && !local_selects) return false; - instr += special; + if (!AllBlocks.empty()) + for (size_t i = 0, N = AllBlocks.size(); i < N; i++) + InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); return true; From 7e813ca4925c26253dcba34daa29cd5140b7b8ba Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Nov 2021 09:23:05 +0100 Subject: [PATCH 34/44] fix --- .../SanitizerCoveragePCGUARD.so.cc | 108 ++++++++++-------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index cfb777ce..4bd62bc7 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -203,7 +203,7 @@ class ModuleSanitizerCoverage { SanitizerCoverageOptions Options; - uint32_t instr = 0, selects = 0; + uint32_t instr = 0, selects = 0, unhandled = 0; GlobalVariable *AFLMapPtr = NULL; ConstantInt * One = NULL; ConstantInt * Zero = NULL; @@ -553,9 +553,9 @@ bool ModuleSanitizerCoverage::instrumentModule( getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); - OKF("Instrumented %u locations with no collisions (%s mode) and %u " - "selects.", - instr, modeline, selects); + OKF("Instrumented %u locations with no collisions (%s mode) of which are " + "%u handled and %u unhandled selects.", + instr, modeline, selects, unhandled); } @@ -856,12 +856,20 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, SelectInst *selectInst = nullptr; - if ((selectInst = dyn_cast(&IN))) { cnt_sel++; } + if ((selectInst = dyn_cast(&IN))) { + + Value *c = selectInst->getCondition(); + auto t = c->getType(); + if (t->getTypeID() == llvm::Type::IntegerTyID) cnt_sel++; + + } } } + fprintf(stderr, "%u selects in %s!\n", cnt_sel, F.getName().str().c_str()); + /* Create PCGUARD array */ CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel * 2); selects += cnt_sel; @@ -897,72 +905,82 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (!skip_next && (selectInst = dyn_cast(&IN))) { - IRBuilder<> IRB(selectInst->getNextNode()); + Value *c = selectInst->getCondition(); + auto t = c->getType(); + if (t->getTypeID() == llvm::Type::IntegerTyID) { - Value *GuardPtr1 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + local_selects * 2 + 1 + AllBlocks.size()) * 4)), - Int32PtrTy); + IRBuilder<> IRB(selectInst->getNextNode()); - Value *GuardPtr2 = IRB.CreateIntToPtr( - IRB.CreateAdd( - IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get( - IntptrTy, - (cnt_cov + local_selects * 2 + 2 + AllBlocks.size()) * 4)), - Int32PtrTy); + Value *GuardPtr1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + local_selects * 2 + 1 + + AllBlocks.size()) * + 4)), + Int32PtrTy); - local_selects++; + Value *GuardPtr2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + local_selects * 2 + 2 + + AllBlocks.size()) * + 4)), + Int32PtrTy); - auto cond = selectInst->getCondition(); - auto result = IRB.CreateSelect(cond, GuardPtr1, GuardPtr2); + local_selects++; - /* Get CurLoc */ + auto cond = selectInst->getCondition(); + auto result = IRB.CreateSelect(cond, GuardPtr1, GuardPtr2); - LoadInst *CurLoc = IRB.CreateLoad(result); + /* Get CurLoc */ - /* Load SHM pointer */ + LoadInst *CurLoc = IRB.CreateLoad(result); - LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + /* Load SHM pointer */ - /* Load counter for CurLoc */ + LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); - Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); + /* Load counter for CurLoc */ - if (use_threadsafe_counters) { + Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); - IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, + if (use_threadsafe_counters) { + + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, #if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), + llvm::MaybeAlign(1), #endif - llvm::AtomicOrdering::Monotonic); + llvm::AtomicOrdering::Monotonic); - } else { + } else { - LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); - /* Update bitmap */ + /* Update bitmap */ - Value *Incr = IRB.CreateAdd(Counter, One); + Value *Incr = IRB.CreateAdd(Counter, One); - if (skip_nozero == NULL) { + if (skip_nozero == NULL) { - auto cf = IRB.CreateICmpEQ(Incr, Zero); - auto carry = IRB.CreateZExt(cf, Int8Ty); - Incr = IRB.CreateAdd(Incr, carry); + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); + + } + + IRB.CreateStore(Incr, MapPtrIdx); } - IRB.CreateStore(Incr, MapPtrIdx); + skip_next = 1; + instr += 2; + + } else { + + unhandled++; } - skip_next = 1; - instr += 2; - } else { skip_next = 0; From f97c5dba2af3c1428ee26e0936c931e58e5d67e7 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Nov 2021 09:25:11 +0100 Subject: [PATCH 35/44] remove debug --- instrumentation/SanitizerCoveragePCGUARD.so.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 4bd62bc7..da1db3ff 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -868,8 +868,6 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } - fprintf(stderr, "%u selects in %s!\n", cnt_sel, F.getName().str().c_str()); - /* Create PCGUARD array */ CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel * 2); selects += cnt_sel; From cd9f596ce04cdf5bb18d73be7052a7f4aa8f7c94 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 1 Nov 2021 17:33:18 +0100 Subject: [PATCH 36/44] remove debug --- instrumentation/SanitizerCoveragePCGUARD.so.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index da1db3ff..6b6a00d1 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -905,6 +905,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, Value *c = selectInst->getCondition(); auto t = c->getType(); + if (t->getTypeID() == llvm::Type::IntegerTyID) { IRBuilder<> IRB(selectInst->getNextNode()); From fb3a71bd253e446de0b71b73c1d4a69c478f1ecd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 2 Nov 2021 17:47:17 +0100 Subject: [PATCH 37/44] support select with vectors --- .../SanitizerCoveragePCGUARD.so.cc | 181 +++++++++++++++--- 1 file changed, 150 insertions(+), 31 deletions(-) diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 6b6a00d1..e8239483 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -834,7 +834,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, ArrayRef AllBlocks, bool IsLeafFunc) { - uint32_t cnt_cov = 0, cnt_sel = 0; + uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0; for (auto &BB : F) { @@ -860,7 +860,22 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, Value *c = selectInst->getCondition(); auto t = c->getType(); - if (t->getTypeID() == llvm::Type::IntegerTyID) cnt_sel++; + if (t->getTypeID() == llvm::Type::IntegerTyID) { + + cnt_sel++; + cnt_sel_inc += 2; + + } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + if (tt) { + + cnt_sel++; + cnt_sel_inc += tt->getElementCount().getFixedValue(); + + } + + } } @@ -869,7 +884,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } /* Create PCGUARD array */ - CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel * 2); + CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel_inc); selects += cnt_sel; uint32_t special = 0, local_selects = 0, skip_next = 0; @@ -889,13 +904,16 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; IRBuilder<> IRB(callInst); - Value * GuardPtr = IRB.CreateIntToPtr( + + Value *GuardPtr = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), ConstantInt::get(IntptrTy, (++special + AllBlocks.size()) * 4)), Int32PtrTy); - callInst->setOperand(1, GuardPtr); + LoadInst *Idx = IRB.CreateLoad(GuardPtr); + + callInst->setOperand(1, Idx); } @@ -903,45 +921,139 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (!skip_next && (selectInst = dyn_cast(&IN))) { - Value *c = selectInst->getCondition(); - auto t = c->getType(); + uint32_t vector_cnt = 0; + Value * condition = selectInst->getCondition(); + Value * result; + auto t = condition->getType(); + IRBuilder<> IRB(selectInst->getNextNode()); if (t->getTypeID() == llvm::Type::IntegerTyID) { - IRBuilder<> IRB(selectInst->getNextNode()); - - Value *GuardPtr1 = IRB.CreateIntToPtr( + auto GuardPtr1 = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (cnt_cov + local_selects * 2 + 1 + - AllBlocks.size()) * - 4)), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), Int32PtrTy); - Value *GuardPtr2 = IRB.CreateIntToPtr( + auto GuardPtr2 = IRB.CreateIntToPtr( IRB.CreateAdd( IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), - ConstantInt::get(IntptrTy, (cnt_cov + local_selects * 2 + 2 + - AllBlocks.size()) * - 4)), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), Int32PtrTy); - local_selects++; + result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); - auto cond = selectInst->getCondition(); - auto result = IRB.CreateSelect(cond, GuardPtr1, GuardPtr2); + } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + if (tt) { + + uint32_t elements = tt->getElementCount().getFixedValue(); + vector_cnt = elements; + if (elements) { + + FixedVectorType *GuardPtr1 = + FixedVectorType::get(Int32PtrTy, elements); + FixedVectorType *GuardPtr2 = + FixedVectorType::get(Int32PtrTy, elements); + Value *x, *y; + + Value *val1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), + Int32PtrTy); + x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); + + Value *val2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get( + IntptrTy, + (cnt_cov + ++local_selects + AllBlocks.size()) * 4)), + Int32PtrTy); + y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); + + for (uint64_t i = 1; i < elements; i++) { + + val1 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + ++local_selects + + AllBlocks.size()) * + 4)), + Int32PtrTy); + x = IRB.CreateInsertElement(x, val1, i); + + val2 = IRB.CreateIntToPtr( + IRB.CreateAdd( + IRB.CreatePointerCast(FunctionGuardArray, IntptrTy), + ConstantInt::get(IntptrTy, (cnt_cov + ++local_selects + + AllBlocks.size()) * + 4)), + Int32PtrTy); + y = IRB.CreateInsertElement(y, val2, i); + + } + + /* + std::string errMsg; + raw_string_ostream os(errMsg); + x->print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ + result = IRB.CreateSelect(condition, x, y); + + } + + } + + } else { + + unhandled++; + + } + + local_selects++; + uint32_t vector_cur = 0; + + /* Load SHM pointer */ + + LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + + /* + std::string errMsg; + raw_string_ostream os(errMsg); + result->print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ + + while (1) { /* Get CurLoc */ - - LoadInst *CurLoc = IRB.CreateLoad(result); - - /* Load SHM pointer */ - - LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + LoadInst *CurLoc = nullptr; + Value * MapPtrIdx = nullptr; /* Load counter for CurLoc */ + if (!vector_cnt) { - Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); + CurLoc = IRB.CreateLoad(result); + MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); + + } else { + + auto element = IRB.CreateExtractElement(result, vector_cur++); + auto elementptr = IRB.CreateIntToPtr(element, Int32PtrTy); + auto elementld = IRB.CreateLoad(elementptr); + MapPtrIdx = IRB.CreateGEP(MapPtr, elementld); + + } if (use_threadsafe_counters) { @@ -971,15 +1083,22 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } - skip_next = 1; - instr += 2; + if (!vector_cnt) { - } else { + vector_cnt = 2; + break; - unhandled++; + } else if (vector_cnt == vector_cur) { + + break; + + } } + skip_next = 1; + instr += vector_cnt; + } else { skip_next = 0; From 682e1d835cac4c33f93d3709c98e5e8489f0ec7e Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 2 Nov 2021 19:20:18 +0100 Subject: [PATCH 38/44] select support for LTO --- instrumentation/SanitizerCoverageLTO.so.cc | 140 ++++++++++++++++++++- 1 file changed, 137 insertions(+), 3 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 7a3d8c4d..bc4df34e 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -235,6 +235,8 @@ class ModuleSanitizerCoverage { uint32_t autodictionary = 1; uint32_t inst = 0; uint32_t afl_global_id = 0; + uint32_t unhandled = 0; + uint32_t select_cnt = 0; uint64_t map_addr = 0; const char * skip_nozero = NULL; const char * use_threadsafe_counters = nullptr; @@ -1150,9 +1152,9 @@ bool ModuleSanitizerCoverage::instrumentModule( getenv("AFL_USE_MSAN") ? ", MSAN" : "", getenv("AFL_USE_CFISAN") ? ", CFISAN" : "", getenv("AFL_USE_UBSAN") ? ", UBSAN" : ""); - OKF("Instrumented %u locations with no collisions (on average %llu " - "collisions would be in afl-gcc/vanilla AFL) (%s mode).", - inst, calculateCollisions(inst), modeline); + OKF("Instrumented %u locations (%u selects) without collisions (%llu " + "collisions have been avoided) (%s mode).", + inst, select_cnt, calculateCollisions(inst), modeline); } @@ -1274,6 +1276,7 @@ void ModuleSanitizerCoverage::instrumentFunction( const DominatorTree * DT = DTCallback(F); const PostDominatorTree *PDT = PDTCallback(F); bool IsLeafFunc = true; + uint32_t skip_next = 0, local_selects = 0; for (auto &BB : F) { @@ -1291,6 +1294,137 @@ void ModuleSanitizerCoverage::instrumentFunction( Value *val = ConstantInt::get(Int32Ty, ++afl_global_id); callInst->setOperand(1, val); + ++inst; + + } + + SelectInst *selectInst = nullptr; + + if (!skip_next && (selectInst = dyn_cast(&IN))) { + + uint32_t vector_cnt = 0; + Value * condition = selectInst->getCondition(); + Value * result; + auto t = condition->getType(); + IRBuilder<> IRB(selectInst->getNextNode()); + + ++select_cnt; + + if (t->getTypeID() == llvm::Type::IntegerTyID) { + + Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); + Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); + result = IRB.CreateSelect(condition, val1, val2); + inst += 2; + + } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + + FixedVectorType *tt = dyn_cast(t); + if (tt) { + + uint32_t elements = tt->getElementCount().getFixedValue(); + vector_cnt = elements; + inst += vector_cnt * 2; + if (elements) { + + FixedVectorType *GuardPtr1 = + FixedVectorType::get(Int32Ty, elements); + FixedVectorType *GuardPtr2 = + FixedVectorType::get(Int32Ty, elements); + Value *x, *y; + + Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); + Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); + x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0); + y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0); + + for (uint64_t i = 1; i < elements; i++) { + + val1 = ConstantInt::get(Int32Ty, ++afl_global_id); + val2 = ConstantInt::get(Int32Ty, ++afl_global_id); + x = IRB.CreateInsertElement(GuardPtr1, val1, i); + y = IRB.CreateInsertElement(GuardPtr2, val2, i); + + } + + /* + std::string errMsg; + raw_string_ostream os(errMsg); + x->print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ + result = IRB.CreateSelect(condition, x, y); + + } + + } + + } else { + + unhandled++; + continue; + + } + + local_selects++; + uint32_t vector_cur = 0; + /* Load SHM pointer */ + LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + + while (1) { + + /* Get CurLoc */ + Value *MapPtrIdx = nullptr; + + /* Load counter for CurLoc */ + if (!vector_cnt) { + + MapPtrIdx = IRB.CreateGEP(MapPtr, result); + + } else { + + auto element = IRB.CreateExtractElement(result, vector_cur++); + MapPtrIdx = IRB.CreateGEP(MapPtr, element); + + } + + if (use_threadsafe_counters) { + + IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, +#if LLVM_VERSION_MAJOR >= 13 + llvm::MaybeAlign(1), +#endif + llvm::AtomicOrdering::Monotonic); + + } else { + + LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + + /* Update bitmap */ + + Value *Incr = IRB.CreateAdd(Counter, One); + + if (skip_nozero == NULL) { + + auto cf = IRB.CreateICmpEQ(Incr, Zero); + auto carry = IRB.CreateZExt(cf, Int8Ty); + Incr = IRB.CreateAdd(Incr, carry); + + } + + IRB.CreateStore(Incr, MapPtrIdx); + + } + + if (!vector_cnt || vector_cnt == vector_cur) { break; } + + } + + skip_next = 1; + + } else { + + skip_next = 0; } From ce41f881a0109ada6b550d96766d52e692a0e0f4 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Tue, 2 Nov 2021 19:53:15 +0100 Subject: [PATCH 39/44] nosan --- instrumentation/SanitizerCoverageLTO.so.cc | 27 +++++++++---------- .../SanitizerCoveragePCGUARD.so.cc | 15 +++++++++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index bc4df34e..b3a6ba45 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1042,8 +1042,7 @@ bool ModuleSanitizerCoverage::instrumentModule( M, Int64Tyi, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr"); ConstantInt *MapAddr = ConstantInt::get(Int64Tyi, map_addr); StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed); - StoreMapAddr->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(Ctx, None)); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreMapAddr); } @@ -1058,8 +1057,7 @@ bool ModuleSanitizerCoverage::instrumentModule( "__afl_final_loc"); ConstantInt *const_loc = ConstantInt::get(Int32Tyi, write_loc); StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); - StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(Ctx, None)); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreFinalLoc); } @@ -1107,8 +1105,7 @@ bool ModuleSanitizerCoverage::instrumentModule( 0, "__afl_dictionary_len"); ConstantInt *const_len = ConstantInt::get(Int32Tyi, offset); StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen); - StoreDictLen->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(Ctx, None)); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDictLen); ArrayType *ArrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset); GlobalVariable *AFLInternalDictionary = new GlobalVariable( @@ -1128,8 +1125,7 @@ bool ModuleSanitizerCoverage::instrumentModule( Value *AFLDictPtr = IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Tyi, 0)); StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary); - StoreDict->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(Ctx, None)); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDict); } @@ -1370,6 +1366,7 @@ void ModuleSanitizerCoverage::instrumentFunction( uint32_t vector_cur = 0; /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); while (1) { @@ -1399,6 +1396,7 @@ void ModuleSanitizerCoverage::instrumentFunction( } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); /* Update bitmap */ @@ -1412,7 +1410,8 @@ void ModuleSanitizerCoverage::instrumentFunction( } - IRB.CreateStore(Incr, MapPtrIdx); + auto nosan = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan); } @@ -1655,8 +1654,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } else { LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); - MapPtr->setMetadata(Mo->getMDKindID("nosanitize"), - MDNode::get(*Ct, None)); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); } @@ -1673,8 +1671,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); - Counter->setMetadata(Mo->getMDKindID("nosanitize"), - MDNode::get(*Ct, None)); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); Value *Incr = IRB.CreateAdd(Counter, One); @@ -1686,8 +1683,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } - IRB.CreateStore(Incr, MapPtrIdx) - ->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None)); + auto nosan = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan); } diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index e8239483..70af2ee2 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -912,6 +912,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, Int32PtrTy); LoadInst *Idx = IRB.CreateLoad(GuardPtr); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(Idx); callInst->setOperand(1, Idx); @@ -1026,6 +1027,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); /* std::string errMsg; @@ -1044,6 +1046,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, if (!vector_cnt) { CurLoc = IRB.CreateLoad(result); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc); MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); } else { @@ -1051,6 +1054,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, auto element = IRB.CreateExtractElement(result, vector_cur++); auto elementptr = IRB.CreateIntToPtr(element, Int32PtrTy); auto elementld = IRB.CreateLoad(elementptr); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(elementld); MapPtrIdx = IRB.CreateGEP(MapPtr, elementld); } @@ -1066,6 +1070,7 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); /* Update bitmap */ @@ -1079,7 +1084,8 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } - IRB.CreateStore(Incr, MapPtrIdx); + StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx); } @@ -1309,10 +1315,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, Int32PtrTy); LoadInst *CurLoc = IRB.CreateLoad(GuardPtr); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc); /* Load SHM pointer */ LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr); /* Load counter for CurLoc */ @@ -1329,6 +1337,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } else { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter); + /* Update bitmap */ Value *Incr = IRB.CreateAdd(Counter, One); @@ -1341,7 +1351,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, } - IRB.CreateStore(Incr, MapPtrIdx); + StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx); + ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx); } From caf68e5bf25a8a73bcc21b870499b640e7702d85 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 3 Nov 2021 12:34:26 +0100 Subject: [PATCH 40/44] support vectorized cmps --- instrumentation/cmplog-instructions-pass.cc | 219 ++++++++++++++------ 1 file changed, 155 insertions(+), 64 deletions(-) diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 0562c5b2..86e206f1 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -274,14 +274,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) { Value *op0 = selectcmpInst->getOperand(0); Value *op1 = selectcmpInst->getOperand(1); + Value *op0_saved = op0, *op1_saved = op1; + auto ty0 = op0->getType(); + auto ty1 = op1->getType(); - IntegerType * intTyOp0 = NULL; - IntegerType * intTyOp1 = NULL; - unsigned max_size = 0, cast_size = 0; - unsigned char attr = 0; - std::vector args; - - CmpInst *cmpInst = dyn_cast(selectcmpInst); + IntegerType *intTyOp0 = NULL; + IntegerType *intTyOp1 = NULL; + unsigned max_size = 0, cast_size = 0; + unsigned attr = 0, vector_cnt = 0; + CmpInst * cmpInst = dyn_cast(selectcmpInst); if (!cmpInst) { continue; } @@ -327,7 +328,21 @@ bool CmpLogInstructions::hookInstrs(Module &M) { if (selectcmpInst->getOpcode() == Instruction::FCmp) { - auto ty0 = op0->getType(); + if (ty0->isVectorTy()) { + + VectorType *tt = dyn_cast(ty0); + if (!tt) { + + fprintf(stderr, "Warning: cmplog cmp vector is not a vector!\n"); + continue; + + } + + vector_cnt = tt->getElementCount().getFixedValue(); + ty0 = tt->getElementType(); + + } + if (ty0->isHalfTy() #if LLVM_VERSION_MAJOR >= 11 || ty0->isBFloatTy() @@ -342,13 +357,32 @@ bool CmpLogInstructions::hookInstrs(Module &M) { max_size = 80; else if (ty0->isFP128Ty() || ty0->isPPC_FP128Ty()) max_size = 128; + else if (ty0->getTypeID() != llvm::Type::PointerTyID && !be_quiet) + fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u!\n", + ty0->getTypeID()); attr += 8; } else { - intTyOp0 = dyn_cast(op0->getType()); - intTyOp1 = dyn_cast(op1->getType()); + if (ty0->isVectorTy()) { + + VectorType *tt = dyn_cast(ty0); + if (!tt) { + + fprintf(stderr, "Warning: cmplog cmp vector is not a vector!\n"); + continue; + + } + + vector_cnt = tt->getElementCount().getFixedValue(); + ty1 = ty0 = tt->getElementType(); + fprintf(stderr, "vec %u\n", vector_cnt); + + } + + intTyOp0 = dyn_cast(ty0); + intTyOp1 = dyn_cast(ty1); if (intTyOp0 && intTyOp1) { @@ -356,11 +390,25 @@ bool CmpLogInstructions::hookInstrs(Module &M) { ? intTyOp0->getBitWidth() : intTyOp1->getBitWidth(); + } else { + + if (ty0->getTypeID() != llvm::Type::PointerTyID && !be_quiet) { + + fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u!\n", + ty0->getTypeID()); + + } + } } - if (!max_size || max_size < 16) { continue; } + if (!max_size || max_size < 16) { + + // fprintf(stderr, "too small\n"); + continue; + + } if (max_size % 8) { max_size = (((max_size / 8) + 1) * 8); } @@ -393,67 +441,110 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } - // errs() << "[CMPLOG] cmp " << *cmpInst << "(in function " << - // cmpInst->getFunction()->getName() << ")\n"; + uint64_t cur = 0, last_val0 = 0, last_val1 = 0, cur_val; - // first bitcast to integer type of the same bitsize as the original - // type (this is a nop, if already integer) - Value *op0_i = IRB.CreateBitCast( - op0, IntegerType::get(C, op0->getType()->getPrimitiveSizeInBits())); - // then create a int cast, which does zext, trunc or bitcast. In our case - // usually zext to the next larger supported type (this is a nop if - // already the right type) - Value *V0 = - IRB.CreateIntCast(op0_i, IntegerType::get(C, cast_size), false); - args.push_back(V0); - Value *op1_i = IRB.CreateBitCast( - op1, IntegerType::get(C, op1->getType()->getPrimitiveSizeInBits())); - Value *V1 = - IRB.CreateIntCast(op1_i, IntegerType::get(C, cast_size), false); - args.push_back(V1); + while (1) { - // errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " << *V1 - // << "\n"; + std::vector args; + uint32_t skip = 0; - ConstantInt *attribute = ConstantInt::get(Int8Ty, attr); - args.push_back(attribute); + if (vector_cnt) { - if (cast_size != max_size) { + op0 = IRB.CreateExtractElement(op0_saved, cur); + op1 = IRB.CreateExtractElement(op1_saved, cur); + ConstantInt *i0 = dyn_cast(op0); + ConstantInt *i1 = dyn_cast(op1); + if (i0 && i0->uge(0xffffffffffffffff) == false) { - ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1); - args.push_back(bitsize); - - } - - // fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast %u\n", - // max_size, cast_size, attr); - - switch (cast_size) { - - case 8: - IRB.CreateCall(cmplogHookIns1, args); - break; - case 16: - IRB.CreateCall(cmplogHookIns2, args); - break; - case 32: - IRB.CreateCall(cmplogHookIns4, args); - break; - case 64: - IRB.CreateCall(cmplogHookIns8, args); - break; - case 128: - if (max_size == 128) { - - IRB.CreateCall(cmplogHookIns16, args); - - } else { - - IRB.CreateCall(cmplogHookInsN, args); + cur_val = i0->getZExtValue(); + if (last_val0 && last_val0 == cur_val) { skip = 1; } + last_val0 = cur_val; } - break; + if (i1 && i1->uge(0xffffffffffffffff) == false) { + + cur_val = i1->getZExtValue(); + if (last_val1 && last_val1 == cur_val) { skip = 1; } + last_val1 = cur_val; + + } + + } + + if (!skip) { + + // errs() << "[CMPLOG] cmp " << *cmpInst << "(in function " << + // cmpInst->getFunction()->getName() << ")\n"; + + // first bitcast to integer type of the same bitsize as the original + // type (this is a nop, if already integer) + Value *op0_i = IRB.CreateBitCast( + op0, IntegerType::get(C, ty0->getPrimitiveSizeInBits())); + // then create a int cast, which does zext, trunc or bitcast. In our + // case usually zext to the next larger supported type (this is a nop + // if already the right type) + Value *V0 = + IRB.CreateIntCast(op0_i, IntegerType::get(C, cast_size), false); + args.push_back(V0); + Value *op1_i = IRB.CreateBitCast( + op1, IntegerType::get(C, ty1->getPrimitiveSizeInBits())); + Value *V1 = + IRB.CreateIntCast(op1_i, IntegerType::get(C, cast_size), false); + args.push_back(V1); + + // errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " << + // *V1 + // << "\n"; + + ConstantInt *attribute = ConstantInt::get(Int8Ty, attr); + args.push_back(attribute); + + if (cast_size != max_size) { + + ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1); + args.push_back(bitsize); + + } + + // fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast %u\n", + // max_size, cast_size, attr); + + switch (cast_size) { + + case 8: + IRB.CreateCall(cmplogHookIns1, args); + break; + case 16: + IRB.CreateCall(cmplogHookIns2, args); + break; + case 32: + IRB.CreateCall(cmplogHookIns4, args); + break; + case 64: + IRB.CreateCall(cmplogHookIns8, args); + break; + case 128: + if (max_size == 128) { + + IRB.CreateCall(cmplogHookIns16, args); + + } else { + + IRB.CreateCall(cmplogHookInsN, args); + + } + + break; + + } + + } + + /* else fprintf(stderr, "skipped\n"); */ + + ++cur; + if (cur >= vector_cnt) { break; } } From ccded9fc5cfead1b88104484c4acde12e81e0afe Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 3 Nov 2021 12:49:54 +0100 Subject: [PATCH 41/44] vectorized coverage only possible for llvm 14 :( --- instrumentation/SanitizerCoverageLTO.so.cc | 10 ++++++++-- instrumentation/SanitizerCoveragePCGUARD.so.cc | 17 +++++++++++++++-- instrumentation/cmplog-instructions-pass.cc | 1 - 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index b3a6ba45..fbbe24a2 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1313,7 +1313,10 @@ void ModuleSanitizerCoverage::instrumentFunction( result = IRB.CreateSelect(condition, val1, val2); inst += 2; - } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + } + +#if LLVM_VERSION_MAJOR > 13 + else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { FixedVectorType *tt = dyn_cast(t); if (tt) { @@ -1355,7 +1358,10 @@ void ModuleSanitizerCoverage::instrumentFunction( } - } else { + } else + +#endif + { unhandled++; continue; diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 70af2ee2..10c9430e 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -895,6 +895,12 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, CallInst *callInst = nullptr; + /* + std::string errMsg; + raw_string_ostream os(errMsg); + IN.print(os); + fprintf(stderr, "X: %s\n", os.str().c_str()); + */ if ((callInst = dyn_cast(&IN))) { Function *Callee = callInst->getCalledFunction(); @@ -948,7 +954,10 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2); - } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + } else + +#if LLVM_VERSION_MAJOR > 13 + if (t->getTypeID() == llvm::Type::FixedVectorTyID) { FixedVectorType *tt = dyn_cast(t); if (tt) { @@ -1015,9 +1024,13 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } - } else { + } else + +#endif + { unhandled++; + continue; } diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index 86e206f1..cb149e9a 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -377,7 +377,6 @@ bool CmpLogInstructions::hookInstrs(Module &M) { vector_cnt = tt->getElementCount().getFixedValue(); ty1 = ty0 = tt->getElementType(); - fprintf(stderr, "vec %u\n", vector_cnt); } From 7a7630ae91c87e000b40f63c592fad9e09ad45d3 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Wed, 3 Nov 2021 13:18:02 +0100 Subject: [PATCH 42/44] support llvm >= 11 --- instrumentation/SanitizerCoverageLTO.so.cc | 18 ++++++++++-------- instrumentation/SanitizerCoveragePCGUARD.so.cc | 7 ++++++- instrumentation/cmplog-instructions-pass.cc | 11 ++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index fbbe24a2..ee8c317e 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1296,6 +1296,12 @@ void ModuleSanitizerCoverage::instrumentFunction( SelectInst *selectInst = nullptr; + /* + std::string errMsg; + raw_string_ostream os(errMsg); + IN.print(os); + fprintf(stderr, "X(%u): %s\n", skip_next, os.str().c_str()); + */ if (!skip_next && (selectInst = dyn_cast(&IN))) { uint32_t vector_cnt = 0; @@ -1311,12 +1317,13 @@ void ModuleSanitizerCoverage::instrumentFunction( Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id); Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id); result = IRB.CreateSelect(condition, val1, val2); + skip_next = 1; inst += 2; - } + } else #if LLVM_VERSION_MAJOR > 13 - else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + if (t->getTypeID() == llvm::Type::FixedVectorTyID) { FixedVectorType *tt = dyn_cast(t); if (tt) { @@ -1346,13 +1353,8 @@ void ModuleSanitizerCoverage::instrumentFunction( } - /* - std::string errMsg; - raw_string_ostream os(errMsg); - x->print(os); - fprintf(stderr, "X: %s\n", os.str().c_str()); - */ result = IRB.CreateSelect(condition, x, y); + skip_next = 1; } diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 10c9430e..be3f4f49 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -865,7 +865,10 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, cnt_sel++; cnt_sel_inc += 2; - } else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { + } + +#if LLVM__MAJOR > 11 + else if (t->getTypeID() == llvm::Type::FixedVectorTyID) { FixedVectorType *tt = dyn_cast(t); if (tt) { @@ -877,6 +880,8 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F, } +#endif + } } diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index cb149e9a..01a8a637 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -338,8 +338,10 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } +#if LLVM_MAJOR > 11 vector_cnt = tt->getElementCount().getFixedValue(); ty0 = tt->getElementType(); +#endif } @@ -357,9 +359,11 @@ bool CmpLogInstructions::hookInstrs(Module &M) { max_size = 80; else if (ty0->isFP128Ty() || ty0->isPPC_FP128Ty()) max_size = 128; +#if LLVM_MAJOR > 11 else if (ty0->getTypeID() != llvm::Type::PointerTyID && !be_quiet) fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u!\n", ty0->getTypeID()); +#endif attr += 8; @@ -367,6 +371,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { if (ty0->isVectorTy()) { +#if LLVM_MAJOR > 11 VectorType *tt = dyn_cast(ty0); if (!tt) { @@ -377,6 +382,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) { vector_cnt = tt->getElementCount().getFixedValue(); ty1 = ty0 = tt->getElementType(); +#endif } @@ -391,13 +397,16 @@ bool CmpLogInstructions::hookInstrs(Module &M) { } else { +#if LLVM_MAJOR > 11 if (ty0->getTypeID() != llvm::Type::PointerTyID && !be_quiet) { - fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u!\n", + fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u\n", ty0->getTypeID()); } +#endif + } } From 3670412d2e6841f2cee26e3624a02c08a24671c8 Mon Sep 17 00:00:00 2001 From: yuan Date: Wed, 3 Nov 2021 23:44:37 +0800 Subject: [PATCH 43/44] Fix request size & remove redundant code (#1139) * fix request size * fix null terminator index * remove redundant code --- src/afl-common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/afl-common.c b/src/afl-common.c index db19f0a7..26a0d54b 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -217,11 +217,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } - char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); + char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc + 3] = NULL; new_argv[2] = *target_path_p; new_argv[1] = "--"; @@ -237,11 +236,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { - char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); + char **new_argv = ck_alloc(sizeof(char *) * (argc + 2)); if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1)); - new_argv[argc + 2] = NULL; new_argv[1] = *target_path_p; From 651133ea00ae803377f941b95a9d396bf92eb407 Mon Sep 17 00:00:00 2001 From: llzmb <46303940+llzmb@users.noreply.github.com> Date: Wed, 3 Nov 2021 21:11:11 +0100 Subject: [PATCH 44/44] Clean up references to power_schedules.md --- docs/parallel_fuzzing.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/parallel_fuzzing.md b/docs/parallel_fuzzing.md index e37276a5..d24f2837 100644 --- a/docs/parallel_fuzzing.md +++ b/docs/parallel_fuzzing.md @@ -27,9 +27,8 @@ will not be able to use that input to guide their work. To help with this problem, afl-fuzz offers a simple way to synchronize test cases on the fly. -Note that AFL++ has AFLfast's power schedules implemented. -It is therefore a good idea to use different power schedules if you run -several instances in parallel. See [power_schedules.md](power_schedules.md) +It is a good idea to use different power schedules if you run several instances +in parallel (`-p` option). Alternatively running other AFL spinoffs in parallel can be of value, e.g. Angora (https://github.com/AngoraFuzzer/Angora/) @@ -39,7 +38,7 @@ e.g. Angora (https://github.com/AngoraFuzzer/Angora/) If you wish to parallelize a single job across multiple cores on a local system, simply create a new, empty output directory ("sync dir") that will be shared by all the instances of afl-fuzz; and then come up with a naming scheme -for every instance - say, "fuzzer01", "fuzzer02", etc. +for every instance - say, "fuzzer01", "fuzzer02", etc. Run the first one ("main node", -M) like this: @@ -93,7 +92,7 @@ file name. There is support for parallelizing the deterministic checks. This is only needed where - + 1. many new paths are found fast over a long time and it looks unlikely that main node will ever catch up, and 2. deterministic fuzzing is actively helping path discovery (you can see this @@ -195,7 +194,7 @@ to keep in mind: - You do not want a "main" instance of afl-fuzz on every system; you should run them all with -S, and just designate a single process somewhere within the fleet to run with -M. - + - Syncing is only necessary for the main nodes on a system. It is possible to run main-less with only secondaries. However then you need to find out which secondary took over the temporary role to be the main node. Look for