Merge branch 'dev' into newpm2

This commit is contained in:
van Hauser
2022-03-17 16:30:29 +01:00
committed by GitHub
42 changed files with 980 additions and 493 deletions

View File

@ -76,9 +76,9 @@ else
endif endif
endif endif
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" #ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli # SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
endif #endif
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" #ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
# ifndef SOURCE_DATE_EPOCH # ifndef SOURCE_DATE_EPOCH
@ -92,12 +92,10 @@ ifneq "$(SYS)" "Darwin"
# SPECIAL_PERFORMANCE += -march=native # SPECIAL_PERFORMANCE += -march=native
#endif #endif
# OS X does not like _FORTIFY_SOURCE=2 # OS X does not like _FORTIFY_SOURCE=2
ifndef DEBUG ifndef DEBUG
CFLAGS_OPT += -D_FORTIFY_SOURCE=2 CFLAGS_OPT += -D_FORTIFY_SOURCE=2
endif endif
endif else
ifeq "$(SYS)" "Darwin"
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly # On some odd MacOS system configurations, the Xcode sdk path is not set correctly
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
LDFLAGS += $(SDK_LD) LDFLAGS += $(SDK_LD)
@ -144,12 +142,13 @@ ifdef DEBUG
$(info Compiling DEBUG version of binaries) $(info Compiling DEBUG version of binaries)
override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT) override CFLAGS += -ggdb3 -O0 -Wall -Wextra -Werror $(CFLAGS_OPT)
else else
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) CFLAGS ?= -O2 $(CFLAGS_OPT) # -funroll-loops is slower on modern compilers
endif endif
override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \ override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpointer-arith \
-fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \ -fPIC -I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
# -fstack-protector
ifeq "$(SYS)" "FreeBSD" ifeq "$(SYS)" "FreeBSD"
override CFLAGS += -I /usr/local/include/ override CFLAGS += -I /usr/local/include/
@ -175,7 +174,7 @@ ifeq "$(SYS)" "Haiku"
SHMAT_OK=0 SHMAT_OK=0
override CFLAGS += -DUSEMMAP=1 -Wno-error=format override CFLAGS += -DUSEMMAP=1 -Wno-error=format
override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork override LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
SPECIAL_PERFORMANCE += -DUSEMMAP=1 #SPECIAL_PERFORMANCE += -DUSEMMAP=1
endif endif
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
@ -247,9 +246,6 @@ else
endif endif
ifneq "$(filter Linux GNU%,$(SYS))" "" ifneq "$(filter Linux GNU%,$(SYS))" ""
ifndef DEBUG
override CFLAGS += -D_FORTIFY_SOURCE=2
endif
override LDFLAGS += -ldl -lrt -lm override LDFLAGS += -ldl -lrt -lm
endif endif
@ -426,7 +422,7 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
@ln -sf afl-as as @ln -sf afl-as as
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
$(CC) $(CFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o $(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o $(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o

View File

@ -112,7 +112,7 @@ Step-by-step quick start:
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. if your target is using stdin:
``` ```
cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...] cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]

View File

@ -12,6 +12,9 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix */build_...sh scripts to work outside of git - fix */build_...sh scripts to work outside of git
- new custom_mutator: libafl with token fuzzing :) - new custom_mutator: libafl with token fuzzing :)
- afl-fuzz: - afl-fuzz:
- when you just want to compile once and set CMPLOG, then just
set -c 0 to tell afl-fuzz that the fuzzing binary is also for
CMPLOG.
- new commandline options -g/G to set min/max length of generated - new commandline options -g/G to set min/max length of generated
fuzz inputs fuzz inputs
- reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow - reintroduced AFL_PERSISTENT and AFL_DEFER_FORKSRV to allow

View File

@ -48,11 +48,12 @@ The following setup to use QEMU mode is recommended:
Then run as many instances as you have cores left with either -Q mode or - even Then run as many instances as you have cores left with either -Q mode or - even
better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc. better - use a binary rewriter like Dyninst, RetroWrite, ZAFL, etc.
The binary rewriters all have their own advantages and caveats.
ZAFL is the best but cannot be used in a business/commercial context.
If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for your If a binary rewriter works for your target then you can use afl-fuzz normally
binary, then you can use afl-fuzz normally and it will have twice the speed and it will have twice the speed compared to QEMU mode (but slower than QEMU
compared to QEMU mode (but slower than QEMU persistent mode). Note that several persistent mode).
other binary rewriters exist, all with their advantages and caveats.
The speed decrease of QEMU mode is at about 50%. However, various options exist The speed decrease of QEMU mode is at about 50%. However, various options exist
to increase the speed: to increase the speed:

View File

@ -817,9 +817,9 @@ Here are some of the most important caveats for AFL++:
- There is no direct support for fuzzing network services, background daemons, - There is no direct support for fuzzing network services, background daemons,
or interactive apps that require UI interaction to work. You may need to make or interactive apps that require UI interaction to work. You may need to make
simple code changes to make them behave in a more traditional way. Preeny may simple code changes to make them behave in a more traditional way. Preeny or libdesock may
offer a relatively simple option, too - see: offer a relatively simple option, too - see:
[https://github.com/zardus/preeny](https://github.com/zardus/preeny) [https://github.com/zardus/preeny](https://github.com/zardus/preeny) or [https://github.com/fkie-cad/libdesock](https://github.com/fkie-cad/libdesock)
Some useful tips for modifying network-based services can be also found at: Some useful tips for modifying network-based services can be also found at:
[https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop) [https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)

View File

@ -151,25 +151,25 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
* `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks * `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
and their instrumented counterparts during block compilation. and their instrumented counterparts during block compilation.
``` Creating block for 0x7ffff7953313:
*** 0x7ffff7953313 mov qword ptr [rax], 0
0x7ffff795331a add rsp, 8
0x7ffff795331e ret
Creating block for 0x7ffff7953313: Generated block 0x7ffff75e98e2
0x7ffff7953313 mov qword ptr [rax], 0 0x7ffff75e98e2 mov qword ptr [rax], 0
0x7ffff795331a add rsp, 8 0x7ffff75e98e9 add rsp, 8
0x7ffff795331e ret 0x7ffff75e98ed lea rsp, [rsp - 0x80]
0x7ffff75e98f5 push rcx
0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
0x7ffff75e9900 jmp 0x7ffff75e9384
Generated block 0x7ffff75e98e2
0x7ffff75e98e2 mov qword ptr [rax], 0
0x7ffff75e98e9 add rsp, 8
0x7ffff75e98ed lea rsp, [rsp - 0x80]
0x7ffff75e98f5 push rcx
0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
0x7ffff75e9900 jmp 0x7ffff75e9384
*** ***
``` ```
* `AFL_FRIDA_INST_CACHE_SIZE` - Set the size of the instrumentation cache used
as a look-up table to cache real to instrumented address block translations.
Default is 256Mb.
* `AFL_FRIDA_INST_INSN` - Generate instrumentation for conditional * `AFL_FRIDA_INST_INSN` - Generate instrumentation for conditional
instructions (e.g. `CMOV` instructions on x64). instructions (e.g. `CMOV` instructions on x64).
* `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled * `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled
@ -178,6 +178,8 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
instrumentation (the default where available). Required to use instrumentation (the default where available). Required to use
`AFL_FRIDA_INST_TRACE`. `AFL_FRIDA_INST_TRACE`.
* `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to
instrumented address block translations.
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will * `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will
report instrumented blocks back to the parent so that it can also instrument report instrumented blocks back to the parent so that it can also instrument
them and they be inherited by the next child on fork, implies them and they be inherited by the next child on fork, implies

View File

@ -9,8 +9,10 @@
js_api_done; js_api_done;
js_api_error; js_api_error;
js_api_set_backpatch_disable; js_api_set_backpatch_disable;
js_api_set_cache_disable;
js_api_set_debug_maps; js_api_set_debug_maps;
js_api_set_entrypoint; js_api_set_entrypoint;
js_api_set_instrument_cache_size;
js_api_set_instrument_coverage_file; js_api_set_instrument_coverage_file;
js_api_set_instrument_debug_file; js_api_set_instrument_debug_file;
js_api_set_instrument_jit; js_api_set_instrument_jit;

View File

@ -22,6 +22,9 @@ extern uint32_t __afl_map_size;
extern __thread guint64 *instrument_previous_pc_addr; extern __thread guint64 *instrument_previous_pc_addr;
extern gboolean instrument_cache_enabled;
extern gsize instrument_cache_size;
void instrument_config(void); void instrument_config(void);
void instrument_init(void); void instrument_init(void);
@ -59,5 +62,10 @@ void instrument_on_fork(void);
guint64 instrument_get_offset_hash(GumAddress current_rip); guint64 instrument_get_offset_hash(GumAddress current_rip);
void instrument_cache_config(void);
void instrument_cache_init(void);
void instrument_cache_insert(gpointer real_address, gpointer code_address);
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output);
#endif #endif

View File

@ -5,6 +5,14 @@
#include "debug.h" #include "debug.h"
#ifndef MAP_FIXED_NOREPLACE
#ifdef MAP_EXCL
#define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
#else
#define MAP_FIXED_NOREPLACE MAP_FIXED
#endif
#endif
#define UNUSED_PARAMETER(x) (void)(x) #define UNUSED_PARAMETER(x) (void)(x)
#define IGNORED_RETURN(x) (void)!(x) #define IGNORED_RETURN(x) (void)!(x)

View File

@ -249,6 +249,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
} }
instrument_cache(instr, output);
if (js_stalker_callback(instr, begin, excluded, output)) { if (js_stalker_callback(instr, begin, excluded, output)) {
gum_stalker_iterator_keep(iterator); gum_stalker_iterator_keep(iterator);
@ -282,6 +284,7 @@ void instrument_config(void) {
instrument_coverage_config(); instrument_coverage_config();
asan_config(); asan_config();
cmplog_config(); cmplog_config();
instrument_cache_config();
} }
@ -392,6 +395,7 @@ void instrument_init(void) {
instrument_coverage_init(); instrument_coverage_init();
instrument_coverage_optimize_init(); instrument_coverage_optimize_init();
instrument_debug_init(); instrument_debug_init();
instrument_cache_init();
} }

View File

@ -5,6 +5,9 @@
#if defined(__arm__) #if defined(__arm__)
gboolean instrument_cache_enabled = FALSE;
gsize instrument_cache_size = 0;
gboolean instrument_is_coverage_optimize_supported(void) { gboolean instrument_is_coverage_optimize_supported(void) {
return false; return false;
@ -55,5 +58,27 @@ gpointer instrument_cur(GumStalkerOutput *output) {
} }
void instrument_cache_config(void) {
}
void instrument_cache_init(void) {
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
UNUSED_PARAMETER(real_address);
UNUSED_PARAMETER(code_address);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
#endif #endif

View File

@ -379,5 +379,27 @@ gpointer instrument_cur(GumStalkerOutput *output) {
} }
void instrument_cache_config(void) {
}
void instrument_cache_init(void) {
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
UNUSED_PARAMETER(real_address);
UNUSED_PARAMETER(code_address);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
#endif #endif

View File

@ -202,10 +202,17 @@ static void instrument_coverage_switch(GumStalkerObserver *self,
} }
if (op[0].type != X86_OP_IMM) { return; } if (op[0].type != X86_OP_IMM) {
instrument_cache_insert(start_address, *target);
return;
}
break; break;
case X86_INS_RET: case X86_INS_RET:
instrument_cache_insert(start_address,
(guint8 *)*target + sizeof(afl_log_code));
break; break;
default: default:
return; return;

View File

@ -0,0 +1,435 @@
#include <sys/mman.h>
#include <sys/resource.h>
#include "instrument.h"
#include "util.h"
#if defined(__x86_64__)
#define INVALID 1
#define DEFAULT_CACHE_SIZE (256ULL << 20)
gboolean instrument_cache_enabled = TRUE;
gsize instrument_cache_size = DEFAULT_CACHE_SIZE;
static gpointer *map_base = MAP_FAILED;
void instrument_cache_config(void) {
instrument_cache_enabled = (getenv("AFL_FRIDA_INST_NO_CACHE") == NULL);
if (getenv("AFL_FRIDA_INST_CACHE_SIZE") != NULL) {
if (!instrument_cache_enabled) {
FFATAL(
"AFL_FRIDA_INST_CACHE_SIZE incomatible with "
"AFL_FRIDA_INST_NO_CACHE");
}
instrument_cache_size =
util_read_address("AFL_FRIDA_INST_CACHE_SIZE", DEFAULT_CACHE_SIZE);
util_log2(instrument_cache_size);
}
}
void instrument_cache_init(void) {
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache:" cYEL " [%c]",
instrument_cache_enabled ? 'X' : ' ');
if (!instrument_cache_enabled) { return; }
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache size:" cYEL " [0x%016lX]",
instrument_cache_size);
const struct rlimit data_limit = {.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY};
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
FFATAL("Failed to setrlimit: %d", errno);
}
map_base =
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
GUM_PAGE_READ | GUM_PAGE_WRITE);
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
GUM_ADDRESS(map_base));
}
static gpointer *instrument_cache_get_addr(gpointer addr) {
gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1;
return &map_base[GPOINTER_TO_SIZE(addr) & mask];
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
if (!instrument_cache_enabled) { return; }
gpointer *target = instrument_cache_get_addr(real_address);
if (*target == code_address) {
return;
} else if (*target == NULL) {
*target = code_address;
} else {
*target = GSIZE_TO_POINTER(INVALID);
}
}
static gboolean instrument_cache_relocate(GumAddress old_pc, GumAddress new_pc,
gint32 old_offset,
gint32 *new_offset) {
guint64 old_target = old_pc + old_offset;
gint64 relocated = old_target - new_pc;
if (relocated > G_MAXINT32 || relocated < G_MININT32) { return FALSE; }
*new_offset = relocated;
return TRUE;
}
static void instrument_cache_rewrite_branch_insn(const cs_insn * instr,
GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
cs_x86 * x86 = &instr->detail->x86;
guint8 modified[sizeof(instr->bytes)] = {0};
guint8 offset = 0;
guint8 skip = 0;
g_assert(sizeof(x86->prefix) == 4);
g_assert(sizeof(x86->opcode) == 4);
/*
* If the target is simply RAX, we can skip writing the code to load the
* RIP
*/
if (x86->operands[0].type == X86_OP_REG ||
x86->operands[0].reg == X86_REG_RAX) {
return;
}
/* Write the prefix */
for (gsize i = 0; i < sizeof(x86->prefix); i++) {
if (x86->prefix[i] != 0) {
if (x86->prefix[i] == 0xf2) {
skip++;
} else {
modified[offset++] = x86->prefix[i];
skip++;
}
}
}
/* Write the REX */
if (x86->rex == 0) {
/*
* CALL (near) and JMP (near) default to 64-bit operands, MOV does not,
* write REX.W
*/
modified[offset++] = 0x48;
} else {
if ((x86->rex & 0xF8) != 0x40) {
FATAL("Unexpected REX byte: 0x%02x", x86->rex);
}
modified[offset++] = x86->rex | 0x08;
skip++;
}
/*
* CALL is FF /2, JMP is FF /4. The remaining op-code fields should thus be
* unused
*/
if (x86->opcode[0] != 0xFF || x86->opcode[1] != 0x00 ||
x86->opcode[2] != 0x00 || x86->opcode[3] != 0x00) {
FFATAL("Unexpected Op-code: 0x%02x 0x%02x 0x%02x 0x%02x", x86->opcode[0],
x86->opcode[1], x86->opcode[2], x86->opcode[3]);
}
/* The reg field of the ModRM should be set to 2 for CALL and 4 for JMP */
guint8 reg = (x86->modrm >> 3) & 7;
if (reg != 0x4 && reg != 0x2) {
FFATAL("Unexpected Reg: 0x%02x, ModRM: 0x%02x", reg, x86->modrm);
}
/* MOV */
modified[offset++] = 0x8b;
skip++;
/* Clear the reg field (RAX) */
modified[offset++] = x86->modrm & 0xc7;
skip++;
/* Operands */
guint8 op_len = instr->size - skip;
/* If our branch was RIP relative, we'll need to fix-up the offset */
if (x86->operands[0].type == X86_OP_MEM &&
x86->operands[0].mem.base == X86_REG_RIP) {
/* RIP relative offsets should be 32-bits */
if (op_len != sizeof(gint32)) {
FFATAL("Unexpected operand length: %d\n", op_len);
}
gint32 old_offset = *(gint32 *)&instr->bytes[skip];
gint32 new_offset = 0;
if (instrument_cache_relocate(instr->address, cw->pc, old_offset,
&new_offset)) {
gint32 *output = (gint32 *)&modified[offset];
*output = new_offset;
offset += sizeof(gint32);
} else {
GumAddress target = instr->address + old_offset;
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, target);
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_RAX, GUM_REG_RAX);
return;
}
} else {
for (int i = 0; i < op_len; i++) {
guint8 val = instr->bytes[i + skip];
modified[offset++] = val;
}
}
gum_x86_writer_put_bytes(cw, modified, offset);
}
static void instrument_cache_write_push_frame(GumX86Writer *cw) {
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))),
GUM_REG_XAX);
gum_x86_writer_put_lahf(cw);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))),
GUM_REG_XAX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))),
GUM_REG_XBX);
}
static void instrument_cache_write_pop_frame(GumX86Writer *cw) {
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_REG_XBX, GUM_REG_XSP,
-(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))));
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_REG_XAX, GUM_REG_XSP,
-(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))));
gum_x86_writer_put_sahf(cw);
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_REG_XAX, GUM_REG_XSP,
-(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))));
}
static void instrument_cache_write_lookup(GumX86Writer *cw) {
/* &map_base[GPOINTER_TO_SIZE(addr) & MAP_MASK]; */
gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1;
gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, mask);
gum_x86_writer_put_and_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX);
gum_x86_writer_put_shl_reg_u8(cw, GUM_REG_XAX, util_log2(sizeof(gpointer)));
gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, GPOINTER_TO_SIZE(map_base));
gum_x86_writer_put_add_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX);
/* Read the return address lookup */
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XAX);
}
void instrument_cache_jmp_call(const cs_insn *instr, GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
cs_x86 * x86 = &instr->detail->x86;
if (x86->op_count != 1) { FFATAL("Unexpected operand count"); }
if (x86->operands[0].type == X86_OP_IMM) { return; }
gconstpointer null = cw->code;
instrument_cache_write_push_frame(cw);
/*
* We are about to re-write the CALL or JMP instruction, but replace the
* op-code with that for a MOV into RAX. Since we are keeping the operand from
* the JMP exactly the same, it is imperative that the target register state
* be exactly the same as how the target left it. Since `LAHF` spoils `RAX` we
* must restore it from the stack. We also must avoid adjusting `RSP`, so we
* use `MOV` instructions to store our context into the stack beyond the
* red-zone.
*/
gum_x86_writer_put_mov_reg_reg_offset_ptr(
cw, GUM_REG_XAX, GUM_REG_XSP,
-(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))));
instrument_cache_rewrite_branch_insn(instr, output);
instrument_cache_write_lookup(cw);
/* Test if its set*/
gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID);
gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY);
/* If it's set, then stash the address beyond the red-zone */
gum_x86_writer_put_mov_reg_offset_ptr_reg(
cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))),
GUM_REG_XAX);
if (instr->id == X86_INS_JMP) {
instrument_cache_write_pop_frame(cw);
gum_x86_writer_put_jmp_reg_offset_ptr(
cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))));
} else {
gum_x86_writer_put_mov_reg_address(
cw, GUM_REG_XAX, GUM_ADDRESS(instr->address + instr->size));
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_XSP,
-sizeof(gpointer), GUM_REG_XAX);
instrument_cache_write_pop_frame(cw);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_XSP, GUM_REG_XSP,
-sizeof(gpointer));
gum_x86_writer_put_jmp_reg_offset_ptr(
cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + ((4 - 1) * sizeof(gpointer))));
}
/* Tidy up our mess and let FRIDA handle it */
gum_x86_writer_put_label(cw, null);
instrument_cache_write_pop_frame(cw);
}
void instrument_cache_ret(const cs_insn *instr, GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
cs_x86 * x86 = &instr->detail->x86;
guint16 n = 0;
if (x86->op_count != 0) {
if (x86->operands[0].type != X86_OP_IMM) {
FFATAL("Unexpected operand type");
}
n = x86->operands[0].imm;
}
gconstpointer null = cw->code;
instrument_cache_write_push_frame(cw);
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XSP);
instrument_cache_write_lookup(cw);
/* Test if its set*/
gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID);
gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY);
/* If it's set, then overwrite our return address and return */
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_XSP, GUM_REG_XAX);
instrument_cache_write_pop_frame(cw);
if (n == 0) {
gum_x86_writer_put_ret(cw);
} else {
gum_x86_writer_put_ret_imm(cw, n);
}
/* Tidy up our mess and let FRIDA handle it */
gum_x86_writer_put_label(cw, null);
instrument_cache_write_pop_frame(cw);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
if (!instrument_cache_enabled) { return; }
switch (instr->id) {
case X86_INS_RET:
instrument_cache_ret(instr, output);
break;
case X86_INS_CALL:
case X86_INS_JMP:
instrument_cache_jmp_call(instr, output);
break;
default:
return;
}
}
#endif

View File

@ -6,6 +6,9 @@
#if defined(__i386__) #if defined(__i386__)
gboolean instrument_cache_enabled = FALSE;
gsize instrument_cache_size = 0;
static GHashTable *coverage_blocks = NULL; static GHashTable *coverage_blocks = NULL;
#pragma pack(push, 1) #pragma pack(push, 1)
@ -242,5 +245,27 @@ gpointer instrument_cur(GumStalkerOutput *output) {
} }
void instrument_cache_config(void) {
}
void instrument_cache_init(void) {
}
void instrument_cache_insert(gpointer real_address, gpointer code_address) {
UNUSED_PARAMETER(real_address);
UNUSED_PARAMETER(code_address);
}
void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
}
#endif #endif

View File

@ -68,6 +68,12 @@ class Afl {
static setBackpatchDisable() { static setBackpatchDisable() {
Afl.jsApiSetBackpatchDisable(); Afl.jsApiSetBackpatchDisable();
} }
/**
* See `AFL_FRIDA_INST_NO_CACHE`.
*/
static setCacheDisable() {
Afl.jsApiSetCacheDisable();
}
/** /**
* See `AFL_FRIDA_DEBUG_MAPS`. * See `AFL_FRIDA_DEBUG_MAPS`.
*/ */
@ -91,6 +97,13 @@ class Afl {
static setInMemoryFuzzing() { static setInMemoryFuzzing() {
Afl.jsApiAflSharedMemFuzzing.writeInt(1); Afl.jsApiAflSharedMemFuzzing.writeInt(1);
} }
/**
* See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number`
* as an argument.
*/
static setInstrumentCacheSize(size) {
Afl.jsApiSetInstrumentCacheSize(size);
}
/** /**
* See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string`
* as an argument. * as an argument.
@ -299,8 +312,10 @@ Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing");
Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []); Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []);
Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]); Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]);
Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []); Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []);
Afl.jsApiSetCacheDisable = Afl.jsApiGetFunction("js_api_set_cache_disable", "void", []);
Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []); Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []);
Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]); Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]);
Afl.jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction("js_api_set_instrument_cache_size", "void", ["size_t"]);
Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]); Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]); Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []); Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []);

View File

@ -262,6 +262,19 @@ __attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks(
} }
__attribute__((visibility("default"))) void js_api_set_cache_disable(void) {
instrument_cache_enabled = FALSE;
}
__attribute__((visibility("default"))) void js_api_set_instrument_cache_size(
gsize size) {
instrument_cache_size = size;
}
__attribute__((visibility("default"))) void js_api_set_js_main_hook( __attribute__((visibility("default"))) void js_api_set_js_main_hook(
const js_main_hook_t hook) { const js_main_hook_t hook) {

97
frida_mode/test/cache/GNUmakefile vendored Normal file
View File

@ -0,0 +1,97 @@
PWD:=$(shell pwd)/
ROOT:=$(PWD)../../../
BUILD_DIR:=$(PWD)build/
TEST_CACHE_SRC:=$(PWD)cache.c
TEST_CACHE_OBJ:=$(BUILD_DIR)cache
TEST_DATA_DIR:=$(BUILD_DIR)in/
CACHE_INPUT:=$(TEST_DATA_DIR)in
QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out
ADDR_BIN:=$(ROOT)frida_mode/build/addr
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_CACHE_OBJ) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
DUMMY_DATA_FILE:=$(BUILD_DIR)dummy.dat
.PHONY: all 32 clean frida frida_noinst debug format
all: $(TEST_CACHE_OBJ)
make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR):
mkdir -p $@
$(TEST_DATA_DIR): | $(BUILD_DIR)
mkdir -p $@
$(CACHE_INPUT): | $(TEST_DATA_DIR)
echo -n "ABC" > $@
$(TEST_CACHE_OBJ): $(TEST_CACHE_SRC) | $(BUILD_DIR)
$(CC) -g $(CFLAGS) $(LDFLAGS) $< -o $@
########## DUMMY #######
$(DUMMY_DATA_FILE): | $(BUILD_DIR)
dd if=/dev/zero bs=1048576 count=1 of=$@
frida: $(TEST_CACHE_OBJ) $(CACHE_INPUT) $(DUMMY_DATA_FILE)
AFL_FRIDA_INST_INSN=1 \
AFL_FRIDA_PERSISTENT_CNT=1000000 \
AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
$(ROOT)afl-fuzz \
-O \
-i $(TEST_DATA_DIR) \
-o $(FRIDA_OUT) \
-Z \
-t 10000+ \
-- \
$(TEST_CACHE_OBJ) $(DUMMY_DATA_FILE)
frida_nocache: $(TEST_CACHE_OBJ) $(CACHE_INPUT) $(DUMMY_DATA_FILE)
AFL_FRIDA_INST_NO_CACHE=1 \
AFL_FRIDA_PERSISTENT_CNT=1000000 \
AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
$(ROOT)afl-fuzz \
-O \
-i $(TEST_DATA_DIR) \
-o $(FRIDA_OUT) \
-Z \
-- \
$(TEST_CACHE_OBJ) $(DUMMY_DATA_FILE)
debug: $(TEST_CACHE_OBJ) $(CACHE_INPUT)
gdb \
--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
--ex 'set disassembly-flavor intel' \
--ex 'r $(CACHE_INPUT)' \
--args $(TEST_CACHE_OBJ) $(CACHE_INPUT)
show: $(TEST_CACHE_OBJ) $(CACHE_INPUT)
gdb \
--ex "set disassembly-flavor intel" \
--ex "set confirm off" \
--ex "symbol-file $(TEST_CACHE_OBJ)" \
--ex "x/50i LLVMFuzzerTestOneInput" \
--ex "r" \
--args $(TEST_CACHE_OBJ) $(CACHE_INPUT)
clean:
rm -rf $(BUILD_DIR)
format:
cd $(ROOT) && echo $(TEST_CACHE_SRC) | xargs -L1 ./.custom-format.py -i

22
frida_mode/test/cache/Makefile vendored Normal file
View File

@ -0,0 +1,22 @@
all:
@echo trying to use GNU make...
@gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
frida:
@gmake frida
frida_nocache:
@gmake frida_nocache
debug:
@gmake debug
clean:
@gmake clean
format:
@gmake format

115
frida_mode/test/cache/cache.c vendored Normal file
View File

@ -0,0 +1,115 @@
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void LLVMFuzzerTestOneInput(char *buf, int len);
__asm__ (
"LLVMFuzzerTestOneInput:\n"
".func LLVMFuzzerTestOneInput\n"
".global LLVMFuzzerTestOneInput\n"
" jmpq *jmp_offset(%rip)\n"
" nop\n"
" nop\n"
"call_target:\n"
" ret\n"
" nop\n"
" nop\n"
"jmp_target:\n"
" callq *call_offset(%rip)\n"
" nop\n"
" nop\n"
" leaq rax_offset(%rip), %rax\n"
" jmp (%rax)\n"
" nop\n"
" ud2\n"
" nop\n"
"rax_target:\n"
" ret\n"
"\n"
"\n"
".global jmp_offset\n"
".p2align 3\n"
"jmp_offset:\n"
" .quad jmp_target\n"
"call_offset:\n"
" .quad call_target\n"
"rax_offset:\n"
" .quad rax_target\n"
);
int main(int argc, char **argv) {
char * file;
int fd = -1;
off_t len;
char * buf = NULL;
size_t n_read;
int result = -1;
if (argc != 2) { return 1; }
do {
file = argv[1];
dprintf(STDERR_FILENO, "Running: %s\n", file);
fd = open(file, O_RDONLY);
if (fd < 0) {
perror("open");
break;
}
len = lseek(fd, 0, SEEK_END);
if (len < 0) {
perror("lseek (SEEK_END)");
break;
}
if (lseek(fd, 0, SEEK_SET) != 0) {
perror("lseek (SEEK_SET)");
break;
}
buf = (char *)malloc(len);
if (buf == NULL) {
perror("malloc");
break;
}
n_read = read(fd, buf, len);
if (n_read != len) {
perror("read");
break;
}
dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read);
LLVMFuzzerTestOneInput(buf, len);
dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
result = 0;
} while (false);
if (buf != NULL) { free(buf); }
if (fd != -1) { close(fd); }
return result;
}

View File

@ -125,7 +125,7 @@ vorbis: $(VORBIS_LIB)
########## HARNESS ####### ########## HARNESS #######
$(DECODE_SRC): $(DECODE_SRC):
wget -O $@ $(DECODE_URL) wget -O $@ $(DECODE_URL) || curl -L -o $@ $(DECODE_URL)
$(DECODE_OBJ): $(DECODE_SRC) $(DECODE_OBJ): $(DECODE_SRC)
$(CXX) -o $@ -c $< -I$(VORBIS_DIR)include/ -I$(OGG_DIR)include/ $(CXX) -o $@ -c $< -I$(VORBIS_DIR)include/ -I$(OGG_DIR)include/
@ -135,7 +135,7 @@ decode: $(DECODE_OBJ)
########## HARNESS ####### ########## HARNESS #######
$(HARNESS_SRC): $(HARNESS_SRC):
wget -O $@ $(HARNESS_URL) wget -O $@ $(HARNESS_URL) || curl -L -o $@ $(HARNESS_URL)
$(HARNESS_OBJ): $(HARNESS_SRC) $(HARNESS_OBJ): $(HARNESS_SRC)
$(CC) -o $@ -c $< $(CC) -o $@ -c $<
@ -165,8 +165,8 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
###### TEST DATA ####### ###### TEST DATA #######
$(TEST_DATA_FILE): $(TEST_DATA_DIR) $(TEST_DATA_FILE): | $(TEST_DATA_DIR)
wget -O $@ $(TEST_DATA_SRC) wget -O $@ $(TEST_DATA_SRC) || curl -L -o $@ $(TEST_DATA_SRC)
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)

View File

@ -84,6 +84,13 @@ class Afl {
Afl.jsApiSetBackpatchDisable(); Afl.jsApiSetBackpatchDisable();
} }
/**
* See `AFL_FRIDA_INST_NO_CACHE`.
*/
public static setCacheDisable(): void {
Afl.jsApiSetCacheDisable();
}
/** /**
* See `AFL_FRIDA_DEBUG_MAPS`. * See `AFL_FRIDA_DEBUG_MAPS`.
*/ */
@ -110,6 +117,14 @@ class Afl {
Afl.jsApiAflSharedMemFuzzing.writeInt(1); Afl.jsApiAflSharedMemFuzzing.writeInt(1);
} }
/**
* See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number`
* as an argument.
*/
public static setInstrumentCacheSize(size: number): void {
Afl.jsApiSetInstrumentCacheSize(size);
}
/** /**
* See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string`
* as an argument. * as an argument.
@ -354,6 +369,11 @@ class Afl {
"void", "void",
[]); []);
private static readonly jsApiSetCacheDisable = Afl.jsApiGetFunction(
"js_api_set_cache_disable",
"void",
[]);
private static readonly jsApiSetDebugMaps = Afl.jsApiGetFunction( private static readonly jsApiSetDebugMaps = Afl.jsApiGetFunction(
"js_api_set_debug_maps", "js_api_set_debug_maps",
"void", "void",
@ -364,6 +384,11 @@ class Afl {
"void", "void",
["pointer"]); ["pointer"]);
private static readonly jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction(
"js_api_set_instrument_cache_size",
"void",
["size_t"]);
private static readonly jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction( private static readonly jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction(
"js_api_set_instrument_coverage_file", "js_api_set_instrument_coverage_file",
"void", "void",

View File

@ -57,10 +57,12 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_DEBUG_MAPS",
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_DRIVER_NO_HOOK",
"AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_EXCLUDE_RANGES",
"AFL_FRIDA_INST_CACHE_SIZE",
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_COVERAGE_FILE",
"AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
"AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_INSN",
"AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_JIT",
"AFL_FRIDA_INST_NO_CACHE",
"AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_OPTIMIZE",
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH",
"AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",

View File

@ -70,6 +70,8 @@ typedef struct {
enum NyxReturnValue (*nyx_exec)(void *qemu_process); enum NyxReturnValue (*nyx_exec)(void *qemu_process);
uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process); uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process);
size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process); size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process);
uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer,
uint32_t size);
} nyx_plugin_handler_t; } nyx_plugin_handler_t;
@ -173,6 +175,7 @@ typedef struct afl_forkserver {
void * nyx_runner; /* nyx runner object */ void * nyx_runner; /* nyx runner object */
u32 nyx_id; /* nyx runner id (0 -> master) */ u32 nyx_id; /* nyx runner id (0 -> master) */
u32 nyx_bind_cpu_id; /* nyx runner cpu id */ u32 nyx_bind_cpu_id; /* nyx runner cpu id */
char * nyx_aux_string;
#endif #endif
} afl_forkserver_t; } afl_forkserver_t;

View File

@ -46,21 +46,12 @@ typedef long double max_align_t;
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ #include "llvm/IR/LegacyPassManager.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/PassManager.h"
#else
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
#include "llvm/IR/BasicBlock.h" #include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ #include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Passes/OptimizationLevel.h"
#endif
#if LLVM_VERSION_MAJOR >= 4 || \ #if LLVM_VERSION_MAJOR >= 4 || \
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
@ -78,30 +69,17 @@ using namespace llvm;
namespace { namespace {
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
class AFLCoverage : public PassInfoMixin<AFLCoverage> {
public:
AFLCoverage() {
#else
class AFLCoverage : public ModulePass { class AFLCoverage : public ModulePass {
public: public:
static char ID; static char ID;
AFLCoverage() : ModulePass(ID) { AFLCoverage() : ModulePass(ID) {
#endif
initInstrumentList(); initInstrumentList();
} }
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
#else
bool runOnModule(Module &M) override; bool runOnModule(Module &M) override;
#endif
protected: protected:
uint32_t ngram_size = 0; uint32_t ngram_size = 0;
@ -115,55 +93,7 @@ class AFLCoverage : public ModulePass {
} // namespace } // namespace
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1",
/* lambda to insert our pass into the pass pipeline. */
[](PassBuilder &PB) {
#if 1
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(AFLCoverage());
});
/* TODO LTO registration */
#else
using PipelineElement = typename PassBuilder::PipelineElement;
PB.registerPipelineParsingCallback([](StringRef Name,
ModulePassManager &MPM,
ArrayRef<PipelineElement>) {
if (Name == "AFLCoverage") {
MPM.addPass(AFLCoverage());
return true;
} else {
return false;
}
});
#endif
}};
}
#else
char AFLCoverage::ID = 0; char AFLCoverage::ID = 0;
#endif
/* needed up to 3.9.0 */ /* needed up to 3.9.0 */
#if LLVM_VERSION_MAJOR == 3 && \ #if LLVM_VERSION_MAJOR == 3 && \
@ -189,15 +119,8 @@ uint64_t PowerOf2Ceil(unsigned in) {
(LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1) (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
#define AFL_HAVE_VECTOR_INTRINSICS 1 #define AFL_HAVE_VECTOR_INTRINSICS 1
#endif #endif
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) {
#else
bool AFLCoverage::runOnModule(Module &M) { bool AFLCoverage::runOnModule(Module &M) {
#endif
LLVMContext &C = M.getContext(); LLVMContext &C = M.getContext();
IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
@ -211,10 +134,6 @@ bool AFLCoverage::runOnModule(Module &M) {
u32 rand_seed; u32 rand_seed;
unsigned int cur_loc = 0; unsigned int cur_loc = 0;
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */ /* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
gettimeofday(&tv, &tz); gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
@ -1079,15 +998,10 @@ bool AFLCoverage::runOnModule(Module &M) {
} }
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
#else
return true; return true;
#endif
} }
#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */
static void registerAFLPass(const PassManagerBuilder &, static void registerAFLPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
@ -1100,5 +1014,4 @@ static RegisterStandardPasses RegisterAFLPass(
static RegisterStandardPasses RegisterAFLPass0( static RegisterStandardPasses RegisterAFLPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass); PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);
#endif

View File

@ -28,6 +28,7 @@
#include "llvm/Config/llvm-config.h" #include "llvm/Config/llvm-config.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -37,6 +38,7 @@
#include "llvm/IR/PassManager.h" #include "llvm/IR/PassManager.h"
#else #else
#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif #endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
@ -687,7 +689,7 @@ bool CmpLogInstructions::runOnModule(Module &M) {
} }
#if LLVM_MAJOR < 11 /* use old pass manager */ #if LLVM_MAJOR < 11 /* use old pass manager */
static void registerCmpLogInstructionsPass(const PassManagerBuilder &, static void registerCmpLogInstructionsPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
@ -708,4 +710,3 @@ static RegisterStandardPasses RegisterCmpLogInstructionsPassLTO(
registerCmpLogInstructionsPass); registerCmpLogInstructionsPass);
#endif #endif
#endif #endif

View File

@ -26,23 +26,14 @@
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#if LLVM_MAJOR >= 11 /* use new pass manager */ #include "llvm/IR/LegacyPassManager.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/PassManager.h"
#else
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/ValueTracking.h"
#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */
#include "llvm/Passes/OptimizationLevel.h"
#endif
#if LLVM_VERSION_MAJOR >= 4 || \ #if LLVM_VERSION_MAJOR >= 4 || \
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
@ -61,21 +52,12 @@ using namespace llvm;
namespace { namespace {
#if LLVM_MAJOR >= 11 /* use new pass manager */
class CompareTransform : public PassInfoMixin<CompareTransform> {
public:
CompareTransform() {
#else
class CompareTransform : public ModulePass { class CompareTransform : public ModulePass {
public: public:
static char ID; static char ID;
CompareTransform() : ModulePass(ID) { CompareTransform() : ModulePass(ID) {
#endif
initInstrumentList(); initInstrumentList();
} }
@ -88,18 +70,17 @@ class CompareTransform : public ModulePass {
const char *getPassName() const override { const char *getPassName() const override {
#endif #endif
return "transforms compare functions";
return "cmplog transform";
} }
#endif #endif
#if LLVM_MAJOR >= 11 /* use new pass manager */ //#if LLVM_MAJOR >= 11 /* use new pass manager */
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); // PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
#else //#else
bool runOnModule(Module &M) override; bool runOnModule(Module &M) override;
#endif //#endif
private: private:
bool transformCmps(Module &M, const bool processStrcmp, bool transformCmps(Module &M, const bool processStrcmp,
@ -111,54 +92,7 @@ class CompareTransform : public ModulePass {
} // namespace } // namespace
#if LLVM_MAJOR >= 11 /* use new pass manager */
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1",
/* lambda to insert our pass into the pass pipeline. */
[](PassBuilder &PB) {
#if 1
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(CompareTransform());
});
/* TODO LTO registration */
#else
using PipelineElement = typename PassBuilder::PipelineElement;
PB.registerPipelineParsingCallback([](StringRef Name,
ModulePassManager &MPM,
ArrayRef<PipelineElement>) {
if (Name == "comparetransform") {
MPM.addPass(CompareTransform());
return true;
} else {
return false;
}
});
#endif
}};
}
#else
char CompareTransform::ID = 0; char CompareTransform::ID = 0;
#endif
bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
const bool processMemcmp, const bool processMemcmp,
@ -458,7 +392,6 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
bool isCaseInsensitive = false; bool isCaseInsensitive = false;
bool needs_null = false; bool needs_null = false;
Function * Callee = callInst->getCalledFunction(); Function * Callee = callInst->getCalledFunction();
if (Callee) { if (Callee) {
if (!Callee->getName().compare("memcmp") || if (!Callee->getName().compare("memcmp") ||
@ -716,14 +649,8 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
} }
#if LLVM_MAJOR >= 11 /* use new pass manager */
PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) {
#else
bool CompareTransform::runOnModule(Module &M) { bool CompareTransform::runOnModule(Module &M) {
#endif
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
printf( printf(
"Running compare-transform-pass by laf.intel@gmail.com, extended by " "Running compare-transform-pass by laf.intel@gmail.com, extended by "
@ -731,28 +658,13 @@ bool CompareTransform::runOnModule(Module &M) {
else else
be_quiet = 1; be_quiet = 1;
#if LLVM_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
transformCmps(M, true, true, true, true, true); transformCmps(M, true, true, true, true, true);
verifyModule(M); verifyModule(M);
#if LLVM_MAJOR >= 11 /* use new pass manager */
/* if (modified) {
PA.abandon<XX_Manager>();
}*/
return PA;
#else
return true; return true;
#endif
} }
#if LLVM_MAJOR < 11 /* use old pass manager */
static void registerCompTransPass(const PassManagerBuilder &, static void registerCompTransPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
@ -767,9 +679,8 @@ static RegisterStandardPasses RegisterCompTransPass(
static RegisterStandardPasses RegisterCompTransPass0( static RegisterStandardPasses RegisterCompTransPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass); PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
#if LLVM_VERSION_MAJOR >= 11 #if LLVM_VERSION_MAJOR >= 11
static RegisterStandardPasses RegisterCompTransPassLTO( static RegisterStandardPasses RegisterCompTransPassLTO(
PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass); PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass);
#endif
#endif #endif

View File

@ -1,7 +1,6 @@
/* /*
* Copyright 2016 laf-intel * Copyright 2016 laf-intel
* extended for floating point by Heiko Eißfeldt * extended for floating point by Heiko Eißfeldt
* adapted to new pass manager by Heiko Eißfeldt
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,20 +28,10 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#if LLVM_MAJOR >= 11 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/PassManager.h"
#else
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */
#include "llvm/Passes/OptimizationLevel.h"
#endif
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#if LLVM_VERSION_MAJOR >= 4 || \ #if LLVM_VERSION_MAJOR >= 4 || \
@ -64,31 +53,27 @@ using namespace llvm;
namespace { namespace {
#if LLVM_MAJOR >= 11
class SplitComparesTransform : public PassInfoMixin<SplitComparesTransform> {
public:
// static char ID;
SplitComparesTransform() : enableFPSplit(0) {
#else
class SplitComparesTransform : public ModulePass { class SplitComparesTransform : public ModulePass {
public: public:
static char ID; static char ID;
SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) { SplitComparesTransform() : ModulePass(ID), enableFPSplit(0) {
#endif
initInstrumentList(); initInstrumentList();
} }
#if LLVM_MAJOR >= 11
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
#else
bool runOnModule(Module &M) override; bool runOnModule(Module &M) override;
#if LLVM_VERSION_MAJOR >= 4
StringRef getPassName() const override {
#else
const char *getPassName() const override {
#endif #endif
return "AFL_SplitComparesTransform";
}
private: private:
int enableFPSplit; int enableFPSplit;
@ -177,54 +162,7 @@ class SplitComparesTransform : public ModulePass {
} // namespace } // namespace
#if LLVM_MAJOR >= 11
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "splitcompares", "v0.1",
/* lambda to insert our pass into the pass pipeline. */
[](PassBuilder &PB) {
#if 1
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(SplitComparesTransform());
});
/* TODO LTO registration */
#else
using PipelineElement = typename PassBuilder::PipelineElement;
PB.registerPipelineParsingCallback([](StringRef Name,
ModulePassManager &MPM,
ArrayRef<PipelineElement>) {
if (Name == "splitcompares") {
MPM.addPass(SplitComparesTransform());
return true;
} else {
return false;
}
});
#endif
}};
}
#else
char SplitComparesTransform::ID = 0; char SplitComparesTransform::ID = 0;
#endif
/// This function splits FCMP instructions with xGE or xLE predicates into two /// This function splits FCMP instructions with xGE or xLE predicates into two
/// FCMP instructions with predicate xGT or xLT and EQ /// FCMP instructions with predicate xGT or xLT and EQ
@ -1483,15 +1421,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
} }
#if LLVM_MAJOR >= 11
PreservedAnalyses SplitComparesTransform::run(Module & M,
ModuleAnalysisManager &MAM) {
#else
bool SplitComparesTransform::runOnModule(Module &M) { bool SplitComparesTransform::runOnModule(Module &M) {
#endif
char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW"); char *bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW");
if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW"); if (!bitw_env) bitw_env = getenv("LAF_SPLIT_COMPARES_BITW");
if (bitw_env) { target_bitwidth = atoi(bitw_env); } if (bitw_env) { target_bitwidth = atoi(bitw_env); }
@ -1501,7 +1432,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
getenv("AFL_DEBUG") != NULL) { getenv("AFL_DEBUG") != NULL) {
errs() << "Split-compare-newpass by laf.intel@gmail.com, extended by " errs() << "Split-compare-pass by laf.intel@gmail.com, extended by "
"heiko@hexco.de (splitting icmp to " "heiko@hexco.de (splitting icmp to "
<< target_bitwidth << " bit)\n"; << target_bitwidth << " bit)\n";
@ -1513,10 +1444,6 @@ bool SplitComparesTransform::runOnModule(Module &M) {
} }
#if LLVM_MAJOR >= 11
auto PA = PreservedAnalyses::all();
#endif
if (enableFPSplit) { if (enableFPSplit) {
simplifyFPCompares(M); simplifyFPCompares(M);
@ -1546,16 +1473,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
auto op0 = CI->getOperand(0); auto op0 = CI->getOperand(0);
auto op1 = CI->getOperand(1); auto op1 = CI->getOperand(1);
if (!op0 || !op1) { if (!op0 || !op1) { return false; }
#if LLVM_MAJOR >= 11
return PA;
#else
return false;
#endif
}
auto iTy1 = dyn_cast<IntegerType>(op0->getType()); auto iTy1 = dyn_cast<IntegerType>(op0->getType());
if (iTy1 && isa<IntegerType>(op1->getType())) { if (iTy1 && isa<IntegerType>(op1->getType())) {
@ -1604,29 +1522,10 @@ bool SplitComparesTransform::runOnModule(Module &M) {
} }
if ((isatty(2) && getenv("AFL_QUIET") == NULL) ||
getenv("AFL_DEBUG") != NULL) {
errs() << count << " comparisons found\n";
}
#if LLVM_MAJOR >= 11
/* if (modified) {
PA.abandon<XX_Manager>();
}*/
return PA;
#else
return true; return true;
#endif
} }
#if LLVM_MAJOR < 11 /* use old pass manager */
static void registerSplitComparesPass(const PassManagerBuilder &, static void registerSplitComparesPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
@ -1640,15 +1539,14 @@ static RegisterStandardPasses RegisterSplitComparesPass(
static RegisterStandardPasses RegisterSplitComparesTransPass0( static RegisterStandardPasses RegisterSplitComparesTransPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass); PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
#if LLVM_VERSION_MAJOR >= 11 #if LLVM_VERSION_MAJOR >= 11
static RegisterStandardPasses RegisterSplitComparesTransPassLTO( static RegisterStandardPasses RegisterSplitComparesTransPassLTO(
PassManagerBuilder::EP_FullLinkTimeOptimizationLast, PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
registerSplitComparesPass); registerSplitComparesPass);
#endif #endif
static RegisterPass<SplitComparesTransform> X("splitcompares", static RegisterPass<SplitComparesTransform> X("splitcompares",
"AFL++ split compares", "AFL++ split compares",
true /* Only looks at CFG */, true /* Only looks at CFG */,
true /* Analysis Pass */); true /* Analysis Pass */);
#endif

View File

@ -27,23 +27,14 @@
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ #include "llvm/IR/LegacyPassManager.h"
#include "llvm/Passes/PassPlugin.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/IR/PassManager.h"
#else
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#endif
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/ValueTracking.h"
#if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */
#include "llvm/Passes/OptimizationLevel.h"
#endif
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
#if LLVM_VERSION_MAJOR >= 4 || \ #if LLVM_VERSION_MAJOR >= 4 || \
@ -63,42 +54,29 @@ using namespace llvm;
namespace { namespace {
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
class SplitSwitchesTransform : public PassInfoMixin<SplitSwitchesTransform> {
public:
SplitSwitchesTransform() {
#else
class SplitSwitchesTransform : public ModulePass { class SplitSwitchesTransform : public ModulePass {
public: public:
static char ID; static char ID;
SplitSwitchesTransform() : ModulePass(ID) { SplitSwitchesTransform() : ModulePass(ID) {
#endif
initInstrumentList(); initInstrumentList();
} }
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */ bool runOnModule(Module &M) override;
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
#else
bool runOnModule(Module &M) override;
#if LLVM_VERSION_MAJOR >= 4 #if LLVM_VERSION_MAJOR >= 4
StringRef getPassName() const override { StringRef getPassName() const override {
#else #else
const char *getPassName() const override { const char *getPassName() const override {
#endif #endif
return "splits switch constructs"; return "splits switch constructs";
} }
#endif
struct CaseExpr { struct CaseExpr {
ConstantInt *Val; ConstantInt *Val;
@ -125,54 +103,7 @@ class SplitSwitchesTransform : public ModulePass {
} // namespace } // namespace
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo() {
return {LLVM_PLUGIN_API_VERSION, "splitswitches", "v0.1",
/* lambda to insert our pass into the pass pipeline. */
[](PassBuilder &PB) {
#if 1
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(SplitSwitchesTransform());
});
/* TODO LTO registration */
#else
using PipelineElement = typename PassBuilder::PipelineElement;
PB.registerPipelineParsingCallback([](StringRef Name,
ModulePassManager &MPM,
ArrayRef<PipelineElement>) {
if (Name == "splitswitches") {
MPM.addPass(SplitSwitchesTransform());
return true;
} else {
return false;
}
});
#endif
}};
}
#else
char SplitSwitchesTransform::ID = 0; char SplitSwitchesTransform::ID = 0;
#endif
/* switchConvert - Transform simple list of Cases into list of CaseRange's */ /* switchConvert - Transform simple list of Cases into list of CaseRange's */
BasicBlock *SplitSwitchesTransform::switchConvert( BasicBlock *SplitSwitchesTransform::switchConvert(
@ -482,42 +413,19 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) {
} }
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
PreservedAnalyses SplitSwitchesTransform::run(Module & M,
ModuleAnalysisManager &MAM) {
#else
bool SplitSwitchesTransform::runOnModule(Module &M) { bool SplitSwitchesTransform::runOnModule(Module &M) {
#endif
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
printf("Running split-switches-pass by laf.intel@gmail.com\n"); printf("Running split-switches-pass by laf.intel@gmail.com\n");
else else
be_quiet = 1; be_quiet = 1;
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
splitSwitches(M); splitSwitches(M);
verifyModule(M); verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
/* if (modified) {
PA.abandon<XX_Manager>();
}*/
return PA;
#else
return true; return true;
#endif
} }
#if LLVM_VERSION_MAJOR < 11 /* use old pass manager */
static void registerSplitSwitchesTransPass(const PassManagerBuilder &, static void registerSplitSwitchesTransPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) { legacy::PassManagerBase &PM) {
@ -532,10 +440,9 @@ static RegisterStandardPasses RegisterSplitSwitchesTransPass(
static RegisterStandardPasses RegisterSplitSwitchesTransPass0( static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass); PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);
#if LLVM_VERSION_MAJOR >= 11 #if LLVM_VERSION_MAJOR >= 11
static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO( static RegisterStandardPasses RegisterSplitSwitchesTransPassLTO(
PassManagerBuilder::EP_FullLinkTimeOptimizationLast, PassManagerBuilder::EP_FullLinkTimeOptimizationLast,
registerSplitSwitchesTransPass); registerSplitSwitchesTransPass);
#endif
#endif #endif

View File

@ -1 +1 @@
2e45754 8a77c71

View File

@ -1 +1 @@
76100c5 5d143ee

View File

@ -1 +1 @@
c2c69cfc52 c08e4ac942

View File

@ -7,7 +7,7 @@
#define TRACE_BUFFER_SIZE (64) #define TRACE_BUFFER_SIZE (64)
#define PAGE_SIZE 0x1000 #define PAGE_SIZE 0x1000
#define MMAP_SIZE(x) ((x & ~(PAGE_SIZE-1)) + PAGE_SIZE) #define MMAP_SIZE(x) ((x & ~(PAGE_SIZE - 1)) + PAGE_SIZE)
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -30,8 +30,9 @@ int main(int argc, char **argv) {
/* this is our "bitmap" that is later shared with the fuzzer (you can also /* this is our "bitmap" that is later shared with the fuzzer (you can also
* pass the pointer of the bitmap used by compile-time instrumentations in * pass the pointer of the bitmap used by compile-time instrumentations in
* your target) */ * your target) */
uint8_t *trace_buffer = mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | uint8_t *trace_buffer =
PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); mmap(NULL, MMAP_SIZE(TRACE_BUFFER_SIZE), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
memset(trace_buffer, 0, memset(trace_buffer, 0,
TRACE_BUFFER_SIZE); // makes sure that the bitmap buffer is already TRACE_BUFFER_SIZE); // makes sure that the bitmap buffer is already
// mapped into the guest's memory (alternatively // mapped into the guest's memory (alternatively

View File

@ -514,16 +514,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else { } else {
#if LLVM_MAJOR >= 11
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path);
#else
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
alloc_printf("%s/split-compares-pass.so", obj_path); alloc_printf("%s/split-compares-pass.so", obj_path);
#endif
} }
@ -553,17 +548,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
alloc_printf("%s/cmplog-switches-pass.so", obj_path); alloc_printf("%s/cmplog-switches-pass.so", obj_path);
// reuse split switches from laf // reuse split switches from laf
#if LLVM_MAJOR >= 11
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
#else
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
alloc_printf("%s/split-switches-pass.so", obj_path); alloc_printf("%s/split-switches-pass.so", obj_path);
#endif
} }
@ -571,10 +560,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} }
#if LLVM_MAJOR == 13 // TODO: set to 14 when done FIXME //#if LLVM_MAJOR >= 13
// Use the old pass manager in LLVM 13 which the afl++ passes still use. // // Use the old pass manager in LLVM 14 which the afl++ passes still use.
cc_params[cc_par_cnt++] = "-flegacy-pass-manager"; // cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
#endif //#endif
if (lto_mode && !have_c) { if (lto_mode && !have_c) {
@ -665,16 +654,10 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else { } else {
#if LLVM_MAJOR >= 11
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path);
#else
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
#endif
} }
@ -695,19 +678,22 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager"; cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
cc_params[cc_par_cnt++] = alloc_printf( cc_params[cc_par_cnt++] = alloc_printf(
"-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path); "-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path);
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
cc_params[cc_par_cnt++] = alloc_printf(
"-fpass-plugin=%s/cmplog-routines-pass.so", obj_path);
#else #else
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
alloc_printf("%s/cmplog-instructions-pass.so", obj_path); alloc_printf("%s/cmplog-instructions-pass.so", obj_path);
#endif
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = "-load"; cc_params[cc_par_cnt++] = "-load";
cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-Xclang";
cc_params[cc_par_cnt++] = cc_params[cc_par_cnt++] =
alloc_printf("%s/cmplog-routines-pass.so", obj_path); alloc_printf("%s/cmplog-routines-pass.so", obj_path);
#endif
} }

View File

@ -450,6 +450,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0); fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0);
fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner);
fsrv->nyx_aux_string = malloc(0x1000);
memset(fsrv->nyx_aux_string, 0, 0x1000);
/* dry run */ /* dry run */
fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, "INIT", 4); fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, "INIT", 4);
switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) { switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
@ -1253,7 +1256,13 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
fsrv->child_pid = -1; fsrv->child_pid = -1;
#ifdef __linux__ #ifdef __linux__
if (fsrv->nyx_mode) { fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); } if (fsrv->nyx_mode) {
free(fsrv->nyx_aux_string);
fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
}
#endif #endif
} }

View File

@ -423,10 +423,10 @@ void write_crash_readme(afl_state_t *afl) {
"them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n" "them to a vendor? Check out the afl-tmin that comes with the fuzzer!\n\n"
"Found any cool bugs in open-source tools using afl-fuzz? If yes, please " "Found any cool bugs in open-source tools using afl-fuzz? If yes, please "
"drop\n" "post\n"
"an mail at <afl-users@googlegroups.com> once the issues are fixed\n\n" "to https://github.com/AFLplusplus/AFLplusplus/issues/286 once the "
"issues\n"
" https://github.com/AFLplusplus/AFLplusplus\n\n", " are fixed :)\n\n",
afl->orig_cmdline, afl->orig_cmdline,
stringify_mem_size(val_buf, sizeof(val_buf), stringify_mem_size(val_buf, sizeof(val_buf),
@ -771,6 +771,25 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
ck_write(fd, mem, len, fn); ck_write(fd, mem, len, fn);
close(fd); close(fd);
#ifdef __linux__
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {
u8 fn_log[PATH_MAX];
snprintf(fn_log, PATH_MAX, "%s.log", fn);
fd = open(fn_log, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn_log); }
u32 nyx_aux_string_len = afl->fsrv.nyx_handlers->nyx_get_aux_string(
afl->fsrv.nyx_runner, afl->fsrv.nyx_aux_string, 0x1000);
ck_write(fd, afl->fsrv.nyx_aux_string, nyx_aux_string_len, fn_log);
close(fd);
}
#endif
return keeping; return keeping;
} }

View File

@ -2136,7 +2136,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
if ((i % 2)) { if ((i % 2)) {
if (len > idx + i && is_hex(orig_buf + idx + i)) { if (len > idx + i + 1 && is_hex(orig_buf + idx + i)) {
fromhex += 2; fromhex += 2;
@ -2323,7 +2323,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex, // fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex,
// *status); // *status);
memcpy(buf + idx + i, save + i, i + 1 + off); memcpy(buf + idx, save, i + 1 + off);
} }

View File

@ -232,7 +232,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
memcpy(afl->fsrv.shmem_fuzz, mem, skip_at); memcpy(afl->fsrv.shmem_fuzz, mem, skip_at);
memcpy(afl->fsrv.shmem_fuzz, mem + skip_at + skip_len, tail_len); memcpy(afl->fsrv.shmem_fuzz + skip_at, mem + skip_at + skip_len, tail_len);
} }

View File

@ -167,7 +167,9 @@ static void usage(u8 *argv0, int more_help) {
" See docs/README.MOpt.md\n" " See docs/README.MOpt.md\n"
" -c program - enable CmpLog by specifying a binary compiled for " " -c program - enable CmpLog by specifying a binary compiled for "
"it.\n" "it.\n"
" if using QEMU, just use -c 0.\n" " if using QEMU/FRIDA or if you the fuzzing target is "
"compiled"
" for CmpLog then just use -c 0.\n"
" -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
" 1=small files, 2=larger files (default), 3=all " " 1=small files, 2=larger files (default), 3=all "
"files,\n" "files,\n"
@ -466,6 +468,9 @@ nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
dlsym(handle, "nyx_get_bitmap_buffer_size"); dlsym(handle, "nyx_get_bitmap_buffer_size");
if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; } if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
if (plugin->nyx_get_aux_string == NULL) { goto fail; }
OKF("libnyx plugin is ready!"); OKF("libnyx plugin is ready!");
return plugin; return plugin;
@ -1458,6 +1463,13 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->use_banner) { afl->use_banner = argv[optind]; } if (!afl->use_banner) { afl->use_banner = argv[optind]; }
if (afl->shm.cmplog_mode &&
(!strcmp("-", afl->cmplog_binary) || !strcmp("0", afl->cmplog_binary))) {
afl->cmplog_binary = argv[optind];
}
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
WARNF(cLRD WARNF(cLRD
@ -1675,7 +1687,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("LD_PRELOAD")) { if (getenv("LD_PRELOAD")) {
WARNF( WARNF(
"LD_PRELOAD is set, are you sure that is what to you want to do " "LD_PRELOAD is set, are you sure that is what you want to do "
"instead of using AFL_PRELOAD?"); "instead of using AFL_PRELOAD?");
} }