aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2022-05-16 12:34:38 +0200
committerGitHub <noreply@github.com>2022-05-16 12:34:38 +0200
commita2eb1f14126cffd046c44d5e87e945ed2699cec5 (patch)
tree2eecf55a92eec04e67aa3a9d9bec8e5f50659de6
parentc7bb0a9638a8929a5b664f16032c23a55a84be70 (diff)
parentc08eeb95ca78625cf3f8a96bd04320c57c50d0f1 (diff)
downloadafl++-a2eb1f14126cffd046c44d5e87e945ed2699cec5.tar.gz
Merge pull request #1404 from AFLplusplus/dev
push to stable
-rw-r--r--Dockerfile33
-rw-r--r--GNUmakefile.llvm2
-rw-r--r--docs/Changelog.md6
-rw-r--r--frida_mode/GNUmakefile2
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c2
-rw-r--r--frida_mode/src/instrument/instrument_x64.c3
-rw-r--r--frida_mode/src/instrument/instrument_x86.c2
-rw-r--r--frida_mode/src/module.c4
-rw-r--r--frida_mode/src/prefetch.c106
-rw-r--r--frida_mode/src/stalker.c2
-rw-r--r--frida_mode/test/dynamic/GNUmakefile76
-rw-r--r--frida_mode/test/dynamic/Makefile19
-rw-r--r--frida_mode/test/dynamic/testinstr.c98
-rw-r--r--frida_mode/test/dynamic/testinstrlib.c14
-rw-r--r--include/afl-fuzz.h15
-rw-r--r--include/debug.h2
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc24
-rw-r--r--nyx_mode/LIBNYX_VERSION2
-rw-r--r--nyx_mode/PACKER_VERSION2
m---------nyx_mode/QEMU-Nyx0
-rw-r--r--nyx_mode/QEMU_NYX_VERSION2
m---------nyx_mode/libnyx0
m---------nyx_mode/packer0
-rw-r--r--src/afl-fuzz-bitmap.c2
-rw-r--r--src/afl-fuzz-cmplog.c2
-rw-r--r--src/afl-fuzz-init.c2
-rw-r--r--src/afl-fuzz-mutators.c4
-rw-r--r--src/afl-fuzz-one.c397
-rw-r--r--src/afl-fuzz-run.c24
-rw-r--r--src/afl-fuzz-stats.c12
-rw-r--r--src/afl-sharedmem.c38
-rw-r--r--unicorn_mode/UNICORNAFL_VERSION2
32 files changed, 705 insertions, 194 deletions
diff --git a/Dockerfile b/Dockerfile
index 522e801a..bdfa1c56 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,9 +1,9 @@
#
-# This Dockerfile for AFLplusplus uses Ubuntu 20.04 focal and
-# installs LLVM 11 from llvm.org for afl-clang-lto support :-)
+# This Dockerfile for AFLplusplus uses Ubuntu 22.04 jammy and
+# installs LLVM 14 for afl-clang-lto support :-)
#
-FROM ubuntu:20.04 AS aflplusplus
+FROM ubuntu:22.04 AS aflplusplus
LABEL "maintainer"="afl++ team <afl@aflplus.plus>"
LABEL "about"="AFLplusplus docker image"
@@ -29,20 +29,21 @@ RUN apt-get update && \
gnuplot-nox \
&& rm -rf /var/lib/apt/lists/*
-RUN echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main" >> /etc/apt/sources.list && \
- wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
+# TODO: reactivate in timely manner
+#RUN echo "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main" >> /etc/apt/sources.list && \
+# wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
-RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu focal main" >> /etc/apt/sources.list && \
+RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu jammy main" >> /etc/apt/sources.list && \
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 1E9377A2BA9EF27F
RUN apt-get update && apt-get full-upgrade -y && \
apt-get -y install --no-install-suggests --no-install-recommends \
- gcc-10 g++-10 gcc-10-plugin-dev gdb lcov \
- clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
- libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
- libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
- liblld-12-dev liblldb-12 liblldb-12-dev libllvm12 libomp-12-dev \
- libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools
+ gcc-12 g++-12 gcc-12-plugin-dev gdb lcov \
+ clang-14 clang-tools-14 libc++1-14 libc++-14-dev \
+ libc++abi1-14 libc++abi-14-dev libclang1-14 libclang-14-dev \
+ libclang-common-14-dev libclang-cpp14 libclang-cpp14-dev liblld-14 \
+ liblld-14-dev liblldb-14 liblldb-14-dev libllvm14 libomp-14-dev \
+ libomp5-14 lld-14 lldb-14 llvm-14 llvm-14-dev llvm-14-runtime llvm-14-tools
# arm64 doesn't have gcc-multilib, and it's only used for -m32 support on x86
ARG TARGETPLATFORM
@@ -52,10 +53,10 @@ RUN [ "$TARGETPLATFORM" = "linux/amd64" ] && \
RUN rm -rf /var/lib/apt/lists/*
-RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 0
-RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0
+RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 0
+RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 0
-ENV LLVM_CONFIG=llvm-config-12
+ENV LLVM_CONFIG=llvm-config-14
ENV AFL_SKIP_CPUFREQ=1
ENV AFL_TRY_AFFINITY=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
@@ -66,7 +67,7 @@ RUN cd /afl-cov && make install && cd ..
COPY . /AFLplusplus
WORKDIR /AFLplusplus
-RUN export CC=gcc-10 && export CXX=g++-10 && make clean && \
+RUN export CC=gcc-12 && export CXX=g++-12 && make clean && \
make distrib && make install && make clean
RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc'
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index 685964b7..538ca4a2 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -407,7 +407,7 @@ ifeq "$(LLVM_LTO)" "1"
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
endif
-./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc
+./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc instrumentation/afl-llvm-common.o
ifeq "$(LLVM_LTO)" "1"
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto.o
diff --git a/docs/Changelog.md b/docs/Changelog.md
index a841cca3..b6271a22 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -26,10 +26,16 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- "saved timeouts" was wrong information, timeouts are still thrown
away by default even if they have new coverage (hangs are always
kept), unless AFL_KEEP_TIMEOUTS are set
+ - AFL never implemented auto token inserts (but user token inserts,
+ user token overwrite and auto token overwrite), added now!
+ - Mopt fix to always select the correct algorithm
+ - fix effector map calculation (deterministic mode)
+ - fix custom mutator post_process functionality
- document and auto-activate pizza mode on condition
- afl-cc:
- converted all passed to use the new llvm pass manager for llvm 11+
- AFL++ PCGUARD mode is not available for 10.0.1 anymore (11+ only)
+ - trying to stay on top on all these #$&ยง!! changes in llvm 15 ...
- frida_mode:
- update to new frida release, handles now c++ throw/catch
- unicorn_mode:
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile
index 0b5f52cb..014dcca5 100644
--- a/frida_mode/GNUmakefile
+++ b/frida_mode/GNUmakefile
@@ -116,7 +116,7 @@ ifndef OS
$(error "Operating system unsupported")
endif
-GUM_DEVKIT_VERSION=15.1.15
+GUM_DEVKIT_VERSION=15.1.22
GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index 2bc8f8aa..fab9eee2 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -157,11 +157,13 @@ static gboolean instrument_is_deterministic(const cs_insn *from_insn) {
}
static void instrument_coverage_switch(GumStalkerObserver *self,
+ gpointer from_address,
gpointer start_address,
const cs_insn * from_insn,
gpointer * target) {
UNUSED_PARAMETER(self);
+ UNUSED_PARAMETER(from_address);
UNUSED_PARAMETER(start_address);
gsize fixup_offset;
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index f02c971e..a764b054 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -172,12 +172,13 @@ void instrument_coverage_optimize_init(void) {
}
static void instrument_coverage_switch(GumStalkerObserver *self,
+ gpointer from_address,
gpointer start_address,
const cs_insn * from_insn,
gpointer * target) {
UNUSED_PARAMETER(self);
- UNUSED_PARAMETER(start_address);
+ UNUSED_PARAMETER(from_address);
cs_x86 * x86;
cs_x86_op *op;
diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c
index 6a899248..1baa98ca 100644
--- a/frida_mode/src/instrument/instrument_x86.c
+++ b/frida_mode/src/instrument/instrument_x86.c
@@ -84,11 +84,13 @@ gboolean instrument_is_coverage_optimize_supported(void) {
}
static void instrument_coverage_switch(GumStalkerObserver *self,
+ gpointer from_address,
gpointer start_address,
const cs_insn * from_insn,
gpointer * target) {
UNUSED_PARAMETER(self);
+ UNUSED_PARAMETER(from_address);
UNUSED_PARAMETER(start_address);
cs_x86 * x86;
diff --git a/frida_mode/src/module.c b/frida_mode/src/module.c
index 65b394cd..60e69fec 100644
--- a/frida_mode/src/module.c
+++ b/frida_mode/src/module.c
@@ -42,7 +42,7 @@ gboolean found_range(const GumRangeDetails *details, gpointer user_data) {
}
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
static int on_dlclose(void *handle) {
GArray * ranges = NULL;
@@ -95,7 +95,7 @@ void module_init(void) {
FOKF(cBLU "Module" cRST " - " cYEL " [%c]", handle_dlclose ? 'X' : ' ');
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
if (!handle_dlclose) { return; }
page_size = gum_query_page_size();
diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c
index fa0288cc..59bfecc2 100644
--- a/frida_mode/src/prefetch.c
+++ b/frida_mode/src/prefetch.c
@@ -32,6 +32,8 @@ gboolean prefetch_backpatch = TRUE;
static prefetch_data_t *prefetch_data = NULL;
static int prefetch_shm_id = -1;
+static GHashTable *cant_prefetch = NULL;
+
static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
const GumBackpatch *backpatch,
gsize size) {
@@ -40,6 +42,18 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
if (!entry_run) { return; }
gsize remaining =
sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size;
+
+ gpointer from = gum_stalker_backpatch_get_from(backpatch);
+ gpointer to = gum_stalker_backpatch_get_to(backpatch);
+
+ /* Stop reporting patches which can't be prefetched */
+ if (g_hash_table_contains(cant_prefetch, GSIZE_TO_POINTER(from)) ||
+ g_hash_table_contains(cant_prefetch, GSIZE_TO_POINTER(to))) {
+
+ return;
+
+ }
+
if (sizeof(gsize) + size > remaining) { return; }
gsize *dst_backpatch_size =
@@ -68,6 +82,9 @@ void prefetch_write(void *addr) {
/* Bail if we aren't initialized */
if (prefetch_data == NULL) return;
+ /* Stop reporting blocks which can't be prefetched */
+ if (g_hash_table_contains(cant_prefetch, GSIZE_TO_POINTER(addr))) { return; }
+
/*
* Our shared memory IPC is large enough for about 1000 entries, we can fine
* tune this if we need to. But if we have more new blocks that this in a
@@ -84,6 +101,38 @@ void prefetch_write(void *addr) {
}
+typedef struct {
+
+ GumAddress address;
+ gboolean executable;
+
+} check_executable_t;
+
+static gboolean prefetch_find_executable(const GumRangeDetails *details,
+ gpointer user_data) {
+
+ check_executable_t *ctx = (check_executable_t *)user_data;
+ if (GUM_MEMORY_RANGE_INCLUDES(details->range, ctx->address)) {
+
+ ctx->executable = TRUE;
+ return FALSE;
+
+ }
+
+ return TRUE;
+
+}
+
+static gboolean prefetch_is_executable(void *address) {
+
+ check_executable_t ctx = {.address = GUM_ADDRESS(address),
+ .executable = FALSE};
+ gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, prefetch_find_executable,
+ &ctx);
+ return ctx.executable;
+
+}
+
static void prefetch_read_blocks(void) {
GumStalker *stalker = stalker_get();
@@ -92,7 +141,24 @@ static void prefetch_read_blocks(void) {
for (size_t i = 0; i < prefetch_data->count; i++) {
void *addr = prefetch_data->entry[i];
- gum_stalker_prefetch(stalker, addr, 1);
+
+ if (prefetch_is_executable(addr)) {
+
+ gum_stalker_prefetch(stalker, addr, 1);
+
+ } else {
+
+ /*
+ * If our child process creates a new executable mapping, e.g. by
+ * dynamically loading a new DSO, then this won't appear in our parent
+ * process' memory map and hence we can't prefetch it. Add it to a
+ * hashtable which the child will inherit on the next fork to prevent the
+ * child from keep reporting it and exhausting the shared memory buffers
+ * used to pass new blocks from the child back to the parent.
+ */
+ g_hash_table_add(cant_prefetch, GSIZE_TO_POINTER(addr));
+
+ }
}
@@ -125,7 +191,36 @@ static void prefetch_read_patches(void) {
}
backpatch = (GumBackpatch *)&prefetch_data->backpatch_data[offset];
- gum_stalker_prefetch_backpatch(stalker, backpatch);
+
+ gpointer from = gum_stalker_backpatch_get_from(backpatch);
+ gpointer to = gum_stalker_backpatch_get_to(backpatch);
+
+ /*
+ * If our child process creates a new executable mapping, e.g. by
+ * dynamically loading a new DSO, then this won't appear in our parent
+ * process' memory map and hence we can't prefetch it. Add it to a
+ * hashtable which the child will inherit on the next fork to prevent the
+ * child from keep reporting it and exhausting the shared memory buffers
+ * used to pass new blocks from the child back to the parent.
+ */
+ if (!prefetch_is_executable(from)) {
+
+ g_hash_table_add(cant_prefetch, GSIZE_TO_POINTER(from));
+
+ }
+
+ if (!prefetch_is_executable(to)) {
+
+ g_hash_table_add(cant_prefetch, GSIZE_TO_POINTER(to));
+
+ }
+
+ if (prefetch_is_executable(from) && prefetch_is_executable(to)) {
+
+ gum_stalker_prefetch_backpatch(stalker, backpatch);
+
+ }
+
offset += size;
}
@@ -215,6 +310,13 @@ void prefetch_init(void) {
prefetch_hook_fork();
+ cant_prefetch = g_hash_table_new(g_direct_hash, g_direct_equal);
+ if (cant_prefetch == NULL) {
+
+ FFATAL("Failed to g_hash_table_new, errno: %d", errno);
+
+ }
+
if (!prefetch_backpatch) { return; }
GumStalkerObserver * observer = stalker_get_observer();
diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c
index 80e4e707..ddc17b81 100644
--- a/frida_mode/src/stalker.c
+++ b/frida_mode/src/stalker.c
@@ -131,6 +131,8 @@ void stalker_init(void) {
}
+ gum_stalker_activate_experimental_unwind_support();
+
#if defined(__x86_64__) || defined(__i386__)
stalker = g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries,
"adjacent-blocks", stalker_adjacent_blocks, NULL);
diff --git a/frida_mode/test/dynamic/GNUmakefile b/frida_mode/test/dynamic/GNUmakefile
new file mode 100644
index 00000000..f43416f7
--- /dev/null
+++ b/frida_mode/test/dynamic/GNUmakefile
@@ -0,0 +1,76 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+TESTINSTLIB:=$(BUILD_DIR)testinstrlib.so
+TESTINSTLIBSRC:=$(PWD)testinstrlib.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
+
+ADDR_BIN:=$(ROOT)frida_mode/build/addr
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
+
+AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
+AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) testinstr $(AFL_FRIDA_BASE_ADDR))
+
+CFLAGS+=-D_GNU_SOURCE=1
+LDFLAGS+=-ldl
+
+.PHONY: all clean qemu frida
+
+all: $(TESTINSTBIN) $(TESTINSTLIB)
+ make -C $(ROOT)frida_mode/
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
+ dd if=/dev/zero bs=1048576 count=1 of=$@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTLIB): $(TESTINSTLIBSRC) | $(BUILD_DIR)
+ $(CC) \
+ $(CFLAGS) \
+ -shared \
+ -o $@ \
+ $(LDFLAGS) \
+ $<
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) \
+ $(CFLAGS) \
+ -o $@ \
+ $< \
+ $(LDFLAGS) \
+ -Wl,-rpath,'$$ORIGIN'
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT)
+ 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 \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
diff --git a/frida_mode/test/dynamic/Makefile b/frida_mode/test/dynamic/Makefile
new file mode 100644
index 00000000..f843af19
--- /dev/null
+++ b/frida_mode/test/dynamic/Makefile
@@ -0,0 +1,19 @@
+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
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+frida:
+ @gmake frida
+
+debug:
+ @gmake debug
diff --git a/frida_mode/test/dynamic/testinstr.c b/frida_mode/test/dynamic/testinstr.c
new file mode 100644
index 00000000..ad26d060
--- /dev/null
+++ b/frida_mode/test/dynamic/testinstr.c
@@ -0,0 +1,98 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+typedef void (*fntestinstrlib)(char *buf, int len);
+
+void testinstr(char *buf, int len) {
+ void *lib = dlopen("testinstrlib.so", RTLD_NOW);
+ if (lib == NULL) {
+ puts("Library not found");
+ abort();
+ }
+
+ fntestinstrlib fn = (fntestinstrlib)(dlsym(lib, "testinstrlib"));
+ if (fn == NULL) {
+ puts("Function not found");
+ abort();
+ }
+
+ fn(buf, len);
+}
+
+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];
+ printf("file: %s\n", file);
+
+ 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;
+ }
+
+ printf("len: %ld\n", len);
+
+ buf = 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);
+
+ testinstr(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;
+}
diff --git a/frida_mode/test/dynamic/testinstrlib.c b/frida_mode/test/dynamic/testinstrlib.c
new file mode 100644
index 00000000..987cbf91
--- /dev/null
+++ b/frida_mode/test/dynamic/testinstrlib.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+
+void testinstrlib(char *buf, int len) {
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+}
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 8bb61e22..9992e841 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -230,12 +230,13 @@ enum {
/* 12 */ STAGE_EXTRAS_UO,
/* 13 */ STAGE_EXTRAS_UI,
/* 14 */ STAGE_EXTRAS_AO,
- /* 15 */ STAGE_HAVOC,
- /* 16 */ STAGE_SPLICE,
- /* 17 */ STAGE_PYTHON,
- /* 18 */ STAGE_CUSTOM_MUTATOR,
- /* 19 */ STAGE_COLORIZATION,
- /* 20 */ STAGE_ITS,
+ /* 15 */ STAGE_EXTRAS_AI,
+ /* 16 */ STAGE_HAVOC,
+ /* 17 */ STAGE_SPLICE,
+ /* 18 */ STAGE_PYTHON,
+ /* 19 */ STAGE_CUSTOM_MUTATOR,
+ /* 20 */ STAGE_COLORIZATION,
+ /* 21 */ STAGE_ITS,
STAGE_NUM_MAX
@@ -1098,7 +1099,7 @@ int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen);
/* Run */
void sync_fuzzers(afl_state_t *);
-u32 write_to_testcase(afl_state_t *, void *, u32, u32);
+u32 write_to_testcase(afl_state_t *, void **, u32, u32);
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
u8 trim_case(afl_state_t *, struct queue_entry *, u8 *);
u8 common_fuzz_stuff(afl_state_t *, u8 *, u32);
diff --git a/include/debug.h b/include/debug.h
index e2ee16a8..c2f20f0f 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -388,6 +388,8 @@ static inline const char *colorfilter(const char *x) {
\
} while (1); \
\
+ \
+ \
} while (0)
#define ck_read(fd, buf, len, fn) \
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index f80b1a1e..408353b3 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -313,13 +313,25 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module & M,
std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd(
Module &M, const char *Section, Type *Ty) {
- GlobalVariable *SecStart = new GlobalVariable(
- M, Ty->getPointerElementType(), false,
- GlobalVariable::ExternalWeakLinkage, nullptr, getSectionStart(Section));
+ GlobalVariable *SecStart =
+ new GlobalVariable(M,
+#if LLVM_VERSION_MAJOR >= 15
+ Ty,
+#else
+ Ty->getPointerElementType(),
+#endif
+ false, GlobalVariable::ExternalWeakLinkage, nullptr,
+ getSectionStart(Section));
SecStart->setVisibility(GlobalValue::HiddenVisibility);
- GlobalVariable *SecEnd = new GlobalVariable(
- M, Ty->getPointerElementType(), false,
- GlobalVariable::ExternalWeakLinkage, nullptr, getSectionEnd(Section));
+ GlobalVariable *SecEnd =
+ new GlobalVariable(M,
+#if LLVM_VERSION_MAJOR >= 15
+ Ty,
+#else
+ Ty->getPointerElementType(),
+#endif
+ false, GlobalVariable::ExternalWeakLinkage, nullptr,
+ getSectionEnd(Section));
SecEnd->setVisibility(GlobalValue::HiddenVisibility);
IRBuilder<> IRB(M.getContext());
if (!TargetTriple.isOSBinFormatCOFF())
diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION
index 65e119c9..00165a63 100644
--- a/nyx_mode/LIBNYX_VERSION
+++ b/nyx_mode/LIBNYX_VERSION
@@ -1 +1 @@
-8a77c71
+acaf7f6
diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION
index d67dee20..a8ebe13a 100644
--- a/nyx_mode/PACKER_VERSION
+++ b/nyx_mode/PACKER_VERSION
@@ -1 +1 @@
-5d143ee
+86b159b
diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx
-Subproject c08e4ac94244a9739b4484b3010abc06b372923
+Subproject 5c8cf793ec615b0df5fa722878c8f6906ad7936
diff --git a/nyx_mode/QEMU_NYX_VERSION b/nyx_mode/QEMU_NYX_VERSION
index 2d9ee5e3..f5888136 100644
--- a/nyx_mode/QEMU_NYX_VERSION
+++ b/nyx_mode/QEMU_NYX_VERSION
@@ -1 +1 @@
-c08e4ac942
+5c8cf793ec
diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx
-Subproject 8a77c71dc8a8c0b73abd8fb9c22e30d565184ef
+Subproject acaf7f6346eeb5f1e2cf043543316909fca4365
diff --git a/nyx_mode/packer b/nyx_mode/packer
-Subproject 5d143eee4e4dcd12a1fc5d6786dd8da25cbb995
+Subproject 86b159bafc0b2ba8feeaa8761a45b6201d34084
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 7c2b35d6..26e70d81 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -648,7 +648,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (afl->fsrv.exec_tmout < afl->hang_tmout) {
u8 new_fault;
- len = write_to_testcase(afl, mem, len, 0);
+ len = write_to_testcase(afl, &mem, len, 0);
new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout);
classify_counts(&afl->fsrv);
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 7d94085d..258d9ea7 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -49,7 +49,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
- write_to_testcase(afl, out_buf, len, 0);
+ write_to_testcase(afl, (void **)&out_buf, len, 0);
fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout);
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 05a654c8..6a653a00 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -617,7 +617,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
}
- u32 len = write_to_testcase(afl, mem, st.st_size, 1);
+ u32 len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
afl->syncing_party = foreign_name;
afl->queued_imported += save_if_interesting(afl, mem, len, fault);
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index e78e2dc4..9407adfb 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -428,7 +428,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
if (likely(retlen)) {
- retlen = write_to_testcase(afl, retbuf, retlen, 0);
+ retlen = write_to_testcase(afl, (void **)&retbuf, retlen, 0);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs;
@@ -460,6 +460,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
}
out_len = retlen;
+ // TODO are we sure that retbuf fits into out_buf if retbuf can actually
+ // increase in size?
memcpy(out_buf, retbuf, retlen);
/* Tell the custom mutator that the trimming was successful */
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index b28ee80a..19f41ebe 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -373,7 +373,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
u32 j;
u32 i;
u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
- u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum;
+ u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, prev_cksum, _prev_cksum;
u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1;
u8 ret_val = 1, doing_det = 0;
@@ -630,7 +630,14 @@ u8 fuzz_one_original(afl_state_t *afl) {
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
- prev_cksum = afl->queue_cur->exec_cksum;
+ /* Get a clean cksum. */
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+ _prev_cksum = prev_cksum;
+
+ /* Now flip bits. */
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -716,7 +723,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
/* Continue collecting string, but only if the bit flip actually made
any difference - we don't want no-op tokens. */
- if (cksum != afl->queue_cur->exec_cksum) {
+ if (cksum != _prev_cksum) {
if (a_len < MAX_AUTO_EXTRA) {
@@ -839,6 +846,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_max = len;
orig_hit_cnt = new_hit_cnt;
+ prev_cksum = _prev_cksum;
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -871,11 +879,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
} else {
- cksum = ~afl->queue_cur->exec_cksum;
+ cksum = ~prev_cksum;
}
- if (cksum != afl->queue_cur->exec_cksum) {
+ if (cksum != prev_cksum) {
eff_map[EFF_APOS(afl->stage_cur)] = 1;
++eff_cnt;
@@ -1779,6 +1787,62 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max;
+ /* Insertion of auto extras. */
+
+ afl->stage_name = "auto extras (insert)";
+ afl->stage_short = "ext_AI";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->a_extras_cnt * (len + 1);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ ex_tmp = afl_realloc(AFL_BUF_PARAM(ex), len + MAX_DICT_FILE);
+ if (unlikely(!ex_tmp)) { PFATAL("alloc"); }
+
+ for (i = 0; i <= (u32)len; ++i) {
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < afl->a_extras_cnt; ++j) {
+
+ if (len + afl->a_extras[j].len > MAX_FILE) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ /* Insert token */
+ memcpy(ex_tmp + i, afl->a_extras[j].data, afl->a_extras[j].len);
+
+ /* Copy tail */
+ memcpy(ex_tmp + i + afl->a_extras[j].len, out_buf + i, len - i);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s AUTO_EXTRAS_insert-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, ex_tmp, len + afl->a_extras[j].len)) {
+
+ goto abandon_entry;
+
+ }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Copy head */
+ ex_tmp[i] = out_buf[i];
+
+ }
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max;
+
skip_extras:
/* If we made this to here without jumping to havoc_stage or abandon_entry,
@@ -1905,11 +1969,7 @@ custom_mutator_stage:
}
- /* `(afl->)out_buf` may have been changed by the call to custom_fuzz
- */
- /* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs
- * Memcpy.
- */
+ /* out_buf may have been changed by the call to custom_fuzz */
memcpy(out_buf, in_buf, len);
}
@@ -2994,7 +3054,8 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
u32 i;
u32 j;
u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0;
- u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, cur_ms_lv, prev_cksum;
+ u64 havoc_queued = 0, orig_hit_cnt, new_hit_cnt = 0, cur_ms_lv, prev_cksum,
+ _prev_cksum;
u32 splice_cycle = 0, perf_score = 100, orig_perf, eff_cnt = 1;
u8 ret_val = 1, doing_det = 0;
@@ -3238,7 +3299,14 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
- prev_cksum = afl->queue_cur->exec_cksum;
+ /* Get a clean cksum. */
+
+ if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; }
+
+ prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+ _prev_cksum = prev_cksum;
+
+ /* Now flip bits. */
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -3323,7 +3391,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
/* Continue collecting string, but only if the bit flip actually made
any difference - we don't want no-op tokens. */
- if (cksum != afl->queue_cur->exec_cksum) {
+ if (cksum != _prev_cksum) {
if (a_len < MAX_AUTO_EXTRA) {
@@ -3444,6 +3512,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_max = len;
orig_hit_cnt = new_hit_cnt;
+ prev_cksum = _prev_cksum;
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
@@ -3475,11 +3544,11 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
} else {
- cksum = ~afl->queue_cur->exec_cksum;
+ cksum = ~prev_cksum;
}
- if (cksum != afl->queue_cur->exec_cksum) {
+ if (cksum != prev_cksum) {
eff_map[EFF_APOS(afl->stage_cur)] = 1;
++eff_cnt;
@@ -4367,6 +4436,62 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max;
+ /* Insertion of auto extras. */
+
+ afl->stage_name = "auto extras (insert)";
+ afl->stage_short = "ext_AI";
+ afl->stage_cur = 0;
+ afl->stage_max = afl->a_extras_cnt * (len + 1);
+
+ orig_hit_cnt = new_hit_cnt;
+
+ ex_tmp = afl_realloc(AFL_BUF_PARAM(ex), len + MAX_DICT_FILE);
+ if (unlikely(!ex_tmp)) { PFATAL("alloc"); }
+
+ for (i = 0; i <= (u32)len; ++i) {
+
+ afl->stage_cur_byte = i;
+
+ for (j = 0; j < afl->a_extras_cnt; ++j) {
+
+ if (len + afl->a_extras[j].len > MAX_FILE) {
+
+ --afl->stage_max;
+ continue;
+
+ }
+
+ /* Insert token */
+ memcpy(ex_tmp + i, afl->a_extras[j].data, afl->a_extras[j].len);
+
+ /* Copy tail */
+ memcpy(ex_tmp + i + afl->a_extras[j].len, out_buf + i, len - i);
+
+#ifdef INTROSPECTION
+ snprintf(afl->mutation, sizeof(afl->mutation),
+ "%s MOPT_AUTO_EXTRAS_insert-%u-%u", afl->queue_cur->fname, i, j);
+#endif
+
+ if (common_fuzz_stuff(afl, ex_tmp, len + afl->a_extras[j].len)) {
+
+ goto abandon_entry;
+
+ }
+
+ ++afl->stage_cur;
+
+ }
+
+ /* Copy head */
+ ex_tmp[i] = out_buf[i];
+
+ } /* for i = 0; i <= len */
+
+ new_hit_cnt = afl->queued_items + afl->saved_crashes;
+
+ afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt;
+ afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max;
+
skip_extras:
/* If we made this to here without jumping to havoc_stage or abandon_entry,
@@ -4464,14 +4589,14 @@ pacemaker_fuzzing:
havoc_queued = afl->queued_items;
- u32 r_max;
+ u32 r_max, r;
- r_max = 15 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
+ r_max = 16 + ((afl->extras_cnt + afl->a_extras_cnt) ? 2 : 0);
if (unlikely(afl->expand_havoc && afl->ready_for_splicing_count > 1)) {
/* add expensive havoc cases here, they are activated after a full
- cycle without finds happened */
+ cycle without any finds happened */
++r_max;
@@ -4497,7 +4622,7 @@ pacemaker_fuzzing:
for (i = 0; i < use_stacking; ++i) {
- switch (select_algorithm(afl, r_max)) {
+ switch (r = (select_algorithm(afl, r_max))) {
case 0:
/* Flip a single bit somewhere. Spooky! */
@@ -4914,192 +5039,196 @@ pacemaker_fuzzing:
} /* case 15 */
+ default: {
+
/* Values 16 and 17 can be selected only if there are any extras
present in the dictionaries. */
- case 16: {
+ r -= 16;
+
+ if (r == 0 && (afl->extras_cnt || afl->a_extras_cnt)) {
- /* Overwrite bytes with an extra. */
+ /* Overwrite bytes with an extra. */
- if (!afl->extras_cnt ||
- (afl->a_extras_cnt && rand_below(afl, 2))) {
+ if (!afl->extras_cnt ||
+ (afl->a_extras_cnt && rand_below(afl, 2))) {
- /* No user-specified extras or odds in our favor. Let's use an
- auto-detected one. */
+ /* No user-specified extras or odds in our favor. Let's use an
+ auto-detected one. */
- u32 use_extra = rand_below(afl, afl->a_extras_cnt);
- u32 extra_len = afl->a_extras[use_extra].len;
+ u32 use_extra = rand_below(afl, afl->a_extras_cnt);
+ u32 extra_len = afl->a_extras[use_extra].len;
- if (extra_len > (u32)temp_len) break;
+ if (extra_len > (u32)temp_len) break;
- u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
- extra_len);
+ memcpy(out_buf + insert_at, afl->a_extras[use_extra].data,
+ extra_len);
- } else {
+ } else {
- /* No auto extras or odds in our favor. Use the dictionary. */
+ /* No auto extras or odds in our favor. Use the dictionary. */
- u32 use_extra = rand_below(afl, afl->extras_cnt);
- u32 extra_len = afl->extras[use_extra].len;
+ u32 use_extra = rand_below(afl, afl->extras_cnt);
+ u32 extra_len = afl->extras[use_extra].len;
- if (extra_len > (u32)temp_len) break;
+ if (extra_len > (u32)temp_len) break;
- u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
+ u32 insert_at = rand_below(afl, temp_len - extra_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " EXTRA_OVERWRITE-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memcpy(out_buf + insert_at, afl->extras[use_extra].data,
- extra_len);
+ memcpy(out_buf + insert_at, afl->extras[use_extra].data,
+ extra_len);
- }
+ }
- MOpt_globals.cycles_v2[STAGE_OverWriteExtra]++;
+ MOpt_globals.cycles_v2[STAGE_OverWriteExtra]++;
- break;
+ break;
- }
+ }
/* Insert an extra. */
- case 17: {
+ else if (r == 1 && (afl->extras_cnt || afl->a_extras_cnt)) {
- u32 use_extra, extra_len,
- insert_at = rand_below(afl, temp_len + 1);
- u8 *ptr;
+ u32 use_extra, extra_len,
+ insert_at = rand_below(afl, temp_len + 1);
+ u8 *ptr;
- /* Insert an extra. Do the same dice-rolling stuff as for the
- previous case. */
+ /* Insert an extra. Do the same dice-rolling stuff as for the
+ previous case. */
- if (!afl->extras_cnt ||
- (afl->a_extras_cnt && rand_below(afl, 2))) {
+ if (!afl->extras_cnt ||
+ (afl->a_extras_cnt && rand_below(afl, 2))) {
- use_extra = rand_below(afl, afl->a_extras_cnt);
- extra_len = afl->a_extras[use_extra].len;
- ptr = afl->a_extras[use_extra].data;
+ use_extra = rand_below(afl, afl->a_extras_cnt);
+ extra_len = afl->a_extras[use_extra].len;
+ ptr = afl->a_extras[use_extra].data;
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " AUTO_EXTRA_INSERT-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- } else {
+ } else {
- use_extra = rand_below(afl, afl->extras_cnt);
- extra_len = afl->extras[use_extra].len;
- ptr = afl->extras[use_extra].data;
+ use_extra = rand_below(afl, afl->extras_cnt);
+ extra_len = afl->extras[use_extra].len;
+ ptr = afl->extras[use_extra].data;
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp), " EXTRA_INSERT-%u-%u",
- insert_at, extra_len);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " EXTRA_INSERT-%u-%u", insert_at, extra_len);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- }
-
- if (temp_len + extra_len >= MAX_FILE) break;
+ }
- out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
- if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ if (temp_len + extra_len >= MAX_FILE) break;
- /* Tail */
- memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
- temp_len - insert_at);
+ out_buf = afl_realloc(AFL_BUF_PARAM(out), temp_len + extra_len);
+ if (unlikely(!out_buf)) { PFATAL("alloc"); }
- /* Inserted part */
- memcpy(out_buf + insert_at, ptr, extra_len);
+ /* Tail */
+ memmove(out_buf + insert_at + extra_len, out_buf + insert_at,
+ temp_len - insert_at);
- temp_len += extra_len;
- MOpt_globals.cycles_v2[STAGE_InsertExtra]++;
- break;
+ /* Inserted part */
+ memcpy(out_buf + insert_at, ptr, extra_len);
- }
+ temp_len += extra_len;
+ MOpt_globals.cycles_v2[STAGE_InsertExtra]++;
+ break;
- default: {
+ } else {
- if (unlikely(afl->ready_for_splicing_count < 2)) break;
+ if (unlikely(afl->ready_for_splicing_count < 2)) break;
- u32 tid;
- do {
+ u32 tid;
+ do {
- tid = rand_below(afl, afl->queued_items);
+ tid = rand_below(afl, afl->queued_items);
- } while (tid == afl->current_entry ||
+ } while (tid == afl->current_entry ||
- afl->queue_buf[tid]->len < 4);
+ afl->queue_buf[tid]->len < 4);
- /* Get the testcase for splicing. */
- struct queue_entry *target = afl->queue_buf[tid];
- u32 new_len = target->len;
- u8 * new_buf = queue_testcase_get(afl, target);
+ /* Get the testcase for splicing. */
+ struct queue_entry *target = afl->queue_buf[tid];
+ u32 new_len = target->len;
+ u8 * new_buf = queue_testcase_get(afl, target);
- if ((temp_len >= 2 && rand_below(afl, 2)) ||
- temp_len + HAVOC_BLK_XL >= MAX_FILE) {
+ if ((temp_len >= 2 && rand_below(afl, 2)) ||
+ temp_len + HAVOC_BLK_XL >= MAX_FILE) {
- /* overwrite mode */
+ /* overwrite mode */
- u32 copy_from, copy_to, copy_len;
+ u32 copy_from, copy_to, copy_len;
- copy_len = choose_block_len(afl, new_len - 1);
- if (copy_len > temp_len) copy_len = temp_len;
+ copy_len = choose_block_len(afl, new_len - 1);
+ if (copy_len > temp_len) copy_len = temp_len;
- copy_from = rand_below(afl, new_len - copy_len + 1);
- copy_to = rand_below(afl, temp_len - copy_len + 1);
+ copy_from = rand_below(afl, new_len - copy_len + 1);
+ copy_to = rand_below(afl, temp_len - copy_len + 1);
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
- copy_len, target->fname);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_OVERWRITE-%u-%u-%u-%s", copy_from, copy_to,
+ copy_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
+ memmove(out_buf + copy_to, new_buf + copy_from, copy_len);
- } else {
+ } else {
- /* insert mode */
+ /* insert mode */
- u32 clone_from, clone_to, clone_len;
+ u32 clone_from, clone_to, clone_len;
- clone_len = choose_block_len(afl, new_len);
- clone_from = rand_below(afl, new_len - clone_len + 1);
- clone_to = rand_below(afl, temp_len + 1);
+ clone_len = choose_block_len(afl, new_len);
+ clone_from = rand_below(afl, new_len - clone_len + 1);
+ clone_to = rand_below(afl, temp_len + 1);
- u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
- temp_len + clone_len + 1);
- if (unlikely(!temp_buf)) { PFATAL("alloc"); }
+ u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch),
+ temp_len + clone_len + 1);
+ if (unlikely(!temp_buf)) { PFATAL("alloc"); }
#ifdef INTROSPECTION
- snprintf(afl->m_tmp, sizeof(afl->m_tmp),
- " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
- clone_len, target->fname);
- strcat(afl->mutation, afl->m_tmp);
+ snprintf(afl->m_tmp, sizeof(afl->m_tmp),
+ " SPLICE_INSERT-%u-%u-%u-%s", clone_from, clone_to,
+ clone_len, target->fname);
+ strcat(afl->mutation, afl->m_tmp);
#endif
- /* Head */
+ /* Head */
- memcpy(temp_buf, out_buf, clone_to);
+ memcpy(temp_buf, out_buf, clone_to);
- /* Inserted part */
+ /* Inserted part */
- memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
+ memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
- /* Tail */
- memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
- temp_len - clone_to);
+ /* Tail */
+ memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
+ temp_len - clone_to);
- out_buf = temp_buf;
- afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
- temp_len += clone_len;
+ out_buf = temp_buf;
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+ temp_len += clone_len;
- }
+ }
- MOpt_globals.cycles_v2[STAGE_Splice]++;
- break;
+ MOpt_globals.cycles_v2[STAGE_Splice]++;
+ break;
+
+ }
} // end of default:
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index ffba3475..09e773f0 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -74,7 +74,7 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
rewound and truncated. */
u32 __attribute__((hot))
-write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) {
+write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
#ifdef _AFL_DOCUMENT_MUTATIONS
s32 doc_fd;
@@ -86,7 +86,7 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) {
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION)) >=
0) {
- if (write(doc_fd, mem, len) != len)
+ if (write(doc_fd, *mem, len) != len)
PFATAL("write to mutation file failed: %s", fn);
close(doc_fd);
@@ -97,7 +97,7 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) {
if (unlikely(afl->custom_mutators_count)) {
ssize_t new_size = len;
- u8 * new_mem = mem;
+ u8 * new_mem = *mem;
u8 * new_buf = NULL;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
@@ -130,8 +130,14 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) {
}
+ if (new_mem != *mem) {
+
+ *mem = new_mem;
+
+ }
+
/* everything as planned. use the potentially new data. */
- afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size);
+ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size);
len = new_size;
} else {
@@ -147,7 +153,7 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) {
}
/* boring uncustom. */
- afl_fsrv_write_to_testcase(&afl->fsrv, mem, len);
+ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len);
}
@@ -370,7 +376,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
/* we need a dummy run if this is LTO + cmplog */
if (unlikely(afl->shm.cmplog_mode)) {
- (void)write_to_testcase(afl, use_mem, q->len, 1);
+ (void)write_to_testcase(afl, (void **)&use_mem, q->len, 1);
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
@@ -413,7 +419,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u64 cksum;
- (void)write_to_testcase(afl, use_mem, q->len, 1);
+ (void)write_to_testcase(afl, (void **)&use_mem, q->len, 1);
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
@@ -724,7 +730,7 @@ void sync_fuzzers(afl_state_t *afl) {
/* See what happens. We rely on save_if_interesting() to catch major
errors and save the test case. */
- (void)write_to_testcase(afl, mem, st.st_size, 1);
+ (void)write_to_testcase(afl, (void **)&mem, st.st_size, 1);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
@@ -967,7 +973,7 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
- len = write_to_testcase(afl, out_buf, len, 0);
+ len = write_to_testcase(afl, (void **)&out_buf, len, 0);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 9737c692..5b237748 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -1021,13 +1021,15 @@ void show_stats_normal(afl_state_t *afl) {
if (unlikely(!afl->skip_deterministic)) {
- sprintf(tmp, "%s/%s, %s/%s, %s/%s",
+ sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
- u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
+ u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]),
+ u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]),
+ u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI]));
} else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
@@ -1839,13 +1841,15 @@ void show_stats_pizza(afl_state_t *afl) {
if (unlikely(!afl->skip_deterministic)) {
- sprintf(tmp, "%s/%s, %s/%s, %s/%s",
+ sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
- u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
+ u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]),
+ u_stringify_int(IB(6), afl->stage_finds[STAGE_EXTRAS_AI]),
+ u_stringify_int(IB(7), afl->stage_cycles[STAGE_EXTRAS_AI]));
} else if (unlikely(!afl->extras_cnt || afl->custom_only)) {
diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c
index 8d58bb3e..b48c6fb3 100644
--- a/src/afl-sharedmem.c
+++ b/src/afl-sharedmem.c
@@ -107,7 +107,7 @@ void afl_shm_deinit(sharedmem_t *shm) {
if (shm->cmp_map != NULL) {
munmap(shm->cmp_map, shm->map_size);
- shm->map = NULL;
+ shm->cmp_map = NULL;
}
@@ -153,6 +153,8 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
shm->g_shm_fd = -1;
shm->cmplog_g_shm_fd = -1;
+ const int shmflags = O_RDWR | O_EXCL;
+
/* ======
generate random file name for multi instance
@@ -161,9 +163,39 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
so we do this worse workaround */
snprintf(shm->g_shm_file_path, L_tmpnam, "/afl_%d_%ld", getpid(), random());
+ #ifdef SHM_LARGEPAGE_ALLOC_DEFAULT
+ /* trying to get large memory segment optimised and monitorable separately as
+ * such */
+ static size_t sizes[4] = {(size_t)-1};
+ static int psizes = 0;
+ int i;
+ if (sizes[0] == (size_t)-1) { psizes = getpagesizes(sizes, 4); }
+
+ /* very unlikely to fail even if the arch supports only two sizes */
+ if (likely(psizes > 0)) {
+
+ for (i = psizes - 1; shm->g_shm_fd == -1 && i >= 0; --i) {
+
+ if (sizes[i] == 0 || map_size % sizes[i]) { continue; }
+
+ shm->g_shm_fd =
+ shm_create_largepage(shm->g_shm_file_path, shmflags, i,
+ SHM_LARGEPAGE_ALLOC_DEFAULT, DEFAULT_PERMISSION);
+
+ }
+
+ }
+
+ #endif
+
/* create the shared memory segment as if it was a file */
- shm->g_shm_fd = shm_open(shm->g_shm_file_path, O_CREAT | O_RDWR | O_EXCL,
- DEFAULT_PERMISSION);
+ if (shm->g_shm_fd == -1) {
+
+ shm->g_shm_fd =
+ shm_open(shm->g_shm_file_path, shmflags | O_CREAT, DEFAULT_PERMISSION);
+
+ }
+
if (shm->g_shm_fd == -1) { PFATAL("shm_open() failed"); }
/* configure the size of the shared memory segment */
diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION
index cda1d700..77fc69b5 100644
--- a/unicorn_mode/UNICORNAFL_VERSION
+++ b/unicorn_mode/UNICORNAFL_VERSION
@@ -1 +1 @@
-09ad7d4784e50ec4ddf590a2c29764e2a7f37442
+c3e15a7d