Merge pull request #1142 from AFLplusplus/dev

Dev
This commit is contained in:
van Hauser 2021-11-03 21:55:21 +01:00 committed by GitHub
commit f5535e348d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 986 additions and 255 deletions

104
README.md
View File

@ -6,7 +6,8 @@ Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 3.15a GitHub version: 3.15a
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
AFL++ is maintained by: AFL++ is maintained by:
@ -17,57 +18,74 @@ AFL++ is maintained by:
Originally developed by Michał "lcamtuf" Zalewski. Originally developed by Michał "lcamtuf" Zalewski.
AFL++ is a superior fork to Google's AFL - more speed, more and better mutations, more and better instrumentation, custom module support, etc. AFL++ is a superior fork to Google's AFL - more speed, more and better
mutations, more and better instrumentation, custom module support, etc.
You are free to copy, modify, and distribute AFL++ with attribution under the terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details. You are free to copy, modify, and distribute AFL++ with attribution under the
terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
## Getting started ## Getting started
Here is some information to get you started: Here is some information to get you started:
* For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab and [branches](docs/branches.md). Also take a look at the list of [major 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:
@ -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 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.

View File

@ -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

View File

@ -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

View File

@ -96,6 +96,16 @@
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
@ -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)

View File

@ -7,4 +7,5 @@ The following branches exist:
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state of AFL++ - bleeding edge and you might catch a checkout which does not compile or has a bug. *We only accept PRs in dev!!* * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state of AFL++ - bleeding edge and you might catch a checkout which does not compile or has a bug. *We only accept PRs in dev!!*
* (any other): experimental branches to work on specific features or testing new functionality or changes. * (any other): experimental branches to work on specific features or testing new functionality or changes.
For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab. Also take a look at the list of [major 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).

View File

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

View File

@ -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/)

View File

@ -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))" ""

View File

@ -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

View File

@ -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:
*; *;

View File

@ -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

View File

@ -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); }

View File

@ -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"]);

View File

@ -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;
}

View File

@ -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
} }

View File

@ -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;

View File

@ -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>

View File

@ -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"),

View File

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

View File

@ -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",

View File

@ -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);
} }

View File

@ -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,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++) for (size_t i = 0, N = AllBlocks.size(); i < N; i++)
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc); InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
instr += special;
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);
} }

View File

@ -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! */

View File

@ -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;

View File

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

View File

@ -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,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 " << // errs() << "[CMPLOG] cmp " << *cmpInst << "(in function " <<
// cmpInst->getFunction()->getName() << ")\n"; // cmpInst->getFunction()->getName() << ")\n";
// first bitcast to integer type of the same bitsize as the original // first bitcast to integer type of the same bitsize as the original
// type (this is a nop, if already integer) // type (this is a nop, if already integer)
Value *op0_i = IRB.CreateBitCast( Value *op0_i = IRB.CreateBitCast(
op0, IntegerType::get(C, op0->getType()->getPrimitiveSizeInBits())); op0, IntegerType::get(C, ty0->getPrimitiveSizeInBits()));
// then create a int cast, which does zext, trunc or bitcast. In our case // then create a int cast, which does zext, trunc or bitcast. In our
// usually zext to the next larger supported type (this is a nop if // case usually zext to the next larger supported type (this is a nop
// already the right type) // if already the right type)
Value *V0 = Value *V0 =
IRB.CreateIntCast(op0_i, IntegerType::get(C, cast_size), false); IRB.CreateIntCast(op0_i, IntegerType::get(C, cast_size), false);
args.push_back(V0); args.push_back(V0);
Value *op1_i = IRB.CreateBitCast( Value *op1_i = IRB.CreateBitCast(
op1, IntegerType::get(C, op1->getType()->getPrimitiveSizeInBits())); op1, IntegerType::get(C, ty1->getPrimitiveSizeInBits()));
Value *V1 = Value *V1 =
IRB.CreateIntCast(op1_i, IntegerType::get(C, cast_size), false); IRB.CreateIntCast(op1_i, IntegerType::get(C, cast_size), false);
args.push_back(V1); args.push_back(V1);
// errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " << *V1 // errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " <<
// *V1
// << "\n"; // << "\n";
ConstantInt *attribute = ConstantInt::get(Int8Ty, attr); 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()) if (icomps.size())

View File

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

View File

@ -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) {

View File

@ -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,8 +1017,12 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} }
// prevent unnecessary build errors // prevent unnecessary build errors
if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) {
cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument";
}
if (preprocessor_only || have_c) { if (preprocessor_only || have_c) {
/* In the preprocessor_only case (-E), we are not actually compiling at /* In the preprocessor_only case (-E), we are not actually compiling at

View File

@ -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;

View File

@ -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++;

View File

@ -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) {

View File

@ -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) {

View File

@ -442,6 +442,7 @@ void show_stats(afl_state_t *afl) {
u64 cur_ms; u64 cur_ms;
u32 t_bytes, t_bits; u32 t_bytes, t_bits;
static u8 banner[128];
u32 banner_len, banner_pad; u32 banner_len, banner_pad;
u8 tmp[256]; u8 tmp[256];
u8 time_tmp[64]; u8 time_tmp[64];
@ -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; }
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; banner_pad = (79 - banner_len) / 2;
memset(tmp, ' ', banner_pad); memset(banner, ' ', banner_pad);
#ifdef HAVE_AFFINITY sprintf(banner + banner_pad,
sprintf( "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
tmp + banner_pad, afl->crash_mode ? cPIN "peruvian were-rabbit"
"%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}", : cYEL "american fuzzy lop",
afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", si, afl->use_banner, afl->power_name);
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); }
SAYF("\n%s\n", banner);
/* "Handy" shortcuts for drawing boxes... */ /* "Handy" shortcuts for drawing boxes... */

View File

@ -1189,7 +1189,17 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->sync_id) { fix_up_sync(afl); } if (afl->sync_id) {
if (strlen(afl->sync_id) > 24) {
FATAL("sync_id max length is 24 characters");
}
fix_up_sync(afl);
}
if (!strcmp(afl->in_dir, afl->out_dir)) { if (!strcmp(afl->in_dir, afl->out_dir)) {
@ -1218,6 +1228,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); } if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
if (!afl->use_banner) { afl->use_banner = argv[optind]; }
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
WARNF(cLRD WARNF(cLRD
@ -1486,9 +1498,6 @@ int main(int argc, char **argv_orig, char **envp) {
} }
save_cmdline(afl, argc, argv); save_cmdline(afl, argc, argv);
fix_up_banner(afl, argv[optind]);
check_if_tty(afl); check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }
@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -1 +1 @@
d4915053d477dd827b3fe4b494173d3fbf9f456e 94617f5b

View File

@ -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

View File

@ -6,6 +6,6 @@ for sending input to stdin which the target binary will think is coming from
a network socket. a network socket.
This is desock_dup.c from the amazing preeny project This is desock_dup.c from the amazing preeny project
https://github.com/zardus/preeny [https://github.com/zardus/preeny](https://github.com/zardus/preeny)
It is packaged in AFL++ to have it at hand if needed It is packaged in AFL++ to have it at hand if needed