diff options
Diffstat (limited to 'frida_mode/test')
28 files changed, 1205 insertions, 419 deletions
diff --git a/frida_mode/test/deferred/GNUmakefile b/frida_mode/test/deferred/GNUmakefile index c268ef66..ae580e3f 100644 --- a/frida_mode/test/deferred/GNUmakefile +++ b/frida_mode/test/deferred/GNUmakefile @@ -37,7 +37,7 @@ ifeq "$(ARCH)" "x86" AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000) endif -.PHONY: all clean qemu frida +.PHONY: all clean frida all: $(TESTINSTBIN) make -C $(ROOT)frida_mode/ diff --git a/frida_mode/test/jpeg/GNUmakefile b/frida_mode/test/jpeg/GNUmakefile new file mode 100644 index 00000000..e3a8f321 --- /dev/null +++ b/frida_mode/test/jpeg/GNUmakefile @@ -0,0 +1,164 @@ +PWD:=$(shell pwd)/ +ROOT:=$(shell realpath $(PWD)../../..)/ +BUILD_DIR:=$(PWD)build/ + +AFLPP_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/hook.so + +LIBJPEG_BUILD_DIR:=$(BUILD_DIR)libjpeg/ +HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/ +JPEGTEST_BUILD_DIR:=$(BUILD_DIR)jpegtest/ + +LIBJPEG_URL:=https://github.com/libjpeg-turbo/libjpeg-turbo.git +LIBJPEG_DIR:=$(LIBJPEG_BUILD_DIR)libjpeg/ +LIBJPEG_CONFIGURE:=$(LIBJPEG_DIR)configure.ac +LIBJPEG_MAKEFILE:=$(LIBJPEG_DIR)Makefile +LIBJPEG_LIB:=$(LIBJPEG_DIR).libs/libturbojpeg.a + +HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c +HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o +HARNESS_URL:="https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/aflpp_driver/aflpp_qemu_driver.c" + +JPEGTEST_FILE:=$(JPEGTEST_BUILD_DIR)target.cc +JPEGTEST_OBJ:=$(JPEGTEST_BUILD_DIR)target.o +JPEGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libjpeg-turbo-07-2017/libjpeg_turbo_fuzzer.cc" + +LDFLAGS += -lpthread + +TEST_BIN:=$(BUILD_DIR)test +ifeq "$(shell uname)" "Darwin" +TEST_BIN_LDFLAGS:=-undefined dynamic_lookup +endif + +TEST_DATA_DIR:=$(BUILD_DIR)in/ +TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed + +FRIDA_OUT:=$(BUILD_DIR)frida-out + +ifndef ARCH + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + +ifeq "$(ARCH)" "aarch64" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000) +endif + +ifeq "$(ARCH)" "x86_64" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000) +endif + +ifeq "$(ARCH)" "x86" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000) +endif + +.PHONY: all clean frida hook + +all: $(TEST_BIN) + make -C $(ROOT)frida_mode/ + +32: + CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +######### HARNESS ######## +$(HARNESS_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(HARNESS_FILE): | $(HARNESS_BUILD_DIR) + wget -O $@ $(HARNESS_URL) + +$(HARNESS_OBJ): $(HARNESS_FILE) + $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ -c $< + +######### JPEGTEST ######## + +$(JPEGTEST_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(JPEGTEST_FILE): | $(JPEGTEST_BUILD_DIR) + wget -O $@ $(JPEGTEST_URL) + +$(JPEGTEST_OBJ): $(JPEGTEST_FILE) | $(LIBJPEG_MAKEFILE) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBJPEG_DIR) -o $@ -c $< + +######### LIBJPEG ######## + +$(LIBJPEG_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(LIBJPEG_CONFIGURE): $(LIBJPEG_BUILD_DIR) + git clone $(LIBJPEG_URL) $(LIBJPEG_DIR) + cd $(LIBJPEG_DIR) && git checkout b0971e47d76fdb81270e93bbf11ff5558073350d + +$(LIBJPEG_MAKEFILE): $(LIBJPEG_CONFIGURE) + cd $(LIBJPEG_DIR) && autoreconf -fiv + cd $(LIBJPEG_DIR) && ./configure + +$(LIBJPEG_LIB): $(LIBJPEG_MAKEFILE) + make -C $(LIBJPEG_DIR) -j $(shell nproc) + +######### TEST ######## + +$(TEST_BIN): $(HARNESS_OBJ) $(JPEGTEST_OBJ) $(LIBJPEG_LIB) + $(CXX) \ + $(CFLAGS) \ + -o $@ \ + $(HARNESS_OBJ) $(JPEGTEST_OBJ) $(LIBJPEG_LIB) \ + -lz \ + $(LDFLAGS) \ + $(TEST_BIN_LDFLAGS) \ + +########## DUMMY ####### + +$(TEST_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TEST_DATA_FILE): | $(TEST_DATA_DIR) + echo "hi" > $(TEST_DATA_FILE) + +###### TEST DATA ####### + +clean: + rm -rf $(BUILD_DIR) + +frida: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) + AFL_DEBUG_CHILD=1 \ + AFL_DISABLE_TRIM=1 \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \ + AFL_NO_AFFINITY=1 \ + X__AFL_NO_UI=1 \ + AFL_PATH=/out \ + AFL_SHUFFLE_QUEUE=1 \ + AFL_SKIP_CPUFREQ=1 \ + AFL_SKIP_CRASHES=1 \ + AFL_TESTCACHE_SIZE=2 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -m none \ + -t 1000+ \ + -d \ + -O \ + -c 0\ + -V 30 \ + -- \ + $(TEST_BIN) 2147483647 + +debug: + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --args $(TEST_BIN) $(TEST_DATA_DIR)basn0g01.jpeg diff --git a/frida_mode/test/jpeg/Makefile b/frida_mode/test/jpeg/Makefile new file mode 100644 index 00000000..7a237f99 --- /dev/null +++ b/frida_mode/test/jpeg/Makefile @@ -0,0 +1,16 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + +clean: + @gmake clean + +frida: + @gmake frida + +debug: + @gmake debug diff --git a/frida_mode/test/jpeg/get_symbol_addr.py b/frida_mode/test/jpeg/get_symbol_addr.py new file mode 100755 index 00000000..1c46e010 --- /dev/null +++ b/frida_mode/test/jpeg/get_symbol_addr.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +import argparse +from elftools.elf.elffile import ELFFile + +def process_file(file, symbol, base): + with open(file, 'rb') as f: + elf = ELFFile(f) + symtab = elf.get_section_by_name('.symtab') + mains = symtab.get_symbol_by_name(symbol) + if len(mains) != 1: + print ("Failed to find main") + return 1 + + main_addr = mains[0]['st_value'] + main = base + main_addr + print ("0x%016x" % main) + return 0 + +def hex_value(x): + return int(x, 16) + +def main(): + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument('-f', '--file', dest='file', type=str, + help='elf file name', required=True) + parser.add_argument('-s', '--symbol', dest='symbol', type=str, + help='symbol name', required=True) + parser.add_argument('-b', '--base', dest='base', type=hex_value, + help='elf base address', required=True) + + args = parser.parse_args() + return process_file (args.file, args.symbol, args.base) + +if __name__ == "__main__": + ret = main() + exit(ret) diff --git a/frida_mode/test/js/GNUmakefile b/frida_mode/test/js/GNUmakefile new file mode 100644 index 00000000..af40c1c4 --- /dev/null +++ b/frida_mode/test/js/GNUmakefile @@ -0,0 +1,80 @@ +PWD:=$(shell pwd)/ +ROOT:=$(shell realpath $(PWD)../../..)/ +BUILD_DIR:=$(PWD)build/ +TEST_DATA_DIR:=$(BUILD_DIR)in/ +TEST_DATA_FILE:=$(TEST_DATA_DIR)in + +TESTINSTBIN:=$(BUILD_DIR)test +TESTINSTSRC:=$(PWD)test.c + +TESTINSTBIN2:=$(BUILD_DIR)test2 +TESTINSTSRC2:=$(PWD)test2.c + +QEMU_OUT:=$(BUILD_DIR)qemu-out +FRIDA_OUT:=$(BUILD_DIR)frida-out + +.PHONY: all 32 clean qemu frida + +all: $(TESTINSTBIN) $(TESTINSTBIN2) + make -C $(ROOT)frida_mode/ + +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +$(TEST_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TEST_DATA_FILE): | $(TEST_DATA_DIR) + echo -n "000" > $@ + +$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +$(TESTINSTBIN2): $(TESTINSTSRC2) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +clean: + rm -rf $(BUILD_DIR) + +frida_js_entry: $(TESTINSTBIN) $(TEST_DATA_FILE) + AFL_FRIDA_JS_SCRIPT=entry.js \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) @@ + +frida_js_replace: $(TESTINSTBIN) $(TEST_DATA_FILE) + AFL_FRIDA_JS_SCRIPT=replace.js \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) @@ + +frida_js_patch: $(TESTINSTBIN2) $(TEST_DATA_FILE) + AFL_FRIDA_JS_SCRIPT=patch.js \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN2) @@ + +frida_js_stalker: $(TESTINSTBIN2) $(TEST_DATA_FILE) + AFL_FRIDA_JS_SCRIPT=stalker.js \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN2) @@ diff --git a/frida_mode/test/js/Makefile b/frida_mode/test/js/Makefile new file mode 100644 index 00000000..8a2b6fb0 --- /dev/null +++ b/frida_mode/test/js/Makefile @@ -0,0 +1,25 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + +clean: + @gmake clean + +frida_js_entry: + @gmake frida_js_entry + +frida_js_replace: + @gmake frida_js_replace + +frida_js_patch: + @gmake frida_js_patch + +frida_js_stalker: + @gmake frida_js_stalker + +debug: + @gmake debug diff --git a/frida_mode/test/js/entry.js b/frida_mode/test/js/entry.js new file mode 100644 index 00000000..f10ef2d1 --- /dev/null +++ b/frida_mode/test/js/entry.js @@ -0,0 +1,20 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +Afl.print(`PID: ${Process.id}`); + +new ModuleMap().values().forEach(m => { + Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`); +}); + +const entry_point = DebugSymbol.fromName('run'); +Afl.print(`entry_point: ${entry_point.address}`); + +Afl.setEntryPoint(entry_point.address); + +// Afl.error('HARD NOPE'); + +Afl.done(); +Afl.print("done"); diff --git a/frida_mode/test/js/patch.js b/frida_mode/test/js/patch.js new file mode 100644 index 00000000..485a434f --- /dev/null +++ b/frida_mode/test/js/patch.js @@ -0,0 +1,34 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +const main = DebugSymbol.fromName('main').address; +Afl.print(`main: ${main}`); +Afl.setEntryPoint(main); +Afl.setPersistentAddress(main); +Afl.setPersistentCount(10000000); + +const crc32_check = DebugSymbol.fromName('crc32_check').address; +const crc32_replacement = new NativeCallback( + (buf, len) => { + Afl.print(`len: ${len}`); + if (len < 4) { + return 0; + } + + return 1; + }, + 'int', + ['pointer', 'int']); +Interceptor.replace(crc32_check, crc32_replacement); + +const some_boring_bug = DebugSymbol.fromName('some_boring_bug').address +const boring_replacement = new NativeCallback( + (c) => { }, + 'void', + ['char']); +Interceptor.replace(some_boring_bug, boring_replacement); + +Afl.done(); +Afl.print("done"); diff --git a/frida_mode/test/js/replace.js b/frida_mode/test/js/replace.js new file mode 100644 index 00000000..4e1e7eb7 --- /dev/null +++ b/frida_mode/test/js/replace.js @@ -0,0 +1,43 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +Afl.print(`PID: ${Process.id}`); + +const name = Process.enumerateModules()[0].name; +Afl.print(`Name: ${name}`); + +new ModuleMap().values().forEach(m => { + Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`); +}); + +const slow = DebugSymbol.fromName('slow').address; +Afl.print(`slow: ${slow}`); + +const LLVMFuzzerTestOneInput = DebugSymbol.fromName('LLVMFuzzerTestOneInput').address; +Afl.print(`LLVMFuzzerTestOneInput: ${LLVMFuzzerTestOneInput}`); + +const cm = new CModule(` + + extern unsigned char * __afl_fuzz_ptr; + extern unsigned int * __afl_fuzz_len; + extern void LLVMFuzzerTestOneInput(char *buf, int len); + + void slow(void) { + + LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len); + } + `, + { + LLVMFuzzerTestOneInput: LLVMFuzzerTestOneInput, + __afl_fuzz_ptr: Afl.getAflFuzzPtr(), + __afl_fuzz_len: Afl.getAflFuzzLen() + }); + +Afl.setEntryPoint(cm.slow); +Afl.setPersistentAddress(cm.slow); +Afl.setInMemoryFuzzing(); +Interceptor.replace(slow, cm.slow); +Afl.print("done"); +Afl.done(); diff --git a/frida_mode/test/js/stalker.js b/frida_mode/test/js/stalker.js new file mode 100644 index 00000000..33f024f5 --- /dev/null +++ b/frida_mode/test/js/stalker.js @@ -0,0 +1,109 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +const main = DebugSymbol.fromName('main').address; +Afl.print(`main: ${main}`); +Afl.setEntryPoint(main); +Afl.setPersistentAddress(main); +Afl.setPersistentCount(10000000); + +/* Replace CRC-32 check */ +const crc32_check = DebugSymbol.fromName('crc32_check').address; +const crc32_replacement = new NativeCallback( + (buf, len) => { + if (len < 4) { + return 0; + } + + return 1; + }, + 'int', + ['pointer', 'int']); +Interceptor.replace(crc32_check, crc32_replacement); + +/* Patch out the first boring bug */ +const some_boring_bug = DebugSymbol.fromName('some_boring_bug').address +const boring_replacement = new NativeCallback( + (c) => { }, + 'void', + ['char']); +Interceptor.replace(some_boring_bug, boring_replacement); + +/* Modify the instructions */ +const some_boring_bug2 = DebugSymbol.fromName('some_boring_bug2').address +const pid = Memory.alloc(4); +pid.writeInt(Process.id); + +const cm = new CModule(` + #include <stdio.h> + #include <gum/gumstalker.h> + + typedef int pid_t; + + #define STDERR_FILENO 2 + #define BORING2_LEN 10 + + extern int dprintf(int fd, const char *format, ...); + extern void some_boring_bug2(char c); + extern pid_t getpid(void); + extern pid_t pid; + + gboolean js_stalker_callback(const cs_insn *insn, gboolean begin, + gboolean excluded, GumStalkerOutput *output) + { + pid_t my_pid = getpid(); + GumX86Writer *cw = output->writer.x86; + + if (GUM_ADDRESS(insn->address) < GUM_ADDRESS(some_boring_bug2)) { + + return TRUE; + + } + + if (GUM_ADDRESS(insn->address) >= + GUM_ADDRESS(some_boring_bug2) + BORING2_LEN) { + + return TRUE; + + } + + if (my_pid == pid) { + + if (begin) { + + dprintf(STDERR_FILENO, "\n> 0x%016lX: %s %s\n", insn->address, + insn->mnemonic, insn->op_str); + + } else { + + dprintf(STDERR_FILENO, " 0x%016lX: %s %s\n", insn->address, + insn->mnemonic, insn->op_str); + + } + + } + + if (insn->id == X86_INS_UD2) { + + gum_x86_writer_put_nop(cw); + return FALSE; + + } else { + + return TRUE; + + } + } + `, + { + dprintf: Module.getExportByName(null, 'dprintf'), + getpid: Module.getExportByName(null, 'getpid'), + some_boring_bug2: some_boring_bug2, + pid: pid + }); +Afl.setStalkerCallback(cm.js_stalker_callback) +Afl.setStdErr("/tmp/stderr.txt"); +Afl.done(); +Afl.print("done"); diff --git a/frida_mode/test/js/test.c b/frida_mode/test/js/test.c new file mode 100644 index 00000000..bbda5ccf --- /dev/null +++ b/frida_mode/test/js/test.c @@ -0,0 +1,115 @@ +/* + american fuzzy lop++ - a trivial program to test the build + -------------------------------------------------------- + Originally written by Michal Zalewski + Copyright 2014 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include <fcntl.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +void LLVMFuzzerTestOneInput(char *buf, int len) { + + if (len < 1) return; + buf[len] = 0; + + // we support three input cases + if (buf[0] == '0') + printf("Looks like a zero to me!\n"); + else if (buf[0] == '1') + printf("Pretty sure that is a one!\n"); + else + printf("Neither one or zero? How quaint!\n"); + +} + +int run(char *file) { + + int fd = -1; + off_t len; + char * buf = NULL; + size_t n_read; + int result = -1; + + do { + + dprintf(STDERR_FILENO, "Running: %s\n", file); + + fd = open(file, O_RDONLY); + if (fd < 0) { + + perror("open"); + break; + + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + + perror("lseek (SEEK_END)"); + break; + + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + + perror("lseek (SEEK_SET)"); + break; + + } + + buf = malloc(len); + if (buf == NULL) { + + perror("malloc"); + break; + + } + + n_read = read(fd, buf, len); + if (n_read != len) { + + perror("read"); + break; + + } + + dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); + + LLVMFuzzerTestOneInput(buf, len); + dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); + + result = 0; + + } while (false); + + if (buf != NULL) { free(buf); } + + if (fd != -1) { close(fd); } + + return result; + +} + +void slow() { + + usleep(100000); + +} + +int main(int argc, char **argv) { + + if (argc != 2) { return 1; } + slow(); + return run(argv[1]); + +} + diff --git a/frida_mode/test/js/test2.c b/frida_mode/test/js/test2.c new file mode 100644 index 00000000..d16f35fc --- /dev/null +++ b/frida_mode/test/js/test2.c @@ -0,0 +1,177 @@ +/* + american fuzzy lop++ - a trivial program to test the build + -------------------------------------------------------- + Originally written by Michal Zalewski + Copyright 2014 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include <fcntl.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#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; +} + +/* + * Don't you hate those contrived examples which CRC their data. We can use + * 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) { + 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; +} + +/* + * So you've found a really boring bug in an earlier campaign which results in + * a NULL dereference or something like that. That bug can get in the way, + * causing the persistent loop to exit whenever it is triggered, and can also + * 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': + __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"); + +void LLVMFuzzerTestOneInput(char *buf, int len) { + + if (!crc32_check(buf, len)) return; + + some_boring_bug(buf[0]); + some_boring_bug2(buf[0]); + + if (buf[0] == '0') { + printf("Looks like a zero to me!\n"); + } + else if (buf[0] == '1') { + printf("Pretty sure that is a one!\n"); + } + else if (buf[0] == '2') { + printf("Oh we, weren't expecting that!"); + __builtin_trap(); + } + else + printf("Neither one or zero? How quaint!\n"); + +} + +int main(int argc, char **argv) { + + int fd = -1; + off_t len; + char * buf = NULL; + size_t n_read; + int result = -1; + + if (argc != 2) { return 1; } + + printf("Running: %s\n", argv[1]); + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { return 1; } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { return 1; } + + if (lseek(fd, 0, SEEK_SET) != 0) { return 1; } + + buf = malloc(len); + if (buf == NULL) { return 1; } + + n_read = read(fd, buf, len); + if (n_read != len) { return 1; } + + printf("Running: %s: (%zd bytes)\n", argv[1], n_read); + + LLVMFuzzerTestOneInput(buf, len); + printf("Done: %s: (%zd bytes)\n", argv[1], n_read); + + return 0; +} + diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile index e30f2049..8a10be07 100644 --- a/frida_mode/test/libpcap/GNUmakefile +++ b/frida_mode/test/libpcap/GNUmakefile @@ -2,8 +2,7 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c -AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so +AFLPP_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/hook.so LIBPCAP_BUILD_DIR:=$(BUILD_DIR)libpcap/ HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/ @@ -137,11 +136,6 @@ $(TEST_BIN): $(HARNESS_OBJ) $(PCAPTEST_OBJ) $(LIBPCAP_LIB) $(LDFLAGS) \ $(TEST_BIN_LDFLAGS) \ -########## HOOK ######## - -$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR) - $(CC) -shared $(CFLAGS) $(LDFLAGS) $< -o $@ - ########## DUMMY ####### $(AFLPP_DRIVER_DUMMY_INPUT): | $(TCPDUMP_TESTS_DIR) @@ -149,8 +143,6 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(TCPDUMP_TESTS_DIR) ###### TEST DATA ####### -hook: $(AFLPP_DRIVER_HOOK_OBJ) - clean: rm -rf $(BUILD_DIR) diff --git a/frida_mode/test/libpcap/aflpp_qemu_driver_hook.c b/frida_mode/test/libpcap/aflpp_qemu_driver_hook.c deleted file mode 100644 index 059d438d..00000000 --- a/frida_mode/test/libpcap/aflpp_qemu_driver_hook.c +++ /dev/null @@ -1,97 +0,0 @@ -#include <stdint.h> -#include <string.h> - -#if defined(__x86_64__) - -struct x86_64_regs { - - uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, - r15; - - union { - - uint64_t rip; - uint64_t pc; - - }; - - union { - - uint64_t rsp; - uint64_t sp; - - }; - - union { - - uint64_t rflags; - uint64_t flags; - - }; - - uint8_t zmm_regs[32][64]; - -}; - -void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - memcpy((void *)regs->rdi, input_buf, input_buf_len); - regs->rsi = input_buf_len; - -} - -#elif defined(__i386__) - -struct x86_regs { - - uint32_t eax, ebx, ecx, edx, edi, esi, ebp; - - union { - - uint32_t eip; - uint32_t pc; - - }; - - union { - - uint32_t esp; - uint32_t sp; - - }; - - union { - - uint32_t eflags; - uint32_t flags; - - }; - - uint8_t xmm_regs[8][16]; - -}; - -void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - void **esp = (void **)regs->esp; - void * arg1 = esp[1]; - void **arg2 = &esp[2]; - memcpy(arg1, input_buf, input_buf_len); - *arg2 = (void *)input_buf_len; - -} - -#else - #pragma error "Unsupported architecture" -#endif - -int afl_persistent_hook_init(void) { - - // 1 for shared memory input (faster), 0 for normal input (you have to use - // read(), input_buf will be NULL) - return 1; - -} - diff --git a/frida_mode/test/persistent_ret/GNUmakefile b/frida_mode/test/persistent_ret/GNUmakefile index 2de51d86..f11269e3 100644 --- a/frida_mode/test/persistent_ret/GNUmakefile +++ b/frida_mode/test/persistent_ret/GNUmakefile @@ -82,6 +82,16 @@ frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) -- \ $(TESTINSTBIN) @@ +frida_js: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + AFL_FRIDA_JS_SCRIPT=test.js \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) gdb \ --ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \ @@ -92,6 +102,15 @@ debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) --ex 'set disassembly-flavor intel' \ --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) +debug_js: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + gdb \ + --ex 'set environment AFL_FRIDA_JS_SCRIPT=test.js' \ + --ex 'set environment AFL_FRIDA_PERSISTENT_DEBUG=1' \ + --ex 'set environment AFL_DEBUG_CHILD=1' \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + run: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \ diff --git a/frida_mode/test/persistent_ret/test.js b/frida_mode/test/persistent_ret/test.js new file mode 100644 index 00000000..8adb45b2 --- /dev/null +++ b/frida_mode/test/persistent_ret/test.js @@ -0,0 +1,48 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +Afl.print(`PID: ${Process.id}`); + +const name = Process.enumerateModules()[0].name; +Afl.print(`Name: ${name}`); + +new ModuleMap().values().forEach(m => { + Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`); +}); + +if (name === 'testinstr') { + const persistent_addr = DebugSymbol.fromName('LLVMFuzzerTestOneInput').address; + Afl.print(`persistent_addr: ${persistent_addr}`); + Afl.setEntryPoint(persistent_addr); + Afl.setPersistentAddress(persistent_addr); + Afl.setInstrumentDebugFile("/dev/stdout"); + Afl.setPersistentDebug(); + Afl.setInstrumentNoOptimize(); + Afl.setInstrumentEnableTracing(); + + const LLVMFuzzerTestOneInput = new NativeFunction( + persistent_addr, + 'void', + ['pointer', 'uint64'], + {traps: "all"}); + + const persistentHook = new NativeCallback( + (data, size) => { + const input = Afl.aflFuzzPtr.readPointer(); + const len = Afl.aflFuzzLen.readPointer().readU32(); + const hd = hexdump(input, {length: len, header: false, ansi: true}); + Afl.print(`input: ${hd}`); + LLVMFuzzerTestOneInput(input, len); + }, + 'void', + ['pointer', 'uint64']); + + Afl.aflSharedMemFuzzing.writeInt(1); + Interceptor.replace(persistent_addr, persistentHook); + Interceptor.flush(); +} + +Afl.print("done"); +Afl.done(); diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c index 6cb88a50..42e3519a 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -17,13 +17,14 @@ #include <unistd.h> #ifdef __APPLE__ - #define TESTINSTR_SECTION + #define MAIN_SECTION #else - #define TESTINSTR_SECTION __attribute__((section(".testinstr"))) + #define MAIN_SECTION __attribute__((section(".main"))) #endif -void testinstr(char *buf, int len) { +void LLVMFuzzerTestOneInput(char *buf, int len) { + printf (">>> LLVMFuzzerTestOneInput >>>\n"); if (len < 1) return; buf[len] = 0; @@ -43,7 +44,7 @@ void slow() { } -TESTINSTR_SECTION int main(int argc, char **argv) { +MAIN_SECTION int main(int argc, char **argv) { char * file; int fd = -1; @@ -101,7 +102,7 @@ TESTINSTR_SECTION int main(int argc, char **argv) { dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); - testinstr(buf, len); + LLVMFuzzerTestOneInput(buf, len); dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); slow(); diff --git a/frida_mode/test/png/persistent/hook/GNUmakefile b/frida_mode/test/png/persistent/hook/GNUmakefile index b17f3775..0ff9fe86 100644 --- a/frida_mode/test/png/persistent/hook/GNUmakefile +++ b/frida_mode/test/png/persistent/hook/GNUmakefile @@ -2,8 +2,7 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c -AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so +AFLPP_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/hook.so CFLAGS+=-O3 \ -funroll-loops \ @@ -48,7 +47,7 @@ endif .PHONY: all 32 clean format qemu qemu_entry frida frida_entry debug -all: $(AFLPP_DRIVER_HOOK_OBJ) +all: make -C $(ROOT)frida_mode/test/png/persistent/ 32: @@ -68,9 +67,6 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) truncate -s 1M $@ -$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR) - $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ - qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ @@ -124,6 +120,28 @@ frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) +frida_js_load: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) + AFL_FRIDA_JS_SCRIPT=load.js \ + $(ROOT)afl-fuzz \ + -D \ + -V 30 \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + +frida_js_cmodule: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) + AFL_FRIDA_JS_SCRIPT=cmodule.js \ + $(ROOT)afl-fuzz \ + -D \ + -V 30 \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + debug: $(AFLPP_DRIVER_DUMMY_INPUT) echo $(AFL_FRIDA_PERSISTENT_ADDR) gdb \ diff --git a/frida_mode/test/png/persistent/hook/Makefile b/frida_mode/test/png/persistent/hook/Makefile index 983d009e..dca51d85 100644 --- a/frida_mode/test/png/persistent/hook/Makefile +++ b/frida_mode/test/png/persistent/hook/Makefile @@ -24,5 +24,8 @@ frida: frida_entry: @gmake frida_entry +frida_js: + @gmake frida_js + debug: @gmake debug diff --git a/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c b/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c deleted file mode 100644 index 1542c0bf..00000000 --- a/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c +++ /dev/null @@ -1,193 +0,0 @@ -#include <stdint.h> -#include <string.h> - -#if defined(__x86_64__) - -struct x86_64_regs { - - uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, - r15; - - union { - - uint64_t rip; - uint64_t pc; - - }; - - union { - - uint64_t rsp; - uint64_t sp; - - }; - - union { - - uint64_t rflags; - uint64_t flags; - - }; - - uint8_t zmm_regs[32][64]; - -}; - -void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - memcpy((void *)regs->rdi, input_buf, input_buf_len); - regs->rsi = input_buf_len; - -} - -#elif defined(__i386__) - -struct x86_regs { - - uint32_t eax, ebx, ecx, edx, edi, esi, ebp; - - union { - - uint32_t eip; - uint32_t pc; - - }; - - union { - - uint32_t esp; - uint32_t sp; - - }; - - union { - - uint32_t eflags; - uint32_t flags; - - }; - - uint8_t xmm_regs[8][16]; - -}; - -void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - void **esp = (void **)regs->esp; - 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 { - - uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10; - - union { - - uint64_t x11; - uint32_t fp_32; - - }; - - union { - - uint64_t x12; - uint32_t ip_32; - - }; - - union { - - uint64_t x13; - uint32_t sp_32; - - }; - - union { - - uint64_t x14; - uint32_t lr_32; - - }; - - union { - - uint64_t x15; - uint32_t pc_32; - - }; - - union { - - uint64_t x16; - uint64_t ip0; - - }; - - union { - - uint64_t x17; - uint64_t ip1; - - }; - - uint64_t x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28; - - union { - - uint64_t x29; - uint64_t fp; - - }; - - union { - - uint64_t x30; - uint64_t lr; - - }; - - union { - - uint64_t x31; - uint64_t sp; - - }; - - // the zero register is not saved here ofc - - uint64_t pc; - - uint32_t cpsr; - - uint8_t vfp_zregs[32][16 * 16]; - uint8_t vfp_pregs[17][32]; - uint32_t vfp_xregs[16]; - -}; - -void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - memcpy((void *)regs->x0, input_buf, input_buf_len); - regs->x1 = input_buf_len; -} - -#else - #pragma error "Unsupported architecture" -#endif - -int afl_persistent_hook_init(void) { - - // 1 for shared memory input (faster), 0 for normal input (you have to use - // read(), input_buf will be NULL) - return 1; - -} - diff --git a/frida_mode/test/png/persistent/hook/cmodule.js b/frida_mode/test/png/persistent/hook/cmodule.js new file mode 100644 index 00000000..ab8bdc66 --- /dev/null +++ b/frida_mode/test/png/persistent/hook/cmodule.js @@ -0,0 +1,39 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +Afl.print(`PID: ${Process.id}`); + +const name = Process.enumerateModules()[0].name; +Afl.print(`Name: ${name}`); + +new ModuleMap().values().forEach(m => { + Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`); +}); + +const persistent_addr = DebugSymbol.fromName('LLVMFuzzerTestOneInput').address; +Afl.print(`persistent_addr: ${persistent_addr}`); +Afl.setEntryPoint(persistent_addr); +Afl.setPersistentAddress(persistent_addr); + +const cm = new CModule(` + + #include <string.h> + #include <gum/gumdefs.h> + + void afl_persistent_hook(GumCpuContext *regs, uint8_t *input_buf, + uint32_t input_buf_len) { + + memcpy((void *)regs->rdi, input_buf, input_buf_len); + regs->rsi = input_buf_len; + + } + `, + { + memcpy: Module.getExportByName(null, 'memcpy') + }); +Afl.setPersistentHook(cm.afl_persistent_hook); + +Afl.print("done"); +Afl.done(); diff --git a/frida_mode/test/png/persistent/hook/load.js b/frida_mode/test/png/persistent/hook/load.js new file mode 100644 index 00000000..ce4374ae --- /dev/null +++ b/frida_mode/test/png/persistent/hook/load.js @@ -0,0 +1,27 @@ +Afl.print('******************'); +Afl.print('* AFL FRIDA MODE *'); +Afl.print('******************'); +Afl.print(''); + +Afl.print(`PID: ${Process.id}`); + +const name = Process.enumerateModules()[0].name; +Afl.print(`Name: ${name}`); + +new ModuleMap().values().forEach(m => { + Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`); +}); + +const persistent_addr = DebugSymbol.fromName('LLVMFuzzerTestOneInput').address; +Afl.print(`persistent_addr: ${persistent_addr}`); +Afl.setEntryPoint(persistent_addr); +Afl.setPersistentAddress(persistent_addr); + +const path = Afl.module.path; +const dir = path.substring(0, path.lastIndexOf("/")); +const mod = Module.load(`${dir}/frida_mode/build/hook.so`); +const hook = mod.getExportByName('afl_persistent_hook'); +Afl.setPersistentHook(hook); + +Afl.print("done"); +Afl.done(); diff --git a/frida_mode/test/proj4/GNUmakefile b/frida_mode/test/proj4/GNUmakefile new file mode 100644 index 00000000..e324a5d0 --- /dev/null +++ b/frida_mode/test/proj4/GNUmakefile @@ -0,0 +1,164 @@ +PWD:=$(shell pwd)/ +ROOT:=$(shell realpath $(PWD)../../..)/ +BUILD_DIR:=$(PWD)build/ + +AFLPP_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/hook.so + +LIBPROJ4_BUILD_DIR:=$(BUILD_DIR)libproj4/ +HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/ +PROJ4TEST_BUILD_DIR:=$(BUILD_DIR)proj4test/ + +LIBPROJ4_URL:=https://github.com/OSGeo/PROJ +LIBPROJ4_DIR:=$(LIBPROJ4_BUILD_DIR)libproj4/ +LIBPROJ4_CONFIGURE:=$(LIBPROJ4_DIR)configure.ac +LIBPROJ4_MAKEFILE:=$(LIBPROJ4_DIR)Makefile +LIBPROJ4_LIB:=$(LIBPROJ4_DIR)src/.libs/libproj.a + +HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c +HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o +HARNESS_URL:="https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/aflpp_driver/aflpp_qemu_driver.c" + +PROJ4TEST_FILE:=$(PROJ4TEST_BUILD_DIR)target.cc +PROJ4TEST_OBJ:=$(PROJ4TEST_BUILD_DIR)target.o +PROJ4TEST_URL:="https://raw.githubusercontent.com/OSGeo/PROJ/d00501750b210a73f9fb107ac97a683d4e3d8e7a/test/fuzzers/standard_fuzzer.cpp" + +LDFLAGS += -lpthread + +TEST_BIN:=$(BUILD_DIR)test +ifeq "$(shell uname)" "Darwin" +TEST_BIN_LDFLAGS:=-undefined dynamic_lookup +endif + +TEST_DATA_DIR:=$(BUILD_DIR)in/ +TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed + +FRIDA_OUT:=$(BUILD_DIR)frida-out + +ifndef ARCH + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + +ifeq "$(ARCH)" "aarch64" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000) +endif + +ifeq "$(ARCH)" "x86_64" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000) +endif + +ifeq "$(ARCH)" "x86" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000) +endif + +.PHONY: all clean frida hook + +all: $(TEST_BIN) + make -C $(ROOT)frida_mode/ + +32: + CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +######### HARNESS ######## +$(HARNESS_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(HARNESS_FILE): | $(HARNESS_BUILD_DIR) + wget -O $@ $(HARNESS_URL) + +$(HARNESS_OBJ): $(HARNESS_FILE) + $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ -c $< + +######### PROJ4TEST ######## + +$(PROJ4TEST_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(PROJ4TEST_FILE): | $(PROJ4TEST_BUILD_DIR) + wget -O $@ $(PROJ4TEST_URL) + +$(PROJ4TEST_OBJ): $(PROJ4TEST_FILE) | $(LIBPROJ4_MAKEFILE) + $(CXX) $(CXXFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBPROJ4_DIR)src/ -o $@ -c $< + +######### LIBPROJ4 ######## + +$(LIBPROJ4_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(LIBPROJ4_CONFIGURE): $(LIBPROJ4_BUILD_DIR) + git clone $(LIBPROJ4_URL) $(LIBPROJ4_DIR) + cd $(LIBPROJ4_DIR) && git checkout d00501750b210a73f9fb107ac97a683d4e3d8e7a + +$(LIBPROJ4_MAKEFILE): $(LIBPROJ4_CONFIGURE) + cd $(LIBPROJ4_DIR) && ./autogen.sh + cd $(LIBPROJ4_DIR) && ./configure + +$(LIBPROJ4_LIB): $(LIBPROJ4_MAKEFILE) + make -C $(LIBPROJ4_DIR) -j $(shell nproc) + +######### TEST ######## + +$(TEST_BIN): $(HARNESS_OBJ) $(PROJ4TEST_OBJ) $(LIBPROJ4_LIB) + $(CXX) \ + $(CFLAGS) \ + -o $@ \ + $(HARNESS_OBJ) $(PROJ4TEST_OBJ) $(LIBPROJ4_LIB) \ + -lz \ + $(LDFLAGS) \ + $(TEST_BIN_LDFLAGS) \ + +########## DUMMY ####### + +$(TEST_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TEST_DATA_FILE): | $(TEST_DATA_DIR) + echo "hi" > $(TEST_DATA_FILE) + +###### TEST DATA ####### + +clean: + rm -rf $(BUILD_DIR) + +frida: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) + AFL_DEBUG_CHILD=1 \ + AFL_DISABLE_TRIM=1 \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \ + AFL_NO_AFFINITY=1 \ + X__AFL_NO_UI=1 \ + AFL_PATH=/out \ + AFL_SHUFFLE_QUEUE=1 \ + AFL_SKIP_CPUFREQ=1 \ + AFL_SKIP_CRASHES=1 \ + AFL_TESTCACHE_SIZE=2 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -m none \ + -t 1000+ \ + -d \ + -O \ + -c 0\ + -V 30 \ + -- \ + $(TEST_BIN) 2147483647 + +debug: + gdb \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --args $(TEST_BIN) $(TEST_DATA_DIR)basn0g01.proj4 diff --git a/frida_mode/test/proj4/Makefile b/frida_mode/test/proj4/Makefile new file mode 100644 index 00000000..f83e2992 --- /dev/null +++ b/frida_mode/test/proj4/Makefile @@ -0,0 +1,17 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + +clean: + @gmake clean + +frida: + @gmake frida + +debug: + @gmake debug + diff --git a/frida_mode/test/proj4/get_symbol_addr.py b/frida_mode/test/proj4/get_symbol_addr.py new file mode 100755 index 00000000..1c46e010 --- /dev/null +++ b/frida_mode/test/proj4/get_symbol_addr.py @@ -0,0 +1,36 @@ +#!/usr/bin/python3 +import argparse +from elftools.elf.elffile import ELFFile + +def process_file(file, symbol, base): + with open(file, 'rb') as f: + elf = ELFFile(f) + symtab = elf.get_section_by_name('.symtab') + mains = symtab.get_symbol_by_name(symbol) + if len(mains) != 1: + print ("Failed to find main") + return 1 + + main_addr = mains[0]['st_value'] + main = base + main_addr + print ("0x%016x" % main) + return 0 + +def hex_value(x): + return int(x, 16) + +def main(): + parser = argparse.ArgumentParser(description='Process some integers.') + parser.add_argument('-f', '--file', dest='file', type=str, + help='elf file name', required=True) + parser.add_argument('-s', '--symbol', dest='symbol', type=str, + help='symbol name', required=True) + parser.add_argument('-b', '--base', dest='base', type=hex_value, + help='elf base address', required=True) + + args = parser.parse_args() + return process_file (args.file, args.symbol, args.base) + +if __name__ == "__main__": + ret = main() + exit(ret) diff --git a/frida_mode/test/re2/GNUmakefile b/frida_mode/test/re2/GNUmakefile index 9f0b31d3..e1c5347d 100644 --- a/frida_mode/test/re2/GNUmakefile +++ b/frida_mode/test/re2/GNUmakefile @@ -2,8 +2,7 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c -AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so +AFLPP_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/hook.so LIBRE2_BUILD_DIR:=$(BUILD_DIR)libre2/ HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/ @@ -116,11 +115,6 @@ $(TEST_BIN): $(HARNESS_OBJ) $(RE2TEST_OBJ) $(LIBRE2_LIB) $(LDFLAGS) \ $(TEST_BIN_LDFLAGS) \ -########## HOOK ######## - -$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR) - $(CC) -shared $(CFLAGS) $(LDFLAGS) $< -o $@ - ########## DUMMY ####### $(TEST_DATA_DIR): | $(BUILD_DIR) @@ -131,8 +125,6 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(TEST_DATA_DIR) ###### TEST DATA ####### -hook: $(AFLPP_DRIVER_HOOK_OBJ) - clean: rm -rf $(BUILD_DIR) diff --git a/frida_mode/test/re2/Makefile b/frida_mode/test/re2/Makefile index 00b2b287..360cdc44 100644 --- a/frida_mode/test/re2/Makefile +++ b/frida_mode/test/re2/Makefile @@ -18,5 +18,3 @@ frida: debug: @gmake debug -hook: - @gmake hook diff --git a/frida_mode/test/re2/aflpp_qemu_driver_hook.c b/frida_mode/test/re2/aflpp_qemu_driver_hook.c deleted file mode 100644 index 059d438d..00000000 --- a/frida_mode/test/re2/aflpp_qemu_driver_hook.c +++ /dev/null @@ -1,97 +0,0 @@ -#include <stdint.h> -#include <string.h> - -#if defined(__x86_64__) - -struct x86_64_regs { - - uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, - r15; - - union { - - uint64_t rip; - uint64_t pc; - - }; - - union { - - uint64_t rsp; - uint64_t sp; - - }; - - union { - - uint64_t rflags; - uint64_t flags; - - }; - - uint8_t zmm_regs[32][64]; - -}; - -void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - memcpy((void *)regs->rdi, input_buf, input_buf_len); - regs->rsi = input_buf_len; - -} - -#elif defined(__i386__) - -struct x86_regs { - - uint32_t eax, ebx, ecx, edx, edi, esi, ebp; - - union { - - uint32_t eip; - uint32_t pc; - - }; - - union { - - uint32_t esp; - uint32_t sp; - - }; - - union { - - uint32_t eflags; - uint32_t flags; - - }; - - uint8_t xmm_regs[8][16]; - -}; - -void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_buf_len) { - - void **esp = (void **)regs->esp; - void * arg1 = esp[1]; - void **arg2 = &esp[2]; - memcpy(arg1, input_buf, input_buf_len); - *arg2 = (void *)input_buf_len; - -} - -#else - #pragma error "Unsupported architecture" -#endif - -int afl_persistent_hook_init(void) { - - // 1 for shared memory input (faster), 0 for normal input (you have to use - // read(), input_buf will be NULL) - return 1; - -} - |