mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-08 00:01:33 +00:00
commit
f5535e348d
110
README.md
110
README.md
@ -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 changes in AFL++](docs/important_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.
|
||||||
|
|
||||||
|
@ -17,14 +17,17 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
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
|
- fix stability issue with LTO and cmplog
|
||||||
|
- better banner
|
||||||
- frida_mode: David Carlier added Android support :)
|
- 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:
|
||||||
for more speed. thanks to dloffre-snl for reporting!
|
- 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
|
- Prevent accidently killing non-afl/fuzz services when aborting
|
||||||
afl-showmap and other tools.
|
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
|
||||||
|
@ -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
|
# 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 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 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
|
git clone https://github.com/AFLplusplus/AFLplusplus
|
||||||
cd AFLplusplus
|
cd AFLplusplus
|
||||||
make distrib
|
make distrib
|
||||||
|
@ -96,12 +96,22 @@
|
|||||||
It is slower than AFL FRIDA (see above).
|
It is slower than AFL FRIDA (see above).
|
||||||
|
|
||||||
|
|
||||||
|
## ZAFL
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
## DYNINST
|
## DYNINST
|
||||||
|
|
||||||
Dyninst is a binary instrumentation framework similar to Pintool and
|
Dyninst is a binary instrumentation framework similar to Pintool and
|
||||||
Dynamorio (see far below). However whereas Pintool and Dynamorio work at
|
Dynamorio (see far below). However whereas Pintool and Dynamorio work at
|
||||||
runtime, dyninst instruments the target at load time, and then let it run -
|
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,
|
This is great for some things, e.g. fuzzing, and not so effective for others,
|
||||||
e.g. malware analysis.
|
e.g. malware analysis.
|
||||||
|
|
||||||
@ -116,13 +126,10 @@
|
|||||||
The speed decrease is about 15-35%, depending on the optimization options
|
The speed decrease is about 15-35%, depending on the optimization options
|
||||||
used with afl-dyninst.
|
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)
|
[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
|
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++
|
with position independant code (PIC/PIE) and does not use most of the C++
|
||||||
@ -131,7 +138,6 @@
|
|||||||
|
|
||||||
It is at about 80-85% performance.
|
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)
|
[https://github.com/HexHive/retrowrite](https://github.com/HexHive/retrowrite)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 changes in AFL++](important_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).
|
@ -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).
|
||||||
|
@ -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 [tools.md](tools.md).
|
(some might be deprecated or unsupported), see [tools.md](tools.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
|
To help with this problem, afl-fuzz offers a simple way to synchronize test
|
||||||
cases on the fly.
|
cases on the fly.
|
||||||
|
|
||||||
Note that AFL++ has AFLfast's power schedules implemented.
|
It is a good idea to use different power schedules if you run several instances
|
||||||
It is therefore a good idea to use different power schedules if you run
|
in parallel (`-p` option).
|
||||||
several instances in parallel. See [power_schedules.md](power_schedules.md)
|
|
||||||
|
|
||||||
Alternatively running other AFL spinoffs in parallel can be of value,
|
Alternatively running other AFL spinoffs in parallel can be of value,
|
||||||
e.g. Angora (https://github.com/AngoraFuzzer/Angora/)
|
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
|
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
|
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
|
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:
|
Run the first one ("main node", -M) like this:
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ file name.
|
|||||||
|
|
||||||
There is support for parallelizing the deterministic checks.
|
There is support for parallelizing the deterministic checks.
|
||||||
This is only needed where
|
This is only needed where
|
||||||
|
|
||||||
1. many new paths are found fast over a long time and it looks unlikely that
|
1. many new paths are found fast over a long time and it looks unlikely that
|
||||||
main node will ever catch up, and
|
main node will ever catch up, and
|
||||||
2. deterministic fuzzing is actively helping path discovery (you can see this
|
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
|
- 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
|
run them all with -S, and just designate a single process somewhere within
|
||||||
the fleet to run with -M.
|
the fleet to run with -M.
|
||||||
|
|
||||||
- Syncing is only necessary for the main nodes on a system. It is possible
|
- 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
|
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
|
which secondary took over the temporary role to be the main node. Look for
|
||||||
|
@ -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 [technical_details.md](technical_details.md).
|
near the end of [technical_details.md](technical_details.md).
|
@ -78,6 +78,9 @@ endif
|
|||||||
|
|
||||||
ifeq "$(shell uname)" "Linux"
|
ifeq "$(shell uname)" "Linux"
|
||||||
OS:=linux
|
OS:=linux
|
||||||
|
ifneq "$(findstring musl, $(shell ldd --version 2>&1 | head -n 1))" ""
|
||||||
|
CFLAGS+= -D__MUSL__
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
||||||
|
@ -288,6 +288,12 @@ ucomisd 2 ( 0.86%)
|
|||||||
* `AFL_FRIDA_STATS_INTERVAL` - The maximum frequency to output statistics
|
* `AFL_FRIDA_STATS_INTERVAL` - The maximum frequency to output statistics
|
||||||
information. Stats will be written whenever they are updated if the given
|
information. Stats will be written whenever they are updated if the given
|
||||||
interval has elapsed since last time they were written.
|
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
|
## FASAN - Frida Address Sanitizer Mode
|
||||||
Frida mode also supports FASAN. The design of this is actually quite simple and
|
Frida mode also supports FASAN. The design of this is actually quite simple and
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
js_api_set_stats_interval;
|
js_api_set_stats_interval;
|
||||||
js_api_set_stderr;
|
js_api_set_stderr;
|
||||||
js_api_set_stdout;
|
js_api_set_stdout;
|
||||||
|
js_api_set_traceable;
|
||||||
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "frida-gumjs.h"
|
#include "frida-gumjs.h"
|
||||||
|
|
||||||
extern guint64 entry_point;
|
extern guint64 entry_point;
|
||||||
|
extern gboolean traceable;
|
||||||
extern gboolean entry_compiled;
|
extern gboolean entry_compiled;
|
||||||
extern gboolean entry_run;
|
extern gboolean entry_run;
|
||||||
|
|
||||||
@ -15,5 +16,7 @@ void entry_start(void);
|
|||||||
|
|
||||||
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output);
|
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output);
|
||||||
|
|
||||||
|
void entry_on_fork(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#if defined(__linux__) && !defined(__ANDROID__)
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "frida-gumjs.h"
|
#include "frida-gumjs.h"
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -16,6 +20,7 @@
|
|||||||
extern void __afl_manual_init();
|
extern void __afl_manual_init();
|
||||||
|
|
||||||
guint64 entry_point = 0;
|
guint64 entry_point = 0;
|
||||||
|
gboolean traceable = FALSE;
|
||||||
gboolean entry_compiled = FALSE;
|
gboolean entry_compiled = FALSE;
|
||||||
gboolean entry_run = FALSE;
|
gboolean entry_run = FALSE;
|
||||||
|
|
||||||
@ -26,21 +31,48 @@ static void entry_launch(void) {
|
|||||||
|
|
||||||
/* Child here */
|
/* Child here */
|
||||||
entry_run = TRUE;
|
entry_run = TRUE;
|
||||||
|
entry_on_fork();
|
||||||
instrument_on_fork();
|
instrument_on_fork();
|
||||||
seccomp_on_fork();
|
seccomp_on_fork();
|
||||||
stats_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 (traceable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void entry_config(void) {
|
void entry_config(void) {
|
||||||
|
|
||||||
entry_point = util_read_address("AFL_ENTRYPOINT");
|
entry_point = util_read_address("AFL_ENTRYPOINT");
|
||||||
|
if (getenv("AFL_FRIDA_TRACEABLE") != NULL) { traceable = TRUE; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void entry_init(void) {
|
void entry_init(void) {
|
||||||
|
|
||||||
OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
|
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); }
|
if (dlopen(NULL, RTLD_NOW) == NULL) { FATAL("Failed to dlopen: %d", errno); }
|
||||||
|
|
||||||
|
@ -243,6 +243,12 @@ class Afl {
|
|||||||
const buf = Memory.allocUtf8String(file);
|
const buf = Memory.allocUtf8String(file);
|
||||||
Afl.jsApiSetStdOut(buf);
|
Afl.jsApiSetStdOut(buf);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* See `AFL_FRIDA_TRACEABLE`.
|
||||||
|
*/
|
||||||
|
static setTraceable() {
|
||||||
|
Afl.jsApiSetTraceable();
|
||||||
|
}
|
||||||
static jsApiGetFunction(name, retType, argTypes) {
|
static jsApiGetFunction(name, retType, argTypes) {
|
||||||
const addr = Afl.module.getExportByName(name);
|
const addr = Afl.module.getExportByName(name);
|
||||||
return new NativeFunction(addr, retType, argTypes);
|
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.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]);
|
||||||
Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
|
Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
|
||||||
Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "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(
|
Afl.jsApiWrite = new NativeFunction(
|
||||||
/* tslint:disable-next-line:no-null-keyword */
|
/* tslint:disable-next-line:no-null-keyword */
|
||||||
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach-o/dyld_images.h>
|
#include <mach-o/dyld_images.h>
|
||||||
|
#include <crt_externs.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/personality.h>
|
#include <sys/personality.h>
|
||||||
@ -90,6 +91,7 @@ static void embedded_init(void) {
|
|||||||
|
|
||||||
static void afl_print_cmdline(void) {
|
static void afl_print_cmdline(void) {
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
char * buffer = g_malloc0(PROC_MAX);
|
char * buffer = g_malloc0(PROC_MAX);
|
||||||
gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid());
|
gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid());
|
||||||
int fd = open(fname, O_RDONLY);
|
int fd = open(fname, O_RDONLY);
|
||||||
@ -123,6 +125,17 @@ static void afl_print_cmdline(void) {
|
|||||||
close(fd);
|
close(fd);
|
||||||
g_free(fname);
|
g_free(fname);
|
||||||
g_free(buffer);
|
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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#if defined(__linux__) && !defined(__ANDROID__)
|
#if defined(__linux__) && !defined(__ANDROID__)
|
||||||
|
|
||||||
|
#if !defined(__MUSL__)
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "seccomp.h"
|
#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[0], req->data.args[1], req->data.args[2],
|
||||||
req->data.args[3], req->data.args[4], req->data.args[5]);
|
req->data.args[3], req->data.args[4], req->data.args[5]);
|
||||||
|
|
||||||
|
#if !defined(__MUSL__)
|
||||||
seccomp_print("FRAMES: (%u)\n", frames->len);
|
seccomp_print("FRAMES: (%u)\n", frames->len);
|
||||||
char **syms = backtrace_symbols(frames->items, frames->len);
|
char **syms = backtrace_symbols(frames->items, frames->len);
|
||||||
if (syms == NULL) { FATAL("Failed to get symbols"); }
|
if (syms == NULL) { FATAL("Failed to get symbols"); }
|
||||||
@ -49,6 +52,23 @@ static void seccomp_callback_filter(struct seccomp_notif * req,
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(syms);
|
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;
|
resp->error = 0;
|
||||||
resp->val = 0;
|
resp->val = 0;
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#if !defined(__MUSL__)
|
||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
|
#endif
|
||||||
#include <linux/filter.h>
|
#include <linux/filter.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
@ -284,6 +284,13 @@ class Afl {
|
|||||||
Afl.jsApiSetStdOut(buf);
|
Afl.jsApiSetStdOut(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See `AFL_FRIDA_TRACEABLE`.
|
||||||
|
*/
|
||||||
|
public static setTraceable(): void {
|
||||||
|
Afl.jsApiSetTraceable();
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction(
|
private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction(
|
||||||
"js_api_add_exclude_range",
|
"js_api_add_exclude_range",
|
||||||
"void",
|
"void",
|
||||||
@ -431,6 +438,11 @@ class Afl {
|
|||||||
"void",
|
"void",
|
||||||
["pointer"]);
|
["pointer"]);
|
||||||
|
|
||||||
|
private static readonly jsApiSetTraceable = Afl.jsApiGetFunction(
|
||||||
|
"js_api_set_traceable",
|
||||||
|
"void",
|
||||||
|
[]);
|
||||||
|
|
||||||
private static readonly jsApiWrite = new NativeFunction(
|
private static readonly jsApiWrite = new NativeFunction(
|
||||||
/* tslint:disable-next-line:no-null-keyword */
|
/* tslint:disable-next-line:no-null-keyword */
|
||||||
Module.getExportByName(null, "write"),
|
Module.getExportByName(null, "write"),
|
||||||
|
@ -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 **);
|
||||||
|
@ -76,6 +76,7 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_FRIDA_PERSISTENT_RET",
|
"AFL_FRIDA_PERSISTENT_RET",
|
||||||
"AFL_FRIDA_STATS_FILE",
|
"AFL_FRIDA_STATS_FILE",
|
||||||
"AFL_FRIDA_STATS_INTERVAL",
|
"AFL_FRIDA_STATS_INTERVAL",
|
||||||
|
"AFL_FRIDA_TRACEABLE",
|
||||||
"AFL_FUZZER_ARGS", // oss-fuzz
|
"AFL_FUZZER_ARGS", // oss-fuzz
|
||||||
"AFL_GDB",
|
"AFL_GDB",
|
||||||
"AFL_GCC_ALLOWLIST",
|
"AFL_GCC_ALLOWLIST",
|
||||||
|
@ -235,6 +235,8 @@ class ModuleSanitizerCoverage {
|
|||||||
uint32_t autodictionary = 1;
|
uint32_t autodictionary = 1;
|
||||||
uint32_t inst = 0;
|
uint32_t inst = 0;
|
||||||
uint32_t afl_global_id = 0;
|
uint32_t afl_global_id = 0;
|
||||||
|
uint32_t unhandled = 0;
|
||||||
|
uint32_t select_cnt = 0;
|
||||||
uint64_t map_addr = 0;
|
uint64_t map_addr = 0;
|
||||||
const char * skip_nozero = NULL;
|
const char * skip_nozero = NULL;
|
||||||
const char * use_threadsafe_counters = nullptr;
|
const char * use_threadsafe_counters = nullptr;
|
||||||
@ -447,8 +449,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
||||||
|
|
||||||
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||||
if (dFile.is_open())
|
if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
|
||||||
WARNF("Cannot access document file %s", ptr);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1041,8 +1042,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
M, Int64Tyi, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr");
|
M, Int64Tyi, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr");
|
||||||
ConstantInt *MapAddr = ConstantInt::get(Int64Tyi, map_addr);
|
ConstantInt *MapAddr = ConstantInt::get(Int64Tyi, map_addr);
|
||||||
StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed);
|
StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed);
|
||||||
StoreMapAddr->setMetadata(M.getMDKindID("nosanitize"),
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreMapAddr);
|
||||||
MDNode::get(Ctx, None));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,15 +1050,14 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
|
|
||||||
uint32_t write_loc = afl_global_id;
|
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 =
|
GlobalVariable *AFLFinalLoc =
|
||||||
new GlobalVariable(M, Int32Tyi, true, GlobalValue::ExternalLinkage, 0,
|
new GlobalVariable(M, Int32Tyi, true, GlobalValue::ExternalLinkage, 0,
|
||||||
"__afl_final_loc");
|
"__afl_final_loc");
|
||||||
ConstantInt *const_loc = ConstantInt::get(Int32Tyi, write_loc);
|
ConstantInt *const_loc = ConstantInt::get(Int32Tyi, write_loc);
|
||||||
StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
|
StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
|
||||||
StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"),
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreFinalLoc);
|
||||||
MDNode::get(Ctx, None));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1083,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -1106,8 +1105,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
0, "__afl_dictionary_len");
|
0, "__afl_dictionary_len");
|
||||||
ConstantInt *const_len = ConstantInt::get(Int32Tyi, offset);
|
ConstantInt *const_len = ConstantInt::get(Int32Tyi, offset);
|
||||||
StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen);
|
StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen);
|
||||||
StoreDictLen->setMetadata(M.getMDKindID("nosanitize"),
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDictLen);
|
||||||
MDNode::get(Ctx, None));
|
|
||||||
|
|
||||||
ArrayType *ArrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
|
ArrayType *ArrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
|
||||||
GlobalVariable *AFLInternalDictionary = new GlobalVariable(
|
GlobalVariable *AFLInternalDictionary = new GlobalVariable(
|
||||||
@ -1127,8 +1125,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
Value *AFLDictPtr =
|
Value *AFLDictPtr =
|
||||||
IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Tyi, 0));
|
IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Tyi, 0));
|
||||||
StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary);
|
StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary);
|
||||||
StoreDict->setMetadata(M.getMDKindID("nosanitize"),
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDict);
|
||||||
MDNode::get(Ctx, None));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1151,9 +1148,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||||
OKF("Instrumented %u locations with no collisions (on average %llu "
|
OKF("Instrumented %u locations (%u selects) without collisions (%llu "
|
||||||
"collisions would be in afl-gcc/vanilla AFL) (%s mode).",
|
"collisions have been avoided) (%s mode).",
|
||||||
inst, calculateCollisions(inst), modeline);
|
inst, select_cnt, calculateCollisions(inst), modeline);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1275,6 +1272,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
|||||||
const DominatorTree * DT = DTCallback(F);
|
const DominatorTree * DT = DTCallback(F);
|
||||||
const PostDominatorTree *PDT = PDTCallback(F);
|
const PostDominatorTree *PDT = PDTCallback(F);
|
||||||
bool IsLeafFunc = true;
|
bool IsLeafFunc = true;
|
||||||
|
uint32_t skip_next = 0, local_selects = 0;
|
||||||
|
|
||||||
for (auto &BB : F) {
|
for (auto &BB : F) {
|
||||||
|
|
||||||
@ -1292,6 +1290,148 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
|||||||
|
|
||||||
Value *val = ConstantInt::get(Int32Ty, ++afl_global_id);
|
Value *val = ConstantInt::get(Int32Ty, ++afl_global_id);
|
||||||
callInst->setOperand(1, val);
|
callInst->setOperand(1, val);
|
||||||
|
++inst;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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<SelectInst>(&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);
|
||||||
|
skip_next = 1;
|
||||||
|
inst += 2;
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR > 13
|
||||||
|
if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
||||||
|
|
||||||
|
FixedVectorType *tt = dyn_cast<FixedVectorType>(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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result = IRB.CreateSelect(condition, x, y);
|
||||||
|
skip_next = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
unhandled++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
local_selects++;
|
||||||
|
uint32_t vector_cur = 0;
|
||||||
|
/* Load SHM pointer */
|
||||||
|
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
|
||||||
|
|
||||||
|
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);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nosan = IRB.CreateStore(Incr, MapPtrIdx);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vector_cnt || vector_cnt == vector_cur) { break; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_next = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
skip_next = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1502,7 +1642,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
|
|
||||||
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();
|
||||||
dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str() << " edgeID=" << afl_global_id << "\n";
|
dFile << "ModuleID=" << moduleID << " Function=" << F.getName().str()
|
||||||
|
<< " edgeID=" << afl_global_id << "\n";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1521,8 +1662,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
||||||
MapPtr->setMetadata(Mo->getMDKindID("nosanitize"),
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
|
||||||
MDNode::get(*Ct, None));
|
|
||||||
MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
|
MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1539,8 +1679,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||||
Counter->setMetadata(Mo->getMDKindID("nosanitize"),
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
|
||||||
MDNode::get(*Ct, None));
|
|
||||||
|
|
||||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||||
|
|
||||||
@ -1552,8 +1691,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRB.CreateStore(Incr, MapPtrIdx)
|
auto nosan = IRB.CreateStore(Incr, MapPtrIdx);
|
||||||
->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ class ModuleSanitizerCoverage {
|
|||||||
|
|
||||||
SanitizerCoverageOptions Options;
|
SanitizerCoverageOptions Options;
|
||||||
|
|
||||||
uint32_t instr = 0;
|
uint32_t instr = 0, selects = 0, unhandled = 0;
|
||||||
GlobalVariable *AFLMapPtr = NULL;
|
GlobalVariable *AFLMapPtr = NULL;
|
||||||
ConstantInt * One = NULL;
|
ConstantInt * One = NULL;
|
||||||
ConstantInt * Zero = NULL;
|
ConstantInt * Zero = NULL;
|
||||||
@ -553,8 +553,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
|||||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||||
OKF("Instrumented %u locations with no collisions (%s mode).", instr,
|
OKF("Instrumented %u locations with no collisions (%s mode) of which are "
|
||||||
modeline);
|
"%u handled and %u unhandled selects.",
|
||||||
|
instr, modeline, selects, unhandled);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -833,9 +834,8 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
|
|||||||
ArrayRef<BasicBlock *> AllBlocks,
|
ArrayRef<BasicBlock *> AllBlocks,
|
||||||
bool IsLeafFunc) {
|
bool IsLeafFunc) {
|
||||||
|
|
||||||
if (AllBlocks.empty()) return false;
|
uint32_t cnt_cov = 0, cnt_sel = 0, cnt_sel_inc = 0;
|
||||||
|
|
||||||
uint32_t special = 0;
|
|
||||||
for (auto &BB : F) {
|
for (auto &BB : F) {
|
||||||
|
|
||||||
for (auto &IN : BB) {
|
for (auto &IN : BB) {
|
||||||
@ -850,9 +850,37 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
|
|||||||
StringRef FuncName = Callee->getName();
|
StringRef FuncName = Callee->getName();
|
||||||
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
|
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
|
||||||
|
|
||||||
uint32_t id = 1 + instr + (uint32_t)AllBlocks.size() + special++;
|
cnt_cov++;
|
||||||
Value * val = ConstantInt::get(Int32Ty, id);
|
|
||||||
callInst->setOperand(1, val);
|
}
|
||||||
|
|
||||||
|
SelectInst *selectInst = nullptr;
|
||||||
|
|
||||||
|
if ((selectInst = dyn_cast<SelectInst>(&IN))) {
|
||||||
|
|
||||||
|
Value *c = selectInst->getCondition();
|
||||||
|
auto t = c->getType();
|
||||||
|
if (t->getTypeID() == llvm::Type::IntegerTyID) {
|
||||||
|
|
||||||
|
cnt_sel++;
|
||||||
|
cnt_sel_inc += 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LLVM__MAJOR > 11
|
||||||
|
else if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
||||||
|
|
||||||
|
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
|
||||||
|
if (tt) {
|
||||||
|
|
||||||
|
cnt_sel++;
|
||||||
|
cnt_sel_inc += tt->getElementCount().getFixedValue();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,11 +888,256 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CreateFunctionLocalArrays(F, AllBlocks, special);
|
/* Create PCGUARD array */
|
||||||
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
|
CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel_inc);
|
||||||
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
|
selects += cnt_sel;
|
||||||
|
|
||||||
instr += special;
|
uint32_t special = 0, local_selects = 0, skip_next = 0;
|
||||||
|
|
||||||
|
for (auto &BB : F) {
|
||||||
|
|
||||||
|
for (auto &IN : BB) {
|
||||||
|
|
||||||
|
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<CallInst>(&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);
|
||||||
|
|
||||||
|
LoadInst *Idx = IRB.CreateLoad(GuardPtr);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Idx);
|
||||||
|
|
||||||
|
callInst->setOperand(1, Idx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectInst *selectInst = nullptr;
|
||||||
|
|
||||||
|
if (!skip_next && (selectInst = dyn_cast<SelectInst>(&IN))) {
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
auto GuardPtr1 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy,
|
||||||
|
(cnt_cov + ++local_selects + AllBlocks.size()) * 4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
|
||||||
|
auto GuardPtr2 = IRB.CreateIntToPtr(
|
||||||
|
IRB.CreateAdd(
|
||||||
|
IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
|
||||||
|
ConstantInt::get(
|
||||||
|
IntptrTy,
|
||||||
|
(cnt_cov + ++local_selects + AllBlocks.size()) * 4)),
|
||||||
|
Int32PtrTy);
|
||||||
|
|
||||||
|
result = IRB.CreateSelect(condition, GuardPtr1, GuardPtr2);
|
||||||
|
|
||||||
|
} else
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR > 13
|
||||||
|
if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
|
||||||
|
|
||||||
|
FixedVectorType *tt = dyn_cast<FixedVectorType>(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
|
||||||
|
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
unhandled++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
local_selects++;
|
||||||
|
uint32_t vector_cur = 0;
|
||||||
|
|
||||||
|
/* Load SHM pointer */
|
||||||
|
|
||||||
|
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
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 = nullptr;
|
||||||
|
Value * MapPtrIdx = nullptr;
|
||||||
|
|
||||||
|
/* Load counter for CurLoc */
|
||||||
|
if (!vector_cnt) {
|
||||||
|
|
||||||
|
CurLoc = IRB.CreateLoad(result);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc);
|
||||||
|
MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vector_cnt) {
|
||||||
|
|
||||||
|
vector_cnt = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
} else if (vector_cnt == vector_cur) {
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
skip_next = 1;
|
||||||
|
instr += vector_cnt;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
skip_next = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AllBlocks.empty() && !special && !local_selects) return false;
|
||||||
|
|
||||||
|
if (!AllBlocks.empty())
|
||||||
|
for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
|
||||||
|
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -881,8 +1154,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);
|
||||||
@ -1062,10 +1333,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
Int32PtrTy);
|
Int32PtrTy);
|
||||||
|
|
||||||
LoadInst *CurLoc = IRB.CreateLoad(GuardPtr);
|
LoadInst *CurLoc = IRB.CreateLoad(GuardPtr);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc);
|
||||||
|
|
||||||
/* Load SHM pointer */
|
/* Load SHM pointer */
|
||||||
|
|
||||||
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
|
||||||
|
|
||||||
/* Load counter for CurLoc */
|
/* Load counter for CurLoc */
|
||||||
|
|
||||||
@ -1082,6 +1355,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
|
||||||
|
|
||||||
/* Update bitmap */
|
/* Update bitmap */
|
||||||
|
|
||||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||||
@ -1094,7 +1369,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IRB.CreateStore(Incr, MapPtrIdx);
|
StoreInst *StoreCtx = IRB.CreateStore(Incr, MapPtrIdx);
|
||||||
|
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreCtx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,8 +65,10 @@ using namespace llvm;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class AFLdict2filePass : public ModulePass {
|
class AFLdict2filePass : public ModulePass {
|
||||||
|
|
||||||
std::ofstream of;
|
std::ofstream of;
|
||||||
void dict2file(u8 *, u32);
|
void dict2file(u8 *, u32);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID;
|
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);
|
FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr);
|
||||||
|
|
||||||
of.open(ptr, std::ofstream::out | std::ofstream::app);
|
of.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||||
if (!of.is_open())
|
if (!of.is_open()) PFATAL("Could not open/create %s.", ptr);
|
||||||
PFATAL("Could not open/create %s.", ptr);
|
|
||||||
|
|
||||||
/* Instrument all the things! */
|
/* Instrument all the things! */
|
||||||
|
|
||||||
|
@ -138,8 +138,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
|||||||
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
||||||
|
|
||||||
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||||
if (!dFile.is_open())
|
if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
|
||||||
WARNF("Cannot access document file %s", ptr);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,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 "
|
||||||
@ -848,7 +853,9 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
|||||||
|
|
||||||
if (dFile.is_open()) {
|
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";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1015,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;
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,14 +274,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
|
|
||||||
Value *op0 = selectcmpInst->getOperand(0);
|
Value *op0 = selectcmpInst->getOperand(0);
|
||||||
Value *op1 = selectcmpInst->getOperand(1);
|
Value *op1 = selectcmpInst->getOperand(1);
|
||||||
|
Value *op0_saved = op0, *op1_saved = op1;
|
||||||
|
auto ty0 = op0->getType();
|
||||||
|
auto ty1 = op1->getType();
|
||||||
|
|
||||||
IntegerType * intTyOp0 = NULL;
|
IntegerType *intTyOp0 = NULL;
|
||||||
IntegerType * intTyOp1 = NULL;
|
IntegerType *intTyOp1 = NULL;
|
||||||
unsigned max_size = 0, cast_size = 0;
|
unsigned max_size = 0, cast_size = 0;
|
||||||
unsigned char attr = 0;
|
unsigned attr = 0, vector_cnt = 0;
|
||||||
std::vector<Value *> args;
|
CmpInst * cmpInst = dyn_cast<CmpInst>(selectcmpInst);
|
||||||
|
|
||||||
CmpInst *cmpInst = dyn_cast<CmpInst>(selectcmpInst);
|
|
||||||
|
|
||||||
if (!cmpInst) { continue; }
|
if (!cmpInst) { continue; }
|
||||||
|
|
||||||
@ -327,7 +328,23 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
|
|
||||||
if (selectcmpInst->getOpcode() == Instruction::FCmp) {
|
if (selectcmpInst->getOpcode() == Instruction::FCmp) {
|
||||||
|
|
||||||
auto ty0 = op0->getType();
|
if (ty0->isVectorTy()) {
|
||||||
|
|
||||||
|
VectorType *tt = dyn_cast<VectorType>(ty0);
|
||||||
|
if (!tt) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Warning: cmplog cmp vector is not a vector!\n");
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LLVM_MAJOR > 11
|
||||||
|
vector_cnt = tt->getElementCount().getFixedValue();
|
||||||
|
ty0 = tt->getElementType();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (ty0->isHalfTy()
|
if (ty0->isHalfTy()
|
||||||
#if LLVM_VERSION_MAJOR >= 11
|
#if LLVM_VERSION_MAJOR >= 11
|
||||||
|| ty0->isBFloatTy()
|
|| ty0->isBFloatTy()
|
||||||
@ -342,13 +359,35 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
max_size = 80;
|
max_size = 80;
|
||||||
else if (ty0->isFP128Ty() || ty0->isPPC_FP128Ty())
|
else if (ty0->isFP128Ty() || ty0->isPPC_FP128Ty())
|
||||||
max_size = 128;
|
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;
|
attr += 8;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
intTyOp0 = dyn_cast<IntegerType>(op0->getType());
|
if (ty0->isVectorTy()) {
|
||||||
intTyOp1 = dyn_cast<IntegerType>(op1->getType());
|
|
||||||
|
#if LLVM_MAJOR > 11
|
||||||
|
VectorType *tt = dyn_cast<VectorType>(ty0);
|
||||||
|
if (!tt) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Warning: cmplog cmp vector is not a vector!\n");
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vector_cnt = tt->getElementCount().getFixedValue();
|
||||||
|
ty1 = ty0 = tt->getElementType();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
intTyOp0 = dyn_cast<IntegerType>(ty0);
|
||||||
|
intTyOp1 = dyn_cast<IntegerType>(ty1);
|
||||||
|
|
||||||
if (intTyOp0 && intTyOp1) {
|
if (intTyOp0 && intTyOp1) {
|
||||||
|
|
||||||
@ -356,11 +395,28 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
? intTyOp0->getBitWidth()
|
? intTyOp0->getBitWidth()
|
||||||
: intTyOp1->getBitWidth();
|
: intTyOp1->getBitWidth();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
#if LLVM_MAJOR > 11
|
||||||
|
if (ty0->getTypeID() != llvm::Type::PointerTyID && !be_quiet) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u\n",
|
||||||
|
ty0->getTypeID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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); }
|
if (max_size % 8) { max_size = (((max_size / 8) + 1) * 8); }
|
||||||
|
|
||||||
@ -393,67 +449,110 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// errs() << "[CMPLOG] cmp " << *cmpInst << "(in function " <<
|
uint64_t cur = 0, last_val0 = 0, last_val1 = 0, cur_val;
|
||||||
// cmpInst->getFunction()->getName() << ")\n";
|
|
||||||
|
|
||||||
// first bitcast to integer type of the same bitsize as the original
|
while (1) {
|
||||||
// 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);
|
|
||||||
|
|
||||||
// errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " << *V1
|
std::vector<Value *> args;
|
||||||
// << "\n";
|
uint32_t skip = 0;
|
||||||
|
|
||||||
ConstantInt *attribute = ConstantInt::get(Int8Ty, attr);
|
if (vector_cnt) {
|
||||||
args.push_back(attribute);
|
|
||||||
|
|
||||||
if (cast_size != max_size) {
|
op0 = IRB.CreateExtractElement(op0_saved, cur);
|
||||||
|
op1 = IRB.CreateExtractElement(op1_saved, cur);
|
||||||
|
ConstantInt *i0 = dyn_cast<ConstantInt>(op0);
|
||||||
|
ConstantInt *i1 = dyn_cast<ConstantInt>(op1);
|
||||||
|
if (i0 && i0->uge(0xffffffffffffffff) == false) {
|
||||||
|
|
||||||
ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1);
|
cur_val = i0->getZExtValue();
|
||||||
args.push_back(bitsize);
|
if (last_val0 && last_val0 == cur_val) { skip = 1; }
|
||||||
|
last_val0 = cur_val;
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,6 +120,17 @@ static u8 count_class_lookup[256] = {
|
|||||||
#undef TIMES8
|
#undef TIMES8
|
||||||
#undef TIMES4
|
#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) {
|
static void classify_counts(u8 *mem) {
|
||||||
|
|
||||||
u32 i = map_size;
|
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.target_path = find_binary(argv[optind]);
|
||||||
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
|
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||||
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
|
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
|
||||||
|
signal(SIGALRM, kill_child);
|
||||||
|
|
||||||
if (qemu_mode) {
|
if (qemu_mode) {
|
||||||
|
|
||||||
|
16
src/afl-cc.c
16
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);
|
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++] = fplugin_arg;
|
||||||
|
cc_params[cc_par_cnt++] = "-fno-if-conversion";
|
||||||
|
cc_params[cc_par_cnt++] = "-fno-if-conversion2";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,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-")) ||
|
if ((!strncmp(cur, "-fsanitize=fuzzer-", strlen("-fsanitize=fuzzer-")) ||
|
||||||
!strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
|
!strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
|
||||||
(strncmp(cur, "sanitize-coverage-allow",
|
(strncmp(cur, "sanitize-coverage-allow",
|
||||||
@ -1007,7 +1017,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prevent unnecessary build errors
|
// 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) {
|
if (preprocessor_only || have_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"); }
|
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
|
||||||
|
|
||||||
memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
|
memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
|
||||||
new_argv[argc + 3] = NULL;
|
|
||||||
|
|
||||||
new_argv[2] = *target_path_p;
|
new_argv[2] = *target_path_p;
|
||||||
new_argv[1] = "--";
|
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 **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"); }
|
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
|
||||||
|
|
||||||
memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
|
memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
|
||||||
new_argv[argc + 2] = NULL;
|
|
||||||
|
|
||||||
new_argv[1] = *target_path_p;
|
new_argv[1] = *target_path_p;
|
||||||
|
|
||||||
|
@ -608,19 +608,31 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
|||||||
/* Wait for the fork server to come up, but don't wait too long. */
|
/* Wait for the fork server to come up, but don't wait too long. */
|
||||||
|
|
||||||
rlen = 0;
|
rlen = 0;
|
||||||
if (fsrv->exec_tmout) {
|
if (fsrv->init_tmout) {
|
||||||
|
|
||||||
u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
|
u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
|
||||||
stop_soon_p);
|
stop_soon_p);
|
||||||
|
|
||||||
if (!time_ms) {
|
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) {
|
} else if (time_ms > fsrv->init_tmout) {
|
||||||
|
|
||||||
fsrv->last_run_timed_out = 1;
|
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 {
|
} else {
|
||||||
|
|
||||||
@ -1259,7 +1271,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,
|
/* 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 */
|
||||||
|
|
||||||
if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
|
s32 tmp_pid = fsrv->child_pid;
|
||||||
|
if (tmp_pid > 0) {
|
||||||
|
|
||||||
|
kill(tmp_pid, fsrv->kill_signal);
|
||||||
|
fsrv->child_pid = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
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; }
|
||||||
|
|
||||||
@ -1293,7 +1312,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++;
|
fsrv->total_execs++;
|
||||||
|
|
||||||
|
@ -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",
|
sprintf(ret + strlen(ret), ",time:%llu,execs:%llu",
|
||||||
get_cur_time() + afl->prev_run_time - afl->start_time);
|
get_cur_time() + afl->prev_run_time - afl->start_time,
|
||||||
|
afl->fsrv.total_execs);
|
||||||
|
|
||||||
if (afl->current_custom_fuzz &&
|
if (afl->current_custom_fuzz &&
|
||||||
afl->current_custom_fuzz->afl_custom_describe) {
|
afl->current_custom_fuzz->afl_custom_describe) {
|
||||||
|
@ -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,
|
nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
|
||||||
use_name);
|
afl->out_dir, id, afl->fsrv.total_execs, use_name);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@ -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) {
|
||||||
|
@ -442,9 +442,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)])
|
||||||
@ -657,26 +658,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... */
|
||||||
|
|
||||||
|
@ -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; }
|
||||||
|
|
||||||
@ -1697,7 +1706,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
|
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
|
||||||
afl->fsrv.frida_mode || afl->unicorn_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_bits = ck_realloc(afl->virgin_bits, map_size);
|
||||||
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
|
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
|
||||||
afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
|
afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
|
||||||
|
@ -77,7 +77,7 @@ static u32 tcnt, highest; /* tuple content information */
|
|||||||
|
|
||||||
static u32 in_len; /* Input data length */
|
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? */
|
static bool quiet_mode, /* Hide non-essential messages? */
|
||||||
edges_only, /* Ignore hit counts? */
|
edges_only, /* Ignore hit counts? */
|
||||||
@ -146,6 +146,18 @@ static const u8 count_class_binary[256] = {
|
|||||||
#undef TIMES8
|
#undef TIMES8
|
||||||
#undef TIMES4
|
#undef TIMES4
|
||||||
|
|
||||||
|
static void kill_child() {
|
||||||
|
|
||||||
|
timed_out = 1;
|
||||||
|
if (fsrv->child_pid > 0) {
|
||||||
|
|
||||||
|
kill(fsrv->child_pid, fsrv->kill_signal);
|
||||||
|
fsrv->child_pid = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void classify_counts(afl_forkserver_t *fsrv) {
|
static void classify_counts(afl_forkserver_t *fsrv) {
|
||||||
|
|
||||||
u8 * mem = fsrv->trace_bits;
|
u8 * mem = fsrv->trace_bits;
|
||||||
@ -243,10 +255,13 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
|
|||||||
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
|
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
|
||||||
|
|
||||||
if (strcmp(outfile, "-")) {
|
if (strcmp(outfile, "-")) {
|
||||||
|
|
||||||
// create empty file to prevent error messages in afl-cmin
|
// create empty file to prevent error messages in afl-cmin
|
||||||
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -359,9 +374,10 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
|
|||||||
|
|
||||||
if (!quiet_mode) {
|
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);
|
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
||||||
|
timed_out = 0;
|
||||||
|
|
||||||
} else if (stop_soon) {
|
} else if (stop_soon) {
|
||||||
|
|
||||||
@ -523,6 +539,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal(SIGALRM, kill_child);
|
||||||
|
|
||||||
setitimer(ITIMER_REAL, &it, NULL);
|
setitimer(ITIMER_REAL, &it, NULL);
|
||||||
|
|
||||||
if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
|
if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
|
||||||
@ -565,9 +583,10 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
|
|
||||||
if (!quiet_mode) {
|
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);
|
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
||||||
|
timed_out = 0;
|
||||||
|
|
||||||
} else if (stop_soon) {
|
} else if (stop_soon) {
|
||||||
|
|
||||||
|
@ -120,6 +120,17 @@ static const u8 count_class_lookup[256] = {
|
|||||||
#undef TIMES8
|
#undef TIMES8
|
||||||
#undef TIMES4
|
#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,
|
static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
|
||||||
sharedmem_t * shm_fuzz) {
|
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->target_path = find_binary(argv[optind]);
|
||||||
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
|
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||||
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
|
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
|
||||||
|
signal(SIGALRM, kill_child);
|
||||||
|
|
||||||
if (fsrv->qemu_mode) {
|
if (fsrv->qemu_mode) {
|
||||||
|
|
||||||
|
@ -88,6 +88,8 @@ unset AFL_QEMU_PERSISTENT_GPR
|
|||||||
unset AFL_QEMU_PERSISTENT_RET
|
unset AFL_QEMU_PERSISTENT_RET
|
||||||
unset AFL_QEMU_PERSISTENT_HOOK
|
unset AFL_QEMU_PERSISTENT_HOOK
|
||||||
unset AFL_QEMU_PERSISTENT_CNT
|
unset AFL_QEMU_PERSISTENT_CNT
|
||||||
|
unset AFL_QEMU_PERSISTENT_MEM
|
||||||
|
unset AFL_QEMU_PERSISTENT_EXITS
|
||||||
unset AFL_CUSTOM_MUTATOR_LIBRARY
|
unset AFL_CUSTOM_MUTATOR_LIBRARY
|
||||||
unset AFL_PYTHON_MODULE
|
unset AFL_PYTHON_MODULE
|
||||||
unset AFL_PRELOAD
|
unset AFL_PRELOAD
|
||||||
|
@ -1 +1 @@
|
|||||||
d4915053d477dd827b3fe4b494173d3fbf9f456e
|
94617f5b
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
add_executable(optimin OptiMin.cpp)
|
add_executable(optimin OptiMin.cpp)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||||
|
|
||||||
foreach(LIB MaLib EvalMaxSAT glucose)
|
foreach(LIB MaLib EvalMaxSAT glucose)
|
||||||
target_include_directories(optimin PRIVATE
|
target_include_directories(optimin PRIVATE
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user