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

102
README.md
View File

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

View File

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

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

View File

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

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!!*
* (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.
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).

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

View File

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

View File

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

View File

@ -33,6 +33,7 @@
js_api_set_stats_interval;
js_api_set_stderr;
js_api_set_stdout;
js_api_set_traceable;
local:
*;

View File

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

View File

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

View File

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

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__
#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
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -274,13 +274,14 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
Value *op0 = selectcmpInst->getOperand(0);
Value *op1 = selectcmpInst->getOperand(1);
Value *op0_saved = op0, *op1_saved = op1;
auto ty0 = op0->getType();
auto ty1 = op1->getType();
IntegerType *intTyOp0 = NULL;
IntegerType *intTyOp1 = NULL;
unsigned max_size = 0, cast_size = 0;
unsigned char attr = 0;
std::vector<Value *> args;
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())

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

View File

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

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

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

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. */
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++;

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

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

View File

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

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

View File

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

View File

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

View File

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

View File

@ -1 +1 @@
d4915053d477dd827b3fe4b494173d3fbf9f456e
94617f5b

View File

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

View File

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