diff options
119 files changed, 8131 insertions, 914 deletions
diff --git a/.custom-format.py b/.custom-format.py index c8075ace..e787df28 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -24,7 +24,7 @@ import importlib.metadata # string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use -CURRENT_LLVM = os.getenv('LLVM_VERSION', 17) +CURRENT_LLVM = os.getenv('LLVM_VERSION', 18) CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "") diff --git a/.gitignore b/.gitignore index 8e191e29..bc06ef2d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ *.pyc *.so *.swp +.DS_Store .sync_tmp .test .test2 @@ -111,3 +112,5 @@ utils/replay_record/persistent_demo_replay_compat utils/replay_record/persistent_demo_replay_argparse utils/plot_ui/afl-plot-ui vuln_prog +argv_fuzz_demo +argv_fuzz_persistent_demo \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0042bf28..8b4dcb6d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,6 +34,7 @@ file in one the following folders: * [docs/](docs/) (this is where you can find most of our docs content) * [frida_mode/](frida_mode/) * [instrumentation/](instrumentation/) +* [nyx_mode/](nyx_mode/) * [qemu_mode/](qemu_mode/) * [unicorn_mode/](unicorn_mode/) diff --git a/GNUmakefile b/GNUmakefile index dee9bbb3..9f862120 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -441,6 +441,14 @@ test_shm: @echo "[-] shmat seems not to be working, switching to mmap implementation" endif +ifeq "$(shell echo '$(HASH)include <zlib.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -Werror -x c - -lz -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + override SPECIAL_PERFORMANCE += -DHAVE_ZLIB + override LDFLAGS += -lz + $(info [+] ZLIB detected) +else + $(info [!] Warning: no ZLIB detected) +endif + .PHONY: test_python ifeq "$(PYTHON_OK)" "1" test_python: @@ -471,8 +479,8 @@ src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o -afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c | test_x86 - $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -lm +afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86 + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 70c54f1c..d5dcb09b 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -32,6 +32,9 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2 SYS = $(shell uname -s) +override LLVM_TOO_NEW_DEFAULT := 18 +override LLVM_TOO_OLD_DEFAULT := 13 + ifeq "$(SYS)" "OpenBSD" LLVM_CONFIG ?= $(BIN_PATH)/llvm-config HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1) @@ -39,24 +42,36 @@ ifeq "$(SYS)" "OpenBSD" $(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9") endif else - LLVM_CONFIG ?= llvm-config -endif - -LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' ) -LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' ) -LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' ) -LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 ) -LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 ) -LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 ) -LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 ) -LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 ) -LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 ) -LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 ) -LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) -LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) -LLVM_STDCXX = gnu++11 -LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0) -LLVM_LTO = 0 + # Small function to use Bash to detect the latest available clang and clang++ binaries, if using them by that name fails + override _CLANG_VERSIONS_TO_TEST := $(patsubst %,-%,$(shell seq $(LLVM_TOO_NEW_DEFAULT) -1 $(LLVM_TOO_OLD_DEFAULT))) + detect_newest=$(shell for v in "" $(_CLANG_VERSIONS_TO_TEST); do test -n "$$(command -v -- $1$$v)" && { echo "$1$$v"; break; }; done) + LLVM_CONFIG ?= $(call detect_newest,llvm-config) +endif + +ifneq "$(LLVM_CONFIG)" "" + override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null) + LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER))) + + LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null) + LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null) +endif + +ifneq "$(LLVMVER)" "" + LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER))) + LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER)))) + LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0) + LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0) + LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0) + LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0) + LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0) + LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0) +endif + +LLVM_STDCXX := gnu++11 +LLVM_LTO := 0 +LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-8]\.' && echo 1 || echo 0) +# Uncomment to see the values assigned above +# $(foreach var,LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var)))) ifeq "$(LLVMVER)" "" $(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.) @@ -103,10 +118,6 @@ ifeq "$(LLVM_LTO)" "0" $(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.) endif -ifeq "$(LLVM_APPLE_XCODE)" "1" - $(warning llvm_mode will not compile with Xcode clang...) -endif - # We were using llvm-config --bindir to get the location of clang, but # this seems to be busted on some distros, so using the one in $PATH is # probably better. @@ -114,6 +125,11 @@ endif CC = $(LLVM_BINDIR)/clang CXX = $(LLVM_BINDIR)/clang++ +LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0) +ifeq "$(LLVM_APPLE_XCODE)" "1" + $(warning llvm_mode will not compile with Xcode clang...) +endif + # llvm-config --bindir may not providing a valid path, so ... ifeq "$(shell test -e $(CC) || echo 1 )" "1" # however we must ensure that this is not a "CC=gcc make" @@ -245,7 +261,7 @@ endif AFL_CLANG_FUSELD= ifeq "$(LLVM_LTO)" "1" - ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" + ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=$$(command -v ld) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" AFL_CLANG_FUSELD=1 ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(AFL_REAL_LD) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" AFL_CLANG_LDPATH=1 @@ -300,8 +316,8 @@ endif ifneq "$(LLVM_CONFIG)" "" CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include endif -CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations -CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS) +CLANG_CPPFL = $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations +CLANG_LFL = $$($(LLVM_CONFIG) --ldflags) $(LDFLAGS) # wasm fuzzing: disable thread-local storage and unset LLVM debug flag ifdef WAFL_MODE @@ -319,7 +335,7 @@ else endif ifeq "$(SYS)" "OpenBSD" - CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so + CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so CLANG_CPPFL += -mno-retpoline CFLAGS += -mno-retpoline # Needed for unwind symbols @@ -417,7 +433,7 @@ endif endif instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h - $(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@ + $(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@ ./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps ifeq "$(LLVM_MIN_4_0_1)" "0" diff --git a/README.md b/README.md index 1b255a2a..94f02b75 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # American Fuzzy Lop plus plus (AFL++) -<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250"> +<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250"> Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.21c +GitHub version: 4.22a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/TODO.md b/TODO.md index b36269b4..81196339 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,7 @@ ## Must - - fast restart of afl-fuzz if cmdline + target hash is the same + - ijon support? - check for null ptr for xml/curl/g_ string transform functions - hardened_usercopy=0 page_alloc.shuffle=0 - add value_profile but only enable after 15 minutes without finds diff --git a/afl-whatsup b/afl-whatsup index 19841755..6fa2dfc2 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -112,12 +112,12 @@ if [ -z "$NO_COLOR" ]; then fi PLATFORM=`uname -s` -if [ "$PLATFORM" = "Linux" ] ; then - CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'` -else +#if [ "$PLATFORM" = "Linux" ] ; then +# CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'` +#else # This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux CUR_TIME=`date +%s` -fi +#fi TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1 trap "rm -f $TMP" 1 2 3 13 15 diff --git a/custom_mutators/aflpp/aflpp.c b/custom_mutators/aflpp/aflpp.c index 0b236f76..ea50751a 100644 --- a/custom_mutators/aflpp/aflpp.c +++ b/custom_mutators/aflpp/aflpp.c @@ -48,7 +48,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, u8 *ptr = realloc(data->buf, max_size); - if (ptr) { + if (!ptr) { return 0; diff --git a/custom_mutators/aflpp/standalone/Makefile b/custom_mutators/aflpp/standalone/Makefile index f1e99445..d7bc840d 100644 --- a/custom_mutators/aflpp/standalone/Makefile +++ b/custom_mutators/aflpp/standalone/Makefile @@ -4,7 +4,7 @@ CFLAGS = -O3 -funroll-loops -fPIC all: aflpp-standalone aflpp-standalone: aflpp-standalone.c - $(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c + $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c ../../../src/afl-fuzz-extras.c ../../../src/afl-common.c clean: rm -f *.o *~ aflpp-standalone core diff --git a/custom_mutators/aflpp/standalone/README.md b/custom_mutators/aflpp/standalone/README.md index a1ffb5f9..3c26a29a 100644 --- a/custom_mutators/aflpp/standalone/README.md +++ b/custom_mutators/aflpp/standalone/README.md @@ -5,6 +5,6 @@ this is the AFL++ havoc mutator as a standalone mutator just type `make` to build. ``` -aflpp-standalone inputfile outputfile [splicefile] +aflpp-standalone -h # to see all parameteres +cat file | aflpp-standalone -m 4 -x foo.dict - outputfile splicefile # example ``` - diff --git a/custom_mutators/aflpp/standalone/aflpp-standalone.c b/custom_mutators/aflpp/standalone/aflpp-standalone.c index 3a2cbc2f..c059ce11 100644 --- a/custom_mutators/aflpp/standalone/aflpp-standalone.c +++ b/custom_mutators/aflpp/standalone/aflpp-standalone.c @@ -1,6 +1,12 @@ #include "afl-fuzz.h" #include "afl-mutations.h" +#include <unistd.h> +#include <getopt.h> + +static int max_havoc = 16, verbose; +static unsigned char *dict; + typedef struct my_mutator { afl_state_t *afl; @@ -21,14 +27,14 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { } - if ((data->buf = malloc(1024*1024)) == NULL) { + if ((data->buf = malloc(1024 * 1024)) == NULL) { perror("afl_custom_init alloc"); return NULL; } else { - data->buf_size = 1024*1024; + data->buf_size = 1024 * 1024; } @@ -36,9 +42,23 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) { data->afl = calloc(1, sizeof(afl_state_t)); data->afl->queue_cycle = 1; data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); - if (data->afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); } + if (data->afl->fsrv.dev_urandom_fd < 0) { + + PFATAL("Unable to open /dev/urandom"); + + } + rand_set_seed(data->afl, getpid()); + if (dict) { + + load_extras(data->afl, dict); + if (verbose) + fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict, + data->afl->extras_cnt); + + } + return data; } @@ -53,7 +73,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, u8 *ptr = realloc(data->buf, max_size); - if (ptr) { + if (!ptr) { return 0; @@ -66,14 +86,20 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, } - u32 havoc_steps = 1 + rand_below(data->afl, 16); + u32 havoc_steps = 1 + rand_below(data->afl, max_havoc); + if (verbose) fprintf(stderr, "Havoc steps: %u\n", havoc_steps); /* set everything up, costly ... :( */ memcpy(data->buf, buf, buf_size); /* the mutation */ - u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, - false, true, add_buf, add_buf_size, max_size); + u32 out_buf_len; + do { + + out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, false, + true, add_buf, add_buf_size, max_size); + + } while (out_buf_len == buf_size && memcmp(buf, data->buf, buf_size) == 0); /* return size of mutated data */ *out_buf = data->buf; @@ -84,80 +110,143 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size, int main(int argc, char *argv[]) { if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) { - printf("Syntax: %s [-v] [inputfile [outputfile [splicefile]]]\n\n", argv[0]); - printf("Reads a testcase from stdin when no input file (or '-') is specified,\n"); - printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n"); - printf("no output filename is given. As an optional third parameter you can give a file\n"); + + printf( + "Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile " + "[splicefile]]]\n\n", + argv[0]); + printf( + "Reads a testcase from stdin when no input file (or '-') is " + "specified,\n"); + printf( + "mutates according to AFL++'s mutation engine, and write to stdout " + "when '-' or\n"); + printf( + "no output filename is given. As an optional third parameter you can " + "give a file\n"); printf("for splicing. Maximum input and output length is 1MB.\n"); - printf("The -v verbose option prints debug output to stderr.\n"); + printf("Options:\n"); + printf(" -v verbose debug output to stderr.\n"); + printf(" -m val max mutations (1-val, val default is 16)\n"); + printf(" -x file dictionary file (AFL++ format)\n"); return 0; + } - FILE *in = stdin, *out = stdout, *splice = NULL; - unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL; - int verbose = 0, splicelen = 0; + FILE *in = stdin, *out = stdout, *splice = NULL; + unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL; + int splicelen = 0, opt; + + while ((opt = getopt(argc, argv, "vm:x:")) > 0) { + + switch (opt) { + + case 'm': + max_havoc = atoi(optarg); + break; + case 'v': + verbose = 1; + break; + case 'x': + dict = optarg; + break; + default: + fprintf(stderr, "Error: unknown parameter -%c\n", opt); + exit(-1); + + } + + } + + if (max_havoc < 1) { + + fprintf(stderr, "Error: illegal -m value\n"); + exit(-1); - if (argc > 1 && strcmp(argv[1], "-v") == 0) { - verbose = 1; - argc--; - argv++; - fprintf(stderr, "Verbose active\n"); } my_mutator_t *data = afl_custom_init(NULL, 0); - if (argc > 1 && strcmp(argv[1], "-") != 0) { - if ((in = fopen(argv[1], "r")) == NULL) { + if (argc > optind && strcmp(argv[optind], "-") != 0) { + + if ((in = fopen(argv[optind], "r")) == NULL) { + perror(argv[1]); return -1; + } - if (verbose) fprintf(stderr, "Input: %s\n", argv[1]); + + if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]); + } - size_t inlen = fread(inbuf, 1, 1024*1024, in); - + size_t inlen = fread(inbuf, 1, 1024 * 1024, in); + if (!inlen) { - fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin"); + + fprintf(stderr, "Error: empty file %s\n", + argv[optind] ? argv[optind] : "stdin"); return -1; + } - if (argc > 2 && strcmp(argv[2], "-") != 0) { - if ((out = fopen(argv[2], "w")) == NULL) { - perror(argv[2]); + if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) { + + if ((out = fopen(argv[optind + 1], "w")) == NULL) { + + perror(argv[optind + 1]); return -1; + } - if (verbose) fprintf(stderr, "Output: %s\n", argv[2]); + + if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]); + } - if (argc > 3) { - if ((splice = fopen(argv[3], "r")) == NULL) { - perror(argv[3]); + if (argc > optind + 2) { + + if ((splice = fopen(argv[optind + 2], "r")) == NULL) { + + perror(argv[optind + 2]); return -1; + } - if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]); - splicebuf = malloc(1024*1024); - size_t splicelen = fread(splicebuf, 1, 1024*1024, splice); + + if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]); + splicebuf = malloc(1024 * 1024); + size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice); if (!splicelen) { - fprintf(stderr, "Error: empty file %s\n", argv[3]); + + fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]); return -1; + } + if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen); + } if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen); - unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, splicelen, 1024*1024); + unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, + splicelen, 1024 * 1024); if (outlen == 0 || !outbuf) { + fprintf(stderr, "Error: no mutation data returned.\n"); return -1; + } if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen); if (fwrite(outbuf, 1, outlen, out) != outlen) { + fprintf(stderr, "Warning: incomplete write.\n"); return -1; + } - + return 0; + } + diff --git a/custom_mutators/atnwalk/README.md b/custom_mutators/atnwalk/README.md index 730349a3..7dbe8ee5 100644 --- a/custom_mutators/atnwalk/README.md +++ b/custom_mutators/atnwalk/README.md @@ -13,7 +13,7 @@ Just type `make` to build `atnwalk.so`. **NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed) ```bash -# create the required a random seed first +# create the required random seed first mkdir -p ~/campaign/example/seeds cd ~/campaign/example/seeds head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded diff --git a/custom_mutators/atnwalk/atnwalk.c b/custom_mutators/atnwalk/atnwalk.c index c3a2cd95..45ccc181 100644 --- a/custom_mutators/atnwalk/atnwalk.c +++ b/custom_mutators/atnwalk/atnwalk.c @@ -180,7 +180,8 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) { if (fd_socket != -1) { close(fd_socket); } *out_buf = NULL; - return 0; + fprintf(stderr, "atnwalk.socket not found in current directory!\n"); + exit(-1); } diff --git a/custom_mutators/autotokens/autotokens.cpp b/custom_mutators/autotokens/autotokens.cpp index 8135aba1..9bce3da7 100644 --- a/custom_mutators/autotokens/autotokens.cpp +++ b/custom_mutators/autotokens/autotokens.cpp @@ -39,6 +39,7 @@ extern "C" { #ifndef AFL_TXT_MAX_LEN #define AFL_TXT_MAX_LEN 65535 #endif +#define AUTOTOKENS_TXT_MIN_LEN 1 #if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN #error SPLICE_MIN must be lower than SIZE_MIN @@ -57,8 +58,9 @@ typedef struct my_mutator { if (unlikely(debug)) fprintf #define IFDEBUG if (unlikely(debug)) +int module_disabled = 0; + static afl_state *afl_ptr; -static int module_disabled = 0; static int auto_disable = AUTOTOKENS_AUTO_DISABLE; static int debug = AUTOTOKENS_DEBUG; static int only_fav = AUTOTOKENS_ONLY_FAV; @@ -104,9 +106,9 @@ static void first_run(void *data) { if (afl_ptr->custom_only || !auto_disable) { return; } if (unlikely(afl_ptr->active_items == 1 && - afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN)) { + afl_ptr->queue_cur->len < AUTOTOKENS_TXT_MIN_LEN)) { - if (afl_ptr->extras_cnt > 8) { + if (afl_ptr->extras_cnt) { u32 valid = 0; @@ -237,7 +239,7 @@ extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf, } -extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size, +extern "C" size_t afl_custom_fuzz(void *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size) { @@ -655,6 +657,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (current_id > whitespace_ids + 6 && afl_ptr->active_items == 1 && afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) { + retry_thin_air: DEBUGF(stderr, "Creating an entry from thin air...\n"); structure = new vector<u32>(); u32 item, prev, cnt = current_id >> 1; @@ -684,8 +687,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } - create_from_thin_air = 0; - } if (entry == file_mapping.end()) { @@ -693,7 +694,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, // this input file was not analyzed for tokens yet, so let's do it! size_t len = afl_ptr->queue_cur->len; - if (len < AFL_TXT_MIN_LEN) { + if (len < AUTOTOKENS_TXT_MIN_LEN) { file_mapping[fn] = structure; // NULL ptr so we don't read the file again s = NULL; @@ -895,6 +896,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, if (tokens.size() < AUTOTOKENS_SIZE_MIN) { + if (create_from_thin_air) { goto retry_thin_air; } file_mapping[fn] = NULL; s = NULL; DEBUGF(stderr, "too few tokens\n"); @@ -955,7 +957,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data, } -extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { +extern "C" void *afl_custom_init(afl_state_t *afl, unsigned int seed) { (void)(seed); my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t)); @@ -1070,7 +1072,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) { id_to_token[current_id] = "'"; ++current_id; - return data; + return (void *)data; } diff --git a/custom_mutators/autotokens/standalone/Makefile b/custom_mutators/autotokens/standalone/Makefile new file mode 100644 index 00000000..8d5baf13 --- /dev/null +++ b/custom_mutators/autotokens/standalone/Makefile @@ -0,0 +1,19 @@ + +CFLAGS = -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1 -Wno-implicit-function-declaration +CXXFLAGS= -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1 + +all: autotokens-standalone + +autotokens.o: ../autotokens.cpp + $(CXX) $(CXXFLAGS) -I../../../include -I. -I../.. -c ../autotokens.cpp + +autotokens-standalone: autotokens-standalone.c autotokens.o + $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c autotokens-standalone.c + $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-performance.c + $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-extras.c + $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-queue.c + $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-common.c + $(CXX) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o autotokens-standalone *.o + +clean: + rm -f *.o *~ autotokens-standalone core diff --git a/custom_mutators/autotokens/standalone/README.md b/custom_mutators/autotokens/standalone/README.md new file mode 100644 index 00000000..9e9babf7 --- /dev/null +++ b/custom_mutators/autotokens/standalone/README.md @@ -0,0 +1,12 @@ +# Autotokens standalone mutator + +this is a standalone version of the AFL++ autotokens custom mutator. + +just type `make` to build. + +You *MUST* use a dictionary file to have an effective grammarless grammar fuzzer! + +``` +autotokens-standalone -h # to see all parameteres +autotokens-standalone -x foo.dict inputfile outputfile # example +``` diff --git a/custom_mutators/autotokens/standalone/autotokens-standalone.c b/custom_mutators/autotokens/standalone/autotokens-standalone.c new file mode 100644 index 00000000..e7a09cb3 --- /dev/null +++ b/custom_mutators/autotokens/standalone/autotokens-standalone.c @@ -0,0 +1,192 @@ +#include "afl-fuzz.h" +#include "afl-mutations.h" + +#include <unistd.h> +#include <getopt.h> + +static int max_havoc = 16, verbose; +static unsigned char *dict, *mh = "16"; + +extern int module_disabled; + +void *afl_custom_init(afl_state_t *, unsigned int); + +int main(int argc, char *argv[]) { + + if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) { + + printf( + "Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile " + "[splicefile]]]\n\n", + argv[0]); + printf("Reads a testcase from a file (not stdin!),\n"); + printf("writes to stdout when '-' or\n"); + printf( + "no output filename is given. As an optional third parameter you can " + "give a file\n"); + printf("for splicing. Maximum input and output length is 1MB.\n"); + printf("Options:\n"); + printf(" -v verbose debug output to stderr.\n"); + printf(" -m val max mutations (1-val, val default is 16)\n"); + printf(" -x file dictionary file (AFL++ format)\n"); + printf("You can set the following environment variable parameters:\n"); + printf("AUTOTOKENS_COMMENT` - what character or string starts a comment which will be\n"); + printf(" removed. Default: \"/* ... */\"\n"); + return 0; + + } + + FILE *in = stdin, *out = stdout, *splice = NULL; + unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL; + int splicelen = 0, opt; + + while ((opt = getopt(argc, argv, "vm:x:")) > 0) { + + switch (opt) { + + case 'm': + max_havoc = atoi(optarg); + mh = optarg; + break; + case 'v': + verbose = 1; + break; + case 'x': + dict = optarg; + break; + default: + fprintf(stderr, "Error: unknown parameter -%c\n", opt); + exit(-1); + + } + + } + + if (max_havoc < 1) { + + fprintf(stderr, "Error: illegal -m value\n"); + exit(-1); + + } + + if (argc > optind && strcmp(argv[optind], "-") != 0) { + + if ((in = fopen(argv[optind], "r")) == NULL) { + + perror(argv[1]); + return -1; + + } + + if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]); + + } + + size_t inlen = fread(inbuf, 1, 1024 * 1024, in); + + if (!inlen) { + + fprintf(stderr, "Error: empty file %s\n", + argv[optind] ? argv[optind] : "stdin"); + return -1; + + } + + if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) { + + if ((out = fopen(argv[optind + 1], "w")) == NULL) { + + perror(argv[optind + 1]); + return -1; + + } + + if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]); + + } + + if (argc > optind + 2) { + + if ((splice = fopen(argv[optind + 2], "r")) == NULL) { + + perror(argv[optind + 2]); + return -1; + + } + + if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]); + splicebuf = malloc(1024 * 1024); + size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice); + if (!splicelen) { + + fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]); + return -1; + + } + + if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen); + + } + + /* configure autotokens */ + setenv("AUTOTOKENS_LEARN_DICT", "1", 0); + setenv("AUTOTOKENS_CREATE_FROM_THIN_AIR", "1", 0); + setenv("AUTOTOKENS_CHANGE_MAX", mh, 0); + + /* fake AFL++ state */ + afl_state_t *afl = (afl_state_t *)calloc(1, sizeof(afl_state_t)); + afl->queue_cycle = afl->havoc_div = afl->active_items = afl->queued_items = 1; + afl->shm.cmplog_mode = 0; + afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); + if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); } + + rand_set_seed(afl, getpid()); + + if (dict) { + + load_extras(afl, dict); + if (verbose) + fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict, + afl->extras_cnt); + + } + + // setup a fake queue entry + afl->queue_buf = malloc(64); + afl->queue_buf[0] = afl->queue_cur = + (struct queue_entry *)malloc(sizeof(struct queue_entry)); + afl->queue_cur->testcase_buf = inbuf; + afl->queue_cur->fname = (u8 *)argv[optind]; + afl->queue_cur->len = inlen; + afl->queue_cur->perf_score = 100; + afl->queue_cur->favored = afl->queue_cur->is_ascii = 1; + // afl->custom_only = 1; + + void *data = (void *)afl_custom_init(afl, (u32)0); + + u8 res = afl_custom_queue_get(inbuf, (u8 *)argv[optind]); + + if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen); + unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, + splicelen, 1024 * 1024); + + if (outlen == 0 || !outbuf) { + + fprintf(stderr, "Error: no mutation data returned.\n"); + return -1; + + } + + if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen); + + if (fwrite(outbuf, 1, outlen, out) != outlen) { + + fprintf(stderr, "Warning: incomplete write.\n"); + return -1; + + } + + return 0; + +} + diff --git a/custom_mutators/custom_send_tcp/Makefile b/custom_mutators/custom_send_tcp/Makefile new file mode 100644 index 00000000..8549ccad --- /dev/null +++ b/custom_mutators/custom_send_tcp/Makefile @@ -0,0 +1,7 @@ +all: custom_send_tcp.so + +custom_send_tcp.so: + $(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c + +clean: + rm -f custom_send_tcp.so *.o *~ core diff --git a/custom_mutators/custom_send_tcp/README.md b/custom_mutators/custom_send_tcp/README.md new file mode 100644 index 00000000..7b4bb869 --- /dev/null +++ b/custom_mutators/custom_send_tcp/README.md @@ -0,0 +1,13 @@ +# Send testcases via TCP custom mutator + +This custom mutator sends the fuzzing testcases via TCP. + +`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set! +`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense) +`CUSTOM_SEND_PORT` - the TCP port to send to +`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target + +Example: +``` +CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ... +``` diff --git a/custom_mutators/custom_send_tcp/custom_send_tcp.c b/custom_mutators/custom_send_tcp/custom_send_tcp.c new file mode 100644 index 00000000..53689ced --- /dev/null +++ b/custom_mutators/custom_send_tcp/custom_send_tcp.c @@ -0,0 +1,113 @@ +#include <time.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <arpa/inet.h> +#include <sys/select.h> + +#include "afl-fuzz.h" + +static int my_debug = 0; +static int my_read = 0; + +#define DEBUG(...) if (my_debug) printf(__VA_ARGS__) + +typedef struct tcp_send_mutator { + afl_state_t* afl; + struct sockaddr_in server_addr; +} tcp_send_mutator_t; + +void *afl_custom_init(afl_state_t* afl, uint32_t seed) { + const char* ip = getenv("CUSTOM_SEND_IP"); + const char* port = getenv("CUSTOM_SEND_PORT"); + + if (getenv("AFL_DEBUG")) my_debug = 1; + if (getenv("CUSTOM_SEND_READ")) my_read = 1; + + if (!ip || !port) { + fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n"); + exit(1); + } + + tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t)); + if (!mutator) { + fprintf(stderr, "Failed to allocate mutator struct\n"); + exit(1); + } + + mutator->afl = afl; + + bzero(&mutator->server_addr, sizeof(mutator->server_addr)); + mutator->server_addr.sin_family = AF_INET; + if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) { + fprintf(stderr, "Could not convert target ip address!\n"); + exit(1); + } + mutator->server_addr.sin_port = htons(atoi(port)); + + printf("[+] Custom tcp send mutator setup ready to go!\n"); + + return mutator; +} + +int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) { + while (max_attempts > 0) { + if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) { + return 0; + } + + // Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the + // application under test having started to listen for connections and + // afl_custom_fuzz_send being called. To address this race, we attempt + // to connect N times and sleep a short period of time in between + // connection attempts. + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 100; + nanosleep(&t, NULL); + --max_attempts; + } + return 1; +} + +void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + + int written = 0; + if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) { + DEBUG("connected, write()\n"); + written = write(sock, buf, buf_size); + } else { + DEBUG("socket() or connect() error: %d\n", errno); + } + + if (written < 0) { + DEBUG("write() error: %d\n", errno); + } else if (my_read) { + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + fd_set set; + FD_ZERO(&set); + FD_SET(sock, &set); + + int select_res = select(sock + 1, &set, NULL, NULL, &timeout); + if (select_res == -1) { + DEBUG("select() error: %d\n", errno); + } else if (select_res == 0) { + DEBUG("read() timeout!\n"); + } else { + uint8_t buf[64]; + (void)read(sock, buf, sizeof(buf)); + } + } + + close(sock); +} + +void afl_custom_deinit(tcp_send_mutator_t* mutator) { + free(mutator); +} diff --git a/custom_mutators/gramatron/json-c b/custom_mutators/gramatron/json-c -Subproject 11546bfd07a575c47416924cb98de3d33a4e642 +Subproject af8dd4a307e7b837f9fa2959549548ace4afe08 diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION index 02119caf..eea76ba3 100644 --- a/custom_mutators/grammar_mutator/GRAMMAR_VERSION +++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION @@ -1 +1 @@ -95a6857 +05d8f53 diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator -Subproject 95a685773e571620cb6e2788dbbdba333e1b9bf +Subproject 05d8f537f8d656f0754e7ad5dcc653c42cb4f8f diff --git a/custom_mutators/radamsa/libradamsa.c b/custom_mutators/radamsa/libradamsa.c index e6838752..1dcf91d8 100644 --- a/custom_mutators/radamsa/libradamsa.c +++ b/custom_mutators/radamsa/libradamsa.c @@ -3707,7 +3707,7 @@ typedef intptr_t wdiff; 1024 * 1024 * 8 /* static malloc'd heap size if used as a library */ #define FBITS 24 /* bits in fixnum, on the way to 24 and beyond */ #define FMAX \ - ((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \ + ((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \ */ #define MAXOBJ 0xffff /* max words in tuple including header */ #define MAXPAYL \ diff --git a/dictionaries/ruby.dict b/dictionaries/ruby.dict new file mode 100644 index 00000000..601b7363 --- /dev/null +++ b/dictionaries/ruby.dict @@ -0,0 +1,5713 @@ +! +!= +!~ +% +& +* +** ++ ++@ +- +-@ +/ +< +<< +<= +<=> +== +=== +=~ +> +>= +>> +APOP +ASCIIZ +AdditiveExpr +AndExpr +Array +BigDecimal +CSV +Call +CloseKey +Complex +CreateKey +CurrentContext +D +DEBUG +DEBUG= +DelegateClass +DeleteKey +DeleteValue +Digest +E +ESCDELAY +ESCDELAY= +EnumKey +EnumValue +EqualityExpr +Fail +FilterExpr +Float +FlushKey +FunctionCall +Hash +I +Integer +JSON +JobManager +LOG_MASK +LOG_UPTO +LocationPath +MultiplicativeExpr +NodeTest +OpenKey +OrExpr +PI +PathExpr +Pathname +PermaLink? +Predicate +PrimaryExpr +Proxy +QueryInfoKey +QueryValue +Raise +Rational +RelationalExpr +RelativeLocationPath +SP +SP_Z +SetValue +String +TABSIZE +TABSIZE= +URI +UnaryExpr +UnionExpr +Z +[] +[]= +^ +_PermaLink? +__callee__ +__dir__ +__drbref +__drburi +__evaluate__ +__exit__ +__getobj__ +__id__ +__method__ +__send__ +__setobj__ +__to_xpath_helper +__validate +_ac_arg_enable +_attrs +_check_ac_args +_dump +_getproperty +_httpdate +_id2ref +_invoke +_iso8601 +_jisx0301 +_load +_nodeType +_ns +_parse +_parse_date_if_needed +_prepare_run +_print +_racc_do_parse_c +_racc_do_parse_rb +_racc_do_reduce +_racc_evalact +_racc_init_sysvars +_racc_setup +_racc_yyparse_c +_racc_yyparse_rb +_report +_reverse +_rfc2822 +_rfc3339 +_rfc822 +_run_parallel +_run_suite +_run_suites +_set_default_values +_set_last_value +_setproperty +_setup_maker_element +_strptime +_tags +_to_string +_validate +_xmlschema +` +a +abbrev +abbreviate +abi +abort +abort_on_exception +abort_on_exception= +about +abs +abs2 +absolute +absolute? +absolute_name +absolute_path +ac_arg_disable +ac_arg_enable +ac_arg_with +accept +accept_blank_line +accept_block_quote +accept_charset +accept_charset= +accept_document +accept_encoding +accept_heading +accept_indented_paragraph +accept_language +accept_list_end +accept_list_item_end +accept_list_item_start +accept_list_start +accept_loop +accept_nonblock +accept_paragraph +accept_raw +accept_rule +accept_uri_http +accept_verbatim +access_log +acct +acos +acos! +acosh +acosh! +actions +activate +activate_dependencies +activated +activated? +active? +active_count +active_job? +active_jobs +active_jobs_exist? +active_process_controllers +add +add! +add? +add_alias +add_also_in +add_attribute +add_attributes +add_authenticator +add_bindir +add_bulk_threshold_option +add_c_enclosure +add_c_variables +add_cert +add_certid +add_certificate +add_chain_to +add_checksums +add_class +add_class_or_module +add_clear_sources_option +add_comment +add_common_option +add_constant +add_converter +add_crl +add_data +add_date +add_dependency +add_dependency_with_type +add_description +add_development_dependency +add_dictionary +add_element +add_entry +add_event_to_arry +add_extend +add_extends +add_extension +add_extension_modules +add_extra_args +add_field +add_file +add_file_digest +add_file_signed +add_file_simple +add_filter +add_footnote +add_found_dependencies +add_from +add_generator +add_handler +add_have_children_element +add_html +add_import +add_include +add_includes +add_install_update_options +add_introspection +add_key_option +add_label +add_line_numbers +add_listener +add_loader +add_local_remote_options +add_location +add_log_header +add_maker +add_method +add_method_documentation +add_method_list +add_module +add_module_alias +add_multicall +add_namespace +add_need_initialize_variable +add_nonce +add_observer +add_option +add_other_element +add_owners +add_padding +add_paragraph +add_parser_run_info +add_path +add_platform +add_platform_option +add_plural_form +add_prerelease_option +add_private_type +add_protocol +add_proxy_option +add_rakelib +add_recipient +add_require +add_response_handler +add_revoked +add_row +add_ruby_type +add_rubygems_trusted_certs +add_runtime_dependency +add_schedule +add_section +add_self_to_load_path +add_setup_hook +add_signer +add_source_option +add_spec +add_special +add_special_RDOCLINK +add_special_TIDYLINK +add_specific_extra_args +add_specs +add_status +add_tag +add_target +add_teardown_hook +add_text +add_text_tests +add_to +add_to_classes_or_modules +add_to_element_method +add_to_fetcher +add_token +add_token_listener +add_tokens +add_trace_func +add_unconverted_fields +add_update_sources_option +add_value +add_version_option +add_visitor_tests +add_word_pair +addch +addr +addr_mask +addr_port +address +addstr +adler +adler32 +adler32_combine +advise +afamily +after +after_setup +after_teardown +after_worker_down +after_worker_quit +ajd +alert +alert_error +alert_warning +algorithm +alias +alias_command +alias_extension +alias_map +alias_method +aliases +alien +align +alive? +all +all= +all? +all_classes +all_classes_and_modules +all_files +all_modules +all_names +all_spec_names +all_specs +all_symbols +all_waits +allocate +allow_addr? +allow_socket? +alt_name_or_x509_entry +alternate= +amjd +ancestors +ancestors_of +anchor +angle +annotate +any? +any_content +any_to_s +ap_name +api_endpoint +api_endpoints +api_key +api_keys +api_uri +apop? +app_script_text +append +append_data +append_features +application +application= +apply_offset +appname +approximate_recommendation +aref +aref_prefix +aref_to +arg +arg_names +arglists +args +arguments +argv +arity +array +array_attributes +as_href +as_json +as_string +ascend +ascii_compatible? +ascii_only? +asciicompat_encoding +asctime +asin +asin! +asinh +asinh! +ask +ask_for_password +ask_for_password_on_unix +ask_for_password_on_windows +ask_if_ok +ask_yes_no +asn1_flag +asn1_flag= +assemble_template +assert +assert_block +assert_contains_make_command +assert_empty +assert_equal +assert_headers_equal +assert_in_delta +assert_in_epsilon +assert_includes +assert_instance_of +assert_kind_of +assert_match +assert_nil +assert_no_match +assert_not_equal +assert_not_nil +assert_not_same +assert_not_send +assert_nothing_raised +assert_nothing_thrown +assert_operator +assert_output +assert_path_exists +assert_performance +assert_performance_constant +assert_performance_exponential +assert_performance_linear +assert_performance_power +assert_predicate +assert_raise +assert_raises +assert_respond_to +assert_same +assert_send +assert_silent +assert_throws +asset +asset_dirs +asset_rel_path +assign_names +assoc +at +at_exit +atan +atan! +atan2 +atan2! +atanh +atanh! +atime +atom_validate +attempt_rule +attlistdecl +attlistdecl? +attr +attr_accessor +attr_reader +attr_writer +attribute +attribute_manager +attribute_names +attribute_of +attributes +attributes= +attributes_of +attroff +attron +attrset +atype +audit +auth_capable? +auth_cram_md5 +auth_data= +auth_login +auth_method +auth_only +auth_plain +auth_tag +auth_tag= +auth_type +authenticate +authenticated? +author +author= +authors +authors= +auto_indent_mode +autoclose= +autoclose? +autoload +autoload? +autorequire +autorun +avail_in +avail_out +avail_out= +available_specs +available_tags +axe +b +back_trace_limit +backticks +backtrace +backtrace_filter +backtrace_locations +banner +base +base64 +base64_encode +base64digest +base64digest! +base_dir +base_label +base_name +base_uri +basename +basic +basic_auth +basic_encode +basic_quote_characters +basic_quote_characters= +basic_word_break_characters +basic_word_break_characters= +beep +before +before_running_rdoc +before_setup +before_teardown +begin +begin_adding +begin_transport +beginning_of_line? +begins? +begx +begy +bench +bench_exp +bench_linear +bench_performance_constant +bench_performance_exponential +bench_performance_linear +bench_range +benchmark +benchmark_suites +between? +bin_dir +bin_file +bin_for_find +bin_key +bin_path +binary +binary= +binary? +binary_mode +bind +bind_at_call +bind_function +binding +bindir +binmode +binmode= +binmode? +binread +binwrite +bit_set? +bitmap +bitmap_for +bkgd +bkgdset +blank_line +blinding_off! +blinding_on! +blksize +block +block_given? +block_length +block_output_synchronize +block_params +block_params= +block_scanf +blockdev? +blockquote +blocks +bm +bmbm +body +body= +body_exist? +body_permitted? +body_stream +body_stream= +bool +boolean +boolean_writer +both? +bottom +bound? +box +break +break? +break_on_newline +break_outmost_groups +break_points +breakable +breakables +broadcast +broadcast_list +bsearch +buf +buffer +bufferSize +bufferType +build +build2 +build_args +build_args= +build_eigenvectors +build_extensions +build_heading +build_index +build_indicies +build_info_dir +build_info_file +build_list +build_marshal_gemspecs +build_modern +build_modern_index +build_modern_indicies +build_paragraph +build_path_query +build_rake_in +build_verbatim +builtin_curves +bulk_threshold +bump +by_col +by_col! +by_col_or_row +by_col_or_row! +by_id +by_row +by_row! +bytes +bytes_read +bytesize +byteslice +c_class_variables +c_function +c_singleton_class_variables +ca_certs +ca_file +ca_path +cache +cache_dir +cache_file +cache_path +cache_update_path +cachesize= +calc_checksum +calc_indent +calculate +calculate_checksum +call +call2 +call2_async +call_async +call_hook +call_method +call_seq +callcc +caller +caller_locations +calls_super +calltype +calltype= +can_change_color? +can_parse +can_parse_by_name +cancel +canceled? +candidate +canonical +canonical_each +canonname +capabilities +capability +capable? +capable_auth_types +capable_cram_md5_auth? +capable_login_auth? +capable_plain_auth? +capable_starttls? +capitalize +capitalize! +caption +capture2 +capture2e +capture3 +capture_io +capture_subprocess_io +captures +cascade +casecmp +casefold? +cat +catch +cbreak +cbrt +cbrt! +cd +cdata +cdata? +cdatas +cdesc +cdiv +ceil +ceiling +center +cert +cert_chain +cert_path +cert_store +certid +certificate +certificates +certificates= +certificates_matching +certs +chain +chain= +challenge +challenge= +change_attribute +change_privilege +change_workspace +changed +changed? +changed_attribute_by_name +char_pos +character +character_limit +characters +chardev? +charpos +chars +charset +chdir +check +check_arity +check_auth_args +check_auth_continue +check_auth_method +check_auth_response +check_cert +check_chain +check_closed +check_continue +check_credentials_permissions +check_data +check_files +check_fragment +check_gems +check_generator +check_headers +check_host +check_insecure_method +check_inspect_key +check_key +check_modeline +check_modify +check_names +check_nonce +check_ns +check_opaque +check_password +check_path +check_port +check_private_key +check_query +check_registry +check_response +check_root +check_ruby_version +check_scheme +check_shift_log +check_signedness +check_sizeof +check_that_user_bin_dir_is_in_path +check_to +check_trust +check_typecode +check_until +check_user +check_userinfo +checkbox +checkbox_group +checksums +childNodes +child_name +children +chmod +chmod_R +chomp +chomp! +choose_from_list +chop +chop! +chown +chown_R +chr +chroot +chunk +chunked= +chunked? +cipher +cipher= +ciphers +ciphers= +civil +class +class_attributes +class_dir +class_document +class_eval +class_exec +class_file +class_method_list +class_methods +class_name +class_path +class_variable_defined? +class_variable_get +class_variable_set +class_variables +classes +classes_and_includes_and_extends_for +classes_and_modules +classes_hash +classes_or_modules +classify +clean_gems +clean_up +cleanpath +cleanup +clear +clear_actions +clear_comment +clear_comments +clear_default_specs +clear_exclude +clear_paths +clear_prerequisites +client_ca +client_cert +client_cert_cb +client_error? +client_thread +clobber_task_description +clobber_task_name +clone +close +close! +close_enabled? +close_on_empty_response +close_on_exec= +close_on_exec? +close_read +close_screen +close_write +closed? +closed_read? +closed_write? +clrtoeol +cmd +cmds +cmp +cmp_issuer +cmsg_is? +code +code_object +codepage +codepage= +codepoints +coerce +coerce_other +cofactor +col_sep +collapse +collect +collect! +collect2 +collect_attributes +collect_attrs +collect_concat +collect_first_comment +collect_method +collect_tasks +collect_tokens +color_content +color_pair +color_pairs +color_set +colors +cols +column +column_count +column_size +column_vector +column_vectors +columns +combination +comma_breakable +command +command= +command_names +command_processor +commands +comment +comment= +comment? +comment_location +comments +commercial +commit +common_options +compact +compact! +compact_specs +compare +compare_by_identity +compare_by_identity? +compare_file +compare_language +compare_stream +compatible? +compile +compile_error +compile_file +compile_option +compile_option= +complain +complete +complete_authentication +completer_quote_characters +completer_quote_characters= +completer_word_break_characters +completer_word_break_characters= +completion_append_character +completion_append_character= +completion_case_fold +completion_case_fold= +completion_proc +completion_proc= +component +component_ary +compress +compress_indicies +compute_key +concat +conf +config +config= +config_file +config_file_name +configuration +configuration= +configure_connection_for_https +configure_options +conflict +conflicting_dependencies +conflicts +conj +conjugate +connect +connect_address +connect_from +connect_internal +connect_nonblock +connect_to +connecting +connection_close? +connection_for +connection_keep_alive? +connections +consider_local? +consider_remote? +console +const_defined? +const_defined_in? +const_get +const_load +const_missing +const_set +const_warning +constant_aliases +constants +constants_hash +construct +consume +consume_rbuff +contains +contains_requirable_file? +content +content= +content_encoding +content_is_set? +content_length +content_length= +content_range +content_setup +content_type +content_type= +content_writer +contents +context +context= +contextAttributes +continue? +continue_entry_body +continue_timeout +continue_timeout= +continued_exception +conv +conv2value +conv_arg +convert +convert_attr_reader +convert_attrs +convert_fields +convert_flow +convert_html +convert_special +convert_specials +convert_string +convert_to_uri +converter= +converters +convertible_int +convpath +cooked +cooked! +cookie +cookies +copy +copy_entry +copy_file +copy_files +copy_internal +copy_nonce +copy_static +copy_stream +copy_string +coredump? +correct? +correct_for_windows_path +cos +cos! +cosh +cosh! +count +count_objects +count_observers +covector +cover? +coverage_level +coverage_level= +coverage_report +cp +cp_r +cpu +cram_md5_challenge +cram_md5_response +cram_secret +crc +crc32 +crc32_combine +crc_table +create +createCleanedTree +create_carried_function +create_carrier +create_cert +create_cert_email +create_cert_self_signed +create_document +create_entries +create_entry +create_ext +create_ext_from_array +create_ext_from_hash +create_ext_from_string +create_extension +create_from +create_guid +create_header +create_id +create_items +create_key +create_listeners +create_logfile +create_makefile +create_new_id +create_option_parser +create_rule +create_self_signed_cert +create_ssl_params +create_temp_function +create_tmpdir +create_value +created? +credentials +credentials_path +critical +critical= +critical? +crl +crl= +crls +crls= +crmode +cross_reference +crypt +css +cstime +csv_attr_reader +csv_integer_writer +csv_writer +ctime +ctrl_cmd +ctype +ctype= +current +current= +current_element +current_group +current_job +current_line +current_scope +current_section +current_server +curry +curs_set +curve_name +curx +cury +cut_off +cutime +cvs_url +cwd +cwday +cweek +cwyear +cycle +d +d_o_s +daemon +data +data= +data_type +datadir +date +date= +dateTime +date_writer +datetime_format +datetime_format= +day +day= +day_fraction +dclone +deafen +deal +debug +debug= +debug? +debug_level +debug_level= +debug_mode +debug_msg +debug_output= +debug_thread_info +decode +decode64 +decode_all +decode_content +decode_utf7 +decode_www_form +decode_www_form_component +decoded +decrypt +deep_clone +def_array_element +def_atom_persons +def_atom_text_construct +def_children_accessor +def_class +def_class_accessor +def_classed_element +def_classed_element_without_accessor +def_classed_elements +def_convert +def_corresponded_attr_reader +def_corresponded_attr_writer +def_csv_accessor +def_csv_element +def_delegator +def_delegators +def_e2message +def_element_class_accessor +def_elements_class_accessor +def_else_enc +def_erb_method +def_exception +def_extend_command +def_get_text_element +def_head_option +def_iconv_convert +def_inspector +def_instance_delegator +def_instance_delegators +def_method +def_module +def_notifier +def_option +def_other_element +def_other_element_without_accessor +def_post_proc +def_pre_proc +def_prog_mode +def_same_enc +def_single_delegator +def_single_delegators +def_system_command +def_tail_option +def_to_euc_jp_from_iso_2022_jp +def_to_euc_jp_from_shift_jis +def_to_euc_jp_from_utf_8 +def_to_iso_2022_jp_from_euc_jp +def_to_iso_8859_1_from_utf_8 +def_to_shift_jis_from_euc_jp +def_to_shift_jis_from_utf_8 +def_to_utf_8_from_euc_jp +def_to_utf_8_from_iso_8859_1 +def_to_utf_8_from_shift_jis +def_uconv_convert_if_can +def_yes_clean_other_accessor +def_yes_other_accessor +default +default= +default_acl +default_argc_limit +default_argv +default_bindir +default_cert_path +default_dir +default_event_sources +default_exec_format +default_executable +default_external +default_external= +default_gem? +default_id_conv +default_imap_port +default_imaps_port +default_internal +default_internal= +default_key_path +default_load_limit +default_ole_types +default_options +default_parser +default_parser= +default_path +default_pop3_port +default_pop3s_port +default_port +default_proc +default_proc= +default_record_separator +default_record_separator= +default_rubygems_dirs +default_safe_level +default_sources +default_specifications_dir +default_src_encoding +default_ssl_context +default_ssl_port +default_submission_port +default_system_path +default_system_path= +default_title= +default_tls_port +default_value +defaults +defaults_str +define +define_aliases +define_finalizer +define_head +define_method +define_module_function +define_singleton_method +define_tail +define_task +defined_class +defined_in? +definition +definition_lists +deflate +degree +del_jobs_status +del_status_line +delch +delegate +delete +delete! +delete? +delete_all +delete_at +delete_attribute +delete_element +delete_field +delete_if +delete_key +delete_legacy_args +delete_namespace +delete_observer +delete_observers +delete_passwd +delete_unless_alive +delete_value +delete_worker +deleted? +deleteln +denominator +dep +depend_rules +dependencies +dependencies_ok? +dependency +dependency_order +dependent_gems +dependent_specs +deprecate +depth +deq +dequote +desc +descend +descendant_or_self +description +description= +deserialize +dest_directory +dest_latest_specs_index +dest_prerelease_specs_index +dest_specs_index +destination_encoding +destination_encoding_name +det +det_e +detach +detached +detached= +detached? +detect +detect_encoding +detect_gemdeps +detect_implicit +determinant +determinant_bareiss +determinant_e +determine_time +dev +dev_major +dev_minor +development +development_dependencies +dfdxi +dh_compute_key +diagonal +diagonal? +diagonalize +died +diff +diff= +difference +digest +digest! +digest_algorithm +digest_length +digests +dir +dir_config +dir_stack +direct_ancestors +directory +directory? +dirname +dirs +dirs= +disable +disable_close +disable_default_gem_server +disable_ssl +disable_starttls +disable_tls +disasm +disassemble +disconnect +disconnected? +disconnecting +dispatch +dispid +display +display? +display_attributes +display_c_call +display_c_call? +display_class +display_error_message +display_method +display_name +display_names +display_page +display_page_list +display_prerequisites +display_process_id +display_process_id? +display_tasks_and_comments +display_thread_id +display_thread_id? +disposition +div +divide +divmod +dlload +dlopen +dlunwrap +dlwrap +dn +dn= +do_GET +do_HEAD +do_OPTIONS +do_POST +do_aliases +do_attrs +do_boot_defclass +do_classes +do_configuration +do_constants +do_define_class +do_define_class_under +do_define_module +do_define_module_under +do_finish +do_helo +do_includes +do_methods +do_missing +do_modules +do_not_reverse_lookup +do_not_reverse_lookup= +do_nothing +do_parse +do_reply +do_rpc +do_singleton_class +do_sort +do_start +do_struct_define_without_accessor +do_validate +do_validate= +do_write +doc +doc_dir +doc_root +doc_stats +doctor +doctype +doctype? +doctype_end +document +document_children +document_children= +document_order +document_self +document_self= +document_self_or_methods +document_to_str +documentation_page +documentation_search +documentation_source +documented? +domain +done +done? +done_adding +done_documenting +done_documenting= +done_installing +done_installing_hooks +dont_rename_initialize +dot_pat +dot_pat_str +double +double_fig +doupdate +downcase +downcase! +download +download_reporter +download_to_cache +downto +dowrite +drop +drop_while +dry_run +dsa_sign_asn1 +dsa_verify_asn1 +dst? +dummy? +dummy_makefile +dump +dump_call +dump_coder +dump_default_options +dump_ivars +dump_list +dump_response +dump_stream +dup +dynamic_width +dynamic_width_stty +dynamic_width_tput +e2mm_message +each +each2 +each_active_object +each_address +each_ancestor +each_attribute +each_byte +each_capitalized +each_capitalized_name +each_certificate +each_char +each_child +each_classmodule +each_codepoint +each_cons +each_const +each_constant +each_data +each_element +each_element_with_attribute +each_element_with_text +each_entry +each_extend +each_filename +each_header +each_include +each_index +each_installed_parser +each_installed_writer +each_key +each_line +each_localized_path +each_mail +each_method +each_name +each_name_of +each_object +each_option +each_pair +each_parent +each_prime +each_recursive +each_resource +each_response_header +each_section +each_slice +each_source +each_strongly_connected_component +each_strongly_connected_component_from +each_sublocale +each_value +each_with_index +each_with_object +each_with_something +echo +echo= +echo? +edit_path +egid +egid= +ehlo +eid +eigen +eigensystem +eigenvalue_matrix +eigenvalues +eigenvector_matrix +eigenvector_matrix_inv +eigenvectors +ele +element +element= +element_initialize_arguments? +element_name +elementdecl +elementdecl? +elements +elements_to_f +elements_to_i +elements_to_r +emacs_editing_mode +emacs_editing_mode? +email +email_to_name +emailbx +emit_coder +emphasis +empty +empty? +empty_content? +empty_marshal_checksum +empty_marshal_data +enable +enable_close +enable_config +enable_ssl +enable_starttls +enable_starttls_auto +enable_tls +enabled? +enc_key +enclose +enclosed? +enclosure_dependencies +encode +encode! +encode64 +encode_fallback +encode_multipart_form_data +encode_re +encode_str +encode_token +encode_utf7 +encode_with +encode_www_form +encode_www_form_component +encoded +encoding +encoding= +encoding_updated +encrypt +end +endElement +end_accepting +end_document +end_element +end_element? +end_mapping +end_prefix_mapping +end_seen? +end_sequence +end_stream +end_transport +end_with? +ended? +endgrent +endpwent +engines +england +enhance +enhance_with_matching_rule +enq +ensure_dependencies_met +ensure_dependency +ensure_gem_subdirectories +ensure_loadable_spec +ensure_required_ruby_version_met +ensure_required_rubygems_version_met +ensure_xml_content +entities +entity +entity? +entity_class +entity_expansion_count +entity_expansion_limit +entity_expansion_limit= +entity_expansion_text_limit +entity_expansion_text_limit= +entitydecl +entitydecl? +entries +entry_details +entry_versions +enum_for +env_shebang +env_table +environment +eod +eof +eof? +eos? +eql? +equal? +equality_relational_compare +erf +erfc +errno +error +error? +error_bytes +error_char +error_message +error_string +errors +errs +escape +escape8bit +escapeElement +escapeHTML +escape_element +escape_form +escape_html +escape_path +escape_re +escape_userpass +esmtp +esmtp? +euid +euid= +eval +eval_history +eval_history= +eval_input +evaluate +even? +event +event? +event_arg +event_interface +event_type +events +examine +exception +exception_class +exception_details +exchange +exclude +exclude_end? +exclusive +exec +exec_format +exec_if +executable +executable= +executable? +executable_real? +executables +executables= +execute +exist? +exists? +exit +exit! +exit_code +exit_value +exited? +exitstatus +exp +exp! +expand +expand_class +expand_environ +expand_hexstring +expand_name +expand_pair +expand_path +expand_ref_in +expand_tabs +expand_value +expanded_name +expect +expected +expire +expired? +expires +expires= +exponent +export +expr +expunge +ext +extend +extend_object +extend_table +extended +extends +extension +extension? +extension_build_error +extensions +extensions= +extern +external +external_aliases +external_encoding +external_id +extname +extra_args +extra_args= +extra_chain_cert +extra_rdoc_files +extra_rdoc_files= +extract +extract_call_seq +extract_comment +extract_files +extract_reference +facility +fail +failed +false +family +family_addrinfo +fast_generate +fastmode= +fatal +fatal? +fault +faultCode +faultString +fcntl +fdatasync +fdiv +feed +feed_info +feed_subtype +feed_type +feed_version +fetch +fetch_file +fetch_http +fetch_https +fetch_internal +fetch_path +fetch_server +fetch_size +fetch_spec +fetcher +fetcher= +fiddle? +field +field? +field_row? +field_size_limit +fields +file +file= +file? +file_create +file_dir +file_field +file_input? +file_list_string +file_name +file_output +file_path +file_stat +filename +filename_quote_characters +filename_quote_characters= +fileno +files +files= +files_hash +files_so_far +fill +fill_breakable +fill_rbuff +filter +filter= +filter_backtrace +filter_methods +final +finalize +find +find_alias_comment +find_all +find_all_by_name +find_all_satisfiers +find_all_template +find_ancestor_local_symbol +find_attr_comment +find_attribute +find_attribute_named +find_body +find_by_name +find_by_path +find_c_enclosure +find_class +find_class_comment +find_class_method_named +find_class_named +find_class_named_from +find_class_or_module +find_command +find_command_possibilities +find_const_comment +find_constant_named +find_data +find_enclosing_module_named +find_encoding +find_executable +find_external_alias +find_external_alias_named +find_file_named +find_files +find_files_for_gem +find_first_recursive +find_gem +find_gems_with_sources +find_header +find_home +find_in_cache +find_in_unresolved +find_in_unresolved_tree +find_inactive_by_path +find_include_file +find_index +find_instance_method_named +find_ivars +find_library +find_local_symbol +find_location +find_method +find_method_named +find_methods +find_modifiers +find_module_named +find_name +find_override_comment +find_pager_jruby +find_paths +find_proxy +find_rakefile_location +find_reverse_dependencies +find_runnable +find_spec +find_spec_by_name_and_version +find_store +find_symbol +find_symbol_module +find_system_command +find_text_page +find_type +find_unique +find_unresolved_default_spec +finger +finish +finish_page_dir +finish_resolve +finished +finished? +finite? +fips_mode= +first +first? +first_lineno +fit_error +fit_exponential +fit_linear +fit_power +fix +fix_basic_object_inheritance +fix_syck_default_key_in_requirements +fixed_encoding? +flags= +flash +flat_map +flatten +flatten! +flock +floor +flow +flunk +flush +flush_buffer +flush_left +flush_next_in +flush_next_out +flush_sessions +fnmatch +fnmatch? +following +following_node_of +footnotes +for +for_cache +for_current_gems +for_fd +for_files +for_matching_files +for_spec? +force +force_documentation +force_documentation= +force_encoding +force_output +force_quotes? +force_update +foreach +fork +form +form_data= +format +format= +format_date +format_datetime +format_executable +format_line_num +format_message +format_severity +format_text +format_time +format_trace_flags +formatted_program_filename +formatter +found +frac +fragment +fragment= +free +free= +freeze +frexp +friday? +friendly_path +from +from_hash +from_list +from_module +from_name +from_path +from_prime_division +from_specs +from_yaml +front +frozen? +fsync +ftype +fu_blksize +fu_default_blksize +fu_stream_blksize +fu_windows? +full_comment +full_gem_path +full_name +full_name= +full_old_name +full_spec +fully_documented? +fully_expanded_name +function +gamma +garbage_collect +gather_dependencies +gather_files +gcd +gcdlcm +gem +gem_dir +gem_file_list +gem_home +gem_original_require +gem_paths +gem_repository? +gem_spec +gemdirs +gems_dir +gems_to_install +gen_multicall +gen_relative_url +gen_sub_directories +gen_url +generate +generate_bin +generate_bin_script +generate_bin_symlink +generate_class +generate_class_files +generate_default_dirs +generate_event +generate_file_files +generate_index +generate_key +generate_key! +generate_line +generate_name +generate_page +generate_prime +generate_rdoc +generate_ri +generate_servlet_not_found +generate_servlet_root +generate_table_of_contents +generate_tag +generate_windows_script +generation_hook +generator +generator_descriptions +generator_for +generator_options +generic? +genspace +get +get2 +get_all_gem_names +get_all_gem_names_and_versions +get_attribute +get_attribute_ns +get_attributes +get_bool +get_byte +get_candidate_gems +get_class_or_module +get_class_specification +get_constant +get_constant_with_optional_parens +get_credentials +get_default_handler +get_definition +get_description +get_elements +get_fields +get_file_and_line_from_caller +get_first +get_gems_to_cleanup +get_group +get_hosts_path +get_included +get_initial_token +get_instance +get_key_string +get_line +get_listeners +get_metadata +get_methods +get_namespace +get_no_proxy_from_env +get_one_gem_name +get_one_optional_argument +get_option +get_passwd +get_path +get_platform_from_requirements +get_primary_gems +get_print +get_procs +get_proxy_from_env +get_renewer +get_resolv_info +get_response +get_screen_size +get_service_hook +get_sorted_module_list +get_svninfo +get_symbol_or_name +get_tagged_response +get_text +get_thread +get_tk +get_tk_until +get_tkread +get_valid_ip +get_value +get_version_from_requirements +getacl +getaddress +getaddress_orig +getaddresses +getaddrinfo +getbinaryfile +getbkgd +getbyte +getc +getch +getdir +getegid +geteuid +getgid +getgm +getgrent +getgrgid +getgrnam +gethostbyaddr +gethostbyname +gethostname +getlocal +getlogin +getmouse +getname +getnameinfo +getnames +getok +getopts +getpeereid +getpeername +getpgid +getpgrp +getpriority +getpty +getpwent +getpwnam +getpwuid +getquota +getquotaroot +getresource +getresources +getrlimit +gets +getservbyname +getservbyport +getservername +getsid +getsockname +getsockopt +getstr +getter +gettextfile +getuid +getutc +getwd +gid +gid= +github +glob +global_variables +gm +gmt? +gmt_offset +gmtime +gmtoff +grant_privilege +great_job +greeting +gregorian +gregorian? +gregorian_leap? +grep +group +group= +group_by +group_entries +group_queue +group_sub +groups +groups= +grpowned? +gsub +gsub! +guard_inspect_key +guess +guess_type +guess_type_if_need +guid +gunzip +gzip +gzip_to +h +handle +handle_arguments +handle_attr +handle_class_module +handle_constants +handle_directive +handle_ifdefs_in +handle_interrupt +handle_method +handle_options +handle_pipe +handle_rdoc_link +handle_singleton +handle_special_CROSSREF +handle_special_HARD_BREAK +handle_special_HYPERLINK +handle_special_RDOCLINK +handle_special_SUPPRESSED_CROSSREF +handle_special_TIDYLINK +handle_tab_width +handler +handler= +handlers +handles? +hard_break +hasChildNodes +hasOnlyOneChild +has_attributes? +has_chain? +has_colors? +has_elements? +has_expires? +has_key? +has_name? +has_next? +has_rdoc +has_rdoc= +has_rdoc? +has_text? +has_unit_tests? +has_value? +hash +hash? +hash_old +have_author? +have_children_elements +have_const +have_content? +have_framework +have_func +have_header +have_library +have_macro +have_option? +have_rakefile +have_rdoc_4_plus? +have_required_elements? +have_required_values? +have_run? +have_struct_member +have_type +have_var +have_xml_content? +head +head2 +header +header? +header_convert +header_converters +header_row? +headers +headers= +height= +helo +help +helpcontext +helpfile +helpstring +here? +hermitian? +hessenberg_to_real_schur +hex +hexdigest +hexdigest! +hexencode +hidden +hierarchical? +history_file +history_file= +hkey +hmac_md5 +home +home= +home_dir +home_workspace +homepage +hook +host +host= +hostname +hostname= +hour +hour= +href +href= +html +html_escape +html_list_name +html_name +html_tags +hton +http_date +http_default_port +http_error +http_header +http_header_extra +http_last_response +http_resp +http_url +http_version +http_write +httpd +httpdate +https? +https_default_port +hyperlink_all +hypot +i +i_suck_and_my_tests_are_order_dependent! +icon +icon= +iconv +id +id2name +ident +identical? +identity +idle +idle_done +idlok +if_current_indent_equal +if_modified_since +iflush +ignore +ignore_dependencies +ignore_eof +ignore_eof? +ignore_sigint +ignore_sigint? +ignore_unknown_element +ignore_unknown_element= +ignore_whitespace_nodes +ignored? +imag +image +image_button +image_height +image_size +image_size= +image_width +imaginary +img +implemented_ole_types +implicit +implicit_end +import +import_function +import_symbol +import_value +in6_addr +in_addr +in_background +in_files +in_namespace +in_path? +in_service? +in_transaction +in_transaction_wr +in_tt? +inactivate +inc +inch +include +include? +include_file +include_path +included +included_modules +includes +incompatible_argument_styles +incomplete_input? +increment_io +indent +indent_text +indentation +index +index_classes +index_in_parent +index_methods +index_pages +indices +indir +infinite? +infinite_length +infinity? +inflate +info +info? +inherit_convert_attr_reader +inherited +inherited_array_reader +inherited_base +inherited_hash_reader +inherited_reader +init +init_color +init_comments +init_converters +init_headers +init_pair +init_parsers +init_screen +init_separators +init_tags +init_with +init_with_ary +init_with_hash +initgroups +initial_start_RDF +initial_start_entry +initial_start_feed +initial_start_rss +initialize +initialize_copy +initialize_have_children_elements +initialize_http_header +initialize_methods_etc +initialize_pattern +initialize_query +initialize_regexp +initialize_tracer +initialize_variables +inject +inject_into_list +inline +inline_html? +inline_other? +inline_other_base64? +inline_other_text? +inline_other_xml? +inline_text? +inline_xhtml? +inner_product +ino +inplace_mode +inplace_mode= +input +input= +input? +ins +insch +insecure_method? +insert +insert_after +insert_before +insert_output +insert_text +insertln +inspect +inspect? +inspect_mode +inspect_mode= +inspect_sockaddr +inspect_value +install +install_accessor_base +install_acl +install_alias_method +install_class_name +install_date_element +install_default_gems +install_default_specs +install_dublin_core +install_element +install_executables +install_extend_commands +install_file +install_from_gemdeps +install_gem +install_gem_user +install_get_attribute +install_get_text_element +install_have_attribute_element +install_have_child_element +install_have_children_element +install_id_conv +install_image_favicon +install_image_item +install_indicies +install_into +install_lib +install_list +install_model +install_must_call_validator +install_ns +install_rdoc +install_siginfo_handler +install_specs +install_system_commands +install_taxo_topic +install_taxo_topics +install_text_element +install_update_defaults_str +installation_satisfies_dependency? +installed? +installed_docs +installed_gems +installed_specs +instance +instance_attributes +instance_delegate +instance_eval +instance_exec +instance_method +instance_method_list +instance_methods +instance_of? +instance_variable_defined? +instance_variable_get +instance_variable_set +instance_variables +instruction +instruction? +instructions +int +int_from_prime_division +integer +integer? +integer_writer +interactive +intern +internal_encoding +interrupt +intersection +inv +invalidate_memoized_attributes +inverse +invert +invert! +investigation +invkind +invoke +invoke_kind +invoke_service +invoke_service_command +invoke_task +invoke_thread +invoke_with_build_args +io +io? +ioctl +ioflush +ip +ip6_arpa +ip6_int +ip? +ip_address +ip_address_list +ip_pktinfo +ip_port +ip_unpack +ipv4? +ipv4_compat +ipv4_compat? +ipv4_loopback? +ipv4_mapped +ipv4_mapped? +ipv4_multicast? +ipv4_private? +ipv6? +ipv6_linklocal? +ipv6_loopback? +ipv6_mc_global? +ipv6_mc_linklocal? +ipv6_mc_nodelocal? +ipv6_mc_orglocal? +ipv6_mc_sitelocal? +ipv6_multicast? +ipv6_pktinfo +ipv6_pktinfo_addr +ipv6_pktinfo_ifindex +ipv6_sitelocal? +ipv6_to_ipv4 +ipv6_unique_local? +ipv6_unspecified? +ipv6_v4compat? +ipv6_v4mapped? +ipv6only! +irb +irb_abort +irb_at_exit +irb_context +irb_exit +irb_level +irb_load +irb_name +irb_path +irb_require +isEqual +is_a? +is_alias_for +is_version_1_2? +isatty +isdst +iseuc +isjis +iso8601 +issetugid +issjis +issuer +issuer= +issuer_certificate +issuer_certificate= +issuer_of +isutf8 +it +italy +item +items +iterator? +iv= +j +jacobian +jd +jisx0301 +jj +jobs +jobs_exist? +jobs_status +join +join_nowait +jruby? +json_creatable +json_creatable? +json_create +json_index +julian +julian? +julian_leap? +kconv +keep_alive +keep_alive? +keep_alive_timeout +keep_clean +keep_if +key +key= +key? +key_len= +key_path +keyname +keypad +keypad= +keys +keys_with_inspector +kill +kill_job +kind_of? +known_class? +known_classes +l +label +labels +lambda +lambda? +lang +last +lastBuildDate= +last_comment +last_description +last_error +last_error= +last_line +last_match +last_modified +last_request +last_response +last_response_code +last_update +last_update= +last_value +lastresp +latest_rubygems_version +latest_spec_for +latest_specs +latest_version? +latest_version_for +launch +launch_worker +lazy +lchmod +lchown +lcm +ld +ldexp +leap? +length +let +level +level= +level_notifier +level_notifier= +levenshtein_distance +lex +lgamma +lib_dirs_glob +lib_files +lib_path +library_name +libs +libyaml_version +license +license= +licenses +licenses= +limit +line +line_buffer +line_index +line_numbers +line_trace_all +line_trace_specify +line_width +lineno +lineno= +lines +linger +link +link_files +link_to +list +list_end_for +list_files_in_directory +list_index +list_item_from +list_item_start +list_known_classes +list_methods_matching +list_type +list_width +listen +listener +listener= +listeners +literalize +ljust +ln +ln_s +ln_sf +load +load_all +load_and_instantiate +load_api_keys +load_cache +load_call +load_cert +load_certificate +load_class +load_class_data +load_data +load_default_cert +load_default_key +load_default_options +load_defaults +load_documents +load_env_plugins +load_file +load_gemdeps +load_imports +load_key +load_method +load_methods_matching +load_mime_types +load_modules +load_options +load_page +load_path_insert_index +load_plugin_files +load_plugins +load_private_key +load_public_key +load_rakefile +load_rdoc +load_response +load_spec +load_specs +load_stream +load_variable_map +load_yaml +loaded_from +loaded_from= +loaded_specs +loader +loadpath +local +local? +local_address +local_host +local_name +local_name= +local_port +local_variables +locale +locale= +locale_charmap +localtime +location +location_of_caller +locations +lock +locked? +log +log! +log10 +log10! +log2 +log2! +log= +logger +logger= +logging +login +logo +logo= +logout +long +long_name +look_for_directives_in +lookup +lookup_in_scope +lookup_method +lookup_prerequisite +lookup_ring +lookup_ring_any +lookup_server +loop +lower +lower_triangular? +ls +lstat +lstrip +lstrip! +lsub +ludecomp +lup +lup_decomposition +lusolve +magnitude +mail +mailfrom +mails +main +main= +main_irb +main_loop +main_page +main_thread +main_type +major +major_version +make +make_affine! +make_command +make_compiler +make_destination_dirs +make_entry +make_expires +make_feed +make_link +make_message +make_my_diffs_pretty! +make_passwd +make_regexp +make_sources +make_start_tag +make_switch +make_symlink +make_temp_directories +make_thread_list +make_time +make_tuple +make_variable_map +make_xml_stylesheets +makedirs +maker +maker_target +makers +malloc +malloc_allocated_size +malloc_allocations +manage_owners +map +map! +map2 +map= +map_gems_to_specs +mark_version +markup +markup_code +marshal_dump +marshal_load +marshal_version +mask +mask! +mask= +mask_protected_sequences +match +match? +match_platform! +match_platform? +match_to +match_to_consume +matched +matched? +matched_size +matches? +matches_for_glob +matches_spec? +matching_specs +matching_word_pairs +math? +math_mode +math_mode= +max +max= +maxConnections +max_age +max_by +max_flag_count +max_flag_count= +max_size +maxgroups +maxgroups= +maxwidth +maxx +maxy +maybe_xml? +mday +mdtm +measure +media_subtype +member +member? +members +memberwise +merge +merge! +merge0 +merge_key +merge_options +merge_path +merged? +message +message_loop +meta +meta_vars +metadata +meth +method +methodCall +methodCall_document +methodName +methodResponse +methodResponse_document +method_added +method_defined? +method_document +method_file +method_id +method_list +method_missing +method_name +method_removed +method_type +method_undefined +methods +methods_by_type +methods_hash +methods_matching +mime_split +mime_type +min +min= +min_by +minimum +minmax +minmax_by +minor +minor_version +minute +minute= +missing_dependencies +mjd +mkcol +mkdir +mkdir_p +mkmf +mkpath +mktime +mktmpdir +mname +mode +models +modifiable +modifieer +modsort +module +module? +module_eval +module_exec +module_function +module_names +modules +modules_hash +modulo +mon +mon= +mon_check_owner +mon_enter +mon_enter_for_cond +mon_exit +mon_exit_for_cond +mon_initialize +mon_synchronize +mon_try_enter +monday? +month +month= +month_days +mount +mount_proc +mountpoint? +mouseinterval +mousemask +move +mri? +msg +msg2str +mtime +mtime= +mu_lock +mu_locked? +mu_pp +mu_pp_for_diff +mu_synchronize +mu_try_lock +mu_unlock +mul +mult +multicall +multicall2 +multicall2_async +multicall_async +multicall_fault +multipart? +multipart_form +multitask +must_C_version +must_be +must_be_close_to +must_be_empty +must_be_instance_of +must_be_kind_of +must_be_nil +must_be_same_as +must_be_silent +must_be_within_delta +must_be_within_epsilon +must_call_validators +must_equal +must_include +must_match +must_output +must_raise +must_respond_to +must_send +must_throw +mv +n_bytes +n_jobs +n_mails +name +name= +name_for_path +name_list +name_path +name_prefix +name_regexp +name_tuple +named_captures +names +namespace +namespace= +namespace_context +namespace_context= +namespace_of +namespace_uri +namespaces +namespaces= +namesplit +nan? +nary +native +nc +ndata +need_base64_encode? +need_initialize_variables +need_keeper? +need_parent? +need_source_encoding_update? +need_tar +need_tar_bz2 +need_tar_gz +need_zip +needed? +needs +nest +nesting +net_http +new +new2 +new3 +new_alias_name +new_comment +new_cond +new_default_spec +new_from_hash +new_from_uri +new_internet_message_io +new_name +new_ntoh +new_offset +new_ostruct_member +new_scope +new_seed +new_session +new_spec +new_start +new_test +new_toplevel +new_with +new_with_uri +new_with_value_if_need +newline +newobj +next +next! +next_current +next_day +next_element +next_month +next_sibling= +next_sibling_node +next_to +next_token +next_update +next_update= +next_values +next_wait +next_words_on_error +next_year +nil? +nkf +nl +nlink +nlsolve +nlst +nmake_found? +no_proxy? +nocbreak +nocrmode +nodeMustBe +nodeName +nodeType +nodeValue +node_type +nodelay= +nodoc +noecho +non_aliases +non_nil_attributes +non_options +none? +nonl +nonzero? +noop +noraw +norm +normal? +normalize +normalize! +normalize_comment +normalize_path +normalize_rss +normalize_searching_criteria +normalize_space +normalize_uri +normalize_yaml_input +normalized +normalized_file_list +not +not_after +not_after= +not_before +not_before= +not_found +not_need_to_call_setup_maker_variables +not_set_name +not_set_required_variables +notation +notationdecl +notationdecl? +notations +note +note_for +notes +notifiers +notify +notify? +notify_event +notify_observers +notwice +noutrefresh +now +nowrite +nowrite_flag +npn_protocol +npn_protocols +npn_select_cb +nread +ns_declarations +nsec +ntop +null +null? +num_files +num_waiting +number +numerator +obj +object +object_address_group +object_class +object_group +object_id +object_maker +oct +odd? +of +off +off_event +off_tags +offset +offset_vtbl +oflush +oid +oid= +ok? +ok_to_remove? +old_enc= +old_name +ole_activex_initialize +ole_classes +ole_free +ole_func_methods +ole_get_methods +ole_initialize +ole_method +ole_method_help +ole_methods +ole_obj_help +ole_put_methods +ole_query_interface +ole_reference_count +ole_respond_to? +ole_show_help +ole_type +ole_type_detail +ole_typelib +ole_types +ole_uninitialize +omit_headings_below +on +on_attr_charref +on_attr_charref_hex +on_attr_entityref +on_attr_value +on_attribute +on_cdata +on_chardata +on_charref +on_charref_hex +on_connect +on_curve? +on_default +on_entityref +on_error +on_etag +on_event +on_event_with_outargs +on_head +on_parallel_worker? +on_stag +on_stag_end +on_stag_end_empty +on_tags +on_tail +on_windows? +on_xmldecl_encoding +on_xmldecl_end +on_xmldecl_standalone +on_xmldecl_version +one? +ongoing_visibility= +only_signed +only_trusted +op_dir +opaque +opaque= +open +open! +open? +open_and_lock_file +open_logfile +open_message_stream +open_server +open_timeout +open_uri_or_path +open_uri_original_open +opendir +opened? +option_list +option_parser +optional? +options +options= +options_of +optname +ord +order +order! +ordering +ordering= +ordinal +orig_initialize +orig_name +orig_name= +original_dir +orthogonal? +os +os_code +other_elements +others_possible? +out +out_of_date? +out_of_line? +outdated +output +output= +output? +output_encoding +output_encoding= +output_flag_file +output_name +output_query_results +output_versions +outputdir +outs +owned? +owner +p +pack +pack_sockaddr_in +pack_sockaddr_un +package_dir +package_dir_path +package_files +package_name +packdw +packqw +padding= +page +page-ChangeLog +page-NEWS +page_dir +page_file +page_name +paging? +pair +pair_content +pair_number +para +paragraph +paragraph_limit +paragraphs +parallelize_me! +param +param_list +param_seq +parameters +params +params= +params_ok? +paranoid +parent +parent= +parent? +parent_file_name +parent_name +parse +parse! +parseMethodCall +parseMethodResponse +parse_alias +parse_arg +parse_args +parse_attr +parse_attr_accessor +parse_bind_options +parse_call_parameters +parse_class +parse_comment +parse_comment_tomdoc +parse_config +parse_config_lines +parse_constant +parse_content_type +parse_ctype +parse_dn +parse_dot_doc_file +parse_entries +parse_extend +parse_file +parse_files +parse_files_matching +parse_form_data +parse_header +parse_headers +parse_helper +parse_include +parse_int +parse_line +parse_make_command_line +parse_meta_attr +parse_meta_method +parse_method +parse_method_dummy +parse_method_or_yield_parameters +parse_method_parameters +parse_mode +parse_module +parse_name +parse_openssl +parse_pasv_ipv4_host +parse_pasv_ipv6_host +parse_pasv_port +parse_pi_content +parse_printf_format +parse_query +parse_qvalues +parse_range_header +parse_require +parse_rescue +parse_rfc2253 +parse_set_cookie +parse_set_cookies +parse_sig +parse_signature +parse_source +parse_statements +parse_stream +parse_struct_signature +parse_subtree +parse_symbol_arg +parse_symbol_in_arg +parse_task_string +parse_time +parse_top_level_statements +parse_types +parse_url +parse_visibility +parse_yield +parseable? +parser +parsers +partition +parts +pass +passed? +passive +passwd +password +password= +password_field +patch +path +path= +path_info +path_ok? +path_query +path_separator +path_warning +pathmap +pathmap_explode +pathmap_partial +pathmap_replace +paths +paths= +pattern +pbkdf2_hmac +pbkdf2_hmac_sha1 +peek +peek_read +peek_tk +peek_token +peek_values +peep +peer_cert +peer_cert_chain +peeraddr +peg_parse +pem_files_in +pending +pending_interrupt? +percent_doc +permanent_link= +permanent_link? +permutation +permutation? +permute +permute! +pfamily +phase +pi +pick_best! +pid +pipe +pipe? +pipeline +pipeline_r +pipeline_rw +pipeline_start +pipeline_w +pivots +pkcs5_keyivgen +plain +plain_html +platform +platform= +platforms +platforms= +plural_forms +point +point_conversion_form +point_conversion_form= +pointer +pointer= +polar +pop +pop_inspect_key +pop_token +pop_workspace +popd +popdir +popen +popen2 +popen2e +popen3 +popup_menu +port +port= +pos +pos= +position +positive_integer_writer +post +post2 +post_build +post_build_hooks +post_connection_check +post_form +post_install +post_install_hooks +post_install_message +post_match +post_process +post_processors +post_reset +post_reset_hooks +post_uninstall +post_uninstall_hooks +power +power! +pp +pp_hash +pp_object +ppid +ppx +pre_input_hook +pre_input_hook= +pre_install +pre_install_checks +pre_install_hooks +pre_match +pre_reset +pre_reset_hooks +pre_uninstall +pre_uninstall_hooks +preceding +preceding_node_of +precs +pred +predicate +predicate_to_string +preference +prefetch +prefix +prefix_of +prefixes +prepend +prepend_features +prepended +preprocess +prerelease +prerelease? +prerequisite_tasks +prerequisites +pretty +pretty_generate +pretty_inspect +pretty_name +pretty_new_name +pretty_old_name +pretty_print +pretty_print_cycle +pretty_print_inspect +pretty_print_instance_variables +prev_day +prev_month +prev_words_on_error +prev_year +previous= +previous_element +previous_period_end +previous_sibling= +previous_sibling_node +pride +primary +primary_server +prime? +prime_division +prime_fasttest? +primes +primes_so_far +primitive_convert +primitive_errinfo +print +print_alias +print_attribute +print_class +print_constant +print_dependencies +print_file +print_method +print_module +print_profile +print_rakefile_directory +print_usage +printf +printn +priority +priority= +private +private? +private_class_method +private_constant +private_decrypt +private_encrypt +private_instance_methods +private_key +private_key= +private_key? +private_method_defined? +private_methods +problem +proc +procdest +process +process_args +process_based_port +process_controller +process_directive +process_line +process_options +processingInstruction +processing_instruction +product +progid +progids +progname +program_name +progress +progress_reporter +proj_id +project +prompt +prompt_c +prompt_i +prompt_mode +prompt_mode= +prompt_n +prompt_s +prompting? +proper_subset? +proper_superset? +propfind +proppatch +protectable +protected +protected_instance_methods +protected_method_defined? +protected_methods +proto +protocol +provide +proxy +proxy2 +proxy2_async +proxy? +proxy_address +proxy_async +proxy_auth_get +proxy_basic_auth +proxy_class? +proxy_from_env +proxy_from_env? +proxy_pass +proxy_port +proxy_user +proxyaddr +proxyport +prune +psych_to_yaml +psych_yaml_as +ptr +ptr= +pubDate +pubDate= +pubid +public +public? +public_class_method +public_constant +public_decrypt +public_encrypt +public_instance_method +public_instance_methods +public_key +public_key= +public_key? +public_method +public_method_defined? +public_methods +public_send +puke +pull +pull_event +purpose= +push +push_inspect_key +push_workspace +pushd +pushdir +put +put_status +put_string +putback +putbinaryfile +putc +puts +puttextfile +pwd +qdval +qop +query +query= +query_string +quick +quick_gem +quick_spec +quiet +quiet= +quiet? +quit +quit_called +quit_workers +quo +quote +quote_char +quote_string +quoted +r +racc_accept +racc_e_pop +racc_next_state +racc_print_stacks +racc_print_states +racc_read_token +racc_reduce +racc_shift +racc_token2str +radio_button +radio_group +raise +raise_for_undefined_entity? +raise_if_conflicts +raised_exception +rake_check_options +rake_extension +rake_merge_option +rake_original_const_missing +rake_original_time_compare +rake_output_message +rake_require +rake_system +rakefile +rakefile_location +rand +random_bytes +random_iv +random_key +random_number +random_string +range +range= +range_length +rank +rank_e +rassoc +rationalize +raw +raw! +raw_cookie +raw_cookie2 +raw_data +raw_encoding +raw_header +raw_path +rb_files_in +rb_scan_args +rc +rc? +rcptto +rcptto_list +rdev +rdev_major +rdev_minor +rdoc +rdoc_dir +rdoc_files +rdoc_include +rdoc_installed? +rdoc_options +rdoc_options= +rdoc_target +rdoc_task_description +rdoc_task_name +rdoc_version +re_exchange +re_exchangeable? +re_sign +read +read_all +read_bin +read_binary +read_body +read_body_0 +read_cache +read_checksums +read_directive +read_documentation_modifiers +read_file +read_from_cmdline +read_i +read_multipart +read_nonblock +read_s +read_s_expand +read_smime +read_status_line +read_timeout +read_timeout= +read_type_class +read_with_substitution +readable? +readable_after_eof? +readable_real? +readagain_bytes +readbyte +readchar +readline +readlines +readlink +readpartial +ready +ready? +real +real? +real_file +real_load +realdirpath +realloc +really_verbose +realm +realpath +realtime +reason +reason_phrase +receive +receive_responses +received_nodoc +receiver +recipients +record_entity_expansion +record_location +record_response +record_separator +record_task_metadata +recover +rect +rectangular +recurse +recurse_proc +recv +recv_io +recv_nonblock +recv_response +recvfrom +recvfrom_nonblock +recvmsg +recvmsg_nonblock +redirect? +redirect_to_directory_uri +redirector +redisplay +reduce +reduce_to_hessenberg +reenable +ref +reference +references +refine +refresh +refresh_line +refute +refute_empty +refute_equal +refute_in_delta +refute_in_epsilon +refute_includes +refute_instance_of +refute_kind_of +refute_match +refute_nil +refute_operator +refute_path_exists +refute_predicate +refute_respond_to +refute_same +regexp +regist +regist_server +register +register_command +register_default_spec +register_empty +register_spec_type +register_uri +registered +registry +registry= +regular? +rehash +reject +reject! +relative? +relative_name +relative_path_from +release +reload +remainder +remote? +remote_address +remote_ip +remove +removeChild +removeWhitespacesAndComments +remove_all +remove_by_name +remove_cache_file +remove_callback +remove_callback_internal +remove_cdecl_callback +remove_class_variable +remove_coding_comment +remove_comment +remove_commented_out_lines +remove_const +remove_dir +remove_entry +remove_entry_secure +remove_executables +remove_file +remove_from_documentation? +remove_handler +remove_installed! +remove_instance_variable +remove_invisible +remove_method +remove_nodoc +remove_nodoc_children +remove_old_bin_files +remove_old_lib_files +remove_option +remove_owners +remove_private +remove_private_comment +remove_private_comments +remove_response_handler +remove_server +remove_siginfo_handler +remove_spec +remove_specs_unsatisfied_by +remove_stdcall_callback +remove_token_listener +remove_unparseable +remove_unresolved_default_spec +rename +render +render_template +renegotiation_cb +renew +reopen +reorganize +repair_command +repeated_combination +repeated_permutation +replace +replace! +replace_child +replace_with +replacement +replacement= +replicate +reply +reply_service +report +report_attributes +report_class_module +report_constants +report_methods +represent_map +represent_object +represent_scalar +represent_seq +req +request +request_body_permitted? +request_get +request_head +request_http_version +request_line +request_method +request_post +request_time +request_uri +requester +requests +require +require_path +require_path= +require_path_info? +require_paths +require_relative +required_attribute? +required_attributes +required_element? +required_prefix +required_ruby_version +required_ruby_version= +required_rubygems_version +required_rubygems_version= +required_uri +required_variable_names +required_variables_are_set? +requirement +requirements +requirements= +requirements_list +requires +rerdoc_task_description +rerdoc_task_name +res +reset +reset_nil_attributes_to_default +reset_prog_mode +resize +resizeterm +resolve +resolve_add +resolve_aliases +resolve_args +resolve_args_without_dependencies +resolve_class +resolve_current +resolve_for +resource +resource= +resources +respace +respond_to? +respond_to_missing? +response +response_body_permitted? +response_class +response_handlers +responses +rest +rest? +rest_size +restore +restsize +result +resume +retrbinary +retrlines +retry +return_format +return_headers? +return_type +return_type_detail +return_value +return_vtype +retval? +reverse +reverse! +reverse_each +revive +revive_hash +revoked +revoked= +rewind +rfc1123_date +rfc2822 +rfc3339 +rfc822 +ri_dir +ri_installed? +ri_paths +rid +rindex +rjust +rm +rm_f +rm_r +rm_rf +rmailbx +rmdir +rmtree +rname +root +root? +root_node +root_search +roots +rotate +rotate! +round +route_from +route_to +row +row_count +row_sep +row_size +row_vector +row_vectors +rows +rpartition +rsqrt +rss +rss_version +rstrip +rstrip! +rubinius? +ruby +ruby= +ruby? +ruby_code +ruby_engine +ruby_opts +ruby_opts_string +ruby_version +rubybin +rubyforge_project +rubygems_api_key +rubygems_api_key= +rubygems_api_request +rubygems_version +rule +run +run_code +run_config +run_once +run_test +run_tests +run_with_threads +runtime_dependencies +rw +safe_level +safe_ln +safe_unlink +same_attributes? +same_feed_type? +sample +sanitize +sanitize_path +sanitize_string +satisfied_by? +satisfies_requirement? +saturday? +save +save_cache +save_class +save_data +save_data_with_atomic_file_rename_strategy +save_data_with_fast_strategy +save_exception_mode +save_history +save_history= +save_limit +save_method +save_page +save_rounding_mode +say +scalar +scalar= +scan +scan_full +scan_make_command_lines +scan_until +scanf +scanner +scheme +scheme= +scheme_list +scope +scope= +scope_name +script_name +scrl +scroll +scrolling_list +scrollok +search +search_const +search_convpath +search_file +search_for_dependency +search_full +search_internal +search_record +search_servlet +search_string +searcher= +sec +sec= +sec_fraction +second +second= +second_fraction +section +section_contents +sections +secure +secure= +security_policy +see +seed +seed= +seek +seen +select +select! +select_tasks_to_show +select_trace_output +self +send +send_command +send_data +send_entity +send_gem +send_io +send_list_data +send_literal +send_mail +send_message +send_number_data +send_quoted_string +send_request +send_request_with_body +send_request_with_body_data +send_request_with_body_stream +send_string_data +send_symbol_data +send_time_data +sendcmd +sender +sendmail +sendmsg +sendmsg_nonblock +sent_size +separator +seplist +seq +seq= +sequence +serial +serial= +serve +server +server_cert +server_error? +server_name +servername_cb +service +session +session= +session_add +session_cache_mode +session_cache_mode= +session_cache_size +session_cache_size= +session_cache_stats +session_get_cb +session_id +session_id_context +session_new_cb +session_remove +session_remove_cb +session_reused? +set +set_arg_names +set_attributes +set_attrs +set_auth +set_backtrace +set_banner +set_callback +set_callback_internal +set_cdecl_callback +set_close_on_exec +set_component +set_content_type +set_ctypes +set_current_section +set_debug_output +set_default +set_default_handler +set_default_paths +set_default_values +set_dictionary +set_dn +set_element +set_encoding +set_eoutvar +set_error +set_extensions +set_filter +set_form +set_form_data +set_fragment +set_generator +set_get_line_procs +set_headers +set_host +set_last_thread +set_last_value +set_log +set_next_element +set_non_blocking +set_opaque +set_option +set_options +set_params +set_parent +set_parser +set_passwd +set_password +set_path +set_port +set_program_name +set_query +set_range +set_redirect +set_registry +set_scheme +set_scope +set_screen_size +set_service_hook +set_size +set_socket +set_stdcall_callback +set_summary_indent +set_summary_width +set_term_to_element +set_to +set_to_infinity! +set_trace +set_trace_func +set_typecode +set_user +set_userinfo +set_valid_ip +set_visibility_for +set_writer +set_xhtml_uri_as_default_uri +setacl +setbyte +setegid +seteuid +setgid +setgid? +setgrent +setpgid +setpgrp +setpos +setpriority +setproperty +setpwent +setquota +setregid +setresgid +setresuid +setreuid +setrgid +setrlimit +setruid +setscrreg +setsid +setsockopt +setter +setuid +setuid? +setup +setup_certificate +setup_elements +setup_generator +setup_image +setup_items +setup_maker +setup_maker_attributes +setup_maker_element +setup_maker_element_writer +setup_maker_elements +setup_next_element +setup_next_element_in_unknown_element +setup_options +setup_other_elements +setup_output_dir +setup_pager +setup_params +setup_scanner +setup_signer +setup_ssl_context +setup_textinput +setup_values +sev_threshold +sev_threshold= +sexp +sexp_raw +sfork +sh +sharing_detection +shebang +shell +shellescape +shelljoin +shellsplit +shellwords +shift +shift_log_age +shift_log_period +short +short_name +show_all +show_documentation +show_hash +show_help +show_lookup_failure +show_owners +show_rdoc_for_pattern +show_version +shuffle +shuffle! +shutdown +sid_available? +sigma +sign +sign_in +signal +signal_handle +signal_status +signaled? +signame +signature +signature_algorithm +signed_time +signed_value +signers +signing_key +signo +sin +sin! +single? +single_delegate +singleline_format +singleline_pp +singleton +singleton_class +singleton_classes +singleton_method_added +singleton_method_removed +singleton_method_undefined +singleton_methods +singular? +sinh +sinh! +site +site_dir +size +size= +size? +size_opt_params +size_params +sizeof +skip +skip_blanks? +skip_during +skip_for_variable +skip_lines +skip_method +skip_optional_do_after_expression +skip_tkspace +skip_tkspace_comment +skip_until +sleep +slice +slice! +slice_before +sn +snippet +soak_up_spaces +sock +sockaddr_in +sockaddr_un +socket? +socketpair +socktype +solve +sort +sort! +sort_by +sort_by! +sort_if_need +sort_internal +sort_obj +sort_options +sort_sections +sorted +sorted_requests +source +source_encoding +source_encoding_name +source_exception +source_file +source_for +source_location +source_ole_types +sources +sources= +spawn +spec +spec_authors +spec_dir +spec_dirs +spec_file +spec_for_dependency +spec_homepage +spec_license +spec_loaded_from +spec_name +spec_path +spec_platforms +spec_predecessors +spec_summary +spec_type +special +special_prefixes +special_prefixes= +specific? +specific_extra_args +specific_extra_args_hash +specification_version +specs +specs_in +split +split_all +split_header_value +split_into_flow +split_name +split_path +split_userinfo +sprintf +sqrt +sqrt! +square? +squeeze +squeeze! +srand +src +src_type +ssl? +ssl_ca_cert +ssl_params +ssl_socket +ssl_timeout +ssl_verify_mode +ssl_version +ssl_version= +sspi_auth +sspi_auth? +stand_alone? +standalone +standard_exception_handling +standard_rake_options +standend +standout +start +startElement +start_accepting +start_collecting_tokens +start_color +start_doc +start_document +start_element +start_element? +start_else_element +start_export +start_get_text_element +start_have_something_element +start_immediately +start_import +start_job +start_keeper +start_mapping +start_prefix_mapping +start_profile +start_sequence +start_server +start_service +start_stream +start_tls_session +start_watchdog +start_with? +started +started? +starting +starts_with +starttls +starttls? +starttls_always? +starttls_auto? +stat +state +static_path +stats +status +status= +status_line +status_message +status_string +status_type_char +stdinput +stdlog +stdout +stdout= +stdout_mutex +stdoutput +stdscr +step +sticky? +stime +stop +stop? +stop_doc +stop_profile +stop_service +stopped? +stopping +stopsig +storbinary +store +store= +store_for +store_internal +stores +storlines +stream= +stream_check +stream_end? +streaming? +stress +stress= +strftime +strict_decode64 +strict_encode64 +string +string= +string_length +string_value +strings +strip +strip! +strip_hashes +strip_newlines +strip_quotes +strip_stars +strong +strongly_connected_components +strptime +struct +style +su +sub +sub! +sub_ext +sub_type +subdomain_of? +subject +subject= +subject_certificate +subject_certificate= +subject_request +subject_request= +submit +subpad +subscribe +subsec +subset? +substring +substring_after +substring_before +subtract +subwin +succ +succ! +succeed +success? +suffix_pattern +suffixes +suggest_gems_from_name +sum +summarize +summary +summary= +summary_indent +summary_width +sunday? +super_each +superclass +superclass= +superclass_method +superset? +supply_default_content_type +supported? +suppressed? +suspend +suspend_context +suspend_input_method +suspend_name +suspend_workspace +swapcase +swapcase! +switch +switch_name +sym +symlink +symlink? +symlink_files +symmetric? +sync +sync= +sync_ex_count +sync_ex_locker +sync_exclusive? +sync_extend +sync_initialize +sync_inspect +sync_lock +sync_locked? +sync_mode +sync_point? +sync_sh_locker +sync_shared? +sync_synchronize +sync_try_lock +sync_try_lock_sub +sync_unlock +sync_upgrade_waiting +sync_waiting +synchronize +syncmode= +synthesize_file_task +sysaccept +syscall +sysclose +sysconfdir +sysopen +sysread +sysread_nonblock +sysseek +syssign +system +system_dir +system_path +system_path= +systmpdir +sysverify +syswrite +syswrite_nonblock +t +tab_width +table +table_of_contents +tag +tag_class +tag_directives +tag_end +tag_filter +tag_name +tag_name_with_prefix +tag_start +tagging +tagurize +taint +tainted? +take +take_while +tan +tan! +tanh +tanh! +tap +tar_bz2_file +tar_command +tar_dir_header +tar_file_header +tar_gz_file +target +task +task_defined? +tasks +tasks_in_scope +taxo_link +taxo_link= +tcp +tcp_server_loop +tcp_server_sockets +tcp_socket +teardown +tee +tell +telnetmode +telnetmode= +temp_dir +template +template_dir +template_dir_for +template_for +template_result +temporary_section +terminal +terminal_columns +terminal_width +terminate +terminate_interaction +terminate_job +terminated? +termsig +territory +test +test_accept_blank_line +test_accept_block_quote +test_accept_document +test_accept_heading +test_accept_heading_1 +test_accept_heading_2 +test_accept_heading_3 +test_accept_heading_4 +test_accept_heading_b +test_accept_heading_indent +test_accept_heading_suppressed_crossref +test_accept_list_end_bullet +test_accept_list_end_label +test_accept_list_end_lalpha +test_accept_list_end_note +test_accept_list_end_number +test_accept_list_end_ualpha +test_accept_list_item_end_bullet +test_accept_list_item_end_label +test_accept_list_item_end_lalpha +test_accept_list_item_end_note +test_accept_list_item_end_number +test_accept_list_item_end_ualpha +test_accept_list_item_start_bullet +test_accept_list_item_start_label +test_accept_list_item_start_lalpha +test_accept_list_item_start_note +test_accept_list_item_start_note_2 +test_accept_list_item_start_note_multi_description +test_accept_list_item_start_note_multi_label +test_accept_list_item_start_number +test_accept_list_item_start_ualpha +test_accept_list_start_bullet +test_accept_list_start_label +test_accept_list_start_lalpha +test_accept_list_start_note +test_accept_list_start_number +test_accept_list_start_ualpha +test_accept_paragraph +test_accept_paragraph_b +test_accept_paragraph_br +test_accept_paragraph_break +test_accept_paragraph_i +test_accept_paragraph_indent +test_accept_paragraph_plus +test_accept_paragraph_star +test_accept_paragraph_underscore +test_accept_paragraph_wrap +test_accept_raw +test_accept_rule +test_accept_rule_indent +test_accept_verbatim +test_accept_verbatim_big_indent +test_accept_verbatim_indent +test_attributes +test_end_accepting +test_file +test_file= +test_files +test_files= +test_list_nested +test_list_verbatim +test_order +test_start_accepting +text +text= +text? +text_field +text_type_writer +text_zero_one +textarea +textinput +texts +tgz_file +thread +thread_internal +thread_list +thread_list_all +thread_variable? +thread_variable_get +thread_variable_set +thread_variables +threads +throw +thursday? +time +time2wtime +time= +time_delta_string +time_format +timeout +timeout= +timeouts= +times +timestamp +title +title= +tls? +tlsconnect +tmp_dh_callback +tmpdir +to +to= +to_a +to_ary +to_atom +to_basic +to_bn +to_c +to_class_name +to_csv +to_d +to_date +to_datetime +to_der +to_digits +to_element_methods +to_enum +to_f +to_feed +to_feed_for_categories +to_h +to_hash +to_html +to_i +to_id +to_int +to_io +to_json +to_mailtext +to_name +to_obj +to_oct +to_p +to_path +to_pem +to_proc +to_ptr +to_r +to_range +to_rfc822text +to_rss +to_ruby +to_ruby_for_cache +to_run +to_s +to_set +to_sockaddr +to_spec +to_specs +to_str +to_string +to_sym +to_text +to_time +to_toc +to_uri +to_value +to_write_io +to_xml +to_yaml +to_yaml_properties +today +toeuc +tojis +token +token_listener +token_pos +token_stream +token_to_str +tokenize +tokens +tokens_to_s +tolocale +tomdoc? +top +top_level +top_level_tasks +top_level_test +toplevel_load +tosjis +total +total_bytes +total_in +total_out +total_time +touch +toutf16 +toutf32 +toutf8 +tr +tr! +tr_s +tr_s! +trace +trace_func +trace_on +trace_rule +trace_var +trackback_validate +transact +transaction +transfer +transform +translate +transport_request +transpose +trap +traverse +tree +tridiagonalize +true +truncate +truncate_output? +trust +trust= +trust_cert +trust_dir +trusted_certificates +try_activate +try_const +try_convert +try_lock +try_mon_enter +try_type +tsort +tsort_each +tsort_each_child +tsort_each_node +tt? +tt_sections +ttl +tty +tty? +tty_output= +tty_output? +tuesday? +tuples_for +tv_nsec +tv_sec +tv_usec +type +type2name +type= +type_params +typealias +typecode +typecode= +typekind +typelibs +types +u +udp +udp_server_loop +udp_server_loop_on +udp_server_recv +udp_server_sockets +ui +ui= +uid +uid= +uid_copy +uid_fetch +uid_search +uid_sort +uid_store +uid_thread +uidl +ultra_safe +umask +umount +unadvise +unalias_command +unbind +unbind_at_call +unconverted_fields? +undef_method +undef_system_command +undefine_finalizer +undoc_params +unescape +unescapeElement +unescapeHTML +unescape_element +unescape_form +unescape_html +unescape_value +unget +unget_tk +ungetbyte +ungetc +ungetch +ungetmouse +uninstall +uninstall_dep +uninstall_gem +uninstall_old_gemcutter +union +uniq +uniq! +unique_classes +unique_classes_and_modules +unique_id +unique_modules +unit +unitary? +unix +unix? +unix_path +unix_rights +unix_server_loop +unix_server_socket +unix_socket_abstract_name? +unknown +unlink +unlock +unmask_protected_sequences +unmatched_alias_lists +unmount +unnormalize +unnormalized +unpack +unpack_sockaddr_in +unpack_sockaddr_un +unpackdw +unpackqw +unparsed_uri +unregist +unregister_command +unresolved_deps +unscan +unshift +unsigned_value +unsubscribe +untaint +untrace_var +untrust +untrusted? +unused +unyank_gem +upcase +upcase! +update +update_aliases +update_cache? +update_checksum +update_content +update_display +update_extends +update_gem +update_gems +update_includes +update_index +update_output_dir +update_rubygems +update_sources +update_specs_index +update_status +updated +updated= +upgrade_to_class +upload +upload_files +upper +upper_bound +upper_bound= +upper_triangular? +upto +uptodate? +uri +uri_convert_attr_reader +uri_escaper +uri_option +uri_registered? +url_encode +urlsafe_base64 +urlsafe_decode64 +urlsafe_encode64 +usage +use_default_colors +use_loader +use_loader= +use_loader? +use_markup +use_paths +use_prefix +use_readline +use_readline= +use_readline? +use_registry +use_ssl= +use_ssl? +use_stdout +use_tracer +use_tracer= +use_tracer? +use_ui +usec +user +user= +user_agent +user_dir +user_home +userdb +userinfo +userinfo= +utc +utc? +utc_offset +util_build_gem +util_clear_gems +util_dir_entry +util_entry +util_gem +util_gzip +util_inst_bindir +util_installer +util_make_exec +util_make_gems +util_remove_gem +util_set_arch +util_setup_fake_fetcher +util_setup_gem +util_setup_spec_fetcher +util_spec +util_zip +utime +uuid +v +v_inv +v_nil +valid? +valid_civil? +valid_commercial? +valid_date? +valid_encoding? +valid_jd? +valid_ordinal? +valid_v6? +validate +validate_attribute +validate_data +validate_duplicate_links +validate_for_stream +validate_one_tag_name +validate_permissions +validate_sy_updatePeriod +validation_for_fit +value +value= +value? +values +values_at +variable_is_set? +variable_kind +variables +variables= +varkind +vartype +vc_windows? +ver +verb +verbose +verbose= +verbose? +verbose_capture_io +verbose_flag +verbosity +verify +verify_api_key +verify_callback +verify_callback= +verify_certificate_identity +verify_chain +verify_data +verify_depth +verify_files +verify_gem +verify_gem_file +verify_gem_home +verify_mode +verify_result +verify_root +verify_signatures +verify_signer +version +version= +version_1_2 +version_1_2? +versions +vi_editing_mode +vi_editing_mode? +viewer +virtual_host +visibility +visible? +visit +visit_Array +visit_BigDecimal +visit_Class +visit_Complex +visit_Date +visit_DateTime +visit_Exception +visit_FalseClass +visit_Float +visit_Hash +visit_Integer +visit_Module +visit_NilClass +visit_Object +visit_Psych_Nodes_Alias +visit_Psych_Nodes_Document +visit_Psych_Nodes_Mapping +visit_Psych_Nodes_Scalar +visit_Psych_Nodes_Sequence +visit_Psych_Nodes_Stream +visit_Psych_Omap +visit_Psych_Set +visit_Range +visit_Rational +visit_Regexp +visit_String +visit_Struct +visit_Symbol +visit_Time +visit_TrueClass +visit_array_subclass +voidcmd +w3cdtf +wait +wait2 +wait? +wait_all_jobs_execution +wait_for_child_process_to_exit +wait_for_continue +wait_readable +wait_to_finish_all_process_controllers +wait_until +wait_while +wait_writable +waitall +waitfor +waiting +waiting_job? +waiting_jobs +waiting_jobs_exist? +waitpid +waitpid2 +wakeup +warn +warn? +warning +wday +weakref_alive? +webcvs +wednesday? +weight +welcome +when_invoked +when_writing +which_to_update +whitespace +why_not_ok? +width +width= +win32_last_error +win32_last_error= +win_platform= +win_platform? +windows? +windows_stub_script +winsize +winsize= +with +with_config +with_defaults +with_index +with_object +with_response +with_verbose +wont_be +wont_be_close_to +wont_be_empty +wont_be_instance_of +wont_be_kind_of +wont_be_nil +wont_be_same_as +wont_be_within_delta +wont_be_within_epsilon +wont_equal +wont_include +wont_match +wont_respond_to +word_pair_map +wordy +workspace +workspace_home +workspaces +world_readable? +world_writable? +wrap +wrap_arg +wrap_args +wrap_result +wrappers +writable? +writable_real? +write +writeTo +write_bin +write_build_info_file +write_cache_file +write_cdata +write_comment +write_document +write_element +write_file +write_header +write_headers? +write_i +write_instruction +write_nonblock +write_options +write_s +write_service +write_smime +write_spec +write_style_sheet +write_text +write_with_substitution +writeencoding +writethis +written +wrong_type +wtime2time +xhtml +xhtml= +xlist +xml +xml= +xmlDecl +xml_content= +xml_decl +xml_getter +xml_setter +xml_stylesheet_pi +xml_stylesheets +xml_type? +xmldecl +xmldecl? +xmled_content +xmlschema +xmp +xpath +y +yaml +yaml_as +yaml_initialize +yaml_tag +yank_api_request +yank_gem +yday +year +year= +yes_clean_other_attr_reader +yes_clean_other_writer +yes_other_attr_reader +yes_other_writer +yield +yyaccept +yydebug +yydebug= +yyerrok +yyerror +yyparse +zero +zero? +zip +zip? +zip_command +zip_file +zlib_version +zone +zone_offset +zone_utc? +| +~ \ No newline at end of file diff --git a/docs/Changelog.md b/docs/Changelog.md index 50494acc..7043202f 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,6 +3,39 @@ This is the list of all noteworthy changes made in every public release of the tool. See README.md for the general instruction manual. +### Version ++4.22a (dev) + - afl-fuzz: + - fastresume feature added. if you abort fuzzing and resume fuzzing + with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed + then a dump will be loaded and the calibration phase skipped. + to disable this feature set `AFL_NO_FASTRESUME=1` + zlib compression is used if zlib is found at compile time + - improved seed selection algorithm + - added `AFL_CUSTOM_MUTATOR_LATE_SEND=1` to call the custom send() + function after the target has been restarted. + - because of bad math and undefined behaviour fixes we have to change + the CMPLOG map. **YOU NEED TO RECOMPILE CMPLOG TARGETS** + - frida_mode: + - AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just + a function entry + - AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE + - AFL_FRIDA_DEBUG_MAPS now works as expected + - qemu_mode: + - new hooks supported (optional), see qemu_mode/hooking_bridge - thanks to + @CowBoy4mH3LL + - unicorn_mode: + - fix install and forkserver (thanks aarnav!) + - custom mutators: + - custom_send_tcp custom mutator added, thanks to @dergoegge + - afl-cc + - new runtime (!) variable: `AFL_OLD_FORKSERVER` to use the old vanilla + AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with + AFL_LLVM_INSTRUMENT=CLASSIC + - code formatting updated to llvm 18 + - improved custom_mutators/aflpp/standalone/aflpp-standalone + - added custom_mutators/autotokens/standalone/autotokens-standalone + + ### Version ++4.21c (release) * afl-fuzz - fixed a regression in afl-fuzz that resulted in a 5-10% performace loss @@ -42,7 +75,6 @@ * Fixed a shmem mmap bug (that rarely came up on MacOS) * libtokencap: script generate_libtoken_dict.sh added by @a-shvedov - ### Version ++4.20c (release) ! A new forkserver communication model is now introduced. afl-fuzz is backward compatible to old compiled targets if they are not built diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 3089aab2..03f69485 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -30,6 +30,9 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev sudo apt-get install -y ninja-build # for QEMU mode +sudo apt-get install -y cpio libcapstone-dev # for Nyx mode +sudo apt-get install -y wget curl # for Frida mode +sudo apt-get install -y python3-pip # for Unicorn mode git clone https://github.com/AFLplusplus/AFLplusplus cd AFLplusplus make distrib diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md index b7a7032f..3067ceab 100644 --- a/docs/custom_mutators.md +++ b/docs/custom_mutators.md @@ -198,6 +198,11 @@ def deinit(): # optional for Python This method can be used if you want to send data to the target yourself, e.g. via IPC. This replaces some usage of utils/afl_proxy but requires that you start the target with afl-fuzz. + + Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send() + function after the target has been restarted. (This is needed for e.g. TCP + services.) + Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c) - `queue_new_entry` (optional): diff --git a/docs/env_variables.md b/docs/env_variables.md index 22e0ce0f..8c2d5848 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -331,7 +331,26 @@ mode. the target performs only a few loops, then this will give a small performance boost. -## 4) Settings for afl-fuzz +## 4) Runtime settings + +The following environment variables are for a compiled AFL++ target. + + - Setting `AFL_DUMP_MAP_SIZE` when executing the target directly will + dump the map size of the target and exit. + + - Setting `AFL_OLD_FORKSERVER` will use the old AFL vanilla forkserver. + This makes only sense when you + a) compile in a classic colliding coverage mode (e.g. + AFL_LLVM_INSTRUMENT=CLASSIC) or if the map size of the target is + below MAP_SIZE (65536 by default), AND + b) you want to use this compiled AFL++ target with a different tool + that expects vanilla AFL behaviour, e.g. symcc, symqemu, nautilus, etc. + You would use this option together with the target fuzzing application. + + - Setting `AFL_DISABLE_LLVM_INSTRUMENTATION` will disable collecting + instrumentation. (More of an internal option.) + +## 5) Settings for afl-fuzz The main fuzzer binary accepts several options that disable a couple of sanity checks or alter some of the more exotic semantics of the tool: @@ -368,6 +387,10 @@ checks or alter some of the more exotic semantics of the tool: XML or other highly flexible structured input. For details, see [custom_mutators.md](custom_mutators.md). + - Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send() + function after the target has been restarted. (This is needed for e.g. TCP + services.) + - Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time a cycle is finished. @@ -514,6 +537,8 @@ checks or alter some of the more exotic semantics of the tool: - `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if the snapshot lkm is loaded. + - `AFL_NO_FASTRESUME` will not try to read or write a fast resume file. + - Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints some basic stats. This behavior is also automatically triggered when the output from afl-fuzz is redirected to a file or to a pipe. @@ -636,7 +661,7 @@ checks or alter some of the more exotic semantics of the tool: Note that will not be exact and with slow targets it can take seconds until there is a slice for the time test. -## 5) Settings for afl-qemu-trace +## 6) Settings for afl-qemu-trace The QEMU wrapper used to instrument binary-only code supports several settings: @@ -708,7 +733,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings: crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when counting crashes based on a file count in that directory. -## 7) Settings for afl-frida-trace +## 8) Settings for afl-frida-trace The FRIDA wrapper used to instrument binary-only code supports many of the same options as `afl-qemu-trace`, but also has a number of additional advanced @@ -798,7 +823,7 @@ support. dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` killing the process whilst it is being dumped. -## 8) Settings for afl-cmin +## 9) Settings for afl-cmin The corpus minimization script offers very little customization: @@ -816,7 +841,7 @@ The corpus minimization script offers very little customization: - `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed. This can help when embedding `afl-cmin` or `afl-showmap` in other scripts. -## 9) Settings for afl-tmin +## 10) Settings for afl-tmin Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a @@ -827,12 +852,12 @@ to match when minimizing crashes. This will make minimization less useful, but may prevent the tool from "jumping" from one crashing condition to another in very buggy software. You probably want to combine it with the `-e` flag. -## 10) Settings for afl-analyze +## 11) Settings for afl-analyze You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead of decimal. -## 11) Settings for libdislocator +## 12) Settings for libdislocator The library honors these environment variables: @@ -854,12 +879,12 @@ The library honors these environment variables: - `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that may be useful for pinpointing the cause of any observed issues. -## 11) Settings for libtokencap +## 13) Settings for libtokencap This library accepts `AFL_TOKEN_FILE` to indicate the location to which the discovered tokens should be written. -## 12) Third-party variables set by afl-fuzz & other tools +## 14) Third-party variables set by afl-fuzz & other tools Several variables are not directly interpreted by afl-fuzz, but are set to optimal values if not already present in the environment: diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index c055fcbb..6f58ebbb 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -214,6 +214,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE arm: CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all +arm64: + ARCH="arm64" TARGET_CC=aarch64-linux-gnu-gcc TARGET_CXX=aarch64-linux-gnu-g++ make all + $(BUILD_DIR): mkdir -p $(BUILD_DIR) diff --git a/frida_mode/addr/addr.c b/frida_mode/addr/addr.c index 371f69d4..69a04b17 100644 --- a/frida_mode/addr/addr.c +++ b/frida_mode/addr/addr.c @@ -6,34 +6,39 @@ #define UNUSED_PARAMETER(x) (void)(x) -int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) -{ - UNUSED_PARAMETER (size); +int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) { - ElfW(Addr) * base = data; + UNUSED_PARAMETER(size); + + ElfW(Addr) *base = data; + + if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; } + return 0; - if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; } - return 0; } -int main (int argc, char** argv, char** envp) { - UNUSED_PARAMETER (argc); +int main(int argc, char **argv, char **envp) { + + UNUSED_PARAMETER(argc); - ElfW(Addr) base = 0; + ElfW(Addr) base = 0; - int persona = personality(ADDR_NO_RANDOMIZE); - if (persona == -1) { + int persona = personality(ADDR_NO_RANDOMIZE); + if (persona == -1) { - printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno); - return 1; - } + printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno); + return 1; - if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); } + } - dl_iterate_phdr(phdr_callback, &base); + if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); } - printf("%p\n", (void *)base); - if (base == 0) { return 1; } + dl_iterate_phdr(phdr_callback, &base); + + printf("%p\n", (void *)base); + if (base == 0) { return 1; } + + return 0; - return 0; } + diff --git a/frida_mode/frida.map b/frida_mode/frida.map index a98c2096..90ea1421 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -45,6 +45,7 @@ js_api_set_stdout; js_api_set_traceable; js_api_set_verbose; + js_api_ijon_set; local: *; diff --git a/frida_mode/hook/frida_hook.c b/frida_mode/hook/frida_hook.c index da1a59b2..59a92e7e 100644 --- a/frida_mode/hook/frida_hook.c +++ b/frida_mode/hook/frida_hook.c @@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook( // do a length check matching the target! void **esp = (void **)regs->esp; - void *arg1 = esp[0]; - void **arg2 = &esp[1]; + void *arg1 = esp[1]; + void **arg2 = &esp[2]; memcpy(arg1, input_buf, input_buf_len); *arg2 = (void *)input_buf_len; diff --git a/frida_mode/hook/qemu_hook.c b/frida_mode/hook/qemu_hook.c index 56e787e3..d7d45974 100644 --- a/frida_mode/hook/qemu_hook.c +++ b/frida_mode/hook/qemu_hook.c @@ -36,7 +36,7 @@ struct x86_64_regs { void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, uint8_t *input_buf, uint32_t input_buf_len) { - (void)guest_base; /* unused */ + (void)guest_base; /* unused */ memcpy((void *)regs->rdi, input_buf, input_buf_len); regs->rsi = input_buf_len; @@ -76,14 +76,15 @@ struct x86_regs { void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base, uint8_t *input_buf, uint32_t input_buf_len) { - (void)guest_base; /* unused */ + (void)guest_base; /* unused */ void **esp = (void **)regs->esp; - void * arg1 = esp[1]; + void *arg1 = esp[1]; void **arg2 = &esp[2]; memcpy(arg1, input_buf, input_buf_len); *arg2 = (void *)input_buf_len; } + #elif defined(__aarch64__) struct arm64_regs { @@ -177,9 +178,10 @@ struct arm64_regs { void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base, uint8_t *input_buf, uint32_t input_buf_len) { - (void)guest_base; /* unused */ + (void)guest_base; /* unused */ memcpy((void *)regs->x0, input_buf, input_buf_len); regs->x1 = input_buf_len; + } #else @@ -193,3 +195,4 @@ int afl_persistent_hook_init(void) { return 1; } + diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index 1825e331..9287019a 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -22,6 +22,7 @@ extern guint64 instrument_fixed_seed; extern uint8_t *__afl_area_ptr; extern uint32_t __afl_map_size; +extern void __afl_coverage_interesting(uint8_t, uint32_t); extern __thread guint64 *instrument_previous_pc_addr; @@ -72,5 +73,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output); void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data); void instrument_regs_format(int fd, char *format, ...); +void ijon_set(uint32_t edge); + #endif diff --git a/frida_mode/src/asan/asan_arm64.c b/frida_mode/src/asan/asan_arm64.c index 94729939..c1d5c10f 100644 --- a/frida_mode/src/asan/asan_arm64.c +++ b/frida_mode/src/asan/asan_arm64.c @@ -39,15 +39,15 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) { address = base + index + mem->disp; - if ((operand->access & CS_AC_READ) == CS_AC_READ) { + if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) { - asan_loadN(address, asan_ctx->size); + asan_storeN(address, asan_ctx->size); } - if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) { + if ((operand->access & CS_AC_READ) == CS_AC_READ) { - asan_storeN(address, asan_ctx->size); + asan_loadN(address, asan_ctx->size); } diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index db73d845..d30e21ec 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -449,3 +449,9 @@ void instrument_regs_format(int fd, char *format, ...) { } +void ijon_set(uint32_t edge) { + + __afl_coverage_interesting(1, edge); + +} + diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c index ff2f4024..140072dd 100644 --- a/frida_mode/src/instrument/instrument_coverage.c +++ b/frida_mode/src/instrument/instrument_coverage.c @@ -818,6 +818,9 @@ void instrument_coverage_unstable_find_output(void) { GDir *dir = g_dir_open(fds_name, 0, NULL); + gchar *path_tmp = getenv("AFL_CUSTOM_INFO_OUT"); + gchar *instance_name = g_path_get_basename(path_tmp); + FVERBOSE("Coverage Unstable - fds: %s", fds_name); for (const gchar *filename = g_dir_read_name(dir); filename != NULL; @@ -829,7 +832,7 @@ void instrument_coverage_unstable_find_output(void) { if (link == NULL) { FFATAL("Failed to read link: %s", fullname); } gchar *basename = g_path_get_basename(link); - if (g_strcmp0(basename, "default") != 0) { + if (g_strcmp0(basename, instance_name) != 0) { g_free(basename); g_free(link); @@ -874,6 +877,7 @@ void instrument_coverage_unstable_find_output(void) { } g_dir_close(dir); + g_free(instance_name); g_free(fds_name); if (unstable_coverage_fuzzer_stats == NULL) { diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index a65d32df..9e2b15c5 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -326,6 +326,12 @@ class Afl { static jsApiGetSymbol(name) { return Afl.module.getExportByName(name); } + + static IJON = class { + static set(addr, val) { + Afl.jsApiIjonSet((addr ^ val) & 0xffffffff); + } + } } /** * Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode @@ -377,3 +383,4 @@ Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []); Afl.jsApiWrite = new NativeFunction( /* tslint:disable-next-line:no-null-keyword */ Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]); +Afl.jsApiIjonSet = Afl.jsApiGetFunction("js_api_ijon_set", "void", ["uint32"]); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 288aec95..274cd1bc 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -316,3 +316,9 @@ __attribute__((visibility("default"))) void js_api_set_verbose(void) { } +__attribute__((visibility("default"))) void js_api_ijon_set(uint32_t edge) { + + ijon_set(edge); + +} + diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index dbe51eb5..8790f483 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -33,7 +33,7 @@ // r15 - pc static GumCpuContext saved_regs = {0}; -static gpointer saved_lr = NULL; +static gpointer persistent_loop = NULL; gboolean persistent_is_supported(void) { @@ -141,17 +141,10 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw, } -static void instrument_exit(GumArmWriter *cw) { +static void instrument_afl_persistent_loop_func(void) { - gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0); - gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1, - GUM_ARG_REGISTER, ARM_REG_R0); + if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); } -} - -static int instrument_afl_persistent_loop_func(void) { - - int ret = __afl_persistent_loop(persistent_count); if (instrument_previous_pc_addr == NULL) { FATAL("instrument_previous_pc_addr uninitialized"); @@ -159,7 +152,6 @@ static int instrument_afl_persistent_loop_func(void) { } *instrument_previous_pc_addr = instrument_hash_zero; - return ret; } @@ -203,7 +195,8 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) { gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, GUM_RED_ZONE_SIZE); - gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, + GUM_ADDRESS(&persistent_ret)); gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0); gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, @@ -214,65 +207,35 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) { void persistent_prologue_arch(GumStalkerOutput *output) { /* + * SAVE RET (Used to write the epilogue if persistent_ret is not set) * SAVE REGS - * SAVE RET - * POP RET - * loop: + * loop: (Save address of where the eiplogue should jump back to) * CALL instrument_afl_persistent_loop - * TEST EAX, EAX - * JZ end: - * call hook (optionally) + * CALL hook (optionally) * RESTORE REGS - * call original - * jmp loop: - * - * end: - * JMP SAVED RET - * - * original: * INSTRUMENTED PERSISTENT FUNC */ GumArmWriter *cw = output->writer.arm; - gconstpointer loop = cw->code + 1; - FVERBOSE("Persistent loop reached"); + if (persistent_ret == 0) { instrument_persitent_save_lr(cw); } + + /* Save the current context */ instrument_persitent_save_regs(cw, &saved_regs); - /* loop: */ - gum_arm_writer_put_label(cw, loop); + /* Store a pointer to where we should return for our next iteration */ + persistent_loop = gum_arm_writer_cur(cw); - /* call instrument_prologue_func */ + /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */ instrument_afl_persistent_loop(cw); - /* jz done */ - gconstpointer done = cw->code + 1; - gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0); - gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done); - /* Optionally call the persistent hook */ persistent_prologue_hook(cw, &saved_regs); + /* Restore our CPU context before we continue execution */ instrument_persitent_restore_regs(cw, &saved_regs); - gconstpointer original = cw->code + 1; - /* call original */ - - gum_arm_writer_put_bl_label(cw, original); - - /* jmp loop */ - gum_arm_writer_put_b_label(cw, loop); - - /* done: */ - gum_arm_writer_put_label(cw, done); - - instrument_exit(cw); - - /* original: */ - gum_arm_writer_put_label(cw, original); - - instrument_persitent_save_lr(cw); if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } @@ -284,7 +247,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) { if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } - gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, + GUM_ADDRESS(&persistent_loop)); gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0); diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c index 565a2b8c..cfd00b17 100644 --- a/frida_mode/src/persistent/persistent_arm64.c +++ b/frida_mode/src/persistent/persistent_arm64.c @@ -16,7 +16,7 @@ typedef struct { } persistent_ctx_t; static persistent_ctx_t saved_regs = {0}; -static gpointer saved_lr = NULL; +static gpointer persistent_loop = NULL; gboolean persistent_is_supported(void) { @@ -216,17 +216,10 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw, } -static void instrument_exit(GumArm64Writer *cw) { +static void instrument_afl_persistent_loop_func(void) { - gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); - gum_arm64_writer_put_call_address_with_arguments( - cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0); - -} - -static int instrument_afl_persistent_loop_func(void) { + if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); } - int ret = __afl_persistent_loop(persistent_count); if (instrument_previous_pc_addr == NULL) { FATAL("instrument_previous_pc_addr uninitialized"); @@ -234,7 +227,6 @@ static int instrument_afl_persistent_loop_func(void) { } *instrument_previous_pc_addr = instrument_hash_zero; - return ret; } @@ -284,7 +276,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) { GUM_INDEX_PRE_ADJUST); gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, - GUM_ADDRESS(&saved_lr)); + GUM_ADDRESS(&persistent_ret)); gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0); @@ -297,65 +289,35 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) { void persistent_prologue_arch(GumStalkerOutput *output) { /* + * SAVE RET (Used to write the epilogue if persistent_ret is not set) * SAVE REGS - * SAVE RET - * POP RET - * loop: + * loop: (Save address of where the eiplogue should jump back to) * CALL instrument_afl_persistent_loop - * TEST EAX, EAX - * JZ end: - * call hook (optionally) + * CALL hook (optionally) * RESTORE REGS - * call original - * jmp loop: - * - * end: - * JMP SAVED RET - * - * original: * INSTRUMENTED PERSISTENT FUNC */ GumArm64Writer *cw = output->writer.arm64; - gconstpointer loop = cw->code + 1; - FVERBOSE("Persistent loop reached"); + if (persistent_ret == 0) { instrument_persitent_save_lr(cw); } + + /* Save the current context */ instrument_persitent_save_regs(cw, &saved_regs); - /* loop: */ - gum_arm64_writer_put_label(cw, loop); + /* Store a pointer to where we should return for our next iteration */ + persistent_loop = gum_arm64_writer_cur(cw); - /* call instrument_prologue_func */ + /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */ instrument_afl_persistent_loop(cw); - /* jz done */ - gconstpointer done = cw->code + 1; - gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); - gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done); - /* Optionally call the persistent hook */ persistent_prologue_hook(cw, &saved_regs); + /* Restore our CPU context before we continue execution */ instrument_persitent_restore_regs(cw, &saved_regs); - gconstpointer original = cw->code + 1; - /* call original */ - - gum_arm64_writer_put_bl_label(cw, original); - - /* jmp loop */ - gum_arm64_writer_put_b_label(cw, loop); - - /* done: */ - gum_arm64_writer_put_label(cw, done); - - instrument_exit(cw); - - /* original: */ - gum_arm64_writer_put_label(cw, original); - - instrument_persitent_save_lr(cw); if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } @@ -368,7 +330,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) { if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, - GUM_ADDRESS(&saved_lr)); + GUM_ADDRESS(&persistent_loop)); gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0); diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index a8bed7be..fd194c75 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -17,7 +17,7 @@ typedef struct { } persistent_ctx_t; static persistent_ctx_t saved_regs = {0}; -static gpointer saved_ret = NULL; +static gpointer persistent_loop = NULL; gboolean persistent_is_supported(void) { @@ -162,17 +162,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw, } -static void instrument_exit(GumX86Writer *cw) { +static void instrument_afl_persistent_loop_func(void) { - gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(_exit)); - gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0); - gum_x86_writer_put_call_reg(cw, GUM_X86_RAX); + if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); } -} - -static int instrument_afl_persistent_loop_func(void) { - - int ret = __afl_persistent_loop(persistent_count); if (instrument_previous_pc_addr == NULL) { FATAL("instrument_previous_pc_addr uninitialized"); @@ -180,7 +173,6 @@ static int instrument_afl_persistent_loop_func(void) { } *instrument_previous_pc_addr = instrument_hash_zero; - return ret; } @@ -190,7 +182,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { -(GUM_RED_ZONE_SIZE)); gum_x86_writer_put_call_address_with_arguments( cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); - gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, (GUM_RED_ZONE_SIZE)); @@ -235,7 +226,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) { gum_x86_writer_put_push_reg(cw, GUM_X86_RAX); gum_x86_writer_put_push_reg(cw, GUM_X86_RBX); - gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, + GUM_ADDRESS(&persistent_ret)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP, offset); gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX); @@ -252,70 +244,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) { void persistent_prologue_arch(GumStalkerOutput *output) { /* + * SAVE RET (Used to write the epilogue if persistent_ret is not set) * SAVE REGS - * SAVE RET - * POP RET - * loop: + * loop: (Save address of where the eiplogue should jump back to) * CALL instrument_afl_persistent_loop - * TEST EAX, EAX - * JZ end: - * call hook (optionally) + * CALL hook (optionally) * RESTORE REGS - * call original - * jmp loop: - * - * end: - * JMP SAVED RET - * - * original: * INSTRUMENTED PERSISTENT FUNC */ GumX86Writer *cw = output->writer.x86; - gconstpointer loop = cw->code + 1; - FVERBOSE("Persistent loop reached"); - /* Pop the return value */ - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8); + /* + * If we haven't set persistent_ret, then assume that we are dealing with a + * function and we should loop when that function returns. + */ + if (persistent_ret == 0) { instrument_persitent_save_ret(cw); } + /* Save the current context */ instrument_persitent_save_regs(cw, &saved_regs); - /* loop: */ - gum_x86_writer_put_label(cw, loop); + /* Store a pointer to where we should return for our next iteration */ + persistent_loop = gum_x86_writer_cur(cw); - /* call instrument_prologue_func */ + /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */ instrument_afl_persistent_loop(cw); - /* jz done */ - gconstpointer done = cw->code + 1; - gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY); - /* Optionally call the persistent hook */ persistent_prologue_hook(cw, &saved_regs); + /* Restore our CPU context before we continue execution */ instrument_persitent_restore_regs(cw, &saved_regs); - gconstpointer original = cw->code + 1; - /* call original */ - - gum_x86_writer_put_call_near_label(cw, original); - - /* jmp loop */ - gum_x86_writer_put_jmp_near_label(cw, loop); - - /* done: */ - gum_x86_writer_put_label(cw, done); - - instrument_exit(cw); - - /* original: */ - gum_x86_writer_put_label(cw, original); - - instrument_persitent_save_ret(cw); if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + /* The original instrumented code is emitted here. */ + } void persistent_epilogue_arch(GumStalkerOutput *output) { @@ -331,7 +297,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) { gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8); gum_x86_writer_put_label(cw, zero); - gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, + GUM_ADDRESS(&persistent_loop)); gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX); } diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index e9bde3d2..8950223f 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -16,8 +16,7 @@ typedef struct { } persistent_ctx_t; static persistent_ctx_t saved_regs = {0}; - -static gpointer saved_ret = NULL; +static gpointer persistent_loop = NULL; gboolean persistent_is_supported(void) { @@ -118,18 +117,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw, } -static void instrument_exit(GumX86Writer *cw) { - - gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(_exit)); - gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_EDI, 0); - gum_x86_writer_put_push_reg(cw, GUM_X86_EDI); - gum_x86_writer_put_call_reg(cw, GUM_X86_EAX); - -} +static void instrument_afl_persistent_loop_func(void) { -static int instrument_afl_persistent_loop_func(void) { + if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }; - int ret = __afl_persistent_loop(persistent_count); if (instrument_previous_pc_addr == NULL) { FATAL("instrument_previous_pc_addr uninitialized"); @@ -137,7 +128,6 @@ static int instrument_afl_persistent_loop_func(void) { } *instrument_previous_pc_addr = instrument_hash_zero; - return ret; } @@ -145,7 +135,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { gum_x86_writer_put_call_address_with_arguments( cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); - gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX); } @@ -179,7 +168,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) { gum_x86_writer_put_push_reg(cw, GUM_X86_EAX); gum_x86_writer_put_push_reg(cw, GUM_X86_EBX); - gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret)); + gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, + GUM_ADDRESS(&persistent_ret)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP, offset); gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX); @@ -193,68 +183,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) { void persistent_prologue_arch(GumStalkerOutput *output) { /* + * SAVE RET (Used to write the epilogue if persistent_ret is not set) * SAVE REGS - * SAVE RET - * POP RET - * loop: + * loop: (Save address of where the eiplogue should jump back to) * CALL instrument_afl_persistent_loop - * TEST EAX, EAX - * JZ end: - * call hook (optionally) + * CALL hook (optionally) * RESTORE REGS - * call original - * jmp loop: - * - * end: - * JMP SAVED RET - * - * original: * INSTRUMENTED PERSISTENT FUNC */ GumX86Writer *cw = output->writer.x86; - gconstpointer loop = cw->code + 1; - FVERBOSE("Persistent loop reached"); - /* Pop the return value */ - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4); + /* + * If we haven't set persistent_ret, then assume that we are dealing with a + * function and we should loop when that function returns. + */ + if (persistent_ret == 0) { instrument_persitent_save_ret(cw); } + /* Save the current context */ instrument_persitent_save_regs(cw, &saved_regs); - /* loop: */ - gum_x86_writer_put_label(cw, loop); + /* Store a pointer to where we should return for our next iteration */ + persistent_loop = gum_x86_writer_cur(cw); - /* call instrument_prologue_func */ + /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */ instrument_afl_persistent_loop(cw); - /* jz done */ - gconstpointer done = cw->code + 1; - gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY); - /* Optionally call the persistent hook */ persistent_prologue_hook(cw, &saved_regs); + /* Restore our CPU context before we continue execution */ instrument_persitent_restore_regs(cw, &saved_regs); - gconstpointer original = cw->code + 1; - /* call original */ - gum_x86_writer_put_call_near_label(cw, original); - /* jmp loop */ - gum_x86_writer_put_jmp_near_label(cw, loop); - - /* done: */ - gum_x86_writer_put_label(cw, done); - - instrument_exit(cw); - - /* original: */ - gum_x86_writer_put_label(cw, original); - - instrument_persitent_save_ret(cw); if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + /* The original instrumented code is emitted here. */ + } void persistent_epilogue_arch(GumStalkerOutput *output) { @@ -263,7 +229,12 @@ void persistent_epilogue_arch(GumStalkerOutput *output) { if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } - gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret)); + /* The stack should be aligned when we re-enter our loop */ + gum_x86_writer_put_and_reg_u32(cw, GUM_X86_ESP, 0xfffffff0); + gum_x86_writer_put_sub_reg_imm(cw, GUM_X86_ESP, 0x4); + + gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, + GUM_ADDRESS(&persistent_loop)); gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX); } diff --git a/frida_mode/src/util.c b/frida_mode/src/util.c index 90c10917..1843a78b 100644 --- a/frida_mode/src/util.c +++ b/frida_mode/src/util.c @@ -110,7 +110,11 @@ gboolean util_verbose_enabled(void) { if (!initialized) { initialized = TRUE; - if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; } + if (getenv("AFL_FRIDA_VERBOSE") || getenv("AFL_DEBUG")) { + + util_verbose = TRUE; + + } } diff --git a/frida_mode/test/cache/cache.c b/frida_mode/test/cache/cache.c index b4102205..6ee8bf01 100644 --- a/frida_mode/test/cache/cache.c +++ b/frida_mode/test/cache/cache.c @@ -6,46 +6,45 @@ 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" -); +__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; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/cmov/cmov.c b/frida_mode/test/cmov/cmov.c index 08c7c132..97f2fb7f 100644 --- a/frida_mode/test/cmov/cmov.c +++ b/frida_mode/test/cmov/cmov.c @@ -6,8 +6,8 @@ static bool cmov_test(char *x, char *y, size_t len) { - register char * __rdi __asm__("rdi") = x; - register char * __rsi __asm__("rsi") = y; + register char *__rdi __asm__("rdi") = x; + register char *__rsi __asm__("rsi") = y; register size_t __rcx __asm__("rcx") = len; register long __rax __asm__("rax"); @@ -49,10 +49,10 @@ void LLVMFuzzerTestOneInput(char *buf, int len) { int main(int argc, char **argv) { - char * file; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c index 4e5124ed..2bd1d718 100644 --- a/frida_mode/test/deferred/testinstr.c +++ b/frida_mode/test/deferred/testinstr.c @@ -41,7 +41,7 @@ int run(char *file) { int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; @@ -51,6 +51,7 @@ int run(char *file) { fd = open(file, O_RDONLY); if (fd < 0) { + perror("open"); break; @@ -110,8 +111,10 @@ void slow() { } -TESTINSTR_SECTION int do_run(char * file) { +TESTINSTR_SECTION int do_run(char *file) { + return run(file); + } int main(int argc, char **argv) { diff --git a/frida_mode/test/dynamic/testinstr.c b/frida_mode/test/dynamic/testinstr.c index 0abc61fd..55bf579e 100644 --- a/frida_mode/test/dynamic/testinstr.c +++ b/frida_mode/test/dynamic/testinstr.c @@ -19,32 +19,40 @@ 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; + + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; if (argc != 2) { return 1; } do { + file = argv[1]; printf("file: %s\n", file); @@ -52,33 +60,43 @@ int main(int argc, char **argv) { 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); @@ -95,4 +113,6 @@ int main(int argc, char **argv) { if (fd != -1) { close(fd); } return result; + } + diff --git a/frida_mode/test/dynamic/testinstrlib.c b/frida_mode/test/dynamic/testinstrlib.c index 987cbf91..85e2c837 100644 --- a/frida_mode/test/dynamic/testinstrlib.c +++ b/frida_mode/test/dynamic/testinstrlib.c @@ -1,6 +1,7 @@ #include <stdio.h> void testinstrlib(char *buf, int len) { + if (len < 1) return; buf[len] = 0; @@ -11,4 +12,6 @@ void testinstrlib(char *buf, int len) { printf("Pretty sure that is a one!\n"); else printf("Neither one or zero? How quaint!\n"); + } + diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c index 75e71bda..5fe17165 100644 --- a/frida_mode/test/entry_point/testinstr.c +++ b/frida_mode/test/entry_point/testinstr.c @@ -41,7 +41,7 @@ int run(char *file) { int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c index 7b603659..8b99352e 100644 --- a/frida_mode/test/exe/testinstr.c +++ b/frida_mode/test/exe/testinstr.c @@ -39,10 +39,10 @@ void testinstr(char *buf, int len) { TESTINSTR_SECTION int main(int argc, char **argv) { - char * file; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/js/test.c b/frida_mode/test/js/test.c index 9799bf3b..e233f13a 100644 --- a/frida_mode/test/js/test.c +++ b/frida_mode/test/js/test.c @@ -35,7 +35,7 @@ int run(char *file) { int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/js/test2.c b/frida_mode/test/js/test2.c index 60b30eb5..c3557bbf 100644 --- a/frida_mode/test/js/test2.c +++ b/frida_mode/test/js/test2.c @@ -22,60 +22,60 @@ #define IGNORED_RETURN(x) (void)!(x) const uint32_t crc32_tab[] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -uint32_t -crc32(const void *buf, size_t size) -{ - const uint8_t *p = buf; - uint32_t crc; - crc = ~0U; - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - return crc ^ ~0U; + + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + +uint32_t crc32(const void *buf, size_t size) { + + const uint8_t *p = buf; + uint32_t crc; + crc = ~0U; + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + return crc ^ ~0U; + } /* @@ -83,11 +83,13 @@ crc32(const void *buf, size_t size) * FRIDA to patch this function out and always return success. Otherwise, we * could change it to actually correct the checksum. */ -int crc32_check (char * buf, int len) { +int crc32_check(char *buf, int len) { + if (len < sizeof(uint32_t)) { return 0; } uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)]; uint32_t calculated = crc32(buf, len - sizeof(uint32_t)); return expected == calculated; + } /* @@ -97,27 +99,31 @@ int crc32_check (char * buf, int len) { * cloud your output unnecessarily. Again, we can use FRIDA to patch it out. */ void some_boring_bug(char c) { + switch (c) { - case 'A'...'Z': - case 'a'...'z': + + case 'A' ... 'Z': + case 'a' ... 'z': __builtin_trap(); break; + } + } extern void some_boring_bug2(char c); -__asm__ ( - ".text \n" - "some_boring_bug2: \n" - ".global some_boring_bug2 \n" - ".type some_boring_bug2, @function \n" - "mov %edi, %eax \n" - "cmp $0xb4, %al \n" - "jne ok \n" - "ud2 \n" - "ok: \n" - "ret \n"); +__asm__( + ".text \n" + "some_boring_bug2: \n" + ".global some_boring_bug2 \n" + ".type some_boring_bug2, @function \n" + "mov %edi, %eax \n" + "cmp $0xb4, %al \n" + "jne ok \n" + "ud2 \n" + "ok: \n" + "ret \n"); void LLVMFuzzerTestOneInput(char *buf, int len) { @@ -127,16 +133,20 @@ void LLVMFuzzerTestOneInput(char *buf, int len) { some_boring_bug2(buf[0]); if (buf[0] == '0') { + printf("Looks like a zero to me!\n"); - } - else if (buf[0] == '1') { + + } else if (buf[0] == '1') { + printf("Pretty sure that is a one!\n"); - } - else if (buf[0] == '2') { + + } else if (buf[0] == '2') { + printf("Oh we, weren't expecting that!"); __builtin_trap(); - } - else + + } else + printf("Neither one or zero? How quaint!\n"); } @@ -145,7 +155,7 @@ int main(int argc, char **argv) { int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; @@ -173,5 +183,6 @@ int main(int argc, char **argv) { printf("Done: %s: (%zd bytes)\n", argv[1], n_read); return 0; + } diff --git a/frida_mode/test/osx-lib/harness.c b/frida_mode/test/osx-lib/harness.c index 3d427b4a..186cfcee 100644 --- a/frida_mode/test/osx-lib/harness.c +++ b/frida_mode/test/osx-lib/harness.c @@ -4,66 +4,68 @@ #include <stdlib.h> #include <dlfcn.h> - -//typedef for our exported target function. +// typedef for our exported target function. typedef void (*CRASHME)(const uint8_t *Data, size_t Size); -//globals +// globals CRASHME fpn_crashme = NULL; +int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { + + fpn_crashme(data, size); + return 0; -int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){ - fpn_crashme(data, size); - return 0; } -int main(int argc, const char * argv[]) -{ - - for (int i = 1; i < argc; i++) { - fprintf(stderr, "Running: %s\n", argv[i]); - FILE *f = fopen(argv[i], "r"); - assert(f); - fseek(f, 0, SEEK_END); - size_t len = ftell(f); - fseek(f, 0, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(len); - size_t n_read = fread(buf, 1, len, f); - fclose(f); - assert(n_read == len); - LLVMFuzzerTestOneInput(buf, len); - free(buf); - fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); - } - - return 0; +int main(int argc, const char *argv[]) { + + for (int i = 1; i < argc; i++) { + + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char *)malloc(len); + size_t n_read = fread(buf, 1, len, f); + fclose(f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + + } + + return 0; + } -__attribute__((constructor())) -void constructor(void) { - // handles to required libs - void *dylib = NULL; +__attribute__((constructor())) void constructor(void) { + + // handles to required libs + void *dylib = NULL; - dylib = dlopen("./libcrashme.dylib", RTLD_NOW); - if (dylib == NULL) - { + dylib = dlopen("./libcrashme.dylib", RTLD_NOW); + if (dylib == NULL) { - printf("[-] Failed to load lib\n"); - printf("[-] Dlerror: %s\n", dlerror()); - exit(1); + printf("[-] Failed to load lib\n"); + printf("[-] Dlerror: %s\n", dlerror()); + exit(1); - } + } - printf("[+] Resolve function\n"); + printf("[+] Resolve function\n"); - fpn_crashme = (CRASHME)dlsym(dylib, "crashme"); - if (!fpn_crashme) - { + fpn_crashme = (CRASHME)dlsym(dylib, "crashme"); + if (!fpn_crashme) { - printf("[-] Failed to find function\n"); - exit(1); + printf("[-] Failed to find function\n"); + exit(1); - } + } + + printf("[+] Found function.\n"); - printf("[+] Found function.\n"); } + diff --git a/frida_mode/test/osx-lib/harness2.c b/frida_mode/test/osx-lib/harness2.c index 464614ee..ed0b85d8 100644 --- a/frida_mode/test/osx-lib/harness2.c +++ b/frida_mode/test/osx-lib/harness2.c @@ -4,66 +4,68 @@ #include <stdlib.h> #include <dlfcn.h> - -//typedef for our exported target function. +// typedef for our exported target function. typedef void (*CRASHME)(const uint8_t *Data, size_t Size); -//globals +// globals CRASHME fpn_crashme = NULL; +int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { + + fpn_crashme(data, size); + return 0; -int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){ - fpn_crashme(data, size); - return 0; } -int main(int argc, const char * argv[]) -{ - - for (int i = 1; i < argc; i++) { - fprintf(stderr, "Running: %s\n", argv[i]); - FILE *f = fopen(argv[i], "r"); - assert(f); - fseek(f, 0, SEEK_END); - size_t len = ftell(f); - fseek(f, 0, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(len); - size_t n_read = fread(buf, 1, len, f); - fclose(f); - assert(n_read == len); - LLVMFuzzerTestOneInput(buf, len); - free(buf); - fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); - } - - return 0; +int main(int argc, const char *argv[]) { + + for (int i = 1; i < argc; i++) { + + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char *)malloc(len); + size_t n_read = fread(buf, 1, len, f); + fclose(f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + + } + + return 0; + } -__attribute__((constructor())) -void constructor(void) { - // handles to required libs - void *dylib = NULL; +__attribute__((constructor())) void constructor(void) { + + // handles to required libs + void *dylib = NULL; - dylib = dlopen("./libcrashme2.dylib", RTLD_NOW); - if (dylib == NULL) - { + dylib = dlopen("./libcrashme2.dylib", RTLD_NOW); + if (dylib == NULL) { - printf("[-] Failed to load lib\n"); - printf("[-] Dlerror: %s\n", dlerror()); - exit(1); + printf("[-] Failed to load lib\n"); + printf("[-] Dlerror: %s\n", dlerror()); + exit(1); - } + } - printf("[+] Resolve function\n"); + printf("[+] Resolve function\n"); - fpn_crashme = (CRASHME)dlsym(dylib, "crashme"); - if (!fpn_crashme) - { + fpn_crashme = (CRASHME)dlsym(dylib, "crashme"); + if (!fpn_crashme) { - printf("[-] Failed to find function\n"); - exit(1); + printf("[-] Failed to find function\n"); + exit(1); - } + } + + printf("[+] Found function.\n"); - printf("[+] Found function.\n"); } + diff --git a/frida_mode/test/osx-lib/harness3.c b/frida_mode/test/osx-lib/harness3.c index 83983c99..ae24db33 100644 --- a/frida_mode/test/osx-lib/harness3.c +++ b/frida_mode/test/osx-lib/harness3.c @@ -4,37 +4,42 @@ #include <stdlib.h> #include <dlfcn.h> - extern void crashme(const uint8_t *Data, size_t Size); -int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){ - crashme(data, size); - return 0; +int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { + + crashme(data, size); + return 0; + } -void run (int argc, const char * argv[]) -{ - for (int i = 1; i < argc; i++) { - fprintf(stderr, "Running: %s\n", argv[i]); - FILE *f = fopen(argv[i], "r"); - assert(f); - fseek(f, 0, SEEK_END); - size_t len = ftell(f); - fseek(f, 0, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(len); - size_t n_read = fread(buf, 1, len, f); - fclose(f); - assert(n_read == len); - LLVMFuzzerTestOneInput(buf, len); - free(buf); - fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); - } +void run(int argc, const char *argv[]) { + + for (int i = 1; i < argc; i++) { + + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char *)malloc(len); + size_t n_read = fread(buf, 1, len, f); + fclose(f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + + } + } -int main(int argc, const char * argv[]) -{ +int main(int argc, const char *argv[]) { - run(argc, argv); + run(argc, argv); + + return 0; - return 0; } + diff --git a/frida_mode/test/osx-lib/lib.c b/frida_mode/test/osx-lib/lib.c index b2dad098..84ceb9da 100644 --- a/frida_mode/test/osx-lib/lib.c +++ b/frida_mode/test/osx-lib/lib.c @@ -2,7 +2,6 @@ #include <stdlib.h> #include <stdint.h> - void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { if (Size < 5) return; @@ -13,5 +12,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { if (Data[3] == '$') if (Data[4] == '$') abort(); - } + diff --git a/frida_mode/test/osx-lib/lib2.c b/frida_mode/test/osx-lib/lib2.c index ba207210..a84ee6f2 100644 --- a/frida_mode/test/osx-lib/lib2.c +++ b/frida_mode/test/osx-lib/lib2.c @@ -3,7 +3,6 @@ #include <stdint.h> #include <string.h> - void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { if (Size < 1) return; @@ -56,6 +55,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { } - } diff --git a/frida_mode/test/output/testinstr.c b/frida_mode/test/output/testinstr.c index 7b603659..8b99352e 100644 --- a/frida_mode/test/output/testinstr.c +++ b/frida_mode/test/output/testinstr.c @@ -39,10 +39,10 @@ void testinstr(char *buf, int len) { TESTINSTR_SECTION int main(int argc, char **argv) { - char * file; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/perf/perf.c b/frida_mode/test/perf/perf.c index 55efba26..596d1bd3 100644 --- a/frida_mode/test/perf/perf.c +++ b/frida_mode/test/perf/perf.c @@ -20,22 +20,32 @@ void LLVMFuzzerTestOneInput(char *buf, int len) { int ret = 0; for (int i = 0; i < 1000; i++) { - switch(buf[i]) { - case 'A': ret += 2; break; - case '1': ret += 3; break; - default: ret++; + + switch (buf[i]) { + + case 'A': + ret += 2; + break; + case '1': + ret += 3; + break; + default: + ret++; + } + } + printf("ret: %d\n", ret); } int main(int argc, char **argv) { - char * file; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c index 85aa2b80..aa28d953 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -18,7 +18,7 @@ void LLVMFuzzerTestOneInput(char *buf, int len) { - printf (">>> LLVMFuzzerTestOneInput >>>\n"); + printf(">>> LLVMFuzzerTestOneInput >>>\n"); if (len < 1) return; buf[len] = 0; @@ -40,10 +40,10 @@ void slow() { int main(int argc, char **argv) { - char * file; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile index eccc66f6..4a023a5d 100644 --- a/frida_mode/test/png/GNUmakefile +++ b/frida_mode/test/png/GNUmakefile @@ -48,7 +48,7 @@ all: $(TEST_BIN) CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN) arm: - CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN) + CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" PNG_ARCH="arm" make $(TEST_BIN) $(BUILD_DIR): mkdir -p $@ @@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR) cd $(LIBZ_DIR) && \ CFLAGS="$(CFLAGS) -fPIC" \ ./configure \ - --static \ - --archs="$(ARCH)" + --static $(LIBZ_LIB): | $(LIBZ_PC) CFLAGS="$(CFLAGS) -fPIC" \ @@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR) CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \ LDFLAGS="-L$(LIBZ_DIR)" \ ./configure \ - --host="$(ARCH)" + --host="$(PNG_ARCH)" $(LIBPNG_LIB): $(LIBPNG_MAKEFILE) CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \ diff --git a/frida_mode/test/testinstr/testinstr.c b/frida_mode/test/testinstr/testinstr.c index 7b603659..8b99352e 100644 --- a/frida_mode/test/testinstr/testinstr.c +++ b/frida_mode/test/testinstr/testinstr.c @@ -39,10 +39,10 @@ void testinstr(char *buf, int len) { TESTINSTR_SECTION int main(int argc, char **argv) { - char * file; + char *file; int fd = -1; off_t len; - char * buf = NULL; + char *buf = NULL; size_t n_read; int result = -1; diff --git a/frida_mode/test/unstable/unstable.c b/frida_mode/test/unstable/unstable.c index 16978e7e..98198578 100644 --- a/frida_mode/test/unstable/unstable.c +++ b/frida_mode/test/unstable/unstable.c @@ -22,7 +22,7 @@ #define TESTINSTR_SECTION __attribute__((section(".testinstr"))) #endif -void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { +void LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { if (size < 1) return; @@ -30,9 +30,13 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (gettimeofday(&tv, NULL) < 0) return; if ((tv.tv_usec % 2) == 0) { - printf ("Hooray all even\n"); + + printf("Hooray all even\n"); + } else { - printf ("Hmm that's odd\n"); + + printf("Hmm that's odd\n"); + } // we support three input cases @@ -45,26 +49,33 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { } -void run_test(char * file) { +void run_test(char *file) { + fprintf(stderr, "Running: %s\n", file); FILE *f = fopen(file, "r"); assert(f); fseek(f, 0, SEEK_END); size_t len = ftell(f); fseek(f, 0, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(len); - size_t n_read = fread(buf, 1, len, f); + unsigned char *buf = (unsigned char *)malloc(len); + size_t n_read = fread(buf, 1, len, f); fclose(f); assert(n_read == len); LLVMFuzzerTestOneInput(buf, len); free(buf); fprintf(stderr, "Done: %s: (%zd bytes)\n", file, n_read); + } int main(int argc, char **argv) { + srand(1); fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); for (int i = 1; i < argc; i++) { + run_test(argv[i]); + } + } + diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e3e4e246..0f0e45d3 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -116,6 +116,10 @@ #include <TargetConditionals.h> #endif +#ifndef __has_builtin + #define __has_builtin(x) 0 +#endif + #undef LIST_FOREACH /* clashes with FreeBSD */ #include "list.h" #ifndef SIMPLE_FILES @@ -236,7 +240,6 @@ struct queue_entry { custom, /* Marker for custom mutators */ stats_mutated; /* stats: # of mutations performed */ - u8 *trace_mini; /* Trace bytes, if kept */ u32 tc_ref; /* Trace bytes ref count */ #ifdef INTROSPECTION @@ -246,13 +249,11 @@ struct queue_entry { double perf_score, /* performance score */ weight; - u8 *testcase_buf; /* The testcase buffer, if loaded. */ - - u8 *cmplog_colorinput; /* the result buf of colorization */ - struct tainted *taint; /* Taint information from CmpLog */ - - struct queue_entry *mother; /* queue entry this based on */ - + struct queue_entry *mother; /* queue entry this based on */ + u8 *trace_mini; /* Trace bytes, if kept */ + u8 *testcase_buf; /* The testcase buffer, if loaded. */ + u8 *cmplog_colorinput; /* the result buf of colorization */ + struct tainted *taint; /* Taint information from CmpLog */ struct skipdet_entry *skipdet_e; }; @@ -448,8 +449,9 @@ extern char *power_names[POWER_SCHEDULES_NUM]; typedef struct afl_env_vars { u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check, - afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui, - afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, + afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, + afl_custom_mutator_late_send, afl_no_ui, afl_force_ui, + afl_i_dont_care_about_missing_crashes, afl_bench_just_one, afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, @@ -457,7 +459,7 @@ typedef struct afl_env_vars { afl_no_startup_calibration, afl_no_warn_instability, afl_post_process_keep_original, afl_crashing_seeds_as_new_crash, afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant, - afl_sha1_filenames, afl_no_sync; + afl_sha1_filenames, afl_no_sync, afl_no_fastresume; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, diff --git a/include/cmplog.h b/include/cmplog.h index a4449a60..9f995da6 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -53,21 +53,24 @@ struct cmp_header { // 16 bit = 2 bytes struct cmp_operands { u64 v0; - u64 v1; u64 v0_128; + u64 v0_256_0; // u256 is unsupported by any compiler for now, so future use + u64 v0_256_1; + u64 v1; u64 v1_128; - u64 unused; - u8 unused1; - u8 unused2; + u64 v1_256_0; + u64 v1_256_1; + u8 unused[8]; } __attribute__((packed)); struct cmpfn_operands { u8 v0[32]; - u8 v0_len; u8 v1[32]; + u8 v0_len; u8 v1_len; + u8 unused[6]; } __attribute__((packed)); diff --git a/include/config.h b/include/config.h index c4acf8db..d8177a75 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.21c" +#define VERSION "++4.22a" /****************************************************** * * diff --git a/include/debug.h b/include/debug.h index 5496135c..e7cbdb5c 100644 --- a/include/debug.h +++ b/include/debug.h @@ -314,8 +314,8 @@ static inline const char *colorfilter(const char *x) { #define FATAL(x...) \ do { \ \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] PROGRAM ABORT : " cRST x); \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ + "\n[-] PROGRAM ABORT : " cRST x); \ SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \ __FILE__, (u32)__LINE__); \ exit(1); \ @@ -327,8 +327,8 @@ static inline const char *colorfilter(const char *x) { #define ABORT(x...) \ do { \ \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] PROGRAM ABORT : " cRST x); \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ + "\n[-] PROGRAM ABORT : " cRST x); \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \ __FILE__, (u32)__LINE__); \ abort(); \ @@ -341,8 +341,8 @@ static inline const char *colorfilter(const char *x) { do { \ \ fflush(stdout); \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] SYSTEM ERROR : " cRST x); \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ + "\n[-] SYSTEM ERROR : " cRST x); \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \ __FILE__, (u32)__LINE__); \ SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ diff --git a/include/envs.h b/include/envs.h index 45b080cb..3accbda0 100644 --- a/include/envs.h +++ b/include/envs.h @@ -24,23 +24,23 @@ static char *afl_environment_variables[] = { "AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", - "AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV", - "AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX", - "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", - "AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", - "AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", - "AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", - "AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", - "AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", - "AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", + "AFL_CUSTOM_MUTATOR_LATE_SEND", "AFL_CUSTOM_INFO_PROGRAM", + "AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT", + "AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", + "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", + "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", "AFL_DISABLE_TRIM", + "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE", + "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV", + "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE", + "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL", + "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE", "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE", "AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", - "AFL_FRIDA_INST_NO_SUPPRESS" - "AFL_FRIDA_INST_RANGES", + "AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES", "AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE", "AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE", "AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR", @@ -49,7 +49,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS", "AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH", "AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE", - "AFL_FRIDA_VERBOSE", + "AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER", "AFL_FUZZER_ARGS", // oss-fuzz "AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST", "AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE", @@ -115,7 +115,8 @@ static char *afl_environment_variables[] = { "AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", - "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL + "AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", + "AFL_NO_FASTRESUME", NULL }; diff --git a/include/forkserver.h b/include/forkserver.h index 593e34a2..6c649528 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -206,6 +206,15 @@ typedef struct afl_forkserver { s32 nyx_log_fd; #endif +#ifdef __AFL_CODE_COVERAGE + u8 *persistent_trace_bits; /* Persistent copy of bitmap */ +#endif + + void *custom_data_ptr; + u8 *custom_input; + u32 custom_input_len; + void (*late_send)(void *, const u8 *, size_t); + } afl_forkserver_t; typedef enum fsrv_run_result { diff --git a/include/t1ha_bits.h b/include/t1ha_bits.h index 0b9bbda5..9ddc8589 100644 --- a/include/t1ha_bits.h +++ b/include/t1ha_bits.h @@ -455,9 +455,10 @@ typedef struct { } __attribute__((__packed__)) t1ha_unaligned_proxy; - #define read_unaligned(ptr, bits) \ - (((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \ - t1ha_unaligned_proxy, unaligned_##bits))) \ + #define read_unaligned(ptr, bits) \ + (((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr) - \ + offsetof(t1ha_unaligned_proxy, \ + unaligned_##bits))) \ ->unaligned_##bits) #elif defined(_MSC_VER) #pragma warning( \ @@ -477,9 +478,10 @@ typedef struct { } t1ha_unaligned_proxy; #pragma pack(pop) - #define read_unaligned(ptr, bits) \ - (((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \ - t1ha_unaligned_proxy, unaligned_##bits))) \ + #define read_unaligned(ptr, bits) \ + (((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr) - \ + offsetof(t1ha_unaligned_proxy, \ + unaligned_##bits))) \ ->unaligned_##bits) #endif #endif /* read_unaligned */ @@ -496,21 +498,24 @@ typedef struct { #elif __has_attribute(__assume_aligned__) static __always_inline const uint16_t *__attribute__(( - __assume_aligned__(ALIGNMENT_16))) cast_aligned_16(const void *ptr) { + __assume_aligned__(ALIGNMENT_16))) +cast_aligned_16(const void *ptr) { return (const uint16_t *)ptr; } static __always_inline const uint32_t *__attribute__(( - __assume_aligned__(ALIGNMENT_32))) cast_aligned_32(const void *ptr) { + __assume_aligned__(ALIGNMENT_32))) +cast_aligned_32(const void *ptr) { return (const uint32_t *)ptr; } static __always_inline const uint64_t *__attribute__(( - __assume_aligned__(ALIGNMENT_64))) cast_aligned_64(const void *ptr) { + __assume_aligned__(ALIGNMENT_64))) +cast_aligned_64(const void *ptr) { return (const uint64_t *)ptr; diff --git a/include/types.h b/include/types.h index cfb2f3d5..d370bcfb 100644 --- a/include/types.h +++ b/include/types.h @@ -155,7 +155,7 @@ typedef int128_t s128; ({ \ \ char *d = (char *)(_x), *s = (char *)(_y); \ - u32 i, l = (_l)-1; \ + u32 i, l = (_l) - 1; \ for (i = 0; i <= l; i++) \ d[l - i] = s[i]; \ \ diff --git a/include/xxhash.h b/include/xxhash.h index 991a8f1e..72044177 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -6616,12 +6616,14 @@ static XXH64_hash_t XXH3_mergeAccs(const xxh_u64 *XXH_RESTRICT acc, } - #define XXH3_INIT_ACC \ - { \ - \ - XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ - XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 \ - \ + #define XXH3_INIT_ACC \ + { \ + \ + \ + XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, \ + XXH_PRIME64_3, XXH_PRIME64_4, XXH_PRIME32_2, \ + XXH_PRIME64_5, XXH_PRIME32_1 \ + \ } XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_internal( diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index a09f28a9..63ea71c1 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -214,8 +214,12 @@ class ModuleSanitizerCoverageLTO void SetNoSanitizeMetadata(Instruction *I) { +#if LLVM_VERSION_MAJOR >= 19 + I->setNoSanitizeMetadata(); +#else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), MDNode::get(*C, None)); +#endif } @@ -225,7 +229,7 @@ class ModuleSanitizerCoverageLTO FunctionCallee SanCovTracePCIndir; FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -416,6 +420,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + PtrTy = PointerType::getUnqual(*C); /* AFL++ START */ char *ptr; @@ -1350,7 +1355,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) { if (F.empty()) return; - if (F.getName().find(".module_ctor") != std::string::npos) + if (F.getName().contains(".module_ctor")) return; // Should not instrument sanitizer init functions. #if LLVM_VERSION_MAJOR >= 18 if (F.getName().starts_with("__sanitizer_")) @@ -1372,6 +1377,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction( if (F.hasPersonalityFn() && isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; + if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; +#if LLVM_VERSION_MAJOR >= 19 + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; +#endif // if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName())) // return; // if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName())) @@ -2023,16 +2032,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray( if (&F.getEntryBlock() == AllBlocks[i]) { - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy)); + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy)); } else { PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); + BlockAddress::get(AllBlocks[i]), PtrTy)); +#if LLVM_VERSION_MAJOR >= 16 + PCs.push_back(Constant::getNullValue(PtrTy)); +#else + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy)); +#endif } diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 01881f28..49fe904b 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -161,7 +161,9 @@ class ModuleSanitizerCoverageAFL void SetNoSanitizeMetadata(Instruction *I) { -#if LLVM_VERSION_MAJOR >= 16 +#if LLVM_VERSION_MAJOR >= 19 + I->setNoSanitizeMetadata(); +#elif LLVM_VERSION_MAJOR >= 16 I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt)); #else I->setMetadata(I->getModule()->getMDKindID("nosanitize"), @@ -179,7 +181,7 @@ class ModuleSanitizerCoverageAFL FunctionCallee SanCovTraceSwitchFunction; GlobalVariable *SanCovLowestStack; Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy, - *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy; + *Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy; Module *CurModule; std::string CurModuleUniqueId; Triple TargetTriple; @@ -272,13 +274,19 @@ std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd( if (!TargetTriple.isOSBinFormatCOFF()) return std::make_pair(SecStart, SecEnd); - // Account for the fact that on windows-msvc __start_* symbols actually - // point to a uint64_t before the start of the array. + // Account for the fact that on windows-msvc __start_* symbols actually + // point to a uint64_t before the start of the array. +#if LLVM_VERSION_MAJOR >= 19 + auto GEP = + IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t))); + return std::make_pair(GEP, SecEnd); +#else auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy); auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr, ConstantInt::get(IntptrTy, sizeof(uint64_t))); return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)), SecEnd); +#endif } @@ -370,6 +378,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule( Int16Ty = IRB.getInt16Ty(); Int8Ty = IRB.getInt8Ty(); Int1Ty = IRB.getInt1Ty(); + PtrTy = PointerType::getUnqual(*C); LLVMContext &Ctx = M.getContext(); AFLMapPtr = @@ -572,7 +581,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( if (F.empty()) return; if (!isInInstrumentList(&F, FMNAME)) return; - if (F.getName().find(".module_ctor") != std::string::npos) + // if (F.getName().find(".module_ctor") != std::string::npos) + if (F.getName().contains(".module_ctor")) return; // Should not instrument sanitizer init functions. #if LLVM_VERSION_MAJOR >= 18 if (F.getName().starts_with("__sanitizer_")) @@ -595,6 +605,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction( isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) return; if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return; +#if LLVM_VERSION_MAJOR >= 19 + if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return; +#endif if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge) SplitAllCriticalEdges( F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests()); @@ -692,16 +705,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( if (&F.getEntryBlock() == AllBlocks[i]) { - PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy)); - PCs.push_back((Constant *)IRB.CreateIntToPtr( - ConstantInt::get(IntptrTy, 1), IntptrPtrTy)); + PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy)); + PCs.push_back( + (Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy)); } else { PCs.push_back((Constant *)IRB.CreatePointerCast( - BlockAddress::get(AllBlocks[i]), IntptrPtrTy)); + BlockAddress::get(AllBlocks[i]), PtrTy)); #if LLVM_VERSION_MAJOR >= 16 - PCs.push_back(Constant::getNullValue(IntptrPtrTy)); + PCs.push_back(Constant::getNullValue(PtrTy)); #else PCs.push_back((Constant *)IRB.CreateIntToPtr( ConstantInt::get(IntptrTy, 0), IntptrPtrTy)); @@ -711,10 +724,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray( } - auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy, - SanCovPCsSectionName); + auto *PCArray = + CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName); PCArray->setInitializer( - ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs)); + ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs)); PCArray->setConstant(true); return PCArray; @@ -822,7 +835,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage( StringRef FuncName = Callee->getName(); if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue; +#if LLVM_VERSION_MAJOR >= 20 + // test canary + InstrumentationIRBuilder IRB(callInst); +#else IRBuilder<> IRB(callInst); +#endif if (!FunctionGuardArray) { diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index c08e6380..0da689b2 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -118,6 +118,7 @@ u32 __afl_map_size = MAP_SIZE; u32 __afl_dictionary_len; u64 __afl_map_addr; u32 __afl_first_final_loc; +u32 __afl_old_forkserver; #ifdef __AFL_CODE_COVERAGE typedef struct afl_module_info_t afl_module_info_t; @@ -616,7 +617,7 @@ static void __afl_map_shm(void) { fprintf(stderr, "DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, " "__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE " - "%u, __afl_final_loc %u, __afl_map_size %u", + "%u, __afl_final_loc %u, __afl_map_size %u\n", id_str == NULL ? "<null>" : id_str, __afl_area_ptr, __afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE, __afl_final_loc, __afl_map_size); @@ -856,7 +857,7 @@ static void __afl_start_forkserver(void) { signal(SIGTERM, at_exit); u32 already_read_first = 0; - u32 was_killed; + u32 was_killed = 0; u32 version = 0x41464c00 + FS_NEW_VERSION_MAX; u32 tmp = version ^ 0xffffffff, status2, status = version; u8 *msg = (u8 *)&status; @@ -866,75 +867,95 @@ static void __afl_start_forkserver(void) { void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); - /* Phone home and tell the parent that we're OK. If parent isn't there, - assume we're not running in forkserver mode and just execute program. */ + if (getenv("AFL_OLD_FORKSERVER")) { - // return because possible non-forkserver usage - if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; } + __afl_old_forkserver = 1; + status = 0; - if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); } - if (tmp != status2) { + if (__afl_final_loc > MAP_SIZE) { - write_error("wrong forkserver message from AFL++ tool"); - _exit(1); + fprintf(stderr, + "Warning: AFL_OLD_FORKSERVER is used with a target compiled with " + "non-colliding coverage instead of AFL_LLVM_INSTRUMENT=CLASSIC - " + "this target may crash!\n"); + + } } - // send the set/requested options to forkserver - status = FS_NEW_OPT_MAPSIZE; // we always send the map size - if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; } - if (__afl_dictionary_len && __afl_dictionary) { + /* Phone home and tell the parent that we're OK. If parent isn't there, + assume we're not running in forkserver mode and just execute program. */ - status |= FS_NEW_OPT_AUTODICT; + if (!__afl_old_forkserver) { - } + // return because possible non-forkserver usage + if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; } - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); } + if (tmp != status2) { - // Now send the parameters for the set options, increasing by option number + write_error("wrong forkserver message from AFL++ tool"); + _exit(1); - // FS_NEW_OPT_MAPSIZE - we always send the map size - status = __afl_map_size; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + } - // FS_NEW_OPT_SHDMEM_FUZZ - no data + // send the set/requested options to forkserver + status = FS_NEW_OPT_MAPSIZE; // we always send the map size + if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; } + if (__afl_dictionary_len && __afl_dictionary) { - // FS_NEW_OPT_AUTODICT - send autodictionary - if (__afl_dictionary_len && __afl_dictionary) { + status |= FS_NEW_OPT_AUTODICT; - // pass the dictionary through the forkserver FD - u32 len = __afl_dictionary_len, offset = 0; + } - if (write(FORKSRV_FD + 1, &len, 4) != 4) { + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - write(2, "Error: could not send dictionary len\n", - strlen("Error: could not send dictionary len\n")); - _exit(1); + // Now send the parameters for the set options, increasing by option number - } + // FS_NEW_OPT_MAPSIZE - we always send the map size + status = __afl_map_size; + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + + // FS_NEW_OPT_SHDMEM_FUZZ - no data - while (len != 0) { + // FS_NEW_OPT_AUTODICT - send autodictionary + if (__afl_dictionary_len && __afl_dictionary) { - s32 ret; - ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + // pass the dictionary through the forkserver FD + u32 len = __afl_dictionary_len, offset = 0; - if (ret < 1) { + if (write(FORKSRV_FD + 1, &len, 4) != 4) { - write_error("could not send dictionary"); + write(2, "Error: could not send dictionary len\n", + strlen("Error: could not send dictionary len\n")); _exit(1); } - len -= ret; - offset += ret; + while (len != 0) { + + s32 ret; + ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + + if (ret < 1) { + + write_error("could not send dictionary"); + _exit(1); + + } + + len -= ret; + offset += ret; + + } } - } + // send welcome message as final message + status = version; + if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } - // send welcome message as final message - status = version; - if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); } + } // END forkserver handshake @@ -948,13 +969,13 @@ static void __afl_start_forkserver(void) { /* Wait for parent by reading from the pipe. Abort if read fails. */ - if (already_read_first) { + if (unlikely(already_read_first)) { already_read_first = 0; } else { - if (read(FORKSRV_FD, &was_killed, 4) != 4) { + if (unlikely(read(FORKSRV_FD, &was_killed, 4) != 4)) { write_error("read from AFL++ tool"); _exit(1); @@ -993,10 +1014,10 @@ static void __afl_start_forkserver(void) { condition and afl-fuzz already issued SIGKILL, write off the old process. */ - if (child_stopped && was_killed) { + if (unlikely(child_stopped && was_killed)) { child_stopped = 0; - if (waitpid(child_pid, &status, 0) < 0) { + if (unlikely(waitpid(child_pid, &status, 0) < 0)) { write_error("child_stopped && was_killed"); _exit(1); @@ -1005,12 +1026,12 @@ static void __afl_start_forkserver(void) { } - if (!child_stopped) { + if (unlikely(!child_stopped)) { /* Once woken up, create a clone of our process. */ child_pid = fork(); - if (child_pid < 0) { + if (unlikely(child_pid < 0)) { write_error("fork"); _exit(1); @@ -1019,7 +1040,7 @@ static void __afl_start_forkserver(void) { /* In child process: close fds, resume execution. */ - if (!child_pid) { + if (unlikely(!child_pid)) { // just to signal afl-fuzz faster //(void)nice(-20); @@ -1044,14 +1065,15 @@ static void __afl_start_forkserver(void) { /* In parent process: write PID to pipe, then wait for child. */ - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { + if (unlikely(write(FORKSRV_FD + 1, &child_pid, 4) != 4)) { write_error("write to afl-fuzz"); _exit(1); } - if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) { + if (unlikely(waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < + 0)) { write_error("waitpid"); _exit(1); @@ -1062,11 +1084,11 @@ static void __afl_start_forkserver(void) { a successful run. In this case, we want to wake it up without forking again. */ - if (WIFSTOPPED(status)) child_stopped = 1; + if (likely(WIFSTOPPED(status))) { child_stopped = 1; } /* Relay wait status to pipe, then loop back. */ - if (write(FORKSRV_FD + 1, &status, 4) != 4) { + if (unlikely(write(FORKSRV_FD + 1, &status, 4) != 4)) { write_error("writing to afl-fuzz"); _exit(1); @@ -2704,7 +2726,7 @@ void __afl_coverage_skip() { // mark this area as especially interesting void __afl_coverage_interesting(u8 val, u32 id) { - __afl_area_ptr[id] = val; + __afl_area_ptr[id % __afl_map_size] = val; } diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index b93f61f0..6559bc84 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -661,6 +661,13 @@ bool AFLdict2filePass::runOnModule(Module &M) { Value *op2 = callInst->getArgOperand(2); ConstantInt *ilen = dyn_cast<ConstantInt>(op2); + if (!ilen) { + + op2 = callInst->getArgOperand(1); + ilen = dyn_cast<ConstantInt>(op2); + + } + if (ilen) { uint64_t literalLength = optLen; diff --git a/nyx_mode/README.md b/nyx_mode/README.md index 7a2a8e6c..a839c157 100644 --- a/nyx_mode/README.md +++ b/nyx_mode/README.md @@ -23,7 +23,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel 2. Additionally, install the following packages: ```shell - apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 + apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 libcapstone-dev ``` 3. As Nyx is written in Rust, install the newest rust compiler (rust packages in @@ -33,7 +33,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` -4. Finally build Nyx mode: +4. Finally build Nyx mode (or use `make distrib` at the repo root to build all AFL++ modes): ```shell ./build_nyx_support.sh @@ -92,7 +92,7 @@ sudo modprobe -r kvm-intel sudo modprobe -r kvm sudo modprobe kvm enable_vmware_backdoor=y sudo modprobe kvm-intel -cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echi OK || echo KVM module problem +cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echo OK || echo KVM module problem ``` All the hard parts are done, fuzzing with Nyx mode is easy - just supply the @@ -186,7 +186,7 @@ make CC=afl-clang-fast CXX=afl-clang-fast++ LD=afl-clang-fast #### Nyx share directories -Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called āshare directoryā to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Both bootstrap scripts use several tools to communicate with the "outer world": +Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called āshare directoryā to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Either of these scripts can be edited to more fully prepare an environment for the target, like transferring configuration files to the target's filesystem. Both bootstrap scripts use several tools to communicate with the "outer world": - `hcat` - this tool copies a given string to the host - `hget` - this program requests a file from the host's share directory diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION index 296745f9..9a62db20 100644 --- a/qemu_mode/QEMUAFL_VERSION +++ b/qemu_mode/QEMUAFL_VERSION @@ -1 +1 @@ -a6f0632a65 +847b43acb1 diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 19336114..4dd4fad2 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -386,6 +386,19 @@ else make -C libqasan CC="$CROSS $CROSS_FLAGS" && echo "[+] libqasan ready" fi +#### Hooking support +if [ "$ENABLE_HOOKING" = "1" ];then + echo "[+] ENABLING HOOKING" + set -e + cd ./hooking_bridge || exit 255 + mkdir -p ./build + echo "[+] Hook compiler = $CROSS" + make CC="$CROSS $CROSS_FLAGS" GLIB_H="$GLIB_H" GLIB_CONFIG_H="$GLIB_CONFIG_H" + set +e + cd .. +fi +#### End of hooking support + echo "[+] All done for qemu_mode, enjoy!" exit 0 diff --git a/qemu_mode/hooking_bridge/Makefile b/qemu_mode/hooking_bridge/Makefile new file mode 100644 index 00000000..dcc6f12a --- /dev/null +++ b/qemu_mode/hooking_bridge/Makefile @@ -0,0 +1,18 @@ +.PHONY: clean + +all: plugin +SRC=./src +BLD=./build +INC=-I./inc -I../qemuafl/include -I$(GLIB_H) -I$(GLIB_CONFIG_H) +# CC=gcc + +$(BLD)/patching.o:$(SRC)/patching.c + $(CC) -c -fPIC $(INC) -o $(BLD)/patching.o $(SRC)/patching.c + +plugin:$(SRC)/main.c $(BLD)/patching.o + $(CC) -c -fPIC $(INC) -o $(BLD)/plugin.o $(SRC)/main.c + $(CC) -shared -o $(BLD)/plugin.so $(BLD)/plugin.o $(BLD)/patching.o + +clean: + rm -rf $(BLD)/*.o + rm -rf $(BLD)/*.so \ No newline at end of file diff --git a/qemu_mode/hooking_bridge/README.md b/qemu_mode/hooking_bridge/README.md new file mode 100644 index 00000000..c6276305 --- /dev/null +++ b/qemu_mode/hooking_bridge/README.md @@ -0,0 +1,96 @@ +# Native hooking support into QEMUAFL +* The essential idea is to have inbuilt hooking support into QEMU, instead of relying on the more expensive options UNICORN and its children. +* This solution comprises a bridge (QEMU plugin) that connects your hooks (in a shared library (.so)) with the QEMU usermode ecosystem. +* Currently, LINUX only + +## Bridge compilation +Run build_qemu_support.sh as you do to compile qemuafl, additionally with three args namely: +* `ENABLE_HOOKING=1` to compile the bridge +* `GLIB_H` and `GLIB_CONFIG_H` point to headers `glib.h` and `glibconfig.h` to wherever they are installed on your system + +## Writting hooks +1. Create one or more hooking functions in a shared library, say `hook.so`. +2. Include `exports.h` in your hook build. You can find this header at `<your AFL++ path>/qemu_mode/hooking_bridge/inc`. +3. Shown below is an example which will use to walkthrough hook creation + ```C + struct ret* hook_000000400deadc08(){ + memset (buf, 0, 8); + scanf("%s",buf); + r_reg(RSI,(void *)&h_addr); + w_mem(h_addr,8, buf); + to_ret = (struct ret){0x400deadcab, 0}; + return &to_ret; + } + ``` + i. Hook functions must be named as `hook_<left padded hook location>`. Here, `<left padded hook location>` means `<hook location>` left padded with 0's to until 16 hex characters. The unpaded part of `<hook location>` is the absolute address where you want to place the hook. It is basically the file base address (which does not change in QEMU as of now) plus the instruction offset where the hooks is to be placed. The hook function must return a `struct ret *`, which is touched upon later. + + ii. Most likely you will need to access memory or registers in the hook. So we provide four functions + ```C + // Read memory (from address, num. bytes, destination buffer) -> returns 0 on success + int r_mem(unsigned long long addr, unsigned long long len, void *dest); + // Write memory (to address, num. bytes, source buffer) -> returns 0 on success + int w_mem(unsigned long long addr, unsigned long long len, void *src); + // Read register (identifier, destination buffer) -> returns number of bytes read + int r_reg(unsigned char reg, void *dest); + // Read register (identifier, source buffer) -> returns number of bytes written + int w_reg(unsigned char reg, char *src); + ``` + When operating on registers, the functions require a `reg` identifier. This is basically a number gdb uses to lookup a register and can be found under `<qemu(afl) path>/gdb-xml` in the architecture specific xml files. For the example case from above, `RSI` is 4 as obtained from `i386-64bit.xml`. + + iii. Once done with the processing, the hooks needs to return a `struct ret` type pointer, the struct format being + ```C + struct ret{ + unsigned long long addr; + char remove_bp; + }; + ``` + As we can see, there are two fields: first that indicates the address to return to and second that indicates whether the installed hook should be removed after the return. The second field becomes critical if the hook is within an ongoing loop and should be kept intact for future references. + + iv. Finally, mention the list of hooks in a `configure` function that we can call and install your hooks + ```C + struct conf config; + struct conf* configure(){ + config.IP_reg_num = 16; + config.entry_addr = 0x4000001000; + config.num_hooks = NUMHOOKS; //1,2,3... + hooks[0] = 0x400deadc08; + // hooks[1] = 0xcafecace + // .... + config.hooks = hooks; + + //Any other processing stuff you need done before fuzztime + + return &config; + } + ``` + The `configure` function must have the signature `struct conf* configure()` i.e. it must return a pointer to the `config` object. The format of the `config` object is + ```C + struct conf{ + unsigned char IP_reg_num; //found in <qemudir>/gdb-xml + unsigned long long entry_addr; //Main, init, or any entry point that is executed by QEMU prior to hooking targets + unsigned long long* hooks; //list of hooked addresses + unsigned long long num_hooks; // Number of hooks + }; + ``` + `IP_reg_num` here is the register number assigned under the architecture specific xml file under `<qemu(afl) path>/gdb-xml` to the instruction pointer. + +## Running with hooks +Set `QEMU_PLUGIN="file=<AFL download path>qemu_mode/hooking_bridge/build/plugin.so,arg=<your hook .so>"` before running AFL++ in QEMU mode. Note `<your hook .so>` is the absolute path to your hooks library. + +## Current limitations +1. Cannot be used to debug (-g option) when using the bridge as it uses the gdbstub internally. This is not a problem if used with AFL++, so not such a big issue. +2. Cannot put a hook on the first block after `<entry point>`. Not typically a hookable location. +3. The current implementation can only function on Linux. We have tested on the following configuration + ```Bash + lsb_release -a + --------------- + Distributor ID: Ubuntu + Description: Ubuntu 22.04.3 LTS + Release: 22.04 + Codename: jammy + ``` + ```Bash + uname -a + ---------- + Linux someone 6.5.0-28-generic #29~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr 4 14:39:20 UTC 2 x86_64 x86_64 x86_64 GNU/Linux + ``` diff --git a/qemu_mode/hooking_bridge/inc/common.h b/qemu_mode/hooking_bridge/inc/common.h new file mode 100644 index 00000000..f2260977 --- /dev/null +++ b/qemu_mode/hooking_bridge/inc/common.h @@ -0,0 +1,11 @@ +#ifndef COMMON_H +#define COMMON_H + +#include <qemu/qemu-plugin.h> + +void patch_finish_cb(void *userdata); +void patch_block_trans_cb(struct qemu_plugin_tb *tb); +void patch_vpu_init_cb(unsigned int vcpu_index); +void patch_init(char *hook_library); + +#endif \ No newline at end of file diff --git a/qemu_mode/hooking_bridge/inc/exports.h b/qemu_mode/hooking_bridge/inc/exports.h new file mode 100644 index 00000000..186976f4 --- /dev/null +++ b/qemu_mode/hooking_bridge/inc/exports.h @@ -0,0 +1,29 @@ +#ifndef API_H +#define API_H + +//# EXPORTS +// Returns 0 on success +int r_mem(unsigned long long addr, unsigned long long len, void *dest); +// // Returns 0 on success +int w_mem(unsigned long long addr, unsigned long long len, void *src); +// Returns num of bytes read; +int r_reg(unsigned char reg, void *dest); +// // Returns num of bytes written +int w_reg(unsigned char reg, char *src); + + +//NOTE hook function must be named hook_<16 hex character at_addr> +//NOTE must define function `struct conf* configure()` +struct conf{ + unsigned char IP_reg_num; + unsigned long long entry_addr; + unsigned long long* hooks; + unsigned long long num_hooks; +}conf; + +struct ret{ + unsigned long long addr; + char remove_bp; +}; + +#endif \ No newline at end of file diff --git a/qemu_mode/hooking_bridge/src/main.c b/qemu_mode/hooking_bridge/src/main.c new file mode 100644 index 00000000..98e8da98 --- /dev/null +++ b/qemu_mode/hooking_bridge/src/main.c @@ -0,0 +1,36 @@ +#include <stdio.h> +#include <stdlib.h> +#include "common.h" + +QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; + +static void finish_cb(qemu_plugin_id_t id, void *userdata) { + + patch_finish_cb(userdata); + +} + +static void block_trans_cb(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { + + patch_block_trans_cb(tb); + +} + +static void vpu_init_cb(qemu_plugin_id_t id, unsigned int vcpu_index) { + + patch_vpu_init_cb(vcpu_index); + +} + +QEMU_PLUGIN_EXPORT +int qemu_plugin_install(qemu_plugin_id_t id, const qemu_info_t *info, int argc, + char **argv) { + + patch_init(argv[0]); + qemu_plugin_register_vcpu_init_cb(id, vpu_init_cb); + qemu_plugin_register_vcpu_tb_trans_cb(id, block_trans_cb); + qemu_plugin_register_atexit_cb(id, finish_cb, NULL); + return 0; + +} + diff --git a/qemu_mode/hooking_bridge/src/patching.c b/qemu_mode/hooking_bridge/src/patching.c new file mode 100644 index 00000000..123ad99d --- /dev/null +++ b/qemu_mode/hooking_bridge/src/patching.c @@ -0,0 +1,173 @@ +#include <stdlib.h> +#include <stdio.h> +#include <dlfcn.h> +#include <glib.h> +#include "common.h" +#include "exports.h" + +void *handle; +struct conf *config; +struct conf *(*configure)(); +GByteArray *out; +void *cpu; +char cbuf[100]; + +// region GDB Imports +#pragma region GDB Imports +void cpu_single_step(void *cpu, int enabled); +int get_sstep_flags(void); +void gdb_accept_init(int fd); +int gdb_breakpoint_insert(int type, unsigned long long addr, + unsigned long long len); +int gdb_breakpoint_remove(int type, unsigned long long addr, + unsigned long long len); +void *qemu_get_cpu(int index); +int target_memory_rw_debug(void *cpu, unsigned long long addr, void *ptr, + unsigned long long len, char is_write); +int gdb_read_register(void *cs, GByteArray *mem_buf, int n); +int gdb_write_register(void *cs, char *mem_buf, int n); +void gdb_set_cpu_pc(unsigned long long pc); +void gdb_continue(void); +#pragma endregion GDB Imports + +// region API +int r_mem(unsigned long long addr, unsigned long long len, void *dest) { + + return target_memory_rw_debug(cpu, addr, dest, len, 0); + +} + +int w_mem(unsigned long long addr, unsigned long long len, void *src) { + + return target_memory_rw_debug(cpu, addr, src, len, 1); + +} + +int r_reg(unsigned char reg, void *dest) { + + g_byte_array_steal(out, NULL); + int op = gdb_read_register(cpu, out, reg); + memcpy(dest, out->data, out->len); + return op; + +} + +int w_reg(unsigned char reg, char *src) { + + return gdb_write_register(cpu, src, reg); + +} + +// region Breakpoint handling +char single_stepped; +unsigned long long gen_addr; +struct ret *(*hook)(); +struct ret *returned; +// Defined and imported gdbstub.c +void set_signal_callback(void (*cb)(int)); +// Breakpoints are set here +void patch_block_trans_cb(struct qemu_plugin_tb *tb) { + + unsigned long long addr; + addr = qemu_plugin_tb_vaddr(tb); + + if (addr == config->entry_addr) { + + // NOTE This means we cannot put a BP in the first basic block + gdb_accept_init(-1); + for (int i = 0; i < config->num_hooks; i++) { + + gdb_breakpoint_insert(0, config->hooks[i], 1); + + } + + } + +} + +void handle_signal_callback(int sig) { + + if (single_stepped) { + + single_stepped = 0; + gdb_breakpoint_insert(0, gen_addr, 1); + cpu_single_step(cpu, 0); + gdb_continue(); + return; + + } + + r_reg(config->IP_reg_num, cbuf); + gen_addr = *(unsigned long long *)cbuf; + + sprintf(cbuf, "hook_%016llx", gen_addr); + // TODO maybe find a way to put the hook function pointers in the TCG data + // structure instead of this dlsym call + *(unsigned long long **)(&hook) = dlsym(handle, cbuf); + if (!hook) { + + exit(-1); + + } + + returned = hook(); + + if (returned->remove_bp || + (returned->addr == + gen_addr)) { //* force removal of bp in returning to the same address, + //otherwise hook will be called again + gdb_breakpoint_remove(0, gen_addr, 1); + + } + + if (returned->addr == gen_addr) { + + single_stepped = 1; + cpu_single_step(cpu, get_sstep_flags()); + + } else { + + //* no need to rexecute the IP instruction + gdb_set_cpu_pc(returned->addr); + + } + + gdb_continue(); + +} + +// region Constructor/Destructor +void patch_finish_cb(void *userdata) { + + g_byte_array_free(out, 1); + dlclose(handle); + +} + +void patch_vpu_init_cb(unsigned int vcpu_index) { + + cpu = qemu_get_cpu(vcpu_index); + +} + +void patch_init(char *hook_lib) { + + // TODO make OS agnostic, remove dlopen + handle = dlopen(hook_lib, RTLD_NOW); + if (!handle) { + + fprintf(stderr, "DLOPEN Error: %s\n", dlerror()); + exit(-1); + + } + + single_stepped = 0; + + *(void **)(&configure) = dlsym(handle, "configure"); + config = configure(); + + set_signal_callback(handle_signal_callback); + out = g_byte_array_new(); + +} + diff --git a/qemu_mode/libqasan/dlmalloc.c b/qemu_mode/libqasan/dlmalloc.c index 1919ae26..d1d4dc08 100644 --- a/qemu_mode/libqasan/dlmalloc.c +++ b/qemu_mode/libqasan/dlmalloc.c @@ -2355,7 +2355,7 @@ typedef unsigned int flag_t; /* The type of various bit flag sets */ /* conversion from malloc headers to user pointers, and back */ #define chunk2mem(p) ((void *)((char *)(p) + TWO_SIZE_T_SIZES)) - #define mem2chunk(mem) ((mchunkptr)((char *)(mem)-TWO_SIZE_T_SIZES)) + #define mem2chunk(mem) ((mchunkptr)((char *)(mem) - TWO_SIZE_T_SIZES)) /* chunk associated with aligned address A */ #define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) diff --git a/qemu_mode/qemuafl b/qemu_mode/qemuafl -Subproject a6f0632a65e101e680dd72643a6128dd180dff7 +Subproject 847b43acb11530e775013dc24b54c6e27406179 diff --git a/src/afl-common.c b/src/afl-common.c index efdb5d60..892745a7 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -108,7 +108,8 @@ void set_sanitizer_defaults() { if (!have_san_options) { strcpy(buf, default_options); } if (have_asan_options) { - if (NULL != strstr(have_asan_options, "detect_leaks=0")) { + if (NULL != strstr(have_asan_options, "detect_leaks=0") || + NULL != strstr(have_asan_options, "detect_leaks=false")) { strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:"); @@ -979,6 +980,7 @@ inline u64 get_cur_time(void) { struct timeval tv; struct timezone tz; + // TO NOT REPLACE WITH clock_gettime!!! gettimeofday(&tv, &tz); return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); @@ -992,6 +994,7 @@ inline u64 get_cur_time_us(void) { struct timeval tv; struct timezone tz; + // TO NOT REPLACE WITH clock_gettime!!! gettimeofday(&tv, &tz); return (tv.tv_sec * 1000000ULL) + tv.tv_usec; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 71d8570d..c7c493cf 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -241,6 +241,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->mem_limit = MEM_LIMIT; fsrv->out_file = NULL; fsrv->child_kill_signal = SIGKILL; + fsrv->max_length = MAX_FILE; /* exec related stuff */ fsrv->child_pid = -1; @@ -252,6 +253,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->uses_crash_exitcode = false; fsrv->uses_asan = false; +#ifdef __AFL_CODE_COVERAGE + fsrv->persistent_trace_bits = NULL; +#endif + fsrv->init_child_func = fsrv_exec_child; list_append(&fsrv_list, fsrv); @@ -278,12 +283,19 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->fsrv_kill_signal = from->fsrv_kill_signal; fsrv_to->debug = from->debug; +#ifdef __AFL_CODE_COVERAGE + fsrv_to->persistent_trace_bits = from->persistent_trace_bits; +#endif + // These are forkserver specific. fsrv_to->out_dir_fd = -1; fsrv_to->child_pid = -1; fsrv_to->use_fauxsrv = 0; fsrv_to->last_run_timed_out = 0; + fsrv_to->late_send = from->late_send; + fsrv_to->custom_data_ptr = from->custom_data_ptr; + fsrv_to->init_child_func = from->init_child_func; // Note: do not copy ->add_extra_func or ->persistent_record* @@ -295,8 +307,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -static u32 __attribute__((hot)) -read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, volatile u8 *stop_soon_p) { +static u32 __attribute__((hot)) read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, + volatile u8 *stop_soon_p) { fd_set readfds; FD_ZERO(&readfds); @@ -1326,6 +1338,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->map_size = tmp_map_size; + } else { + + fsrv->real_map_size = fsrv->map_size = MAP_SIZE; + } if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { @@ -1432,6 +1448,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + } else { + + // The binary is most likely instrumented using AFL's tool, and we will + // set map_size to MAP_SIZE. + fsrv->real_map_size = fsrv->map_size = MAP_SIZE; + } } @@ -1683,8 +1705,8 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, /* Delete the current testcase and write the buf to the testcase file */ -void __attribute__((hot)) -afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { +void __attribute__((hot)) afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, + u8 *buf, size_t len) { #ifdef __linux__ if (unlikely(fsrv->nyx_mode)) { @@ -1802,9 +1824,8 @@ afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t __attribute__((hot)) -afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, - volatile u8 *stop_soon_p) { +fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target( + afl_forkserver_t *fsrv, u32 timeout, volatile u8 *stop_soon_p) { s32 res; u32 exec_ms; @@ -1944,6 +1965,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } + if (unlikely(fsrv->late_send)) { + + fsrv->late_send(fsrv->custom_data_ptr, fsrv->custom_input, + fsrv->custom_input_len); + + } + exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout, stop_soon_p); diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 03bc5d6c..fd75a822 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -75,9 +75,13 @@ u32 count_bits(afl_state_t *afl, u8 *mem) { } +#if __has_builtin(__builtin_popcount) + ret += __builtin_popcount(v); +#else v -= ((v >> 1) & 0x55555555); v = (v & 0x33333333) + ((v >> 2) & 0x33333333); ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24; +#endif } @@ -452,14 +456,14 @@ void write_crash_readme(afl_state_t *afl) { save or queue the input test case for further analysis if so. Returns 1 if entry is saved, 0 otherwise. */ -u8 __attribute__((hot)) -save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { +u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem, + u32 len, u8 fault) { if (unlikely(len == 0)) { return 0; } if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) { - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -485,7 +489,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Generating a hash on every input is super expensive. Bad idea and should only be used for special schedules */ - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { classify_counts(&afl->fsrv); classified = 1; diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 55b6be04..da996602 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -455,13 +455,13 @@ void deunicode_extras(afl_state_t *afl) { case 2: if (!afl->extras[i].data[j]) { ++z3; } - // fall through + __attribute__((fallthrough)); case 0: if (!afl->extras[i].data[j]) { ++z1; } break; case 3: if (!afl->extras[i].data[j]) { ++z4; } - // fall through + __attribute__((fallthrough)); case 1: if (!afl->extras[i].data[j]) { ++z2; } break; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7310e49f..10951300 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1019,7 +1019,7 @@ void perform_dry_run(afl_state_t *afl) { } - if (!q->was_fuzzed) { + if (unlikely(!q->was_fuzzed)) { q->was_fuzzed = 1; afl->reinit_table = 1; @@ -2443,20 +2443,19 @@ void check_crash_handling(void) { SAYF( "\n" cLRD "[-] " cRST - "Hmm, your system is configured to send core dump notifications to an\n" + "Your system is configured to send core dump notifications to an\n" " external utility. This will cause issues: there will be an " "extended delay\n" " between stumbling upon a crash and having this information " "relayed to the\n" " fuzzer via the standard waitpid() API.\n" - " If you're just testing, set " + " If you're just experimenting, set " "'AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1'.\n\n" - " To avoid having crashes misinterpreted as timeouts, please log in " - "as root\n" - " and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" + " To avoid having crashes misinterpreted as timeouts, please \n" + " temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n" - " echo core >/proc/sys/kernel/core_pattern\n"); + " echo core | sudo tee /proc/sys/kernel/core_pattern\n"); if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) { @@ -2717,7 +2716,11 @@ void fix_up_sync(afl_state_t *afl) { } - if (strlen(afl->sync_id) > 32) { FATAL("Fuzzer ID too long"); } + if (strlen(afl->sync_id) > 50) { + + FATAL("sync_id max length is 50 characters"); + + } x = alloc_printf("%s/%s", afl->out_dir, afl->sync_id); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 74bb8cbc..fd5ed87c 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3914,7 +3914,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { #define EFF_APOS(_p) ((_p) >> EFF_MAP_SCALE2) #define EFF_REM(_x) ((_x) & ((1 << EFF_MAP_SCALE2) - 1)) #define EFF_ALEN(_l) (EFF_APOS(_l) + !!EFF_REM(_l)) -#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l)-1) - EFF_APOS(_p) + 1) +#define EFF_SPAN_ALEN(_p, _l) (EFF_APOS((_p) + (_l) - 1) - EFF_APOS(_p) + 1) /* Initialize effector map for the next step (see comments below). Always flag first and last byte as doing something. */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 313e8ae5..8db89775 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -123,7 +123,7 @@ void create_alias_table(afl_state_t *afl) { double weight = 1.0; { // inline does result in a compile error with LTO, weird - if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { u32 hits = afl->n_fuzz[q->n_fuzz_entry]; if (likely(hits)) { weight /= (log10(hits) + 1); } @@ -133,39 +133,127 @@ void create_alias_table(afl_state_t *afl) { if (likely(afl->schedule < RARE)) { double t = q->exec_us / avg_exec_us; + if (likely(t < 0.1)) { // nothing - } else if (likely(t <= 0.25)) + } else if (likely(t <= 0.25)) { + + weight *= 0.95; - weight *= 0.9; - else if (likely(t <= 0.5)) { + } else if (likely(t <= 0.5)) { // nothing - } else if (likely(t < 1.0)) + } else if (likely(t <= 0.75)) { + + weight *= 1.05; + + } else if (likely(t <= 1.0)) { + + weight *= 1.1; + + } else if (likely(t < 1.25)) { + + weight *= 0.2; // WTF ??? makes no sense + + } else if (likely(t <= 1.5)) { + + // nothing + + } else if (likely(t <= 2.0)) { + + weight *= 1.1; + + } else if (likely(t <= 2.5)) { + + } else if (likely(t <= 5.0)) { weight *= 1.15; - else if (unlikely(t > 2.5 && t < 5.0)) + + } else if (likely(t <= 20.0)) { + weight *= 1.1; - // else nothing + // else nothing + + } } double l = q->len / avg_len; - if (likely(l < 0.1)) - weight *= 0.75; - else if (likely(l < 0.25)) - weight *= 1.1; - else if (unlikely(l >= 10)) - weight *= 1.1; + if (likely(l < 0.1)) { + + weight *= 0.5; + + } else if (likely(l <= 0.5)) { + + // nothing + + } else if (likely(l <= 1.25)) { + + weight *= 1.05; + + } else if (likely(l <= 1.75)) { + + // nothing + + } else if (likely(l <= 2.0)) { + + weight *= 0.95; + + } else if (likely(l <= 5.0)) { + + // nothing + + } else if (likely(l <= 10.0)) { + + weight *= 1.05; + + } else { + + weight *= 1.15; + + } double bms = q->bitmap_size / avg_bitmap_size; - if (likely(bms < 0.5)) - weight *= (1.0 + ((bms - 0.5) / 2)); - else if (unlikely(bms > 1.33)) - weight *= 1.1; + if (likely(bms < 0.1)) { + + weight *= 0.01; + + } else if (likely(bms <= 0.25)) { + + weight *= 0.55; + + } else if (likely(bms <= 0.5)) { + + // nothing + + } else if (likely(bms <= 0.75)) { + + weight *= 1.2; + + } else if (likely(bms <= 1.25)) { + + weight *= 1.3; + + } else if (likely(bms <= 1.75)) { + + weight *= 1.25; + + } else if (likely(bms <= 2.0)) { + + // nothing + + } else if (likely(bms <= 2.5)) { + + weight *= 1.3; + + } else { + + weight *= 0.75; + + } if (unlikely(!q->was_fuzzed)) { weight *= 2.5; } if (unlikely(q->fs_redundant)) { weight *= 0.75; } @@ -387,6 +475,17 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { q->fs_redundant = state; + if (likely(q->fs_redundant)) { + + if (unlikely(q->trace_mini)) { + + ck_free(q->trace_mini); + q->trace_mini = NULL; + + } + + } + sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir, strrchr((char *)q->fname, '/') + 1); @@ -400,7 +499,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { } else { - if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); } + if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/ + + } } @@ -698,12 +799,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { void destroy_queue(afl_state_t *afl) { - u32 i; + u32 i; + struct queue_entry *q; for (i = 0; i < afl->queued_items; i++) { - struct queue_entry *q; - q = afl->queue_buf[i]; ck_free(q->fname); ck_free(q->trace_mini); @@ -739,7 +839,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 fav_factor; u64 fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { fuzz_p2 = 0; // Skip the fuzz_p2 comparison @@ -775,7 +875,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 top_rated_fav_factor; u64 top_rated_fuzz_p2; - if (likely(afl->schedule >= FAST && afl->schedule < RARE)) { + if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) { top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison @@ -811,7 +911,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { if (!--afl->top_rated[i]->tc_ref) { ck_free(afl->top_rated[i]->trace_mini); - afl->top_rated[i]->trace_mini = 0; + afl->top_rated[i]->trace_mini = NULL; } @@ -872,7 +972,8 @@ void cull_queue(afl_state_t *afl) { for (i = 0; i < afl->fsrv.map_size; ++i) { - if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { + if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7))) && + afl->top_rated[i]->trace_mini) { u32 j = len; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 6a0da6ab..4ce17eb2 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -41,8 +41,9 @@ u64 time_spent_working = 0; /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t __attribute__((hot)) -fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { +fsrv_run_result_t __attribute__((hot)) fuzz_run_target(afl_state_t *afl, + afl_forkserver_t *fsrv, + u32 timeout) { #ifdef PROFILING static u64 time_spent_start = 0; @@ -60,6 +61,27 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); +#ifdef __AFL_CODE_COVERAGE + if (unlikely(!fsrv->persistent_trace_bits)) { + + // On the first run, we allocate the persistent map to collect coverage. + fsrv->persistent_trace_bits = (u8 *)malloc(fsrv->map_size); + memset(fsrv->persistent_trace_bits, 0, fsrv->map_size); + + } + + for (u32 i = 0; i < fsrv->map_size; ++i) { + + if (fsrv->persistent_trace_bits[i] != 255 && fsrv->trace_bits[i]) { + + fsrv->persistent_trace_bits[i]++; + + } + + } + +#endif + /* If post_run() function is defined in custom mutator, the function will be called each time after AFL++ executes the target program. */ @@ -90,8 +112,8 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is rewound and truncated. */ -u32 __attribute__((hot)) -write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { +u32 __attribute__((hot)) write_to_testcase(afl_state_t *afl, void **mem, + u32 len, u32 fix) { u8 sent = 0; @@ -173,7 +195,17 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { if (el->afl_custom_fuzz_send) { - el->afl_custom_fuzz_send(el->data, *mem, new_size); + if (!afl->afl_env.afl_custom_mutator_late_send) { + + el->afl_custom_fuzz_send(el->data, *mem, new_size); + + } else { + + afl->fsrv.custom_input = *mem; + afl->fsrv.custom_input_len = new_size; + + } + sent = 1; } @@ -185,17 +217,17 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) { /* everything as planned. use the potentially new data. */ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size); - if (likely(!afl->afl_env.afl_post_process_keep_original)) { + } - len = new_size; + if (likely(!afl->afl_env.afl_post_process_keep_original)) { - } else { + len = new_size; - /* restore the original memory which was saved in new_mem */ - *mem = new_mem; - afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); + } else { - } + /* restore the original memory which was saved in new_mem */ + *mem = new_mem; + afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); } @@ -1142,8 +1174,8 @@ abort_trimming: error conditions, returning 1 if it's time to bail out. This is a helper function for fuzz_one(). */ -u8 __attribute__((hot)) -common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { +u8 __attribute__((hot)) common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, + u32 len) { u8 fault; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index fbe6d32a..eead3e50 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -286,6 +286,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_no_sync = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_FASTRESUME", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_fastresume = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY", afl_environment_variable_len)) { @@ -293,6 +300,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_custom_mutator_only = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_LATE_SEND", + + afl_environment_variable_len)) { + + afl->afl_env.afl_custom_mutator_late_send = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_CMPLOG_ONLY_NEW", afl_environment_variable_len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 3a71e158..9f5f59c0 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -76,7 +76,13 @@ char *get_fuzzing_state(afl_state_t *afl) { void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { - u8 fn[PATH_MAX]; + u8 fn[PATH_MAX], fn2[PATH_MAX]; + + snprintf(fn2, PATH_MAX, "%s/target_hash", afl->out_dir); + FILE *f2 = create_ffile(fn2); + fprintf(f2, "%p\n", (void *)get_binary_hash(afl->fsrv.target_path)); + fclose(f2); + snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); FILE *f = create_ffile(fn); u32 i; @@ -957,9 +963,9 @@ void show_stats_normal(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->non_instrumented_mode) { @@ -1001,7 +1007,7 @@ void show_stats_normal(afl_state_t *afl) { u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time); SAYF(bV bSTOP " run time : " cRST "%-33s " bSTG bV bSTOP - " cycles done : %s%-5s " bSTG bV "\n", + " cycles done : %s%-5s " bSTG bV "\n", time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1)); /* We want to warn people about not seeing new paths after a full cycle, @@ -1041,7 +1047,7 @@ void show_stats_normal(afl_state_t *afl) { u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time); SAYF(bV bSTOP "last saved crash : " cRST "%-33s " bSTG bV bSTOP - "saved crashes : %s%-6s" bSTG bV "\n", + "saved crashes : %s%-6s" bSTG bV "\n", time_tmp, crash_color, tmp); sprintf(tmp, "%s%s", u_stringify_int(IB(0), afl->saved_hangs), @@ -1049,12 +1055,12 @@ void show_stats_normal(afl_state_t *afl) { u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time); SAYF(bV bSTOP " last saved hang : " cRST "%-33s " bSTG bV bSTOP - " saved hangs : " cRST "%-6s" bSTG bV "\n", + " saved hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bH2 bHB bH bSTOP cCYA - " map coverage" bSTG bHT bH20 bH2 bVL "\n"); + " map coverage" bSTG bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -1085,9 +1091,9 @@ void show_stats_normal(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-19s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_items); @@ -1095,7 +1101,7 @@ void show_stats_normal(afl_state_t *afl) { /* Yeah... it's still going on... halp? */ SAYF(bV bSTOP " now trying : " cRST "%-22s " bSTG bV bSTOP - " favored items : " cRST "%-20s" bSTG bV "\n", + " favored items : " cRST "%-20s" bSTG bV "\n", afl->stage_name, tmp); if (!afl->stage_max) { @@ -1124,13 +1130,13 @@ void show_stats_normal(afl_state_t *afl) { if (afl->crash_mode) { SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP - " new crashes : %s%-20s" bSTG bV "\n", + " new crashes : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } else { SAYF(bV bSTOP " total execs : " cRST "%-22s " bSTG bV bSTOP - " total crashes : %s%-20s" bSTG bV "\n", + " total crashes : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } @@ -1183,7 +1189,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " bit flips : " cRST "%-36s " bSTG bV bSTOP - " levels : " cRST "%-10s" bSTG bV "\n", + " levels : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->max_depth)); if (unlikely(!afl->skip_deterministic)) { @@ -1199,7 +1205,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP - " pending : " cRST "%-10s" bSTG bV "\n", + " pending : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); if (unlikely(!afl->skip_deterministic)) { @@ -1215,7 +1221,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP - " pend fav : " cRST "%-10s" bSTG bV "\n", + " pend fav : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_favored)); if (unlikely(!afl->skip_deterministic)) { @@ -1231,7 +1237,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP - " own finds : " cRST "%-10s" bSTG bV "\n", + " own finds : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->queued_discovered)); if (unlikely(!afl->skip_deterministic)) { @@ -1257,7 +1263,7 @@ void show_stats_normal(afl_state_t *afl) { } SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP - " imported : " cRST "%-10s" bSTG bV "\n", + " imported : " cRST "%-10s" bSTG bV "\n", tmp, afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a"); @@ -1445,8 +1451,8 @@ void show_stats_normal(afl_state_t *afl) { /* Last line */ - SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP " strategy:" cPIN - " %s " bSTG bH10 cCYA bSTOP " state:" cPIN + SAYF(SET_G1 "\n" bSTG bLB bH cCYA bSTOP " strategy:" cPIN + " %s " bSTG bH10 cCYA bSTOP " state:" cPIN " %s " bSTG bH2 bRB bSTOP cRST RESET_G1, afl->fuzz_mode == 0 ? "explore" : "exploit", get_fuzzing_state(afl)); @@ -1815,8 +1821,8 @@ void show_stats_pizza(afl_state_t *afl) { } u_stringify_time_diff(time_tmp, afl->prev_run_time + cur_ms, afl->start_time); - SAYF(bV bSTOP - " open time : " cRST "%-37s " bSTG bV bSTOP + SAYF(bV bSTOP + " open time : " cRST "%-37s " bSTG bV bSTOP " seasons done : %s%-5s " bSTG bV "\n", time_tmp, tmp, u_stringify_int(IB(0), afl->queue_cycle - 1)); @@ -1859,7 +1865,7 @@ void show_stats_pizza(afl_state_t *afl) { (afl->saved_crashes >= KEEP_UNIQUE_CRASH) ? "+" : ""); u_stringify_time_diff(time_tmp, cur_ms, afl->last_crash_time); - SAYF(bV bSTOP + SAYF(bV bSTOP " last ordered pizza : " cRST "%-33s " bSTG bV bSTOP " at table : %s%-6s " bSTG bV "\n", time_tmp, crash_color, tmp); @@ -1868,15 +1874,15 @@ void show_stats_pizza(afl_state_t *afl) { (afl->saved_hangs >= KEEP_UNIQUE_HANG) ? "+" : ""); u_stringify_time_diff(time_tmp, cur_ms, afl->last_hang_time); - SAYF(bV bSTOP + SAYF(bV bSTOP " last conversation with customers : " cRST "%-33s " bSTG bV bSTOP " number of Peroni : " cRST "%-6s " bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " Baking progress " bSTG bH30 bH20 bH5 bH bX bH bSTOP cCYA - " Pizzeria busyness" bSTG bH30 bH5 bH bH bVL "\n"); + " Pizzeria busyness" bSTG bH30 bH5 bH bH bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -1912,8 +1918,8 @@ void show_stats_pizza(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-19s " bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA - " Pizzas almost ready " bSTG bH30 bH20 bH2 bH bX bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA + " Pizzas almost ready " bSTG bH30 bH20 bH2 bH bX bH bSTOP cCYA " Types of pizzas cooking " bSTG bH10 bH5 bH2 bH10 bH2 bH bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), @@ -1922,7 +1928,7 @@ void show_stats_pizza(afl_state_t *afl) { /* Yeah... it's still going on... halp? */ SAYF(bV bSTOP " now preparing : " cRST - "%-22s " bSTG bV bSTOP + "%-22s " bSTG bV bSTOP " favourite topping : " cRST "%-20s" bSTG bV "\n", afl->stage_name, tmp); @@ -1955,14 +1961,14 @@ void show_stats_pizza(afl_state_t *afl) { if (afl->crash_mode) { SAYF(bV bSTOP " total pizzas : " cRST - "%-22s " bSTG bV bSTOP + "%-22s " bSTG bV bSTOP " pizzas with pineapple : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); } else { SAYF(bV bSTOP " total pizzas : " cRST - "%-22s " bSTG bV bSTOP + "%-22s " bSTG bV bSTOP " total pizzas with pineapple : %s%-20s" bSTG bV "\n", u_stringify_int(IB(0), afl->fsrv.total_execs), crash_color, tmp); @@ -1999,7 +2005,7 @@ void show_stats_pizza(afl_state_t *afl) { /* Aaaalmost there... hold on! */ SAYF(bVR bH cCYA bSTOP " Promotional campaign on TikTok yields " bSTG bH30 bH2 - bH bH2 bX bH bSTOP cCYA + bH bH2 bX bH bSTOP cCYA " Customer type " bSTG bH5 bH2 bH30 bH2 bH bVL "\n"); if (unlikely(afl->custom_only)) { @@ -2022,8 +2028,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " pizzas for celiac : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " pizzas for celiac : " cRST "%-36s " bSTG bV bSTOP " levels : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->max_depth)); @@ -2040,8 +2046,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " pizzas for kids : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " pizzas for kids : " cRST "%-36s " bSTG bV bSTOP " pizzas to make : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); @@ -2058,8 +2064,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " pizza bianca : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " pizza bianca : " cRST "%-36s " bSTG bV bSTOP " nice table : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_favored)); @@ -2076,8 +2082,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " recurring customers : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " recurring customers : " cRST "%-36s " bSTG bV bSTOP " new customers : " cRST "%-10s " bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->queued_discovered)); @@ -2104,8 +2110,8 @@ void show_stats_pizza(afl_state_t *afl) { } - SAYF(bV bSTOP - " dictionary : " cRST "%-36s " bSTG bV bSTOP + SAYF(bV bSTOP + " dictionary : " cRST "%-36s " bSTG bV bSTOP " patrons from old resturant : " cRST "%-10s " bSTG bV "\n", tmp, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index a7ddef6e..726a2260 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -36,6 +36,67 @@ #include <sys/ipc.h> #include <sys/shm.h> #endif +#ifdef HAVE_ZLIB + + #define ck_gzread(fd, buf, len, fn) \ + do { \ + \ + s32 _len = (s32)(len); \ + s32 _res = gzread(fd, buf, _len); \ + if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \ + \ + } while (0) + + #define ck_gzwrite(fd, buf, len, fn) \ + do { \ + \ + if (len <= 0) break; \ + s32 _written = 0, _off = 0, _len = (s32)(len); \ + \ + do { \ + \ + s32 _res = gzwrite(fd, (buf) + _off, _len); \ + if (_res != _len && (_res > 0 && _written + _res != _len)) { \ + \ + if (_res > 0) { \ + \ + _written += _res; \ + _len -= _res; \ + _off += _res; \ + \ + } else { \ + \ + RPFATAL(_res, "Short write to %s (%d of %d bytes)", fn, _res, \ + _len); \ + \ + } \ + \ + } else { \ + \ + break; \ + \ + } \ + \ + } while (1); \ + \ + \ + \ + } while (0) + + #include <zlib.h> + #define ZLIBOPEN gzopen + #define ZLIBREAD ck_gzread + #define NZLIBREAD gzread + #define ZLIBWRITE ck_gzwrite + #define ZLIBCLOSE gzclose + #define ZLIB_EXTRA "9" +#else + #define ZLIBOPEN open + #define NZLIBREAD read + #define ZLIBREAD ck_read + #define ZLIBWRITE ck_write + #define ZLIBCLOSE close +#endif #ifdef __APPLE__ #include <sys/qos.h> @@ -181,7 +242,7 @@ static void usage(u8 *argv0, int more_help) { "it.\n" " if using QEMU/FRIDA or the fuzzing target is " "compiled\n" - " for CmpLog then use '-c 0'. To disable Cmplog use '-c " + " for CmpLog then use '-c 0'. To disable CMPLOG use '-c " "-'.\n" " -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n" " 1=small files, 2=larger files (default), 3=all " @@ -335,6 +396,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" " suported formats: dogstatsd, librato, signalfx, influxdb\n" + "AFL_NO_FASTRESUME: do not read or write a fast resume file\n" "AFL_NO_SYNC: disables all syncing\n" "AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n" "AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n" @@ -960,7 +1022,11 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); } + if (afl->fsrv.mem_limit && afl->fsrv.mem_limit < 5) { + + FATAL("Dangerously low value of -m"); + + } if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) { @@ -1544,17 +1610,7 @@ int main(int argc, char **argv_orig, char **envp) { #endif - if (afl->sync_id) { - - if (strlen(afl->sync_id) > 50) { - - FATAL("sync_id max length is 50 characters"); - - } - - fix_up_sync(afl); - - } + if (afl->sync_id) { fix_up_sync(afl); } if (!strcmp(afl->in_dir, afl->out_dir)) { @@ -1868,6 +1924,15 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Using Frida Address Sanitizer Mode"); + if (afl->fsrv.mem_limit) { + + WARNF( + "in the Frida Address Sanitizer Mode we disable all memory " + "limits"); + afl->fsrv.mem_limit = 0; + + } + fasan_check_afl_preload(afl_preload); setenv("ASAN_OPTIONS", "detect_leaks=false", 1); @@ -2067,6 +2132,31 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->custom_mutators_count && afl->afl_env.afl_custom_mutator_late_send) { + + u32 count_send = 0; + LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, { + + if (el->afl_custom_fuzz_send) { + + if (count_send) { + + FATAL( + "You can only have one custom send() function if you are using " + "AFL_CUSTOM_MUTATOR_LATE_SEND!"); + + } + + afl->fsrv.late_send = el->afl_custom_fuzz_send; + afl->fsrv.custom_data_ptr = el->data; + count_send = 1; + + } + + }); + + } + if (afl->limit_time_sig > 0 && afl->custom_mutators_count) { if (afl->custom_only) { @@ -2101,13 +2191,92 @@ int main(int argc, char **argv_orig, char **envp) { } + setup_cmdline_file(afl, argv + optind); + check_binary(afl, argv[optind]); + + u64 prev_target_hash = 0; + s32 fast_resume = 0; + #ifdef HAVE_ZLIB + gzFile fr_fd = NULL; + #else + s32 fr_fd = -1; + #endif + + if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { + + u8 fn[PATH_MAX], buf[32]; + snprintf(fn, PATH_MAX, "%s/target_hash", afl->out_dir); + s32 fd = open(fn, O_RDONLY); + if (fd >= 0) { + + if (read(fd, buf, 32) >= 16) { + + sscanf(buf, "%p", (void **)&prev_target_hash); + + } + + close(fd); + + } + + } + write_setup_file(afl, argc, argv); - setup_cmdline_file(afl, argv + optind); + if (afl->in_place_resume && !afl->afl_env.afl_no_fastresume) { + + u64 target_hash = get_binary_hash(afl->fsrv.target_path); + + if (!target_hash || prev_target_hash != target_hash) { + + ACTF("Target binary is different, cannot perform FAST RESUME!"); + + } else { + + u8 fn[PATH_MAX]; + snprintf(fn, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + #ifdef HAVE_ZLIB + if ((fr_fd = ZLIBOPEN(fn, "rb")) != NULL) { + + #else + if ((fr_fd = open(fn, O_RDONLY)) >= 0) { + + #endif + + u8 ver_string[8]; + u64 *ver = (u64 *)ver_string; + u64 expect_ver = + afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) != + sizeof(ver_string)) + WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME"); + else if (expect_ver != *ver) + WARNF( + "Different AFL++ version or feature usage, cannot perform FAST " + "RESUME"); + else { + + OKF("Will perform FAST RESUME"); + fast_resume = 1; + + } + + } else { + + ACTF("fastresume.bin not found, cannot perform FAST RESUME!"); + + } + + // If the fast resume file is not valid we will be unable to start, so + // we remove the file but keep the file descriptor open. + unlink(fn); + + } + + } read_testcases(afl, NULL); - // read_foreign_testcases(afl, 1); for the moment dont do this - OKF("Loaded a total of %u seeds.", afl->queued_items); pivot_inputs(afl); @@ -2140,6 +2309,9 @@ int main(int argc, char **argv_orig, char **envp) { } + // read_foreign_testcases(afl, 1); for the moment dont do this + OKF("Loaded a total of %u seeds.", afl->queued_items); + /* If we don't have a file name chosen yet, use a safe default. */ if (!afl->fsrv.out_file) { @@ -2196,8 +2368,6 @@ int main(int argc, char **argv_orig, char **envp) { } - check_binary(afl, argv[optind]); - #ifdef AFL_PERSISTENT_RECORD if (unlikely(afl->fsrv.persistent_record)) { @@ -2416,7 +2586,7 @@ int main(int argc, char **argv_orig, char **envp) { } - OKF("Cmplog forkserver successfully started"); + OKF("CMPLOG forkserver successfully started"); } @@ -2454,29 +2624,102 @@ int main(int argc, char **argv_orig, char **envp) { dedup_extras(afl); if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); } - // after we have the correct bitmap size we can read the bitmap -B option - // and set the virgin maps - if (afl->in_bitmap) { + if (unlikely(fast_resume)) { - read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + u64 resume_start = get_cur_time_us(); + // if we get here then we should abort on errors + ZLIBREAD(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ZLIBREAD(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ZLIBREAD(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ZLIBREAD(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); - } else { + u8 res[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 r = 8 + afl->fsrv.map_size * 4; + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; - memset(afl->virgin_bits, 255, map_size); + for (u32 i = 0; i < afl->queued_items; i++) { - } + q = afl->queue_buf[i]; + ZLIBREAD(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + ZLIBREAD(fr_fd, res, 1, "check map"); + if (res[0]) { + + q->trace_mini = ck_alloc(m_len); + ZLIBREAD(fr_fd, q->trace_mini, m_len, "trace_mini"); + r += q_len + m_len + 1; + + } else { + + r += q_len + 1; + + } + + afl->total_bitmap_size += q->bitmap_size; + ++afl->total_bitmap_entries; + update_bitmap_score(afl, q); + + if (q->was_fuzzed) { --afl->pending_not_fuzzed; } + + if (q->disabled) { + + if (!q->was_fuzzed) { --afl->pending_not_fuzzed; } + --afl->active_items; - memset(afl->virgin_tmout, 255, map_size); - memset(afl->virgin_crash, 255, map_size); + } + + if (q->var_behavior) { ++afl->queued_variable; } + if (q->favored) { - if (likely(!afl->afl_env.afl_no_startup_calibration)) { + ++afl->queued_favored; + if (!q->was_fuzzed) { ++afl->pending_favored; } - perform_dry_run(afl); + } + + } + + u8 buf[4]; + if (NZLIBREAD(fr_fd, buf, 3) > 0) { + + FATAL("invalid trailing data in fastresume.bin"); + + } + + OKF("Successfully loaded fastresume.bin (%u bytes)!", r); + ZLIBCLOSE(fr_fd); + afl->reinit_table = 1; + update_calibration_time(afl, &resume_start); } else { - ACTF("skipping initial seed calibration due option override!"); - usleep(1000); + // after we have the correct bitmap size we can read the bitmap -B option + // and set the virgin maps + if (afl->in_bitmap) { + + read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); + + } else { + + memset(afl->virgin_bits, 255, map_size); + + } + + memset(afl->virgin_tmout, 255, map_size); + memset(afl->virgin_crash, 255, map_size); + + if (likely(!afl->afl_env.afl_no_startup_calibration)) { + + perform_dry_run(afl); + + } else { + + ACTF("Skipping initial seed calibration due option override!"); + usleep(1000); + + } } @@ -2562,7 +2805,7 @@ int main(int argc, char **argv_orig, char **envp) { // (void)nice(-20); // does not improve the speed #ifdef INTROSPECTION - u32 prev_saved_crashes = 0, prev_saved_tmouts = 0; + u32 prev_saved_crashes = 0, prev_saved_tmouts = 0, stat_prev_queued_items = 0; #endif u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1; u8 skipped_fuzz; @@ -2879,10 +3122,11 @@ int main(int argc, char **argv_orig, char **envp) { } else { - if (unlikely(afl->queued_items > prev_queued_items)) { + if (unlikely(afl->queued_items > stat_prev_queued_items)) { - afl->queue_cur->stats_finds += afl->queued_items - prev_queued_items; - prev_queued_items = afl->queued_items; + afl->queue_cur->stats_finds += + afl->queued_items - stat_prev_queued_items; + stat_prev_queued_items = afl->queued_items; } @@ -2984,6 +3228,28 @@ stop_fuzzing: write_bitmap(afl); save_auto(afl); + #ifdef __AFL_CODE_COVERAGE + if (afl->fsrv.persistent_trace_bits) { + + char cfn[4096]; + snprintf(cfn, sizeof(cfn), "%s/covmap.dump", afl->out_dir); + + FILE *cov_fd; + if ((cov_fd = fopen(cfn, "w")) == NULL) { + + PFATAL("could not create '%s'", cfn); + + } + + // Write the real map size, as the map size must exactly match the pointer + // map in length. + fwrite(afl->fsrv.persistent_trace_bits, 1, afl->fsrv.real_map_size, cov_fd); + fclose(cov_fd); + + } + + #endif + if (afl->pizza_is_served) { SAYF(CURSOR_SHOW cLRD "\n\n+++ Baking aborted %s +++\n" cRST, @@ -3067,6 +3333,74 @@ stop_fuzzing: fclose(afl->fsrv.det_plot_file); #endif + if (!afl->afl_env.afl_no_fastresume) { + + /* create fastresume.bin */ + u8 fr[PATH_MAX]; + snprintf(fr, PATH_MAX, "%s/fastresume.bin", afl->out_dir); + ACTF("Writing %s ...", fr); + #ifdef HAVE_ZLIB + if ((fr_fd = ZLIBOPEN(fr, "wb9")) != NULL) { + + #else + if ((fr_fd = open(fr, O_WRONLY | O_TRUNC | O_CREAT, DEFAULT_PERMISSION)) >= + 0) { + + #endif + + u8 ver_string[8]; + u32 w = 0; + u64 *ver = (u64 *)ver_string; + *ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1); + + ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string"); + ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits"); + ZLIBWRITE(fr_fd, afl->virgin_tmout, afl->fsrv.map_size, "virgin_tmout"); + ZLIBWRITE(fr_fd, afl->virgin_crash, afl->fsrv.map_size, "virgin_crash"); + ZLIBWRITE(fr_fd, afl->var_bytes, afl->fsrv.map_size, "var_bytes"); + w += sizeof(ver_string) + afl->fsrv.map_size * 4; + + u8 on[1] = {1}, off[1] = {0}; + u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized); + u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother); + u32 q_len = o_end - o_start; + u32 m_len = (afl->fsrv.map_size >> 3); + struct queue_entry *q; + + afl->pending_not_fuzzed = afl->queued_items; + afl->active_items = afl->queued_items; + + for (u32 i = 0; i < afl->queued_items; i++) { + + q = afl->queue_buf[i]; + ZLIBWRITE(fr_fd, (u8 *)&(q->colorized), q_len, "queue data"); + if (!q->trace_mini) { + + ZLIBWRITE(fr_fd, off, 1, "no_mini"); + w += q_len + 1; + + } else { + + ZLIBWRITE(fr_fd, on, 1, "yes_mini"); + ZLIBWRITE(fr_fd, q->trace_mini, m_len, "trace_mini"); + w += q_len + m_len + 1; + + } + + } + + ZLIBCLOSE(fr_fd); + afl->var_byte_count = count_bytes(afl, afl->var_bytes); + OKF("Written fastresume.bin with %u bytes!", w); + + } else { + + WARNF("Could not create fastresume.bin"); + + } + + } + destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); diff --git a/src/afl-performance.c b/src/afl-performance.c index e8ece6b5..b824fd35 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -99,11 +99,13 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) { u64 get_binary_hash(u8 *fn) { + if (!fn) { return 0; } int fd = open(fn, O_RDONLY); if (fd < 0) { PFATAL("Unable to open '%s'", fn); } struct stat st; if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } u32 f_len = st.st_size; + if (!f_len) { return 0; } u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } close(fd); diff --git a/src/hashmap.c b/src/hashmap.c index a0a9283c..5834802f 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -59,7 +59,7 @@ static inline unsigned int hash(uint64_t key) { bool hashmap_search_and_add(uint8_t type, uint64_t key) { if (unlikely(type >= 8)) return false; - uint64_t val = (key & 0xf8ffffffffffffff) + (type << 56); + uint64_t val = (key & 0xf8ffffffffffffff) + ((uint64_t)type << 56); unsigned int index = hash(val); HashNode *node = _hashmap->table[index]; while (node) { diff --git a/test/test-custom-mutators.sh b/test/test-custom-mutators.sh index 8c8b0ad3..3f0a96ba 100755 --- a/test/test-custom-mutators.sh +++ b/test/test-custom-mutators.sh @@ -38,7 +38,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS # Run afl-fuzz w/ the C mutator $ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds" { - AFL_CUSTOM_MUTATOR_LIBRARY=./libexamplemutator.so AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -d -- ./test-custom-mutator >>errors 2>&1 + AFL_CUSTOM_MUTATOR_LIBRARY=./libexamplemutator.so AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V20 -m ${MEM_LIMIT} -i in -o out -d -- ./test-custom-mutator >>errors 2>&1 } >>errors 2>&1 # Check results @@ -58,7 +58,7 @@ test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUS # Run afl-fuzz w/ multiple C mutators $ECHO "$GREY[*] running afl-fuzz with multiple custom C mutators, this will take approx 10 seconds" { - AFL_CUSTOM_MUTATOR_LIBRARY="./libexamplemutator.so;./libexamplemutator2.so" AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -d -- ./test-multiple-mutators >>errors 2>&1 + AFL_CUSTOM_MUTATOR_LIBRARY="./libexamplemutator.so;./libexamplemutator2.so" AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V20 -m ${MEM_LIMIT} -i in -o out -d -- ./test-multiple-mutators >>errors 2>&1 } >>errors 2>&1 test -n "$( ls out/default/crashes/id:000000* 2>/dev/null )" && { # TODO: update here @@ -88,7 +88,7 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && { { export PYTHONPATH=${CUSTOM_MUTATOR_PATH} export AFL_PYTHON_MODULE=example - AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V07 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 + AFL_CUSTOM_MUTATOR_ONLY=1 ../afl-fuzz -V20 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1 unset PYTHONPATH unset AFL_PYTHON_MODULE } >>errors 2>&1 diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh index 338c5982..9a290bb5 100755 --- a/test/test-unicorn-mode.sh +++ b/test/test-unicorn-mode.sh @@ -34,8 +34,8 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && cd ../unicorn_mode/samples/persistent make >>errors 2>&1 $ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds" - AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V15 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1 - test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && { + AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V15 -U -i sample_inputs -o out -- ./harness @@ >>errors 2>&1 + test -n "$( ls out/default/queue/id:000006* 2>/dev/null )" && { $ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)" } || { echo CUT------------------------------------------------------------------CUT diff --git a/unicorn_mode/README.md b/unicorn_mode/README.md index ce87a2e9..69ccc476 100644 --- a/unicorn_mode/README.md +++ b/unicorn_mode/README.md @@ -144,7 +144,7 @@ The following examples exist at the time of writing: blocks - persistent: A C example using persistent mode for maximum speed, and resetting the target state between each iteration -- simple: A simple Python example +- python_simple: A simple Python example - speedtest/c: The C harness for an example target, used to compare C, Python, and Rust bindings and fix speed issues - speedtest/python: Fuzzing the same target in Python @@ -158,4 +158,4 @@ get shipped pre-built (plus their source). Especially take a look at the [speedtest documentation](./samples/speedtest/README.md) to see how the -languages compare. \ No newline at end of file +languages compare. diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index deac0bf9..00a2aba3 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -4b4fdab1 +1c58dc97 diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 097a2dc9..1be399ff 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -199,26 +199,26 @@ echo "[+] Build process successful!" echo "[*] Installing Unicorn python bindings..." XOPT= -$PYTHONBIN -m pip install --help 2>/dev/null | grep -q break-system-packages && XOPT=--break-system-packages +#$PYTHONBIN -m pip install --help 2>/dev/null | grep -q break-system-packages && XOPT=--break-system-packages cd unicorn/bindings/python || exit 1 if [ -z "$VIRTUAL_ENV" ]; then echo "[*] Info: Installing python unicornafl using --user" - THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1 + THREADS=$CORES $PYTHONBIN setup.py install --user $XOPT --force || exit 1 else echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV" - THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1 + THREADS=$CORES $PYTHONBIN setup.py install --force || exit 1 fi cd ../../../ echo "[*] Installing Unicornafl python bindings..." cd bindings/python || exit 1 if [ -z "$VIRTUAL_ENV" ]; then echo "[*] Info: Installing python unicornafl using --user" - THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1 + THREADS=$CORES $PYTHONBIN setup.py install --user $XOPT --force || exit 1 else echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV" - THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1 + THREADS=$CORES $PYTHONBIN setup.py install --force || exit 1 fi -echo '[*] If needed, you can (re)install the bindings in `./unicornafl/bindings/python` using `pip install --force .`' +echo '[*] If needed, you can (re)install the bindings in `./unicornafl/bindings/python` using `python setup.py install --force .`' cd ../../ || exit 1 diff --git a/unicorn_mode/helper_scripts/unicorn_loader.py b/unicorn_mode/helper_scripts/unicorn_loader.py index a83e7000..4219c6ab 100644 --- a/unicorn_mode/helper_scripts/unicorn_loader.py +++ b/unicorn_mode/helper_scripts/unicorn_loader.py @@ -90,7 +90,7 @@ class UnicornSimpleHeap(object): _chunks_freed = [] # List of all freed chunks _debug_print = False # True to print debug information - def __init__(self, uc, debug_print=Falseļ¼ uaf_check=False): + def __init__(self, uc, debug_print=False, uaf_check=False): self._uc = uc self._debug_print = debug_print diff --git a/unicorn_mode/samples/c/sample_all.sh b/unicorn_mode/samples/c/sample_all.sh index 01daf365..3bb396e7 100644 --- a/unicorn_mode/samples/c/sample_all.sh +++ b/unicorn_mode/samples/c/sample_all.sh @@ -12,7 +12,7 @@ fi -if [ ! test -e $DIR/harness]; then +if [ ! -e $DIR/harness ]; then echo "[!] harness not found in $DIR" exit 1 -fi \ No newline at end of file +fi diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl -Subproject 4b4fdab161c15529affcc1e785d779e318b882a +Subproject 1c58dc9774012bace730df5c1c273356762e848 diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index 9ffb2383..6e992266 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -80,6 +80,7 @@ extern unsigned int __afl_map_size; /*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); +__attribute__((weak)) void LLVMFuzzerCleanup(void); __attribute__((weak)) int LLVMFuzzerRunDriver( int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size)); @@ -338,6 +339,7 @@ __attribute__((weak)) int LLVMFuzzerRunDriver( output_file = stderr; maybe_duplicate_stderr(); maybe_close_fd_mask(); + if (LLVMFuzzerInitialize) { fprintf(stderr, "Running LLVMFuzzerInitialize ...\n"); @@ -441,6 +443,14 @@ __attribute__((weak)) int LLVMFuzzerRunDriver( } + if (LLVMFuzzerCleanup) { + + fprintf(stderr, "Running LLVMFuzzerCleanup ...\n"); + LLVMFuzzerCleanup(); + fprintf(stderr, "Exiting ...\n"); + + } + return 0; } diff --git a/utils/aflpp_driver/aflpp_qemu_driver_hook.c b/utils/aflpp_driver/aflpp_qemu_driver_hook.c index 2979fadc..d75de539 100644 --- a/utils/aflpp_driver/aflpp_qemu_driver_hook.c +++ b/utils/aflpp_driver/aflpp_qemu_driver_hook.c @@ -4,7 +4,7 @@ #include <string.h> #define g2h(x) ((void *)((unsigned long)(x) + guest_base)) -#define h2g(x) ((uint64_t)(x)-guest_base) +#define h2g(x) ((uint64_t)(x) - guest_base) void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, uint8_t *input_buf, uint32_t input_buf_len) { diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index cc499150..8f693c51 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -167,7 +167,7 @@ static void __tokencap_load_mappings(void) { #elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__ - #if defined __FreeBSD__ + #if defined __FreeBSD__ int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid}; #elif defined __OpenBSD__ int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid}; @@ -183,7 +183,7 @@ static void __tokencap_load_mappings(void) { #if defined __FreeBSD__ || defined __NetBSD__ len = len * 4 / 3; - #elif defined __OpenBSD__ + #elif defined __OpenBSD__ len -= len % sizeof(struct kinfo_vmentry); #endif @@ -208,7 +208,7 @@ static void __tokencap_load_mappings(void) { #if defined __FreeBSD__ || defined __NetBSD__ - #if defined __FreeBSD__ + #if defined __FreeBSD__ size_t size = region->kve_structsize; if (size == 0) break; diff --git a/utils/persistent_mode/persistent_demo.c b/utils/persistent_mode/persistent_demo.c index f5e43728..00d59ef4 100644 --- a/utils/persistent_mode/persistent_demo.c +++ b/utils/persistent_mode/persistent_demo.c @@ -34,7 +34,7 @@ /* To ensure checks are not optimized out it is recommended to disable code optimization for the fuzzer harness main() */ #pragma clang optimize off -#pragma GCC optimize("O0") +#pragma GCC optimize("O0") int main(int argc, char **argv) { diff --git a/utils/persistent_mode/persistent_demo_new.c b/utils/persistent_mode/persistent_demo_new.c index 285f50aa..36a0043a 100644 --- a/utils/persistent_mode/persistent_demo_new.c +++ b/utils/persistent_mode/persistent_demo_new.c @@ -51,7 +51,7 @@ __AFL_FUZZ_INIT(); /* To ensure checks are not optimized out it is recommended to disable code optimization for the fuzzer harness main() */ #pragma clang optimize off -#pragma GCC optimize("O0") +#pragma GCC optimize("O0") int main(int argc, char **argv) { diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 72e26e93..7c83f629 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -24,7 +24,7 @@ __AFL_FUZZ_INIT(); /* To ensure checks are not optimized out it is recommended to disable code optimization for the fuzzer harness main() */ #pragma clang optimize off -#pragma GCC optimize("O0") +#pragma GCC optimize("O0") int main(int argc, char **argv) { diff --git a/utils/qemu_persistent_hook/read_into_rdi.c b/utils/qemu_persistent_hook/read_into_rdi.c index 14b2ed85..3e913870 100644 --- a/utils/qemu_persistent_hook/read_into_rdi.c +++ b/utils/qemu_persistent_hook/read_into_rdi.c @@ -4,7 +4,7 @@ #include <string.h> #define g2h(x) ((void *)((unsigned long)(x) + guest_base)) -#define h2g(x) ((uint64_t)(x)-guest_base) +#define h2g(x) ((uint64_t)(x) - guest_base) void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, uint8_t *input_buf, uint32_t input_buf_len) { diff --git a/utils/replay_record/persistent_demo_replay.c b/utils/replay_record/persistent_demo_replay.c index 6f6648f1..fa6255fd 100644 --- a/utils/replay_record/persistent_demo_replay.c +++ b/utils/replay_record/persistent_demo_replay.c @@ -46,7 +46,7 @@ __AFL_FUZZ_INIT(); /* To ensure checks are not optimized out it is recommended to disable code optimization for the fuzzer harness main() */ #pragma clang optimize off -#pragma GCC optimize("O0") +#pragma GCC optimize("O0") int main(int argc, char **argv) { |