mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-08 00:01:33 +00:00
commit
f5535e348d
104
README.md
104
README.md
@ -6,7 +6,8 @@ Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 3.15a
|
||||
|
||||
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
||||
AFL++ is maintained by:
|
||||
|
||||
@ -17,57 +18,74 @@ AFL++ is maintained by:
|
||||
|
||||
Originally developed by Michał "lcamtuf" Zalewski.
|
||||
|
||||
AFL++ is a superior fork to Google's AFL - more speed, more and better mutations, more and better instrumentation, custom module support, etc.
|
||||
AFL++ is a superior fork to Google's AFL - more speed, more and better
|
||||
mutations, more and better instrumentation, custom module support, etc.
|
||||
|
||||
You are free to copy, modify, and distribute AFL++ with attribution under the terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
|
||||
You are free to copy, modify, and distribute AFL++ with attribution under the
|
||||
terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
|
||||
|
||||
## Getting started
|
||||
|
||||
Here is some information to get you started:
|
||||
|
||||
* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [major changes in AFL++](docs/important_changes.md).
|
||||
* If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/) on the website.
|
||||
* For releases, please see the
|
||||
[Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and
|
||||
[branches](docs/branches.md). Also take a look at the list of
|
||||
[important changes in AFL++](docs/important_changes.md).
|
||||
* If you want to use AFL++ for your academic work, check the
|
||||
[papers page](https://aflplus.plus/papers/) on the website.
|
||||
* To cite our work, look at the [Cite](#cite) section.
|
||||
* For comparisons, use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
|
||||
* To get you started with tutorials, go to [docs/tutorials.md](docs/tutorials.md).
|
||||
* For comparisons, use the fuzzbench `aflplusplus` setup, or use
|
||||
`afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus`
|
||||
default configuration on Google's
|
||||
[fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
|
||||
* To get you started with tutorials, go to
|
||||
[docs/tutorials.md](docs/tutorials.md).
|
||||
|
||||
## Building and installing AFL++
|
||||
|
||||
To have AFL++ easily available with everything compiled, pull the image directly from the Docker Hub:
|
||||
To have AFL++ easily available with everything compiled, pull the image
|
||||
directly from the Docker Hub:
|
||||
|
||||
```shell
|
||||
docker pull aflplusplus/aflplusplus
|
||||
docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
|
||||
```
|
||||
|
||||
This image is automatically generated when a push to the stable repo happens (see [docs/branches.md](docs/branches.md)).
|
||||
You will find your target source code in `/src` in the container.
|
||||
This image is automatically generated when a push to the stable repo happens
|
||||
(see [docs/branches.md](docs/branches.md)). You will find your target source
|
||||
code in `/src` in the container.
|
||||
|
||||
To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md).
|
||||
|
||||
## Quick start: Fuzzing with AFL++
|
||||
|
||||
*NOTE: Before you start, please read about the [common sense risks of fuzzing](docs/common_sense_risks.md).*
|
||||
*NOTE: Before you start, please read about the [common sense risks of
|
||||
fuzzing](docs/common_sense_risks.md).*
|
||||
|
||||
This is a quick start for fuzzing targets with the source code available.
|
||||
To read about the process in detail, see [docs/fuzzing_expert.md](docs/fuzzing_expert.md).
|
||||
This is a quick start for fuzzing targets with the source code available. To
|
||||
read about the process in detail, see
|
||||
[docs/fuzzing_expert.md](docs/fuzzing_expert.md).
|
||||
|
||||
To learn about fuzzing other targets, see:
|
||||
* Binary-only targets: [docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md)
|
||||
* Network services: [docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service)
|
||||
* GUI programs: [docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program)
|
||||
* Binary-only targets:
|
||||
[docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md)
|
||||
* Network services:
|
||||
[docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service)
|
||||
* GUI programs:
|
||||
[docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program)
|
||||
|
||||
Step-by-step quick start:
|
||||
|
||||
1. Compile the program or library to be fuzzed using `afl-cc`.
|
||||
A common way to do this would be:
|
||||
1. Compile the program or library to be fuzzed using `afl-cc`. A common way to
|
||||
do this would be:
|
||||
|
||||
CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared
|
||||
make clean all
|
||||
|
||||
2. Get a small but valid input file that makes sense to the program.
|
||||
When fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described
|
||||
in [dictionaries/README.md](dictionaries/README.md), too.
|
||||
2. Get a small but valid input file that makes sense to the program. When
|
||||
fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in
|
||||
[dictionaries/README.md](dictionaries/README.md), too.
|
||||
|
||||
3. If the program reads from stdin, run `afl-fuzz` like so:
|
||||
|
||||
@ -81,39 +99,49 @@ in [dictionaries/README.md](dictionaries/README.md), too.
|
||||
If the program takes input from a file, you can put `@@` in the program's
|
||||
command line; AFL will put an auto-generated file name in there for you.
|
||||
|
||||
4. Investigate anything shown in red in the fuzzer UI by promptly consulting [docs/status_screen.md](docs/status_screen.md).
|
||||
4. Investigate anything shown in red in the fuzzer UI by promptly consulting
|
||||
[docs/status_screen.md](docs/status_screen.md).
|
||||
|
||||
5. You will find found crashes and hangs in the subdirectories `crashes/` and
|
||||
`hangs/` in the `-o output_dir` directory. You can replay the crashes by
|
||||
feeding them to the target, e.g.:
|
||||
`cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]`
|
||||
You can generate cores or use gdb directly to follow up the crashes.
|
||||
feeding them to the target, e.g.: `cat output_dir/crashes/id:000000,* |
|
||||
/path/to/tested/program [...program's cmdline...]` You can generate cores or
|
||||
use gdb directly to follow up the crashes.
|
||||
|
||||
## Contact
|
||||
|
||||
Questions? Concerns? Bug reports?
|
||||
|
||||
* The contributors can be reached via [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
|
||||
* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important question missing, submit it via
|
||||
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
|
||||
* There is a mailing list for the AFL/AFL++ project ([browse archive](https://groups.google.com/group/afl-users)). To compare notes with other users or to get notified about major new features, send an email to <afl-users+subscribe@googlegroups.com>.
|
||||
* The contributors can be reached via
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
|
||||
* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or
|
||||
important question missing, submit it via
|
||||
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
|
||||
* There is a mailing list for the AFL/AFL++ project
|
||||
([browse archive](https://groups.google.com/group/afl-users)). To compare
|
||||
notes with other users or to get notified about major new features, send an
|
||||
email to <afl-users+subscribe@googlegroups.com>.
|
||||
* Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
|
||||
|
||||
## Help wanted
|
||||
|
||||
We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it even better.
|
||||
However, we already work on so many things that we do not have the time for all the big ideas.
|
||||
We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it
|
||||
even better. However, we already work on so many things that we do not have the
|
||||
time for all the big ideas.
|
||||
|
||||
This can be your way to support and contribute to AFL++ - extend it to do something cool.
|
||||
This can be your way to support and contribute to AFL++ - extend it to do
|
||||
something cool.
|
||||
|
||||
For everyone who wants to contribute (and send pull requests), please read our [contributing guidelines](CONTRIBUTING.md) before your submit.
|
||||
For everyone who wants to contribute (and send pull requests), please read our
|
||||
[contributing guidelines](CONTRIBUTING.md) before your submit.
|
||||
|
||||
## Special thanks
|
||||
|
||||
Many of the improvements to the original AFL and AFL++ wouldn't be possible without feedback, bug reports, or patches from our contributors.
|
||||
Many of the improvements to the original AFL and AFL++ wouldn't be possible
|
||||
without feedback, bug reports, or patches from our contributors.
|
||||
|
||||
Thank you!
|
||||
(For people sending pull requests - please add yourself to this list :-)
|
||||
Thank you! (For people sending pull requests - please add yourself to this list
|
||||
:-)
|
||||
|
||||
<details>
|
||||
|
||||
@ -172,7 +200,9 @@ Thank you!
|
||||
|
||||
## Cite
|
||||
|
||||
If you use AFL++ in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20:
|
||||
If you use AFL++ in scientific work, consider citing
|
||||
[our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi)
|
||||
presented at WOOT'20:
|
||||
|
||||
Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020.
|
||||
|
||||
|
@ -17,14 +17,17 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
coverage being detected. thanks to Collin May for reporting!
|
||||
- fix -n dumb mode (nobody should use this)
|
||||
- fix stability issue with LTO and cmplog
|
||||
- better banner
|
||||
- frida_mode: David Carlier added Android support :)
|
||||
- afl-showmap, afl-tmin and afl-analyze now honor persistent mode
|
||||
for more speed. thanks to dloffre-snl for reporting!
|
||||
- afl-showmap, afl-tmin and afl-analyze:
|
||||
- honor persistent mode for more speed. thanks to dloffre-snl for
|
||||
reporting!
|
||||
- fix bug where targets are not killed on timeouts
|
||||
- Prevent accidently killing non-afl/fuzz services when aborting
|
||||
afl-showmap and other tools.
|
||||
- afl-cc:
|
||||
- fix for shared linking on MacOS
|
||||
- llvm and LTO mode verified to work with new llvm 14-dev
|
||||
- llvm and LTO mode modified to work with new llvm 14-dev (again)
|
||||
- added the very good grammar mutator "GramaTron" to the
|
||||
custom_mutators
|
||||
- added optimin, a faster and better corpus minimizer by
|
||||
|
@ -22,6 +22,7 @@ sudo apt-get install -y build-essential python3-dev automake git flex bison libg
|
||||
# try to install llvm 11 and install the distro default if that fails
|
||||
sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang
|
||||
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
|
||||
sudo apt-get install -y ninja-build # for qemu_mode
|
||||
git clone https://github.com/AFLplusplus/AFLplusplus
|
||||
cd AFLplusplus
|
||||
make distrib
|
||||
|
@ -96,6 +96,16 @@
|
||||
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 is a binary instrumentation framework similar to Pintool and
|
||||
@ -116,13 +126,10 @@
|
||||
The speed decrease is about 15-35%, depending on the optimization options
|
||||
used with afl-dyninst.
|
||||
|
||||
So if Dyninst works, it is the best option available. Otherwise it just
|
||||
doesn't work well.
|
||||
|
||||
[https://github.com/vanhauser-thc/afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst)
|
||||
|
||||
|
||||
## RETROWRITE, ZAFL, ... other binary rewriter
|
||||
## RETROWRITE
|
||||
|
||||
If you have an x86/x86_64 binary that still has its symbols, is compiled
|
||||
with position independant code (PIC/PIE) and does not use most of the C++
|
||||
@ -131,7 +138,6 @@
|
||||
|
||||
It is at about 80-85% performance.
|
||||
|
||||
[https://git.zephyr-software.com/opensrc/zafl](https://git.zephyr-software.com/opensrc/zafl)
|
||||
[https://github.com/HexHive/retrowrite](https://github.com/HexHive/retrowrite)
|
||||
|
||||
|
||||
|
@ -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!!*
|
||||
* (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.
|
||||
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
|
||||
`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
|
||||
instrumentation: [utils/afl_untracer/README.md](../utils/afl_untracer/README.md).
|
||||
|
@ -27,9 +27,8 @@ will not be able to use that input to guide their work.
|
||||
To help with this problem, afl-fuzz offers a simple way to synchronize test
|
||||
cases on the fly.
|
||||
|
||||
Note that AFL++ has AFLfast's power schedules implemented.
|
||||
It is therefore a good idea to use different power schedules if you run
|
||||
several instances in parallel. See [power_schedules.md](power_schedules.md)
|
||||
It is a good idea to use different power schedules if you run several instances
|
||||
in parallel (`-p` option).
|
||||
|
||||
Alternatively running other AFL spinoffs in parallel can be of value,
|
||||
e.g. Angora (https://github.com/AngoraFuzzer/Angora/)
|
||||
|
@ -78,6 +78,9 @@ endif
|
||||
|
||||
ifeq "$(shell uname)" "Linux"
|
||||
OS:=linux
|
||||
ifneq "$(findstring musl, $(shell ldd --version 2>&1 | head -n 1))" ""
|
||||
CFLAGS+= -D__MUSL__
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
|
@ -288,6 +288,12 @@ ucomisd 2 ( 0.86%)
|
||||
* `AFL_FRIDA_STATS_INTERVAL` - The maximum frequency to output statistics
|
||||
information. Stats will be written whenever they are updated if the given
|
||||
interval has elapsed since last time they were written.
|
||||
* `AFL_FRIDA_TRACEABLE` - Set the child process to be traceable by any process
|
||||
to aid debugging and overcome the restrictions imposed by YAMA. Supported on
|
||||
Linux only. Permits a non-root user to use `gcore` or similar to collect a core
|
||||
dump of the instrumented target. Note that in order to capture the core dump you
|
||||
must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` killing the
|
||||
process whilst it is being dumped.
|
||||
|
||||
## FASAN - Frida Address Sanitizer Mode
|
||||
Frida mode also supports FASAN. The design of this is actually quite simple and
|
||||
|
@ -33,6 +33,7 @@
|
||||
js_api_set_stats_interval;
|
||||
js_api_set_stderr;
|
||||
js_api_set_stdout;
|
||||
js_api_set_traceable;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
extern guint64 entry_point;
|
||||
extern gboolean traceable;
|
||||
extern gboolean entry_compiled;
|
||||
extern gboolean entry_run;
|
||||
|
||||
@ -15,5 +16,7 @@ void entry_start(void);
|
||||
|
||||
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output);
|
||||
|
||||
void entry_on_fork(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,9 @@
|
||||
#include <dlfcn.h>
|
||||
|
||||
#if defined(__linux__) && !defined(__ANDROID__)
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
@ -16,6 +20,7 @@
|
||||
extern void __afl_manual_init();
|
||||
|
||||
guint64 entry_point = 0;
|
||||
gboolean traceable = FALSE;
|
||||
gboolean entry_compiled = FALSE;
|
||||
gboolean entry_run = FALSE;
|
||||
|
||||
@ -26,21 +31,48 @@ static void entry_launch(void) {
|
||||
|
||||
/* Child here */
|
||||
entry_run = TRUE;
|
||||
entry_on_fork();
|
||||
instrument_on_fork();
|
||||
seccomp_on_fork();
|
||||
stats_on_fork();
|
||||
|
||||
}
|
||||
|
||||
#if defined(__linux__) && !defined(__ANDROID__)
|
||||
void entry_on_fork(void) {
|
||||
|
||||
if (traceable) {
|
||||
|
||||
if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) < 0) {
|
||||
|
||||
FATAL("Failed to PR_SET_PTRACER");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
void entry_on_fork(void) {
|
||||
|
||||
if (traceable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); }
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void entry_config(void) {
|
||||
|
||||
entry_point = util_read_address("AFL_ENTRYPOINT");
|
||||
if (getenv("AFL_FRIDA_TRACEABLE") != NULL) { traceable = TRUE; }
|
||||
|
||||
}
|
||||
|
||||
void entry_init(void) {
|
||||
|
||||
OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
|
||||
OKF("dumpable: [%c]", traceable ? 'X' : ' ');
|
||||
|
||||
if (dlopen(NULL, RTLD_NOW) == NULL) { FATAL("Failed to dlopen: %d", errno); }
|
||||
|
||||
|
@ -243,6 +243,12 @@ class Afl {
|
||||
const buf = Memory.allocUtf8String(file);
|
||||
Afl.jsApiSetStdOut(buf);
|
||||
}
|
||||
/**
|
||||
* See `AFL_FRIDA_TRACEABLE`.
|
||||
*/
|
||||
static setTraceable() {
|
||||
Afl.jsApiSetTraceable();
|
||||
}
|
||||
static jsApiGetFunction(name, retType, argTypes) {
|
||||
const addr = Afl.module.getExportByName(name);
|
||||
return new NativeFunction(addr, retType, argTypes);
|
||||
@ -286,6 +292,7 @@ Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", ["
|
||||
Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]);
|
||||
Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
|
||||
Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]);
|
||||
Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []);
|
||||
Afl.jsApiWrite = new NativeFunction(
|
||||
/* tslint:disable-next-line:no-null-keyword */
|
||||
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
||||
|
@ -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__
|
||||
#include <mach/mach.h>
|
||||
#include <mach-o/dyld_images.h>
|
||||
#include <crt_externs.h>
|
||||
#else
|
||||
#include <sys/wait.h>
|
||||
#include <sys/personality.h>
|
||||
@ -90,6 +91,7 @@ static void embedded_init(void) {
|
||||
|
||||
static void afl_print_cmdline(void) {
|
||||
|
||||
#if defined(__linux__)
|
||||
char * buffer = g_malloc0(PROC_MAX);
|
||||
gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid());
|
||||
int fd = open(fname, O_RDONLY);
|
||||
@ -123,6 +125,17 @@ static void afl_print_cmdline(void) {
|
||||
close(fd);
|
||||
g_free(fname);
|
||||
g_free(buffer);
|
||||
#elif defined(__APPLE__)
|
||||
int idx;
|
||||
char **argv = *_NSGetArgv();
|
||||
int nargv = *_NSGetArgc();
|
||||
|
||||
for (idx = 0; idx < nargv; idx ++) {
|
||||
|
||||
OKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
#if defined(__linux__) && !defined(__ANDROID__)
|
||||
|
||||
#if !defined(__MUSL__)
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
#include <fcntl.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[3], req->data.args[4], req->data.args[5]);
|
||||
|
||||
#if !defined(__MUSL__)
|
||||
seccomp_print("FRAMES: (%u)\n", frames->len);
|
||||
char **syms = backtrace_symbols(frames->items, frames->len);
|
||||
if (syms == NULL) { FATAL("Failed to get symbols"); }
|
||||
@ -49,6 +52,23 @@ static void seccomp_callback_filter(struct seccomp_notif * req,
|
||||
}
|
||||
|
||||
free(syms);
|
||||
#else
|
||||
void **syms = (void **)__builtin_frame_address(0);
|
||||
void *framep = __builtin_frame_address(1);
|
||||
int i = 0;
|
||||
|
||||
syms = framep;
|
||||
while (syms) {
|
||||
|
||||
framep = *syms;
|
||||
syms = framep;
|
||||
|
||||
if (!syms) break;
|
||||
|
||||
seccomp_print("\%3d. %s\n", i ++, (char *)framep);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
resp->error = 0;
|
||||
resp->val = 0;
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#if !defined(__MUSL__)
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
#include <linux/filter.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/prctl.h>
|
||||
|
@ -284,6 +284,13 @@ class Afl {
|
||||
Afl.jsApiSetStdOut(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* See `AFL_FRIDA_TRACEABLE`.
|
||||
*/
|
||||
public static setTraceable(): void {
|
||||
Afl.jsApiSetTraceable();
|
||||
}
|
||||
|
||||
private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction(
|
||||
"js_api_add_exclude_range",
|
||||
"void",
|
||||
@ -431,6 +438,11 @@ class Afl {
|
||||
"void",
|
||||
["pointer"]);
|
||||
|
||||
private static readonly jsApiSetTraceable = Afl.jsApiGetFunction(
|
||||
"js_api_set_traceable",
|
||||
"void",
|
||||
[]);
|
||||
|
||||
private static readonly jsApiWrite = new NativeFunction(
|
||||
/* tslint:disable-next-line:no-null-keyword */
|
||||
Module.getExportByName(null, "write"),
|
||||
|
@ -1130,7 +1130,6 @@ void get_core_count(afl_state_t *);
|
||||
void fix_up_sync(afl_state_t *);
|
||||
void check_asan_opts(afl_state_t *);
|
||||
void check_binary(afl_state_t *, u8 *);
|
||||
void fix_up_banner(afl_state_t *, u8 *);
|
||||
void check_if_tty(afl_state_t *);
|
||||
void setup_signal_handlers(void);
|
||||
void save_cmdline(afl_state_t *, u32, char **);
|
||||
|
@ -76,6 +76,7 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_FRIDA_PERSISTENT_RET",
|
||||
"AFL_FRIDA_STATS_FILE",
|
||||
"AFL_FRIDA_STATS_INTERVAL",
|
||||
"AFL_FRIDA_TRACEABLE",
|
||||
"AFL_FUZZER_ARGS", // oss-fuzz
|
||||
"AFL_GDB",
|
||||
"AFL_GCC_ALLOWLIST",
|
||||
|
@ -235,6 +235,8 @@ class ModuleSanitizerCoverage {
|
||||
uint32_t autodictionary = 1;
|
||||
uint32_t inst = 0;
|
||||
uint32_t afl_global_id = 0;
|
||||
uint32_t unhandled = 0;
|
||||
uint32_t select_cnt = 0;
|
||||
uint64_t map_addr = 0;
|
||||
const char * skip_nozero = NULL;
|
||||
const char * use_threadsafe_counters = nullptr;
|
||||
@ -447,8 +449,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
||||
|
||||
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||
if (dFile.is_open())
|
||||
WARNF("Cannot access document file %s", ptr);
|
||||
if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
|
||||
|
||||
}
|
||||
|
||||
@ -1041,8 +1042,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
M, Int64Tyi, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr");
|
||||
ConstantInt *MapAddr = ConstantInt::get(Int64Tyi, map_addr);
|
||||
StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed);
|
||||
StoreMapAddr->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(Ctx, None));
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreMapAddr);
|
||||
|
||||
}
|
||||
|
||||
@ -1050,15 +1050,14 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
|
||||
uint32_t write_loc = afl_global_id;
|
||||
|
||||
if (afl_global_id % 8) write_loc = (((afl_global_id + 8) >> 3) << 3);
|
||||
write_loc = (((afl_global_id + 8) >> 3) << 3);
|
||||
|
||||
GlobalVariable *AFLFinalLoc =
|
||||
new GlobalVariable(M, Int32Tyi, true, GlobalValue::ExternalLinkage, 0,
|
||||
"__afl_final_loc");
|
||||
ConstantInt *const_loc = ConstantInt::get(Int32Tyi, write_loc);
|
||||
StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc);
|
||||
StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(Ctx, None));
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreFinalLoc);
|
||||
|
||||
}
|
||||
|
||||
@ -1084,7 +1083,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
|
||||
if (count) {
|
||||
|
||||
auto ptrhld = std::unique_ptr<char []>(new char[memlen + count]);
|
||||
auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
|
||||
|
||||
count = 0;
|
||||
|
||||
@ -1106,8 +1105,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
0, "__afl_dictionary_len");
|
||||
ConstantInt *const_len = ConstantInt::get(Int32Tyi, offset);
|
||||
StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen);
|
||||
StoreDictLen->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(Ctx, None));
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDictLen);
|
||||
|
||||
ArrayType *ArrayTy = ArrayType::get(IntegerType::get(Ctx, 8), offset);
|
||||
GlobalVariable *AFLInternalDictionary = new GlobalVariable(
|
||||
@ -1127,8 +1125,7 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
Value *AFLDictPtr =
|
||||
IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Tyi, 0));
|
||||
StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary);
|
||||
StoreDict->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(Ctx, None));
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(StoreDict);
|
||||
|
||||
}
|
||||
|
||||
@ -1151,9 +1148,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||
OKF("Instrumented %u locations with no collisions (on average %llu "
|
||||
"collisions would be in afl-gcc/vanilla AFL) (%s mode).",
|
||||
inst, calculateCollisions(inst), modeline);
|
||||
OKF("Instrumented %u locations (%u selects) without collisions (%llu "
|
||||
"collisions have been avoided) (%s mode).",
|
||||
inst, select_cnt, calculateCollisions(inst), modeline);
|
||||
|
||||
}
|
||||
|
||||
@ -1275,6 +1272,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
||||
const DominatorTree * DT = DTCallback(F);
|
||||
const PostDominatorTree *PDT = PDTCallback(F);
|
||||
bool IsLeafFunc = true;
|
||||
uint32_t skip_next = 0, local_selects = 0;
|
||||
|
||||
for (auto &BB : F) {
|
||||
|
||||
@ -1292,6 +1290,148 @@ void ModuleSanitizerCoverage::instrumentFunction(
|
||||
|
||||
Value *val = ConstantInt::get(Int32Ty, ++afl_global_id);
|
||||
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)(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 {
|
||||
|
||||
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
||||
MapPtr->setMetadata(Mo->getMDKindID("nosanitize"),
|
||||
MDNode::get(*Ct, None));
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
|
||||
MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc);
|
||||
|
||||
}
|
||||
@ -1539,8 +1679,7 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
} else {
|
||||
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(Mo->getMDKindID("nosanitize"),
|
||||
MDNode::get(*Ct, None));
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
@ -1552,8 +1691,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
|
||||
}
|
||||
|
||||
IRB.CreateStore(Incr, MapPtrIdx)
|
||||
->setMetadata(Mo->getMDKindID("nosanitize"), MDNode::get(*Ct, None));
|
||||
auto nosan = IRB.CreateStore(Incr, MapPtrIdx);
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(nosan);
|
||||
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ class ModuleSanitizerCoverage {
|
||||
|
||||
SanitizerCoverageOptions Options;
|
||||
|
||||
uint32_t instr = 0;
|
||||
uint32_t instr = 0, selects = 0, unhandled = 0;
|
||||
GlobalVariable *AFLMapPtr = NULL;
|
||||
ConstantInt * One = NULL;
|
||||
ConstantInt * Zero = NULL;
|
||||
@ -553,8 +553,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
|
||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||
OKF("Instrumented %u locations with no collisions (%s mode).", instr,
|
||||
modeline);
|
||||
OKF("Instrumented %u locations with no collisions (%s mode) of which are "
|
||||
"%u handled and %u unhandled selects.",
|
||||
instr, modeline, selects, unhandled);
|
||||
|
||||
}
|
||||
|
||||
@ -833,9 +834,8 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
|
||||
ArrayRef<BasicBlock *> AllBlocks,
|
||||
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 &IN : BB) {
|
||||
@ -850,9 +850,37 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
|
||||
StringRef FuncName = Callee->getName();
|
||||
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
|
||||
|
||||
uint32_t id = 1 + instr + (uint32_t)AllBlocks.size() + special++;
|
||||
Value * val = ConstantInt::get(Int32Ty, id);
|
||||
callInst->setOperand(1, val);
|
||||
cnt_cov++;
|
||||
|
||||
}
|
||||
|
||||
SelectInst *selectInst = nullptr;
|
||||
|
||||
if ((selectInst = dyn_cast<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,12 +888,257 @@ bool ModuleSanitizerCoverage::InjectCoverage(Function & F,
|
||||
|
||||
}
|
||||
|
||||
CreateFunctionLocalArrays(F, AllBlocks, special);
|
||||
/* Create PCGUARD array */
|
||||
CreateFunctionLocalArrays(F, AllBlocks, cnt_cov + cnt_sel_inc);
|
||||
selects += cnt_sel;
|
||||
|
||||
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);
|
||||
|
||||
instr += special;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
@ -881,8 +1154,6 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
|
||||
Function &F, ArrayRef<Instruction *> IndirCalls) {
|
||||
|
||||
if (IndirCalls.empty()) return;
|
||||
assert(Options.TracePC || Options.TracePCGuard ||
|
||||
Options.Inline8bitCounters /*|| Options.InlineBoolFlag*/);
|
||||
for (auto I : IndirCalls) {
|
||||
|
||||
IRBuilder<> IRB(I);
|
||||
@ -1062,10 +1333,12 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
Int32PtrTy);
|
||||
|
||||
LoadInst *CurLoc = IRB.CreateLoad(GuardPtr);
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(CurLoc);
|
||||
|
||||
/* Load SHM pointer */
|
||||
|
||||
LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(MapPtr);
|
||||
|
||||
/* Load counter for CurLoc */
|
||||
|
||||
@ -1082,6 +1355,8 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB,
|
||||
} else {
|
||||
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
ModuleSanitizerCoverage::SetNoSanitizeMetadata(Counter);
|
||||
|
||||
/* Update bitmap */
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
@ -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 {
|
||||
|
||||
class AFLdict2filePass : public ModulePass {
|
||||
|
||||
std::ofstream of;
|
||||
void dict2file(u8 *, u32);
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
@ -147,8 +149,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
|
||||
FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr);
|
||||
|
||||
of.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||
if (!of.is_open())
|
||||
PFATAL("Could not open/create %s.", ptr);
|
||||
if (!of.is_open()) PFATAL("Could not open/create %s.", ptr);
|
||||
|
||||
/* Instrument all the things! */
|
||||
|
||||
|
@ -138,8 +138,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
||||
|
||||
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||
if (!dFile.is_open())
|
||||
WARNF("Cannot access document file %s", ptr);
|
||||
if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
|
||||
|
||||
}
|
||||
|
||||
@ -244,8 +243,14 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
|
||||
// the instrument file list check
|
||||
AttributeList Attrs = F.getAttributes();
|
||||
#if LLVM_VERSION_MAJOR < 14
|
||||
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
|
||||
|
||||
#else
|
||||
if (Attrs.hasFnAttr(StringRef("skipinstrument"))) {
|
||||
|
||||
#endif
|
||||
|
||||
if (debug)
|
||||
fprintf(stderr,
|
||||
"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()) {
|
||||
|
||||
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) {
|
||||
|
||||
auto ptrhld = std::unique_ptr<char []>(new char[memlen + count]);
|
||||
auto ptrhld = std::unique_ptr<char[]>(new char[memlen + count]);
|
||||
|
||||
count = 0;
|
||||
|
||||
|
@ -116,10 +116,15 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
|
||||
|
||||
auto & Ctx = F.getContext();
|
||||
AttributeList Attrs = F.getAttributes();
|
||||
#if LLVM_VERSION_MAJOR < 14
|
||||
AttrBuilder NewAttrs;
|
||||
NewAttrs.addAttribute("skipinstrument");
|
||||
F.setAttributes(
|
||||
Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
|
||||
#else
|
||||
AttributeList NewAttrs = Attrs.addFnAttribute(Ctx, "skipinstrument");
|
||||
F.setAttributes(NewAttrs);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -274,14 +274,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
Value *op0 = selectcmpInst->getOperand(0);
|
||||
Value *op1 = selectcmpInst->getOperand(1);
|
||||
Value *op0_saved = op0, *op1_saved = op1;
|
||||
auto ty0 = op0->getType();
|
||||
auto ty1 = op1->getType();
|
||||
|
||||
IntegerType * intTyOp0 = NULL;
|
||||
IntegerType * intTyOp1 = NULL;
|
||||
IntegerType *intTyOp0 = NULL;
|
||||
IntegerType *intTyOp1 = NULL;
|
||||
unsigned max_size = 0, cast_size = 0;
|
||||
unsigned char attr = 0;
|
||||
std::vector<Value *> args;
|
||||
|
||||
CmpInst *cmpInst = dyn_cast<CmpInst>(selectcmpInst);
|
||||
unsigned attr = 0, vector_cnt = 0;
|
||||
CmpInst * cmpInst = dyn_cast<CmpInst>(selectcmpInst);
|
||||
|
||||
if (!cmpInst) { continue; }
|
||||
|
||||
@ -327,7 +328,23 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
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 LLVM_VERSION_MAJOR >= 11
|
||||
|| ty0->isBFloatTy()
|
||||
@ -342,13 +359,35 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
max_size = 80;
|
||||
else if (ty0->isFP128Ty() || ty0->isPPC_FP128Ty())
|
||||
max_size = 128;
|
||||
#if LLVM_MAJOR > 11
|
||||
else if (ty0->getTypeID() != llvm::Type::PointerTyID && !be_quiet)
|
||||
fprintf(stderr, "Warning: unsupported cmp type for cmplog: %u!\n",
|
||||
ty0->getTypeID());
|
||||
#endif
|
||||
|
||||
attr += 8;
|
||||
|
||||
} else {
|
||||
|
||||
intTyOp0 = dyn_cast<IntegerType>(op0->getType());
|
||||
intTyOp1 = dyn_cast<IntegerType>(op1->getType());
|
||||
if (ty0->isVectorTy()) {
|
||||
|
||||
#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) {
|
||||
|
||||
@ -356,11 +395,28 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
? intTyOp0->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); }
|
||||
|
||||
@ -393,26 +449,60 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
uint64_t cur = 0, last_val0 = 0, last_val1 = 0, cur_val;
|
||||
|
||||
while (1) {
|
||||
|
||||
std::vector<Value *> args;
|
||||
uint32_t skip = 0;
|
||||
|
||||
if (vector_cnt) {
|
||||
|
||||
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) {
|
||||
|
||||
cur_val = i0->getZExtValue();
|
||||
if (last_val0 && last_val0 == cur_val) { skip = 1; }
|
||||
last_val0 = cur_val;
|
||||
|
||||
}
|
||||
|
||||
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, 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)
|
||||
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, op1->getType()->getPrimitiveSizeInBits()));
|
||||
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
|
||||
// errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " <<
|
||||
// *V1
|
||||
// << "\n";
|
||||
|
||||
ConstantInt *attribute = ConstantInt::get(Int8Ty, attr);
|
||||
@ -459,6 +549,15 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
/* else fprintf(stderr, "skipped\n"); */
|
||||
|
||||
++cur;
|
||||
if (cur >= vector_cnt) { break; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (icomps.size())
|
||||
|
@ -579,15 +579,15 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
|
||||
/* dependent on the cmp of the high parts go to the end or go on with
|
||||
* the comparison */
|
||||
auto term = bb->getTerminator();
|
||||
BranchInst *br = nullptr;
|
||||
|
||||
if (pred == CmpInst::ICMP_EQ) {
|
||||
|
||||
br = BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb);
|
||||
BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb);
|
||||
|
||||
} else {
|
||||
|
||||
/* CmpInst::ICMP_NE */
|
||||
br = BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb);
|
||||
// CmpInst::ICMP_NE
|
||||
BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb);
|
||||
|
||||
}
|
||||
|
||||
|
@ -120,6 +120,17 @@ static u8 count_class_lookup[256] = {
|
||||
#undef TIMES8
|
||||
#undef TIMES4
|
||||
|
||||
static void kill_child() {
|
||||
|
||||
if (fsrv.child_pid > 0) {
|
||||
|
||||
kill(fsrv.child_pid, fsrv.kill_signal);
|
||||
fsrv.child_pid = -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void classify_counts(u8 *mem) {
|
||||
|
||||
u32 i = map_size;
|
||||
@ -1053,6 +1064,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
fsrv.target_path = find_binary(argv[optind]);
|
||||
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
|
||||
signal(SIGALRM, kill_child);
|
||||
|
||||
if (qemu_mode) {
|
||||
|
||||
|
14
src/afl-cc.c
14
src/afl-cc.c
@ -423,6 +423,8 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
||||
|
||||
char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
|
||||
cc_params[cc_par_cnt++] = fplugin_arg;
|
||||
cc_params[cc_par_cnt++] = "-fno-if-conversion";
|
||||
cc_params[cc_par_cnt++] = "-fno-if-conversion2";
|
||||
|
||||
}
|
||||
|
||||
@ -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-")) ||
|
||||
!strncmp(cur, "-fsanitize-coverage", strlen("-fsanitize-coverage"))) &&
|
||||
(strncmp(cur, "sanitize-coverage-allow",
|
||||
@ -1007,8 +1017,12 @@ static void edit_params(u32 argc, char **argv, char **envp) {
|
||||
}
|
||||
|
||||
// prevent unnecessary build errors
|
||||
if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) {
|
||||
|
||||
cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
|
||||
|
||||
}
|
||||
|
||||
if (preprocessor_only || have_c) {
|
||||
|
||||
/* In the preprocessor_only case (-E), we are not actually compiling at
|
||||
|
@ -217,11 +217,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
|
||||
char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
|
||||
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
|
||||
|
||||
memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
|
||||
new_argv[argc + 3] = NULL;
|
||||
|
||||
new_argv[2] = *target_path_p;
|
||||
new_argv[1] = "--";
|
||||
@ -237,11 +236,10 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
|
||||
|
||||
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
|
||||
|
||||
char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
|
||||
char **new_argv = ck_alloc(sizeof(char *) * (argc + 2));
|
||||
if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
|
||||
|
||||
memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
|
||||
new_argv[argc + 2] = NULL;
|
||||
|
||||
new_argv[1] = *target_path_p;
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
rlen = 0;
|
||||
if (fsrv->exec_tmout) {
|
||||
if (fsrv->init_tmout) {
|
||||
|
||||
u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
|
||||
stop_soon_p);
|
||||
|
||||
if (!time_ms) {
|
||||
|
||||
if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); }
|
||||
s32 tmp_pid = fsrv->fsrv_pid;
|
||||
if (tmp_pid > 0) {
|
||||
|
||||
kill(tmp_pid, fsrv->kill_signal);
|
||||
fsrv->fsrv_pid = -1;
|
||||
|
||||
}
|
||||
|
||||
} else if (time_ms > fsrv->init_tmout) {
|
||||
|
||||
fsrv->last_run_timed_out = 1;
|
||||
if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); }
|
||||
s32 tmp_pid = fsrv->fsrv_pid;
|
||||
if (tmp_pid > 0) {
|
||||
|
||||
kill(tmp_pid, fsrv->kill_signal);
|
||||
fsrv->fsrv_pid = -1;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@ -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,
|
||||
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;
|
||||
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++;
|
||||
|
||||
|
@ -317,8 +317,9 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
|
||||
|
||||
}
|
||||
|
||||
sprintf(ret + strlen(ret), ",time:%llu",
|
||||
get_cur_time() + afl->prev_run_time - afl->start_time);
|
||||
sprintf(ret + strlen(ret), ",time:%llu,execs:%llu",
|
||||
get_cur_time() + afl->prev_run_time - afl->start_time,
|
||||
afl->fsrv.total_execs);
|
||||
|
||||
if (afl->current_custom_fuzz &&
|
||||
afl->current_custom_fuzz->afl_custom_describe) {
|
||||
|
@ -1325,8 +1325,8 @@ void pivot_inputs(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", afl->out_dir, id,
|
||||
use_name);
|
||||
nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
|
||||
afl->out_dir, id, afl->fsrv.total_execs, use_name);
|
||||
|
||||
#else
|
||||
|
||||
@ -2815,43 +2815,6 @@ void check_binary(afl_state_t *afl, u8 *fname) {
|
||||
|
||||
}
|
||||
|
||||
/* Trim and possibly create a banner for the run. */
|
||||
|
||||
void fix_up_banner(afl_state_t *afl, u8 *name) {
|
||||
|
||||
if (!afl->use_banner) {
|
||||
|
||||
if (afl->sync_id) {
|
||||
|
||||
afl->use_banner = afl->sync_id;
|
||||
|
||||
} else {
|
||||
|
||||
u8 *trim = strrchr(name, '/');
|
||||
if (!trim) {
|
||||
|
||||
afl->use_banner = name;
|
||||
|
||||
} else {
|
||||
|
||||
afl->use_banner = trim + 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (strlen(afl->use_banner) > 32) {
|
||||
|
||||
u8 *tmp = ck_alloc(36);
|
||||
sprintf(tmp, "%.32s...", afl->use_banner);
|
||||
afl->use_banner = tmp;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Check if we're on TTY. */
|
||||
|
||||
void check_if_tty(afl_state_t *afl) {
|
||||
|
@ -442,6 +442,7 @@ void show_stats(afl_state_t *afl) {
|
||||
u64 cur_ms;
|
||||
u32 t_bytes, t_bits;
|
||||
|
||||
static u8 banner[128];
|
||||
u32 banner_len, banner_pad;
|
||||
u8 tmp[256];
|
||||
u8 time_tmp[64];
|
||||
@ -657,26 +658,34 @@ void show_stats(afl_state_t *afl) {
|
||||
}
|
||||
|
||||
/* Let's start by drawing a centered banner. */
|
||||
if (unlikely(!banner[0])) {
|
||||
|
||||
banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) +
|
||||
strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5;
|
||||
char *si = "";
|
||||
if (afl->sync_id) { si = afl->sync_id; }
|
||||
memset(banner, 0, sizeof(banner));
|
||||
banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
|
||||
strlen(afl->power_name) + 4 + 6;
|
||||
|
||||
if (strlen(afl->use_banner) + banner_len > 75) {
|
||||
|
||||
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(tmp, ' ', banner_pad);
|
||||
memset(banner, ' ', banner_pad);
|
||||
|
||||
#ifdef HAVE_AFFINITY
|
||||
sprintf(
|
||||
tmp + banner_pad,
|
||||
"%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}",
|
||||
afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
|
||||
afl->use_banner, afl->power_name, afl->cpu_aff);
|
||||
#else
|
||||
sprintf(
|
||||
tmp + banner_pad, "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]",
|
||||
afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
|
||||
afl->use_banner, afl->power_name);
|
||||
#endif /* HAVE_AFFINITY */
|
||||
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", tmp);
|
||||
}
|
||||
|
||||
SAYF("\n%s\n", banner);
|
||||
|
||||
/* "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)) {
|
||||
|
||||
@ -1218,6 +1228,8 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
|
||||
|
||||
if (!afl->use_banner) { afl->use_banner = argv[optind]; }
|
||||
|
||||
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
|
||||
|
||||
WARNF(cLRD
|
||||
@ -1486,9 +1498,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
save_cmdline(afl, argc, argv);
|
||||
|
||||
fix_up_banner(afl, argv[optind]);
|
||||
|
||||
check_if_tty(afl);
|
||||
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
|
||||
|
||||
@ -1697,7 +1706,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
|
||||
afl->fsrv.frida_mode || afl->unicorn_mode) {
|
||||
|
||||
map_size = afl->fsrv.map_size = MAP_SIZE;
|
||||
map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
|
||||
afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
|
||||
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
|
||||
afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size);
|
||||
|
@ -77,7 +77,7 @@ static u32 tcnt, highest; /* tuple content information */
|
||||
|
||||
static u32 in_len; /* Input data length */
|
||||
|
||||
static u32 map_size = MAP_SIZE;
|
||||
static u32 map_size = MAP_SIZE, timed_out = 0;
|
||||
|
||||
static bool quiet_mode, /* Hide non-essential messages? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
@ -146,6 +146,18 @@ static const u8 count_class_binary[256] = {
|
||||
#undef TIMES8
|
||||
#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) {
|
||||
|
||||
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))) {
|
||||
|
||||
if (strcmp(outfile, "-")) {
|
||||
|
||||
// create empty file to prevent error messages in afl-cmin
|
||||
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
@ -359,9 +374,10 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
|
||||
|
||||
if (!quiet_mode) {
|
||||
|
||||
if (fsrv->last_run_timed_out) {
|
||||
if (timed_out || fsrv->last_run_timed_out) {
|
||||
|
||||
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
||||
timed_out = 0;
|
||||
|
||||
} else if (stop_soon) {
|
||||
|
||||
@ -523,6 +539,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
signal(SIGALRM, kill_child);
|
||||
|
||||
setitimer(ITIMER_REAL, &it, NULL);
|
||||
|
||||
if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
|
||||
@ -565,9 +583,10 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
if (!quiet_mode) {
|
||||
|
||||
if (fsrv->last_run_timed_out) {
|
||||
if (timed_out || fsrv->last_run_timed_out) {
|
||||
|
||||
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
||||
timed_out = 0;
|
||||
|
||||
} else if (stop_soon) {
|
||||
|
||||
|
@ -120,6 +120,17 @@ static const u8 count_class_lookup[256] = {
|
||||
#undef TIMES8
|
||||
#undef TIMES4
|
||||
|
||||
static void kill_child() {
|
||||
|
||||
if (fsrv->child_pid > 0) {
|
||||
|
||||
kill(fsrv->child_pid, fsrv->kill_signal);
|
||||
fsrv->child_pid = -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
|
||||
sharedmem_t * shm_fuzz) {
|
||||
|
||||
@ -1125,6 +1136,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
fsrv->target_path = find_binary(argv[optind]);
|
||||
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
|
||||
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
|
||||
signal(SIGALRM, kill_child);
|
||||
|
||||
if (fsrv->qemu_mode) {
|
||||
|
||||
|
@ -88,6 +88,8 @@ unset AFL_QEMU_PERSISTENT_GPR
|
||||
unset AFL_QEMU_PERSISTENT_RET
|
||||
unset AFL_QEMU_PERSISTENT_HOOK
|
||||
unset AFL_QEMU_PERSISTENT_CNT
|
||||
unset AFL_QEMU_PERSISTENT_MEM
|
||||
unset AFL_QEMU_PERSISTENT_EXITS
|
||||
unset AFL_CUSTOM_MUTATOR_LIBRARY
|
||||
unset AFL_PYTHON_MODULE
|
||||
unset AFL_PRELOAD
|
||||
|
@ -1 +1 @@
|
||||
d4915053d477dd827b3fe4b494173d3fbf9f456e
|
||||
94617f5b
|
||||
|
@ -1,4 +1,5 @@
|
||||
add_executable(optimin OptiMin.cpp)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
|
||||
foreach(LIB MaLib EvalMaxSAT glucose)
|
||||
target_include_directories(optimin PRIVATE
|
||||
|
@ -6,6 +6,6 @@ for sending input to stdin which the target binary will think is coming from
|
||||
a network socket.
|
||||
|
||||
This is desock_dup.c from the amazing preeny project
|
||||
https://github.com/zardus/preeny
|
||||
[https://github.com/zardus/preeny](https://github.com/zardus/preeny)
|
||||
|
||||
It is packaged in AFL++ to have it at hand if needed
|
||||
|
Loading…
x
Reference in New Issue
Block a user