Merge branch 'dev' of github.com:AFLplusplus/AFLplusplus into dev

This commit is contained in:
Andrea Fioraldi
2021-10-19 13:59:38 +02:00
52 changed files with 565 additions and 505 deletions

112
README.md
View File

@ -6,7 +6,8 @@ Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 3.15a 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: AFL++ is maintained by:
@ -17,57 +18,74 @@ AFL++ is maintained by:
Originally developed by Michał "lcamtuf" Zalewski. 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 ## Getting started
Here is some information to get you 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 [major behaviour changes in AFL++](docs/behaviour_changes.md). * For releases, please see the
* If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website. [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. * 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). * For comparisons, use the fuzzbench `aflplusplus` setup, or use
* To get you started with tutorials, go to [docs/tutorials.md](docs/tutorials.md). `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++ ## 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 ```shell
docker pull aflplusplus/aflplusplus docker pull aflplusplus/aflplusplus
docker run -ti -v /location/of/your/target:/src 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)). This image is automatically generated when a push to the stable repo happens
You will find your target source code in `/src` in the container. (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). To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md).
## Quick start: Fuzzing with AFL++ ## 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. This is a quick start for fuzzing targets with the source code available. To
To read about the process in detail, see [docs/fuzzing_expert.md](docs/fuzzing_expert.md). read about the process in detail, see
[docs/fuzzing_expert.md](docs/fuzzing_expert.md).
To learn about fuzzing other targets, see: To learn about fuzzing other targets, see:
* Binary-only targets: [docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md) * Binary-only targets:
* Network services: [docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service) [docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md)
* GUI programs: [docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program) * 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: Step-by-step quick start:
1. Compile the program or library to be fuzzed using `afl-cc`. 1. Compile the program or library to be fuzzed using `afl-cc`. A common way to
A common way to do this would be: do this would be:
CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared
make clean all make clean all
2. Get a small but valid input file that makes sense to the program. 2. Get a small but valid input file that makes sense to the program. When
When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in
in [dictionaries/README.md](../dictionaries/README.md), too. [dictionaries/README.md](dictionaries/README.md), too.
3. If the program reads from stdin, run `afl-fuzz` like so: 3. If the program reads from stdin, run `afl-fuzz` like so:
@ -78,42 +96,52 @@ in [dictionaries/README.md](../dictionaries/README.md), too.
To add a dictionary, add `-x /path/to/dictionary.txt` to afl-fuzz. 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. 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 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 `hangs/` in the `-o output_dir` directory. You can replay the crashes by
feeding them to the target, e.g.: feeding them to the target, e.g.: `cat output_dir/crashes/id:000000,* |
`cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]` /path/to/tested/program [...program's cmdline...]` You can generate cores or
You can generate cores or use gdb directly to follow up the crashes. use gdb directly to follow up the crashes.
## Contact ## Contact
Questions? Concerns? Bug reports? Questions? Concerns? Bug reports?
* The contributors can be reached via [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). * The contributors can be reached 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](https://github.com/AFLplusplus/AFLplusplus).
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions). * Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or
* 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 <afl-users+subscribe@googlegroups.com>. 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 <afl-users+subscribe@googlegroups.com>.
* Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server. * Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
## Help wanted ## Help wanted
We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it even better. We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it
However, we already work on so many things that we do not have the time for all the big ideas. 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 ## 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! Thank you! (For people sending pull requests - please add yourself to this list
(For people sending pull requests - please add yourself to this list :-) :-)
<details> <details>
@ -172,7 +200,9 @@ Thank you!
## Cite ## 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. 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.
@ -191,4 +221,4 @@ If you use AFL++ in scientific work, consider citing [our paper](https://www.use
} }
``` ```
</details> </details>

View File

@ -1086,6 +1086,7 @@ ATTRIBUTE_INTERFACE size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size,
size_t MaxSize) { size_t MaxSize) {
assert(fuzzer::F); assert(fuzzer::F);
fuzzer::F->GetMD().StartMutationSequence();
size_t r = fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize); size_t r = fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
#ifdef INTROSPECTION #ifdef INTROSPECTION
introspection_ptr = fuzzer::F->GetMD().WriteMutationSequence(); introspection_ptr = fuzzer::F->GetMD().WriteMutationSequence();

View File

@ -16,11 +16,16 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix a regression introduced in 3.10 that resulted in less - fix a regression introduced in 3.10 that resulted in less
coverage being detected. thanks to Collin May for reporting! coverage being detected. thanks to Collin May for reporting!
- fix -n dumb mode (nobody should use this) - 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 - afl-showmap, afl-tmin and afl-analyze now honor persistent mode
for more speed. thanks to dloffre-snl for reporting! for more speed. thanks to dloffre-snl for reporting!
- Prevent accidently killing non-afl/fuzz services when aborting
afl-showmap and other tools.
- afl-cc: - afl-cc:
- fix for shared linking on MacOS - 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 - added the very good grammar mutator "GramaTron" to the
custom_mutators custom_mutators
- added optimin, a faster and better corpus minimizer by - added optimin, a faster and better corpus minimizer by
@ -32,6 +37,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix AFL_PRELOAD issues on MacOS - fix AFL_PRELOAD issues on MacOS
- removed utils/afl_frida because frida_mode/ is now so much better - removed utils/afl_frida because frida_mode/ is now so much better
- added uninstall target to makefile (todo: update new readme!) - added uninstall target to makefile (todo: update new readme!)
- removed indirections in rust callbacks for unicornafl
### Version ++3.14c (release) ### Version ++3.14c (release)

View File

@ -59,10 +59,10 @@ 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). 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). 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). 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). 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. 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). 7. Use your cores! [fuzzing_expert.md:b) Using multiple cores](fuzzing_expert.md#b-using-multiple-cores).
### Improving stability ### Improving stability
@ -117,4 +117,4 @@ Four steps are required to do this and it also requires quite some knowledge of
Recompile, fuzz it, be happy :) Recompile, fuzz it, be happy :)
This link explains this process for [Fuzzbench](https://github.com/google/fuzzbench/issues/677). This link explains this process for [Fuzzbench](https://github.com/google/fuzzbench/issues/677).

View File

@ -7,4 +7,5 @@ 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!!* * [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. * (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). 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).

View File

@ -2,7 +2,7 @@
This document discusses the environment variables used by American Fuzzy Lop++ This document discusses the environment variables used by American Fuzzy Lop++
to expose various exotic functions that may be (rarely) useful for power to expose various exotic functions that may be (rarely) useful for power
users or for some types of custom fuzzing setups. See [README.md](README.md) for the general users or for some types of custom fuzzing setups. See [../README.md](../README.md) for the general
instruction manual. instruction manual.
Note that most tools will warn on any unknown AFL environment variables. Note that most tools will warn on any unknown AFL environment variables.
@ -422,7 +422,7 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_FORCE_UI` will force painting the UI on the screen even if - Setting `AFL_FORCE_UI` will force painting the UI on the screen even if
no valid terminal was detected (for virtual consoles) no valid terminal was detected (for virtual consoles)
- If you are using persistent mode (you should, see [instrumentation/README.persistent_mode.md](instrumentation/README.persistent_mode.md)) - If you are using persistent mode (you should, see [instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md))
some targets keep inherent state due which a detected crash testcase does some targets keep inherent state due which a detected crash testcase does
not crash the target again when the testcase is given. To be able to still not crash the target again when the testcase is given. To be able to still
re-trigger these crashes you can use the `AFL_PERSISTENT_RECORD` variable re-trigger these crashes you can use the `AFL_PERSISTENT_RECORD` variable

View File

@ -72,7 +72,7 @@ cd unicorn_mode
If the goal is to fuzz a dynamic library then there are two options available. 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. For both you need to write a small harness that loads and calls the library.
Then you fuzz this with either frida_mode or qemu_mode, and either use Then you fuzz this with either frida_mode or qemu_mode, and either use
`AFL_INST_LIBS=1` or `AFL_QEMU/FRIDA_INST_RANGES` `AFL_INST_LIBS=1` or `AFL_QEMU/FRIDA_INST_RANGES`.
Another, less precise and slower option is using ptrace with debugger interrupt Another, less precise and slower option is using ptrace with debugger interrupt
instrumentation: [utils/afl_untracer/README.md](../utils/afl_untracer/README.md). instrumentation: [utils/afl_untracer/README.md](../utils/afl_untracer/README.md).

View File

@ -613,7 +613,7 @@ switch or honggfuzz.
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [env_variables.md](env_variables.md) * If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [env_variables.md](env_variables.md)
* Linux: Improve 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 more insecure) - you can also just run `sudo afl-persistent-config` * Linux: Improve 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 more insecure) - you can also just run `sudo afl-persistent-config`
* Linux: Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem * Linux: Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem
* Use your cores! [3.b) Using multiple cores/threads](#b-using-multiple-coresthreads) * Use your cores! [b) Using multiple cores](#b-using-multiple-cores)
* Run `sudo afl-system-config` before starting the first afl-fuzz instance after a reboot * Run `sudo afl-system-config` before starting the first afl-fuzz instance after a reboot
### The End ### The End
@ -625,4 +625,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. 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++ 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). (some might be deprecated or unsupported), see [tools.md](tools.md).

View File

@ -1,6 +1,6 @@
# Interpreting output # 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 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. sure to consult this file especially if any UI elements are highlighted in red.
@ -68,4 +68,4 @@ cd utils/plot_ui
make make
cd ../../ cd ../../
sudo make install sudo make install
``` ```

View File

@ -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 To work around this, you can comment out the relevant checks (see
utils/libpng_no_checksum/ for inspiration); if this is not possible, utils/libpng_no_checksum/ for inspiration); if this is not possible,
you can also write a postprocessor, one of the hooks of custom mutators. 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` `AFL_CUSTOM_MUTATOR_LIBRARY`
- There are some unfortunate trade-offs with ASAN and 64-bit binaries. This - There are some unfortunate trade-offs with ASAN and 64-bit binaries. This
@ -33,4 +33,4 @@ Here are some of the most important caveats for AFL:
- Occasionally, sentient machines rise against their creators. If this - Occasionally, sentient machines rise against their creators. If this
happens to you, please consult [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/). happens to you, please consult [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/).
Beyond this, see [INSTALL.md](INSTALL.md) for platform-specific tips. Beyond this, see [INSTALL.md](INSTALL.md) for platform-specific tips.

View File

@ -1,87 +0,0 @@
# AFL "Life Pro Tips"
Bite-sized advice for those who understand the basics, but can't be bothered
to read or memorize every other piece of documentation for AFL.
## Get more bang for your buck by using fuzzing dictionaries.
See [dictionaries/README.md](../dictionaries/README.md) to learn how.
## You can get the most out of your hardware by parallelizing AFL jobs.
See [parallel_fuzzing.md](parallel_fuzzing.md) for step-by-step tips.
## Improve the odds of spotting memory corruption bugs with libdislocator.so!
It's easy. Consult [utils/libdislocator/README.md](../utils/libdislocator/README.md) for usage tips.
## Want to understand how your target parses a particular input file?
Try the bundled `afl-analyze` tool; it's got colors and all!
## You can visually monitor the progress of your fuzzing jobs.
Run the bundled `afl-plot` utility to generate browser-friendly graphs.
## Need to monitor AFL jobs programmatically?
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!
## Know your target? Convert it to persistent mode for a huge performance gain!
Consult section #5 in README.llvm.md for tips.
## Using clang?
Check out 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.
## 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!
## Not sure if a crash is exploitable? AFL can help you figure it out. Specify
`-C` to enable the peruvian were-rabbit mode.
## Trouble dealing with a machine uprising? Relax, we've all been there.
Find essential survival tips at http://lcamtuf.coredump.cx/prep/.
## Want to automatically spot non-crashing memory handling bugs?
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.
## You can improve the odds of automatically spotting stack corruption issues.
Specify `AFL_HARDEN=1` in the environment to enable hardening flags.
## Bumping into problems with non-reproducible crashes?
It happens, but usually
isn't hard to diagnose. See section #7 in README.md for tips.
## Fuzzing is not just about memory corruption issues in the codebase.
Add some
sanity-checking `assert()` / `abort()` statements to effortlessly catch logic bugs.
## 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!
## 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.
## Need to fuzz the command-line arguments of a particular program?
You can find a simple solution in 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.

View File

@ -4,7 +4,7 @@ This document talks about synchronizing afl-fuzz jobs on a single machine
or across a fleet of systems. See README.md for the general instruction manual. or across a fleet of systems. See README.md for the general instruction manual.
Note that this document is rather outdated. please refer to the main document Note that this document is rather outdated. please refer to the main document
section on multiple core usage [../README.md#Using multiple cores](../README.md#b-using-multiple-coresthreads) section on multiple core usage [fuzzing_expert.md#Using multiple cores](fuzzing_expert.md#b-using-multiple-cores)
for up to date strategies! for up to date strategies!
## 1) Introduction ## 1) Introduction

View File

@ -50,7 +50,7 @@ Depending on your StatsD server, you will be able to monitor, trigger alerts, or
- `librato` - `librato`
- `signalfx` - `signalfx`
For more information on environment variables, see [docs/env_variables.md](docs/env_variables.md). For more information on environment variables, see [env_variables.md](env_variables.md).
Note: When using multiple fuzzer instances with StatsD it is *strongly* recommended to set up `AFL_STATSD_TAGS_FLAVOR` to match your StatsD server. This will allow you to see individual fuzzer performance, detect bad ones, and see the progress of each strategy. Note: When using multiple fuzzer instances with StatsD it is *strongly* recommended to set up `AFL_STATSD_TAGS_FLAVOR` to match your StatsD server. This will allow you to see individual fuzzer performance, detect bad ones, and see the progress of each strategy.
@ -152,4 +152,4 @@ To run your fuzzing instances:
AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -M test-fuzzer-1 -i i -o o [./bin/my-application] @@ AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -M test-fuzzer-1 -i i -o o [./bin/my-application] @@
AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o o [./bin/my-application] @@ AFL_STATSD_TAGS_FLAVOR=dogstatsd AFL_STATSD=1 afl-fuzz -S test-fuzzer-2 -i i -o o [./bin/my-application] @@
... ...
``` ```

View File

@ -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 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 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 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). near the end of [technical_details.md](technical_details.md).

View File

@ -30,8 +30,7 @@ AFL_CFLAGS:=-Wno-unused-parameter \
LDFLAGS+=-shared \ LDFLAGS+=-shared \
-lpthread \ -lpthread \
-lresolv \ -lresolv
-ldl
ifdef DEBUG ifdef DEBUG
CFLAGS+=-Werror \ CFLAGS+=-Werror \
@ -71,7 +70,9 @@ ifdef DEBUG
endif endif
LDFLAGS+= -z noexecstack \ LDFLAGS+= -z noexecstack \
-Wl,--gc-sections \ -Wl,--gc-sections \
-Wl,--exclude-libs,ALL -Wl,--exclude-libs,ALL \
-ldl \
-lrt
LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map
endif endif
@ -79,6 +80,22 @@ ifeq "$(shell uname)" "Linux"
OS:=linux OS:=linux
endif endif
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
OS:=android
ifneq "$(findstring aarch64, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=arm64
endif
ifneq "$(findstring arm, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=arm
endif
ifneq "$(findstring x86_64, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=x86_64
endif
ifneq "$(findstring i686, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=x86
endif
endif
ifndef OS ifndef OS
$(error "Operating system unsupported") $(error "Operating system unsupported")
endif endif

View File

@ -55,6 +55,20 @@ tests in 32-bit mode, run `make ARCH=x86 frida`. When switching between
architectures it may be necessary to run `make clean` first for a given build architectures it may be necessary to run `make clean` first for a given build
target to remove previously generated binaries for a different architecture. target to remove previously generated binaries for a different architecture.
### Android
In order to build, you need to download the Android SDK.
```
https://developer.android.com/ndk/downloads
```
Then creating locally a standalone chain as follow.
```
https://developer.android.com/ndk/guides/standalone_toolchain
```
## Usage ## Usage
FRIDA mode added some small modifications to `afl-fuzz` and similar tools FRIDA mode added some small modifications to `afl-fuzz` and similar tools

View File

@ -29,6 +29,7 @@ GumStalkerTransformer *instrument_get_transformer(void);
/* Functions to be implemented by the different architectures */ /* Functions to be implemented by the different architectures */
gboolean instrument_is_coverage_optimize_supported(void); gboolean instrument_is_coverage_optimize_supported(void);
void instrument_coverage_optimize_init(void);
void instrument_coverage_optimize(const cs_insn * instr, void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output); GumStalkerOutput *output);

View File

@ -10,6 +10,8 @@ extern gboolean ranges_inst_jit;
void ranges_config(void); void ranges_config(void);
void ranges_init(void); void ranges_init(void);
void ranges_print_debug_maps(void);
gboolean range_is_excluded(GumAddress address); gboolean range_is_excluded(GumAddress address);
void ranges_exclude(); void ranges_exclude();

View File

@ -356,6 +356,7 @@ void instrument_init(void) {
instrument_hash_seed); instrument_hash_seed);
instrument_hash_zero = instrument_get_offset_hash(0); instrument_hash_zero = instrument_get_offset_hash(0);
instrument_coverage_optimize_init();
instrument_debug_init(); instrument_debug_init();
instrument_coverage_init(); instrument_coverage_init();
asan_init(); asan_init();

View File

@ -22,6 +22,10 @@ void instrument_coverage_optimize(const cs_insn * instr,
} }
void instrument_coverage_optimize_init(void) {
WARNF("Optimized coverage not supported on this architecture");
}
void instrument_flush(GumStalkerOutput *output) { void instrument_flush(GumStalkerOutput *output) {
gum_arm_writer_flush(output->writer.arm); gum_arm_writer_flush(output->writer.arm);

View File

@ -95,6 +95,9 @@ void instrument_coverage_optimize(const cs_insn * instr,
} }
void instrument_coverage_optimize_init(void) {
}
void instrument_flush(GumStalkerOutput *output) { void instrument_flush(GumStalkerOutput *output) {
gum_arm64_writer_flush(output->writer.arm64); gum_arm64_writer_flush(output->writer.arm64);

View File

@ -1,4 +1,16 @@
#include <fcntl.h>
#include <stddef.h> #include <stddef.h>
#include <sys/mman.h>
#include <sys/shm.h>
#if defined(__linux__)
#if !defined(__ANDROID__)
#include <asm/prctl.h>
#include <sys/syscall.h>
#else
#include <linux/ashmem.h>
#endif
#endif
#include "frida-gumjs.h" #include "frida-gumjs.h"
@ -6,125 +18,17 @@
#include "debug.h" #include "debug.h"
#include "instrument.h" #include "instrument.h"
#include "ranges.h"
#if defined(__x86_64__) #if defined(__x86_64__)
static GumAddress current_log_impl = GUM_ADDRESS(0); #ifndef MAP_FIXED_NOREPLACE
#ifdef MAP_EXCL
#pragma pack(push, 1) #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
#else
typedef struct { #define MAP_FIXED_NOREPLACE MAP_FIXED
#endif
/* #endif
* pushfq
* push rdx
* mov rdx, [&previouspc] (rip relative addr)
* xor rdx, rdi (current_pc)
* shr rdi. 1
* mov [&previouspc], rdi
* lea rsi, [&_afl_area_ptr] (rip relative)
* add rdx, rsi
* add byte ptr [rdx], 1
* adc byte ptr [rdx], 0
* pop rdx
* popfq
*/
uint8_t push_fq;
uint8_t push_rdx;
uint8_t mov_rdx_rip_off[7];
uint8_t xor_rdx_rdi[3];
uint8_t shr_rdi[3];
uint8_t mov_rip_off_rdi[7];
uint8_t lea_rdi_rip_off[7];
uint8_t add_rdx_rdi[3];
uint8_t add_byte_ptr_rdx[3];
uint8_t adc_byte_ptr_rdx[3];
uint8_t pop_rdx;
uint8_t pop_fq;
uint8_t ret;
} afl_log_code_asm_t;
#pragma pack(pop)
#pragma pack(push, 8)
typedef struct {
afl_log_code_asm_t assembly;
uint64_t current_pc;
} afl_log_code_t;
#pragma pack(pop)
typedef union {
afl_log_code_t data;
uint8_t bytes[0];
} afl_log_code;
static const afl_log_code_asm_t template = {
.push_fq = 0x9c,
.push_rdx = 0x52,
.mov_rdx_rip_off =
{
0x48, 0x8b, 0x15,
/* TBC */
},
.xor_rdx_rdi =
{
0x48,
0x31,
0xfa,
},
.shr_rdi = {0x48, 0xd1, 0xef},
.mov_rip_off_rdi = {0x48, 0x89, 0x3d},
.lea_rdi_rip_off =
{
0x48,
0x8d,
0x3d,
},
.add_rdx_rdi = {0x48, 0x01, 0xfA},
.add_byte_ptr_rdx =
{
0x80,
0x02,
0x01,
},
.adc_byte_ptr_rdx =
{
0x80,
0x12,
0x00,
},
.pop_rdx = 0x5a,
.pop_fq = 0x9d,
.ret = 0xc3};
static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
gboolean instrument_is_coverage_optimize_supported(void) { gboolean instrument_is_coverage_optimize_supported(void) {
@ -138,113 +42,266 @@ static gboolean instrument_coverage_in_range(gssize offset) {
} }
static void instrument_coverate_write_function(GumStalkerOutput *output) { #pragma pack(push, 1)
typedef struct {
guint64 misalign = 0; // cur_location = (block_address >> 4) ^ (block_address << 8);
GumX86Writer *cw = output->writer.x86; // shared_mem[cur_location ^ prev_location]++;
GumAddress code_addr = 0; // prev_location = cur_location >> 1;
afl_log_code code = {0};
/*guint64 instrument_hash_zero = 0;*/
if (current_log_impl == 0 || // => 0x7ffff6cfb086: lea rsp,[rsp-0x80]
!gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) || // 0x7ffff6cfb08b: pushf
!gum_x86_writer_can_branch_directly_between(cw->pc + 128, // 0x7ffff6cfb08c: push rsi
current_log_impl)) { // 0x7ffff6cfb08d: mov rsi,0x228
// 0x7ffff6cfb094: xchg QWORD PTR [rip+0x3136a5],rsi # 0x7ffff700e740
// 0x7ffff6cfb09b: xor rsi,0x451
// 0x7ffff6cfb0a2: add BYTE PTR [rsi+0x10000],0x1
// 0x7ffff6cfb0a9: adc BYTE PTR [rsi+0x10000],0x0
// 0x7ffff6cfb0b0: pop rsi
// 0x7ffff6cfb0b1: popf
// 0x7ffff6cfb0b2: lea rsp,[rsp+0x80]
gconstpointer after_log_impl = cw->code + 1;
gum_x86_writer_put_jmp_near_label(cw, after_log_impl); uint8_t lea_rsp_rsp_sub_rz[5];
uint8_t push_fq;
uint8_t push_rsi;
misalign = (cw->pc & 0x7); uint8_t mov_rsi_curr_loc_shr_1[7];
if (misalign != 0) { uint8_t xchg_rsi_prev_loc_curr_loc[7];
uint8_t xor_rsi_curr_loc[7];
gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign); uint8_t add_rsi_1[7];
uint8_t adc_rsi_0[7];
} uint8_t pop_rsi;
uint8_t pop_fq;
uint8_t lsa_rsp_rsp_add_rz[8];
current_log_impl = cw->pc; } afl_log_code_asm_t;
// gum_x86_writer_put_breakpoint(cw);
code_addr = cw->pc;
code.data.assembly = template; #pragma pack(pop)
code.data.current_pc = instrument_get_offset_hash(0);
gssize current_pc_value1 = typedef union {
GPOINTER_TO_SIZE(&instrument_previous_pc) -
(code_addr + offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
sizeof(code.data.assembly.mov_rdx_rip_off));
gssize patch_offset1 =
offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
sizeof(code.data.assembly.mov_rdx_rip_off) - sizeof(gint);
if (!instrument_coverage_in_range(current_pc_value1)) {
FATAL("Patch out of range (current_pc_value1): 0x%016lX", afl_log_code_asm_t code;
current_pc_value1); uint8_t bytes[0];
} } afl_log_code;
gint *dst_pc_value = (gint *)&code.bytes[patch_offset1]; static const afl_log_code_asm_t template =
*dst_pc_value = (gint)current_pc_value1; {
gssize current_pc_value2 = .lea_rsp_rsp_sub_rz = {0x48, 0x8D, 0x64, 0x24, 0x80},
GPOINTER_TO_SIZE(&instrument_previous_pc) - .push_fq = 0x9c,
(code_addr + offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) + .push_rsi = 0x56,
sizeof(code.data.assembly.mov_rip_off_rdi));
gssize patch_offset2 =
offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
sizeof(code.data.assembly.mov_rip_off_rdi) - sizeof(gint);
if (!instrument_coverage_in_range(current_pc_value2)) { .mov_rsi_curr_loc_shr_1 = {0x48, 0xC7, 0xC6},
.xchg_rsi_prev_loc_curr_loc = {0x48, 0x87, 0x35},
.xor_rsi_curr_loc = {0x48, 0x81, 0xF6},
FATAL("Patch out of range (current_pc_value2): 0x%016lX", .add_rsi_1 = {0x80, 0x86, 0x00, 0x00, 0x00, 0x00, 0x01},
current_pc_value2); .adc_rsi_0 = {0x80, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00},
} .pop_rsi = 0x5E,
.pop_fq = 0x9D,
.lsa_rsp_rsp_add_rz = {0x48, 0x8D, 0xA4, 0x24, 0x80, 0x00, 0x00, 0x00},
dst_pc_value = (gint *)&code.bytes[patch_offset2]; }
*dst_pc_value = (gint)current_pc_value2;
gsize afl_area_ptr_value = ;
GPOINTER_TO_SIZE(__afl_area_ptr) -
(code_addr + offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
sizeof(code.data.assembly.lea_rdi_rip_off));
gssize afl_area_ptr_offset =
offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
sizeof(code.data.assembly.lea_rdi_rip_off) - sizeof(gint);
if (!instrument_coverage_in_range(afl_area_ptr_value)) { static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
gpointer user_data) {
FATAL("Patch out of range (afl_area_ptr_value): 0x%016lX", static GumAddress last_limit = (64ULL << 10);
afl_area_ptr_value); gpointer * address = (gpointer *)user_data;
} if ((details->range->base_address - last_limit) > __afl_map_size) {
gint *dst_afl_area_ptr_value = (gint *)&code.bytes[afl_area_ptr_offset]; *address = GSIZE_TO_POINTER(last_limit);
*dst_afl_area_ptr_value = (gint)afl_area_ptr_value; return FALSE;
gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
gum_x86_writer_put_label(cw, after_log_impl);
} }
if (details->range->base_address > ((2ULL << 20) - __afl_map_size)) {
return FALSE;
}
last_limit = details->range->base_address + details->range->size;
return TRUE;
}
static void instrument_coverage_optimize_map_mmap_anon(gpointer address) {
__afl_area_ptr =
mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
}
}
static void instrument_coverage_optimize_map_mmap(char * shm_file_path,
gpointer address) {
int shm_fd = -1;
if (munmap(__afl_area_ptr, __afl_map_size) != 0) {
FATAL("Failed to unmap previous __afl_area_ptr");
}
__afl_area_ptr = NULL;
#if !defined(__ANDROID__)
shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) { FATAL("shm_open() failed\n"); }
#else
shm_fd = open("/dev/ashmem", O_RDWR);
if (shm_fd == -1) { FATAL("open() failed\n"); }
if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { FATAL("ioctl(ASHMEM_SET_NAME) failed"); }
if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { FATAL("ioctl(ASHMEM_SET_SIZE) failed"); }
#endif
__afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
}
if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); }
}
static void instrument_coverage_optimize_map_shm(guint64 shm_env_val,
gpointer address) {
if (shmdt(__afl_area_ptr) != 0) {
FATAL("Failed to detach previous __afl_area_ptr");
}
__afl_area_ptr = shmat(shm_env_val, address, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map shm __afl_area_ptr: %d", errno);
}
}
void instrument_coverage_optimize_init(void) {
gpointer low_address = NULL;
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low,
&low_address);
OKF("Low address: %p", low_address);
if (low_address == 0 ||
GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) {
FATAL("Invalid low_address: %p", low_address);
}
ranges_print_debug_maps();
char *shm_env = getenv(SHM_ENV_VAR);
OKF("SHM_ENV_VAR: %s", shm_env);
if (shm_env == NULL) {
WARNF("SHM_ENV_VAR not set, using anonymous map for debugging purposes");
instrument_coverage_optimize_map_mmap_anon(low_address);
} else {
guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10);
if (shm_env_val == 0) {
instrument_coverage_optimize_map_mmap(shm_env, low_address);
} else {
instrument_coverage_optimize_map_shm(shm_env_val, low_address);
}
}
OKF("__afl_area_ptr: %p", __afl_area_ptr);
OKF("instrument_previous_pc: %p", &instrument_previous_pc);
} }
void instrument_coverage_optimize(const cs_insn * instr, void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) { GumStalkerOutput *output) {
afl_log_code code = {0};
GumX86Writer *cw = output->writer.x86; GumX86Writer *cw = output->writer.x86;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
instrument_coverate_write_function(output); GumAddress code_addr = 0;
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, // gum_x86_writer_put_breakpoint(cw);
-GUM_RED_ZONE_SIZE); code_addr = cw->pc;
gum_x86_writer_put_push_reg(cw, GUM_REG_RDI); code.code = template;
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, area_offset);
gum_x86_writer_put_call_address(cw, current_log_impl); gssize curr_loc_shr_1_offset =
gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI); offsetof(afl_log_code, code.mov_rsi_curr_loc_shr_1) +
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, sizeof(code.code.mov_rsi_curr_loc_shr_1) - sizeof(guint32);
GUM_RED_ZONE_SIZE);
*((guint32 *)&code.bytes[curr_loc_shr_1_offset]) =
(guint32)(area_offset >> 1);
gssize prev_loc_value =
GPOINTER_TO_SIZE(&instrument_previous_pc) -
(code_addr + offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) +
sizeof(code.code.xchg_rsi_prev_loc_curr_loc));
gssize prev_loc_value_offset =
offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) +
sizeof(code.code.xchg_rsi_prev_loc_curr_loc) - sizeof(gint);
if (!instrument_coverage_in_range(prev_loc_value)) {
FATAL("Patch out of range (current_pc_value1): 0x%016lX", prev_loc_value);
}
*((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_rsi_curr_loc) +
sizeof(code.code.xor_rsi_curr_loc) -
sizeof(guint32);
*((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)(area_offset);
gssize add_rsi_1_offset = offsetof(afl_log_code, code.add_rsi_1) +
sizeof(code.code.add_rsi_1) - sizeof(guint32) - 1;
*((guint32 *)&code.bytes[add_rsi_1_offset]) =
(guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
gssize adc_rsi_0_ffset = offsetof(afl_log_code, code.adc_rsi_0) +
sizeof(code.code.adc_rsi_0) - sizeof(guint32) - 1;
*((guint32 *)&code.bytes[adc_rsi_0_ffset]) =
(guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
} }

View File

@ -83,6 +83,9 @@ void instrument_coverage_optimize(const cs_insn * instr,
} }
void instrument_coverage_optimize_init(void) {
}
void instrument_flush(GumStalkerOutput *output) { void instrument_flush(GumStalkerOutput *output) {
gum_x86_writer_flush(output->writer.x86); gum_x86_writer_flush(output->writer.x86);

View File

@ -549,18 +549,19 @@ static GArray *merge_ranges(GArray *a) {
} }
void ranges_print_debug_maps(void) {
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
}
void ranges_config(void) { void ranges_config(void) {
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; } if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; } if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; }
if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; } if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; }
if (ranges_debug_maps) { if (ranges_debug_maps) { ranges_print_debug_maps(); }
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
NULL);
}
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES"); exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <execinfo.h> #include <execinfo.h>
#include <fcntl.h> #include <fcntl.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <fcntl.h> #include <fcntl.h>
#include <sched.h> #include <sched.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <alloca.h> #include <alloca.h>
#include <errno.h> #include <errno.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <stdarg.h> #include <stdarg.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__ #if defined(__linux__) && !defined(__ANDROID__)
#include <limits.h> #include <limits.h>
#include <stdio.h> #include <stdio.h>

View File

@ -1130,7 +1130,6 @@ void get_core_count(afl_state_t *);
void fix_up_sync(afl_state_t *); void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *); void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *); void check_binary(afl_state_t *, u8 *);
void fix_up_banner(afl_state_t *, u8 *);
void check_if_tty(afl_state_t *); void check_if_tty(afl_state_t *);
void setup_signal_handlers(void); void setup_signal_handlers(void);
void save_cmdline(afl_state_t *, u32, char **); void save_cmdline(afl_state_t *, u32, char **);

View File

@ -3,9 +3,8 @@
## Introduction ## Introduction
This originally is the work of an individual nicknamed laf-intel. This originally is the work of an individual nicknamed laf-intel.
His blog [Circumventing Fuzzing Roadblocks with Compiler Transformations] His blog [Circumventing Fuzzing Roadblocks with Compiler Transformations](https://lafintel.wordpress.com/)
(https://lafintel.wordpress.com/) and gitlab repo [laf-llvm-pass] and gitlab repo [laf-llvm-pass](https://gitlab.com/laf-intel/laf-llvm-pass/)
(https://gitlab.com/laf-intel/laf-llvm-pass/)
describe some code transformations that describe some code transformations that
help AFL++ to enter conditional blocks, where conditions consist of help AFL++ to enter conditional blocks, where conditions consist of
comparisons of large values. comparisons of large values.

View File

@ -2,7 +2,7 @@
(See [../README.md](../README.md) for the general instruction manual.) (See [../README.md](../README.md) for the general instruction manual.)
(See [README.gcc_plugin.md](../README.gcc_plugin.md) for the GCC-based instrumentation.) (See [README.gcc_plugin.md](README.gcc_plugin.md) for the GCC-based instrumentation.)
## 1) Introduction ## 1) Introduction

View File

@ -250,7 +250,7 @@ class ModuleSanitizerCoverage {
Module * Mo = NULL; Module * Mo = NULL;
GlobalVariable * AFLMapPtr = NULL; GlobalVariable * AFLMapPtr = NULL;
Value * MapPtrFixed = NULL; Value * MapPtrFixed = NULL;
FILE * documentFile = NULL; std::ofstream dFile;
size_t found = 0; size_t found = 0;
// afl++ END // afl++ END
@ -446,8 +446,8 @@ bool ModuleSanitizerCoverage::instrumentModule(
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) { if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
if ((documentFile = fopen(ptr, "a")) == NULL) dFile.open(ptr, std::ofstream::out | std::ofstream::app);
WARNF("Cannot access document file %s", ptr); if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
} }
@ -1003,12 +1003,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
instrumentFunction(F, DTCallback, PDTCallback); instrumentFunction(F, DTCallback, PDTCallback);
// afl++ START // afl++ START
if (documentFile) { if (dFile.is_open()) dFile.close();
fclose(documentFile);
documentFile = NULL;
}
if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) { if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) {
@ -1069,7 +1064,6 @@ bool ModuleSanitizerCoverage::instrumentModule(
if (dictionary.size()) { if (dictionary.size()) {
size_t memlen = 0, count = 0, offset = 0; size_t memlen = 0, count = 0, offset = 0;
char * ptr;
// sort and unique the dictionary // sort and unique the dictionary
std::sort(dictionary.begin(), dictionary.end()); std::sort(dictionary.begin(), dictionary.end());
@ -1089,13 +1083,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
if (count) { if (count) {
if ((ptr = (char *)malloc(memlen + count)) == NULL) { auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
fprintf(stderr, "Error: malloc for %lu bytes failed!\n",
memlen + count);
exit(-1);
}
count = 0; count = 0;
@ -1103,8 +1091,8 @@ bool ModuleSanitizerCoverage::instrumentModule(
if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) { if (offset + token.length() < 0xfffff0 && count < MAX_AUTO_EXTRAS) {
ptr[offset++] = (uint8_t)token.length(); ptrhld.get()[offset++] = (uint8_t)token.length();
memcpy(ptr + offset, token.c_str(), token.length()); memcpy(ptrhld.get() + offset, token.c_str(), token.length());
offset += token.length(); offset += token.length();
count++; count++;
@ -1124,10 +1112,10 @@ bool ModuleSanitizerCoverage::instrumentModule(
GlobalVariable *AFLInternalDictionary = new GlobalVariable( GlobalVariable *AFLInternalDictionary = new GlobalVariable(
M, ArrayTy, true, GlobalValue::ExternalLinkage, M, ArrayTy, true, GlobalValue::ExternalLinkage,
ConstantDataArray::get(Ctx, ConstantDataArray::get(Ctx,
*(new ArrayRef<char>((char *)ptr, offset))), *(new ArrayRef<char>(ptrhld.get(), offset))),
"__afl_internal_dictionary"); "__afl_internal_dictionary");
AFLInternalDictionary->setInitializer(ConstantDataArray::get( AFLInternalDictionary->setInitializer(ConstantDataArray::get(
Ctx, *(new ArrayRef<char>((char *)ptr, offset)))); Ctx, *(new ArrayRef<char>(ptrhld.get(), offset))));
AFLInternalDictionary->setConstant(true); AFLInternalDictionary->setConstant(true);
GlobalVariable *AFLDictionary = new GlobalVariable( GlobalVariable *AFLDictionary = new GlobalVariable(
@ -1509,12 +1497,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
// afl++ START // afl++ START
++afl_global_id; ++afl_global_id;
if (documentFile) { if (dFile.is_open()) {
unsigned long long int moduleID = unsigned long long int moduleID =
(((unsigned long long int)(rand() & 0xffffffff)) << 32) | getpid(); (((unsigned long long int)(rand() & 0xffffffff)) << 32) | getpid();
fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%u\n", moduleID, dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str()
F.getName().str().c_str(), afl_global_id); << " edgeID=" << afl_global_id << "\n";
} }

View File

@ -881,8 +881,6 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
Function &F, ArrayRef<Instruction *> IndirCalls) { Function &F, ArrayRef<Instruction *> IndirCalls) {
if (IndirCalls.empty()) return; if (IndirCalls.empty()) return;
assert(Options.TracePC || Options.TracePCGuard ||
Options.Inline8bitCounters /*|| Options.InlineBoolFlag*/);
for (auto I : IndirCalls) { for (auto I : IndirCalls) {
IRBuilder<> IRB(I); IRBuilder<> IRB(I);

View File

@ -66,6 +66,9 @@ namespace {
class AFLdict2filePass : public ModulePass { class AFLdict2filePass : public ModulePass {
std::ofstream of;
void dict2file(u8 *, u32);
public: public:
static char ID; static char ID;
@ -81,7 +84,7 @@ class AFLdict2filePass : public ModulePass {
} // namespace } // namespace
void dict2file(int fd, u8 *mem, u32 len) { void AFLdict2filePass::dict2file(u8 *mem, u32 len) {
u32 i, j, binary = 0; u32 i, j, binary = 0;
char line[MAX_AUTO_EXTRA * 8], tmp[8]; char line[MAX_AUTO_EXTRA * 8], tmp[8];
@ -113,9 +116,8 @@ void dict2file(int fd, u8 *mem, u32 len) {
line[j] = 0; line[j] = 0;
strcat(line, "\"\n"); strcat(line, "\"\n");
if (write(fd, line, strlen(line)) <= 0) of << line;
PFATAL("Could not write to dictionary file"); of.flush();
fsync(fd);
if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line); if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line);
@ -125,7 +127,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
DenseMap<Value *, std::string *> valueMap; DenseMap<Value *, std::string *> valueMap;
char * ptr; char * ptr;
int fd, found = 0; int found = 0;
/* Show a banner */ /* Show a banner */
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
@ -146,8 +148,8 @@ bool AFLdict2filePass::runOnModule(Module &M) {
if (!ptr || *ptr != '/') if (!ptr || *ptr != '/')
FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr); FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr);
if ((fd = open(ptr, O_WRONLY | O_APPEND | O_CREAT | O_DSYNC, 0644)) < 0) of.open(ptr, std::ofstream::out | std::ofstream::app);
PFATAL("Could not open/create %s.", ptr); if (!of.is_open()) PFATAL("Could not open/create %s.", ptr);
/* Instrument all the things! */ /* Instrument all the things! */
@ -264,11 +266,11 @@ bool AFLdict2filePass::runOnModule(Module &M) {
} }
dict2file(fd, (u8 *)&val, len); dict2file((u8 *)&val, len);
found++; found++;
if (val2) { if (val2) {
dict2file(fd, (u8 *)&val2, len); dict2file((u8 *)&val2, len);
found++; found++;
} }
@ -630,7 +632,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
ptr = (char *)thestring.c_str(); ptr = (char *)thestring.c_str();
dict2file(fd, (u8 *)ptr, optLen); dict2file((u8 *)ptr, optLen);
found++; found++;
} }
@ -641,7 +643,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
} }
close(fd); of.close();
/* Say something nice. */ /* Say something nice. */

View File

@ -108,8 +108,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
// std::vector<CallInst *> calls; // std::vector<CallInst *> calls;
DenseMap<Value *, std::string *> valueMap; DenseMap<Value *, std::string *> valueMap;
std::vector<BasicBlock *> BlockList; std::vector<BasicBlock *> BlockList;
std::ofstream dFile;
char * ptr; char * ptr;
FILE * documentFile = NULL;
size_t found = 0; size_t found = 0;
srand((unsigned int)time(NULL)); srand((unsigned int)time(NULL));
@ -137,8 +137,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) { if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
if ((documentFile = fopen(ptr, "a")) == NULL) dFile.open(ptr, std::ofstream::out | std::ofstream::app);
WARNF("Cannot access document file %s", ptr); if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
} }
@ -243,8 +243,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
// the instrument file list check // the instrument file list check
AttributeList Attrs = F.getAttributes(); AttributeList Attrs = F.getAttributes();
#if LLVM_VERSION_MAJOR < 14
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) { if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
#else
if (Attrs.hasFnAttr(StringRef("skipinstrument"))) {
#endif
if (debug) if (debug)
fprintf(stderr, fprintf(stderr,
"DEBUG: Function %s is not in a source file that was specified " "DEBUG: Function %s is not in a source file that was specified "
@ -845,10 +851,11 @@ bool AFLLTOPass::runOnModule(Module &M) {
} }
if (documentFile) { if (dFile.is_open()) {
fprintf(documentFile, "ModuleID=%llu Function=%s edgeID=%u\n", dFile << "ModuleID=" << moduleID
moduleID, F.getName().str().c_str(), afl_global_id); << " Function=" << F.getName().str()
<< " edgeID=" << afl_global_id << "\n";
} }
@ -920,8 +927,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
} }
if (documentFile) fclose(documentFile); if (dFile.is_open()) dFile.close();
documentFile = NULL;
// save highest location ID to global variable // save highest location ID to global variable
// do this after each function to fail faster // do this after each function to fail faster
@ -1016,7 +1022,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (count) { if (count) {
auto ptrhld = std::unique_ptr<char []>(new char[memlen + count]); auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
count = 0; count = 0;

View File

@ -116,10 +116,15 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
auto & Ctx = F.getContext(); auto & Ctx = F.getContext();
AttributeList Attrs = F.getAttributes(); AttributeList Attrs = F.getAttributes();
AttrBuilder NewAttrs; #if LLVM_VERSION_MAJOR < 14
AttrBuilder NewAttrs;
NewAttrs.addAttribute("skipinstrument"); NewAttrs.addAttribute("skipinstrument");
F.setAttributes( F.setAttributes(
Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs)); Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
#else
AttributeList NewAttrs = Attrs.addFnAttribute(Ctx, "skipinstrument");
F.setAttributes(NewAttrs);
#endif
} }

View File

@ -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 /* dependent on the cmp of the high parts go to the end or go on with
* the comparison */ * the comparison */
auto term = bb->getTerminator(); auto term = bb->getTerminator();
BranchInst *br = nullptr;
if (pred == CmpInst::ICMP_EQ) { 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 { } else {
/* CmpInst::ICMP_NE */ // CmpInst::ICMP_NE
br = BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb); BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb);
} }

View File

@ -610,12 +610,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!time_ms) { if (!time_ms) {
kill(fsrv->fsrv_pid, fsrv->kill_signal); if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); }
} else if (time_ms > fsrv->init_tmout) { } else if (time_ms > fsrv->init_tmout) {
fsrv->last_run_timed_out = 1; fsrv->last_run_timed_out = 1;
kill(fsrv->fsrv_pid, fsrv->kill_signal); if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); }
} else { } else {
@ -1248,7 +1248,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* If there was no response from forkserver after timeout seconds, /* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */ we kill the child. The forkserver should inform us afterwards */
kill(fsrv->child_pid, fsrv->kill_signal); if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
fsrv->last_run_timed_out = 1; fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; } if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; }

View File

@ -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. */ /* Check if we're on TTY. */
void check_if_tty(afl_state_t *afl) { void check_if_tty(afl_state_t *afl) {

View File

@ -291,8 +291,6 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 handicap, u8 from_queue) { u32 handicap, u8 from_queue) {
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0, u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0,
first_run = (q->exec_cksum == 0); first_run = (q->exec_cksum == 0);
u64 start_us, stop_us, diff_us; u64 start_us, stop_us, diff_us;
@ -300,6 +298,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 use_tmout = afl->fsrv.exec_tmout; u32 use_tmout = afl->fsrv.exec_tmout;
u8 *old_sn = afl->stage_name; u8 *old_sn = afl->stage_name;
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
/* Be a bit more generous about timeouts when resuming sessions, or when /* Be a bit more generous about timeouts when resuming sessions, or when
trying to calibrate already-added finds. This helps avoid trouble due trying to calibrate already-added finds. This helps avoid trouble due
to intermittent latency. */ to intermittent latency. */
@ -343,6 +343,32 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
} }
/* we need a dummy run if this is LTO + cmplog */
if (unlikely(afl->shm.cmplog_mode)) {
write_to_testcase(afl, use_mem, q->len);
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
if (!afl->non_instrumented_mode && !afl->stage_cur &&
!count_bytes(afl, afl->fsrv.trace_bits)) {
fault = FSRV_RUN_NOINST;
goto abort_calibration;
}
#ifdef INTROSPECTION
if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
#endif
}
if (q->exec_cksum) { if (q->exec_cksum) {
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);

View File

@ -441,9 +441,10 @@ void show_stats(afl_state_t *afl) {
u64 cur_ms; u64 cur_ms;
u32 t_bytes, t_bits; u32 t_bytes, t_bits;
u32 banner_len, banner_pad; static u8 banner[128];
u8 tmp[256]; u32 banner_len, banner_pad;
u8 time_tmp[64]; u8 tmp[256];
u8 time_tmp[64];
u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX]; u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
#define IB(i) (val_buf[(i)]) #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. */ /* Let's start by drawing a centered banner. */
if (unlikely(!banner[0])) {
banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) + char *si = "";
strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5; if (afl->sync_id) { si = afl->sync_id; }
banner_pad = (79 - banner_len) / 2; memset(banner, 0, sizeof(banner));
memset(tmp, ' ', banner_pad); banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
strlen(afl->power_name) + 4 + 6;
#ifdef HAVE_AFFINITY if (strlen(afl->use_banner) + banner_len > 75) {
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 */
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... */ /* "Handy" shortcuts for drawing boxes... */

View File

@ -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)) { 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 (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) { if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
WARNF(cLRD WARNF(cLRD
@ -1486,9 +1498,6 @@ int main(int argc, char **argv_orig, char **envp) {
} }
save_cmdline(afl, argc, argv); save_cmdline(afl, argc, argv);
fix_up_banner(afl, argv[optind]);
check_if_tty(afl); check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }

View File

@ -242,9 +242,14 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
if (cmin_mode && if (cmin_mode &&
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) { (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
// create empty file to prevent error messages in afl-cmin if (strcmp(outfile, "-")) {
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
close(fd); // 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; return ret;
} }

View File

@ -1 +1 @@
1c47d1ebc7e904ad4efc1370f23e269fb9ac3f93 d4915053d477dd827b3fe4b494173d3fbf9f456e

View File

@ -12,11 +12,11 @@ use std::{
use unicornafl::{ use unicornafl::{
unicorn_const::{uc_error, Arch, Mode, Permission}, unicorn_const::{uc_error, Arch, Mode, Permission},
RegisterX86::{self, *}, RegisterX86::*,
Unicorn, UnicornHandle, Unicorn,
}; };
const BINARY: &str = &"../target"; const BINARY: &str = "../target";
// Memory map for the code to be tested // Memory map for the code to be tested
// Arbitrary address where code to test will be loaded // Arbitrary address where code to test will be loaded
@ -47,7 +47,7 @@ fn read_file(filename: &str) -> Result<Vec<u8>, io::Error> {
fn parse_locs(loc_name: &str) -> Result<Vec<u64>, io::Error> { fn parse_locs(loc_name: &str) -> Result<Vec<u64>, io::Error> {
let contents = &read_file(&format!("../target.offsets.{}", loc_name))?; let contents = &read_file(&format!("../target.offsets.{}", loc_name))?;
//println!("Read: {:?}", contents); //println!("Read: {:?}", contents);
Ok(str_from_u8_unchecked(&contents) Ok(str_from_u8_unchecked(contents)
.split('\n') .split('\n')
.map(|x| { .map(|x| {
//println!("Trying to convert {}", &x[2..]); //println!("Trying to convert {}", &x[2..]);
@ -87,8 +87,7 @@ fn main() {
} }
fn fuzz(input_file: &str) -> Result<(), uc_error> { fn fuzz(input_file: &str) -> Result<(), uc_error> {
let mut unicorn = Unicorn::new(Arch::X86, Mode::MODE_64, 0)?; let mut uc = Unicorn::new(Arch::X86, Mode::MODE_64, 0)?;
let mut uc: UnicornHandle<'_, _> = unicorn.borrow();
let binary = let binary =
read_file(BINARY).unwrap_or_else(|_| panic!("Could not read modem image: {}", BINARY)); read_file(BINARY).unwrap_or_else(|_| panic!("Could not read modem image: {}", BINARY));
@ -105,7 +104,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
// Set the program counter to the start of the code // Set the program counter to the start of the code
let main_locs = parse_locs("main").unwrap(); let main_locs = parse_locs("main").unwrap();
//println!("Entry Point: {:x}", main_locs[0]); //println!("Entry Point: {:x}", main_locs[0]);
uc.reg_write(RegisterX86::RIP as i32, main_locs[0])?; uc.reg_write(RIP, main_locs[0])?;
// Setup the stack. // Setup the stack.
uc.mem_map( uc.mem_map(
@ -114,14 +113,14 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
Permission::READ | Permission::WRITE, Permission::READ | Permission::WRITE,
)?; )?;
// Setup the stack pointer, but allocate two pointers for the pointers to input. // Setup the stack pointer, but allocate two pointers for the pointers to input.
uc.reg_write(RSP as i32, STACK_ADDRESS + STACK_SIZE - 16)?; uc.reg_write(RSP, STACK_ADDRESS + STACK_SIZE - 16)?;
// Setup our input space, and push the pointer to it in the function params // Setup our input space, and push the pointer to it in the function params
uc.mem_map(INPUT_ADDRESS, INPUT_MAX as usize, Permission::READ)?; uc.mem_map(INPUT_ADDRESS, INPUT_MAX as usize, Permission::READ)?;
// We have argc = 2 // We have argc = 2
uc.reg_write(RDI as i32, 2)?; uc.reg_write(RDI, 2)?;
// RSI points to our little 2 QWORD space at the beginning of the stack... // RSI points to our little 2 QWORD space at the beginning of the stack...
uc.reg_write(RSI as i32, STACK_ADDRESS + STACK_SIZE - 16)?; uc.reg_write(RSI, STACK_ADDRESS + STACK_SIZE - 16)?;
// ... which points to the Input. Write the ptr to mem in little endian. // ... which points to the Input. Write the ptr to mem in little endian.
uc.mem_write( uc.mem_write(
STACK_ADDRESS + STACK_SIZE - 16, STACK_ADDRESS + STACK_SIZE - 16,
@ -133,13 +132,13 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
let already_allocated_malloc = already_allocated.clone(); let already_allocated_malloc = already_allocated.clone();
// We use a very simple malloc/free stub here, // We use a very simple malloc/free stub here,
// that only works for exactly one allocation at a time. // that only works for exactly one allocation at a time.
let hook_malloc = move |mut uc: UnicornHandle<'_, _>, addr: u64, size: u32| { let hook_malloc = move |uc: &mut Unicorn<'_, _>, addr: u64, size: u32| {
if already_allocated_malloc.get() { if already_allocated_malloc.get() {
println!("Double malloc, not supported right now!"); println!("Double malloc, not supported right now!");
abort(); abort();
} }
// read the first param // read the first param
let malloc_size = uc.reg_read(RDI as i32).unwrap(); let malloc_size = uc.reg_read(RDI).unwrap();
if malloc_size > HEAP_SIZE_MAX { if malloc_size > HEAP_SIZE_MAX {
println!( println!(
"Tried to allocate {} bytes, but we may only allocate up to {}", "Tried to allocate {} bytes, but we may only allocate up to {}",
@ -147,20 +146,20 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
); );
abort(); abort();
} }
uc.reg_write(RAX as i32, HEAP_ADDRESS).unwrap(); uc.reg_write(RAX, HEAP_ADDRESS).unwrap();
uc.reg_write(RIP as i32, addr + size as u64).unwrap(); uc.reg_write(RIP, addr + size as u64).unwrap();
already_allocated_malloc.set(true); already_allocated_malloc.set(true);
}; };
let already_allocated_free = already_allocated; let already_allocated_free = already_allocated;
// No real free, just set the "used"-flag to false. // No real free, just set the "used"-flag to false.
let hook_free = move |mut uc: UnicornHandle<'_, _>, addr, size| { let hook_free = move |uc: &mut Unicorn<'_, _>, addr, size| {
if already_allocated_free.get() { if already_allocated_free.get() {
println!("Double free detected. Real bug?"); println!("Double free detected. Real bug?");
abort(); abort();
} }
// read the first param // read the first param
let free_ptr = uc.reg_read(RDI as i32).unwrap(); let free_ptr = uc.reg_read(RDI).unwrap();
if free_ptr != HEAP_ADDRESS { if free_ptr != HEAP_ADDRESS {
println!( println!(
"Tried to free wrong mem region {:x} at code loc {:x}", "Tried to free wrong mem region {:x} at code loc {:x}",
@ -168,7 +167,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
); );
abort(); abort();
} }
uc.reg_write(RIP as i32, addr + size as u64).unwrap(); uc.reg_write(RIP, addr + size as u64).unwrap();
already_allocated_free.set(false); already_allocated_free.set(false);
}; };
@ -177,8 +176,8 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
*/ */
// This is a fancy print function that we're just going to skip for fuzzing. // This is a fancy print function that we're just going to skip for fuzzing.
let hook_magicfn = move |mut uc: UnicornHandle<'_, _>, addr, size| { let hook_magicfn = move |uc: &mut Unicorn<'_, _>, addr, size| {
uc.reg_write(RIP as i32, addr + size as u64).unwrap(); uc.reg_write(RIP, addr + size as u64).unwrap();
}; };
for addr in parse_locs("malloc").unwrap() { for addr in parse_locs("malloc").unwrap() {
@ -195,7 +194,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
} }
let place_input_callback = let place_input_callback =
|uc: &mut UnicornHandle<'_, _>, afl_input: &mut [u8], _persistent_round| { |uc: &mut Unicorn<'_, _>, afl_input: &mut [u8], _persistent_round| {
// apply constraints to the mutated input // apply constraints to the mutated input
if afl_input.len() > INPUT_MAX as usize { if afl_input.len() > INPUT_MAX as usize {
//println!("Skipping testcase with leng {}", afl_input.len()); //println!("Skipping testcase with leng {}", afl_input.len());
@ -209,9 +208,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
// return true if the last run should be counted as crash // return true if the last run should be counted as crash
let crash_validation_callback = let crash_validation_callback =
|_uc: &mut UnicornHandle<'_, _>, result, _input: &[u8], _persistent_round| { |_uc: &mut Unicorn<'_, _>, result, _input: &[u8], _persistent_round| result != uc_error::OK;
result != uc_error::OK
};
let end_addrs = parse_locs("main_ends").unwrap(); let end_addrs = parse_locs("main_ends").unwrap();

View File

@ -6,6 +6,6 @@ for sending input to stdin which the target binary will think is coming from
a network socket. a network socket.
This is desock_dup.c from the amazing preeny project 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 It is packaged in AFL++ to have it at hand if needed