mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
Merge branch 'debug' into taint
This commit is contained in:
@ -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
|
||||
|
||||
|
18
README.md
18
README.md
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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); \
|
||||
|
@ -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
|
||||
|
@ -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"))) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user