Merge branch 'debug' into taint

This commit is contained in:
van Hauser
2020-08-11 03:40:12 +02:00
committed by GitHub
15 changed files with 187 additions and 84 deletions

View File

@ -98,7 +98,7 @@ ifneq "$(shell uname -m)" "x86_64"
endif
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
override CFLAGS += -g -Wno-pointer-sign \
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
@ -198,6 +198,7 @@ else
endif
ifneq "$(filter Linux GNU%,$(shell uname))" ""
override CFLAGS += -D_FORTIFY_SOURCE=2
LDFLAGS += -ldl -lrt
endif

View File

@ -71,18 +71,18 @@ only new bytes in the other cycle.
Android support and much, much, much more.
| Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode | unicorn_mode |
| ------------------------ |:-------:|:---------:|:----------:|:----------------:|:------------:|
| NeverZero | x | x(1) | (2) | x | x |
| Persistent mode | | x | x | x86[_64]/arm[64] | x |
| -------------------------|:-------:|:---------:|:----------:|:----------------:|:------------:|
| NeverZero | x86[_64]| x(1) | (2) | x | x |
| Persistent Mode | | x | x | x86[_64]/arm[64] | x |
| LAF-Intel / CompCov | | x | | x86[_64]/arm[64] | x86[_64]/arm |
| CmpLog | | x | | x86[_64]/arm[64] | |
| Selective instrumentation| | x | x | (x)(3) | |
| Non-colliding coverage | | x(4) | | (x)(5) | |
| Selective Instrumentation| | x | x | (x)(3) | |
| Non-Colliding Coverage | | x(4) | | (x)(5) | |
| InsTrim | | x | | | |
| Ngram prev_loc coverage | | x(6) | | | |
| Context coverage | | x | | | |
| Auto dictionary | | x(7) | | | |
| Snapshot LKM support | | x | | (x)(5) | |
| Ngram prev_loc Coverage | | x(6) | | | |
| Context Coverage | | x | | | |
| Auto Dictionary | | x(7) | | | |
| Snapshot LKM Support | | x | | (x)(5) | |
1. default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8
2. GCC creates non-performant code, hence it is disabled in gcc_plugin

View File

@ -28,6 +28,9 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
sancov, and also supports function matching!
- fixes for laf-intel float splitting (thanks to mark-griffin for
reporting)
- LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR
for a fixed map address (eg. 0x10000)
- LTO: skipping ctors and ifuncs in fix map address instrumentation
- LTO: autodictionary mode is a default
- LTO: instrim instrumentation disabled, only classic support used
as it is always better

View File

@ -670,6 +670,7 @@ typedef struct afl_state {
struct custom_mutator {
const char *name;
char * name_short;
void * dh;
u8 * post_process_buf;
size_t post_process_size;

View File

@ -28,11 +28,6 @@
#include "types.h"
#include "config.h"
/* __FUNCTION__ is non-iso */
#ifdef __func__
#define __FUNCTION__ __func__
#endif
/*******************
* Terminal colors *
*******************/
@ -228,7 +223,7 @@
\
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __FUNCTION__, \
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, __LINE__); \
exit(1); \
\
@ -241,7 +236,7 @@
\
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] PROGRAM ABORT : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __FUNCTION__, \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
__FILE__, __LINE__); \
abort(); \
\
@ -255,7 +250,7 @@
fflush(stdout); \
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
"\n[-] SYSTEM ERROR : " cRST x); \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __FUNCTION__, \
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \
__FILE__, __LINE__); \
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \
exit(1); \

View File

@ -17,9 +17,6 @@ This version requires a current llvm 11+ compiled from the github master.
5. If any problems arise be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`.
Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`.
6. If a target uses _init functions or early constructors then additionally
set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise!
## Introduction and problem description
A big issue with how afl/afl++ works is that the basic block IDs that are
@ -128,14 +125,14 @@ on start. This improves coverage statistically by 5-10% :)
## Fixed memory map
To speed up fuzzing, the shared memory map is hard set to a specific address,
by default 0x10000. In most cases this will work without any problems.
To speed up fuzzing, it is possible to set a fixed shared memory map.
Recommened is the value 0x10000.
In most cases this will work without any problems. However if a target uses
early constructors, ifuncs or a deferred forkserver this can crash the target.
On unusual operating systems/processors/kernels or weird libraries this might
fail so to change the fixed address at compile time set
AFL_LLVM_MAP_ADDR with a better value (a value of 0 or empty sets the map address
to be dynamic - the original afl way, which is slower).
AFL_LLVM_MAP_DYNAMIC can be set so the shared memory address is dynamic (which
is safer but also slower).
## Document edge IDs
@ -262,15 +259,6 @@ If this succeeeds then there is an issue with afl-clang-lto. Please report at
Even some targets where clang-12 fails can be build if the fail is just in
`./configure`, see `Solving difficult targets` above.
### Target crashes immediately
If the target is using early constructors (priority values smaller than 6)
or have their own _init/.init functions and these are instrumented then the
target will likely crash when started. This can be avoided by compiling with
`AFL_LLVM_MAP_DYNAMIC=1` .
This can e.g. happen with OpenSSL.
## History
This was originally envisioned by hexcoder- in Summer 2019, however we saw no

View File

@ -49,6 +49,7 @@
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Pass.h"
#include "llvm/IR/Constants.h"
#include "afl-llvm-common.h"
@ -135,7 +136,10 @@ bool AFLLTOPass::runOnModule(Module &M) {
if (getenv("AFL_LLVM_LTO_AUTODICTIONARY")) autodictionary = 1;
if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0;
// we make this the default as the fixed map has problems with
// defered forkserver, early constructors, ifuncs and maybe more
/*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
map_addr = 0;
if (getenv("AFL_LLVM_SKIPSINGLEBLOCK")) function_minimum_size = 2;
@ -196,7 +200,8 @@ bool AFLLTOPass::runOnModule(Module &M) {
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
/* This dumps all inialized global strings - might be useful in the future
// This dumps all inialized global strings - might be useful in the future
/*
for (auto G=M.getGlobalList().begin(); G!=M.getGlobalList().end(); G++) {
GlobalVariable &GV=*G;
@ -214,18 +219,114 @@ bool AFLLTOPass::runOnModule(Module &M) {
*/
std::vector<std::string> module_block_list;
if (map_addr) {
for (GlobalIFunc &IF : M.ifuncs()) {
StringRef ifunc_name = IF.getName();
Constant *r = IF.getResolver();
StringRef r_name = cast<Function>(r->getOperand(0))->getName();
if (!be_quiet)
fprintf(stderr,
"Warning: Found an ifunc with name %s that points to resolver "
"function %s, we cannot instrument this, putting it into a "
"block list.\n",
ifunc_name.str().c_str(), r_name.str().c_str());
module_block_list.push_back(r_name.str());
}
GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors");
if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) {
ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
if (InitList) {
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
if (ConstantStruct *CS =
dyn_cast<ConstantStruct>(InitList->getOperand(i))) {
if (CS->getNumOperands() >= 2) {
if (CS->getOperand(1)->isNullValue())
break; // Found a null terminator, stop here.
ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
int Priority = CI ? CI->getSExtValue() : 0;
Constant *FP = CS->getOperand(1);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
if (CE->isCast()) FP = CE->getOperand(0);
if (Function *F = dyn_cast<Function>(FP)) {
if (!F->isDeclaration() &&
strncmp(F->getName().str().c_str(), "__afl", 5) != 0 &&
Priority <= 5) {
if (!be_quiet)
fprintf(stderr,
"Warning: Found constructor function %s with prio "
"%u, we cannot instrument this, putting it into a "
"block list.\n",
F->getName().str().c_str(), Priority);
module_block_list.push_back(F->getName().str());
}
}
}
}
}
}
}
}
/* Instrument all the things! */
int inst_blocks = 0;
for (auto &F : M) {
// fprintf(stderr, "DEBUG: Module %s Function %s\n",
// M.getName().str().c_str(), F.getName().str().c_str());
/*For debugging
AttributeSet X = F.getAttributes().getFnAttributes();
fprintf(stderr, "DEBUG: Module %s Function %s attributes %u\n",
M.getName().str().c_str(), F.getName().str().c_str(),
X.getNumAttributes());
*/
if (F.size() < function_minimum_size) continue;
if (isIgnoreFunction(&F)) continue;
if (module_block_list.size()) {
for (auto bname : module_block_list) {
std::string fname = F.getName().str();
if (fname.compare(bname) == 0) {
if (!be_quiet)
WARNF(
"Skipping instrumentation of dangerous early running function "
"%s",
fname.c_str());
}
}
}
// the instrument file list check
AttributeList Attrs = F.getAttributes();
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {

View File

@ -329,10 +329,13 @@ static void __afl_map_shm(void) {
id_str = getenv(CMPLOG_SHM_ENV_VAR);
if (getenv("AFL_DEBUG"))
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "DEBUG: cmplog id_str %s\n",
id_str == NULL ? "<null>" : id_str);
}
if (id_str) {
#ifdef USEMMAP
@ -404,9 +407,12 @@ static void __afl_start_snapshots(void) {
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
if (getenv("AFL_DEBUG"))
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "target forkserver recv: %08x\n", was_killed);
}
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
@ -613,9 +619,12 @@ static void __afl_start_forkserver(void) {
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
if (getenv("AFL_DEBUG"))
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "target forkserver recv: %08x\n", was_killed);
}
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
@ -936,8 +945,12 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
u32 inst_ratio = 100;
char *x;
fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n", start,
stop);
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n",
start, stop);
}
if (start == stop || *start) return;

View File

@ -293,8 +293,8 @@ static void report_error_and_exit(int error) {
FATAL(
"the fuzzing target reports that hardcoded map address might be the "
"reason the mmap of the shared memory failed. Solution: recompile "
"the target with either afl-clang-lto and the environment variable "
"AFL_LLVM_MAP_DYNAMIC set or recompile with afl-clang-fast.");
"the target with either afl-clang-lto and do not set "
"AFL_LLVM_MAP_ADDR or recompile with afl-clang-fast.");
break;
case FS_ERROR_SHM_OPEN:
FATAL("the fuzzing target reports that the shm_open() call failed.");
@ -838,8 +838,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
SAYF("\n" cLRD "[-] " cRST
"Hmm, looks like the target binary terminated before we could"
" complete a handshake with the injected code.\n"
"If the target was compiled with afl-clang-lto then recompiling with"
" AFL_LLVM_MAP_DYNAMIC might solve your problem.\n"
"If the target was compiled with afl-clang-lto and AFL_LLVM_MAP_ADDR"
" then recompiling without this parameter.\n"
"Otherwise there is a horrible bug in the fuzzer.\n"
"Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
@ -870,9 +870,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
" - the target was compiled with afl-clang-lto and a constructor "
"was\n"
" instrumented, recompiling with AFL_LLVM_MAP_DYNAMIC might solve "
"your\n"
" problem\n\n"
" instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve "
"your problem\n\n"
" - Less likely, there is a horrible bug in the fuzzer. If other "
"options\n"

View File

@ -29,10 +29,6 @@
#include "afl-fuzz.h"
#include "cmplog.h"
typedef struct cmplog_data {
} cmplog_data_t;
void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);

View File

@ -142,6 +142,7 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
mutator->name = fn;
mutator->name_short = strrchr(fn, '/') + 1;
ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);

View File

@ -1764,6 +1764,8 @@ custom_mutator_stage:
has_custom_fuzz = true;
afl->stage_short = el->name_short;
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
++afl->stage_cur) {

View File

@ -138,7 +138,7 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
/* The same, but with an adjustable gap. Used for trimming. */
static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at,
static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
u32 skip_len) {
s32 fd = afl->fsrv.out_fd;

View File

@ -300,9 +300,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->cpu_to_bind != -1) FATAL("Multiple -b options not supported");
if (sscanf(optarg, "%u", &afl->cpu_to_bind) < 0 || optarg[0] == '-')
if (sscanf(optarg, "%d", &afl->cpu_to_bind) < 0) {
FATAL("Bad syntax used for -b");
}
break;
}

View File

@ -120,7 +120,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
}
} || {
$ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
INCOMPLETE=1
#this is not incomplete as this feature doesnt exist, so all good
}
. ./test-post.sh