diff options
Diffstat (limited to 'frida_mode')
-rw-r--r-- | frida_mode/GNUmakefile | 2 | ||||
-rw-r--r-- | frida_mode/README.md | 12 | ||||
-rwxr-xr-x[-rw-r--r--] | frida_mode/many-linux/realpath | 0 | ||||
-rw-r--r-- | frida_mode/test/libpcap/GNUmakefile | 2 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/GNUmakefile | 163 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/Makefile | 12 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/harness.c | 69 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/harness2.c | 69 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/harness3.c | 40 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/lib.c | 17 | ||||
-rw-r--r-- | frida_mode/test/osx-lib/lib2.c | 61 | ||||
-rw-r--r-- | frida_mode/test/png/persistent/GNUmakefile | 2 | ||||
-rw-r--r-- | frida_mode/test/png/persistent/hook/GNUmakefile | 2 | ||||
-rw-r--r-- | frida_mode/test/re2/GNUmakefile | 2 | ||||
-rw-r--r-- | frida_mode/test/sqlite/GNUmakefile | 2 |
15 files changed, 449 insertions, 6 deletions
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index fad183e1..6b17982d 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -1,5 +1,5 @@ PWD:=$(shell pwd)/ -ROOT:=$(shell realpath $(PWD)..)/ +ROOT:=$(PWD)../ INC_DIR:=$(PWD)include/ SRC_DIR:=$(PWD)src/ INCLUDES:=$(wildcard $(INC_DIR)*.h) diff --git a/frida_mode/README.md b/frida_mode/README.md index 3009e171..63959af6 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -300,6 +300,18 @@ to validate memory accesses against the shadow memory. FRIDA mode has also introduced some improvements to reduce collisions in the map. See [here](MapDensity.md) for details. +# OSX Library Fuzzing +An example of how to fuzz a dynamic library on OSX is included [here](test/osx-lib). +This requires the use of a simple test harness executable which will load the +library and call a target function within it. The dependent library can either +be loaded in using `dlopen` and `dlsym` in a function marked +`__attribute__((constructor()))` or the test harness can simply be linked +against it. It is important that the target library is loaded before execution +of `main`, since this is the point that FRIDA mode is initialized. Otherwise, it +will not be possible to configure coverage for the test library using +`AFL_FRIDA_INST_RANGES` or similar. + + ## TODO The next features to be added are Aarch32 support as well as looking at diff --git a/frida_mode/many-linux/realpath b/frida_mode/many-linux/realpath index 1fdc49a7..1fdc49a7 100644..100755 --- a/frida_mode/many-linux/realpath +++ b/frida_mode/many-linux/realpath diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile index f1ad06e4..1263ce60 100644 --- a/frida_mode/test/libpcap/GNUmakefile +++ b/frida_mode/test/libpcap/GNUmakefile @@ -142,7 +142,7 @@ $(TEST_BIN): $(HARNESS_OBJ) $(PCAPTEST_OBJ) $(LIBPCAP_LIB) ########## DUMMY ####### $(AFLPP_DRIVER_DUMMY_INPUT): | $(TCPDUMP_TESTS_DIR) - truncate -s 1M $@ + dd if=/dev/zero bs=1M count=1 of=$@ ###### TEST DATA ####### diff --git a/frida_mode/test/osx-lib/GNUmakefile b/frida_mode/test/osx-lib/GNUmakefile new file mode 100644 index 00000000..de0af27b --- /dev/null +++ b/frida_mode/test/osx-lib/GNUmakefile @@ -0,0 +1,163 @@ +PWD:=$(shell pwd)/ +ROOT:=$(PWD)../../../ +BUILD_DIR:=$(PWD)build/ +TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/ +TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in +AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat + +HARNESS_BIN:=$(BUILD_DIR)harness +HARNESS_SRC:=$(PWD)harness.c + +HARNESS2_BIN:=$(BUILD_DIR)harness2 +HARNESS2_SRC:=$(PWD)harness2.c + +HARNESS3_BIN:=$(BUILD_DIR)harness3 +HARNESS3_SRC:=$(PWD)harness3.c + +LIB_BIN:=$(BUILD_DIR)libcrashme.dylib +LIB_SRC:=$(PWD)lib.c + +LIB2_BIN:=$(BUILD_DIR)libcrashme2.dylib +LIB2_SRC:=$(PWD)lib2.c + +QEMU_OUT:=$(BUILD_DIR)qemu-out +FRIDA_OUT:=$(BUILD_DIR)frida-out + +HARNESS_LDFLAGS:=-Wl,-no_pie +LIB_CFLAGS:=-dynamiclib + +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh +AFL_FRIDA_MAIN_ADDR=$(shell $(GET_SYMBOL_ADDR) $(HARNESS_BIN) main 0x0) +AFL_FRIDA_MAIN_ADDR2=$(shell $(GET_SYMBOL_ADDR) $(HARNESS2_BIN) main 0x0) +AFL_FRIDA_FUZZ_ADDR=$(shell $(GET_SYMBOL_ADDR) $(HARNESS_BIN) LLVMFuzzerTestOneInput 0x0) +AFL_FRIDA_FUZZ_ADDR2=$(shell $(GET_SYMBOL_ADDR) $(HARNESS2_BIN) LLVMFuzzerTestOneInput 0x0) +AFL_FRIDA_FUZZ_ADDR3=$(shell $(GET_SYMBOL_ADDR) $(HARNESS3_BIN) LLVMFuzzerTestOneInput 0x0) + +AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so + +TEST_FILE:=$(BUILD_DIR)test.dat + +.PHONY: all clean qemu frida + +all: $(HARNESS_BIN) $(LIB_BIN) + make -C $(ROOT)frida_mode/ + +$(BUILD_DIR): + mkdir -p $@ + +$(TESTINSTR_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) + echo -n "$$FA$$" > $@ + +$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) + dd if=/dev/zero bs=1M count=1 of=$@ + +$(HARNESS_BIN): $(HARNESS_SRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $(HARNESS_LDFLAGS) -o $@ $< + +$(LIB_BIN): $(LIB_SRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $(LIB_CFLAGS) -o $@ $< + +$(LIB2_BIN): $(LIB2_SRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $(LIB_CFLAGS) -o $@ $< + +$(HARNESS2_BIN): $(HARNESS2_SRC) $(LIB_BIN) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $(HARNESS_LDFLAGS) -o $@ $< + +$(HARNESS3_BIN): $(HARNESS3_SRC) $(LIB_BIN) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) $(HARNESS_LDFLAGS) -L$(BUILD_DIR) -lcrashme -o $@ $< + +clean: + rm -rf $(BUILD_DIR) + +LIBASAN?=/usr/local/opt/llvm/lib/clang/10.0.1/lib/darwin/libclang_rt.asan_osx_dynamic.dylib + +.ONESHELL: +frida_persistent: $(HARNESS_BIN) $(LIB_BIN) $(TESTINSTR_DATA_FILE) + cd $(BUILD_DIR) && \ + AFL_INST_LIBS=1 \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_MAIN_ADDR) \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_ENTRYPOINT=$(AFL_FRIDA_MAIN_ADDR) \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -f $(TEST_FILE) \ + -- \ + $(HARNESS_BIN) $(TEST_FILE) + +.ONESHELL: +frida_persistent_asan: $(HARNESS2_BIN) $(LIB2_BIN) $(TESTINSTR_DATA_FILE) + cd $(BUILD_DIR) && \ + AFL_PRELOAD=$(LIBASAN) \ + AFL_USE_FASAN=1 \ + AFL_INST_LIBS=1 \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_MAIN_ADDR2) \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_ENTRYPOINT=$(AFL_FRIDA_MAIN_ADDR2) \ + AFL_FRIDA_INST_RANGES=libcrashme2.dylib,harness2 \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -f $(TEST_FILE) \ + -- \ + $(HARNESS2_BIN) $(TEST_FILE) + +.ONESHELL: +frida_persistent_hook: $(HARNESS_BIN) $(LIB_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) $(TESTINSTR_DATA_FILE) + cd $(BUILD_DIR) && \ + AFL_INST_LIBS=1 \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_FUZZ_ADDR) \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_ENTRYPOINT=$(AFL_FRIDA_FUZZ_ADDR) \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_INST_RANGES=libcrashme.dylib,harness \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(HARNESS_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + +.ONESHELL: +frida_persistent_hook_asan: $(HARNESS2_BIN) $(LIB2_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) $(TESTINSTR_DATA_FILE) + cd $(BUILD_DIR) && \ + AFL_PRELOAD=$(LIBASAN) \ + AFL_USE_FASAN=1 \ + AFL_INST_LIBS=1 \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_FUZZ_ADDR2) \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_ENTRYPOINT=$(AFL_FRIDA_FUZZ_ADDR2) \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_INST_RANGES=libcrashme2.dylib,harness2 \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(HARNESS2_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + +.ONESHELL: +frida_persistent_hook3: $(HARNESS3_BIN) $(LIB_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) $(TESTINSTR_DATA_FILE) + cd $(BUILD_DIR) && \ + AFL_INST_LIBS=1 \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_FUZZ_ADDR3) \ + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_ENTRYPOINT=$(AFL_FRIDA_FUZZ_ADDR3) \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_INST_RANGES=libcrashme.dylib,harness3 \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(HARNESS3_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) diff --git a/frida_mode/test/osx-lib/Makefile b/frida_mode/test/osx-lib/Makefile new file mode 100644 index 00000000..c084de41 --- /dev/null +++ b/frida_mode/test/osx-lib/Makefile @@ -0,0 +1,12 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +clean: + @gmake clean + +frida_persistent: + @gmake frida_persistent + +frida_persistent_hook: + @gmake frida_persistent_hook diff --git a/frida_mode/test/osx-lib/harness.c b/frida_mode/test/osx-lib/harness.c new file mode 100644 index 00000000..3d427b4a --- /dev/null +++ b/frida_mode/test/osx-lib/harness.c @@ -0,0 +1,69 @@ +#include <string.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> + + +//typedef for our exported target function. +typedef void (*CRASHME)(const uint8_t *Data, size_t Size); + +//globals +CRASHME fpn_crashme = NULL; + + +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; +} + +__attribute__((constructor())) +void constructor(void) { + // handles to required libs + void *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("[+] Resolve function\n"); + + fpn_crashme = (CRASHME)dlsym(dylib, "crashme"); + if (!fpn_crashme) + { + + printf("[-] Failed to find function\n"); + exit(1); + + } + + printf("[+] Found function.\n"); +} diff --git a/frida_mode/test/osx-lib/harness2.c b/frida_mode/test/osx-lib/harness2.c new file mode 100644 index 00000000..464614ee --- /dev/null +++ b/frida_mode/test/osx-lib/harness2.c @@ -0,0 +1,69 @@ +#include <string.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <dlfcn.h> + + +//typedef for our exported target function. +typedef void (*CRASHME)(const uint8_t *Data, size_t Size); + +//globals +CRASHME fpn_crashme = NULL; + + +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; +} + +__attribute__((constructor())) +void constructor(void) { + // handles to required libs + void *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("[+] Resolve function\n"); + + fpn_crashme = (CRASHME)dlsym(dylib, "crashme"); + if (!fpn_crashme) + { + + printf("[-] Failed to find function\n"); + exit(1); + + } + + printf("[+] Found function.\n"); +} diff --git a/frida_mode/test/osx-lib/harness3.c b/frida_mode/test/osx-lib/harness3.c new file mode 100644 index 00000000..83983c99 --- /dev/null +++ b/frida_mode/test/osx-lib/harness3.c @@ -0,0 +1,40 @@ +#include <string.h> +#include <assert.h> +#include <stdio.h> +#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; +} + +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[]) +{ + + run(argc, argv); + + return 0; +} diff --git a/frida_mode/test/osx-lib/lib.c b/frida_mode/test/osx-lib/lib.c new file mode 100644 index 00000000..b2dad098 --- /dev/null +++ b/frida_mode/test/osx-lib/lib.c @@ -0,0 +1,17 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> + + +void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { + + if (Size < 5) return; + + if (Data[0] == 'F') + if (Data[1] == 'A') + if (Data[2] == '$') + 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 new file mode 100644 index 00000000..ba207210 --- /dev/null +++ b/frida_mode/test/osx-lib/lib2.c @@ -0,0 +1,61 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> + + +void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) { + + if (Size < 1) return; + + char *buf = malloc(10); + + if (buf == NULL) return; + + switch (Data[0]) { + + /* Underflow */ + case 'U': + printf("Underflow\n"); + buf[-1] = '\0'; + free(buf); + break; + /* Overflow */ + case 'O': + printf("Overflow\n"); + buf[10] = '\0'; + free(buf); + break; + /* Double free */ + case 'D': + printf("Double free\n"); + free(buf); + free(buf); + break; + /* Use after free */ + case 'A': + printf("Use after free\n"); + free(buf); + buf[0] = '\0'; + break; + /* Test Limits (OK) */ + case 'T': + printf("Test-Limits - No Error\n"); + buf[0] = 'A'; + buf[9] = 'I'; + free(buf); + break; + case 'M': + printf("Memset too many\n"); + memset(buf, '\0', 11); + free(buf); + break; + default: + printf("Nop - No Error\n"); + break; + + } + + +} + diff --git a/frida_mode/test/png/persistent/GNUmakefile b/frida_mode/test/png/persistent/GNUmakefile index c1ad86e5..f6ccfcb5 100644 --- a/frida_mode/test/png/persistent/GNUmakefile +++ b/frida_mode/test/png/persistent/GNUmakefile @@ -49,7 +49,7 @@ $(BUILD_DIR): mkdir -p $@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) - truncate -s 1M $@ + dd if=/dev/zero bs=1M count=1 of=$@ qemu: | $(BUILD_DIR) AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ diff --git a/frida_mode/test/png/persistent/hook/GNUmakefile b/frida_mode/test/png/persistent/hook/GNUmakefile index ddf63a96..049861dd 100644 --- a/frida_mode/test/png/persistent/hook/GNUmakefile +++ b/frida_mode/test/png/persistent/hook/GNUmakefile @@ -72,7 +72,7 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) - truncate -s 1M $@ + dd if=/dev/zero bs=1M count=1 of=$@ qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) | $(BUILD_DIR) AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ diff --git a/frida_mode/test/re2/GNUmakefile b/frida_mode/test/re2/GNUmakefile index ce95df3b..8e1f3682 100644 --- a/frida_mode/test/re2/GNUmakefile +++ b/frida_mode/test/re2/GNUmakefile @@ -124,7 +124,7 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(TEST_DATA_DIR) - truncate -s 1M $@ + dd if=/dev/zero bs=1M count=1 of=$@ ###### TEST DATA ####### diff --git a/frida_mode/test/sqlite/GNUmakefile b/frida_mode/test/sqlite/GNUmakefile index 80e0a939..1c856d1e 100644 --- a/frida_mode/test/sqlite/GNUmakefile +++ b/frida_mode/test/sqlite/GNUmakefile @@ -120,7 +120,7 @@ sqlite: $(SQLITE_TEST_DIR) $(TEST_BIN) ########## DUMMY ####### $(AFLPP_DRIVER_DUMMY_INPUT): | $(SQLITE_TEST_DIR) - truncate -s 1M $@ + dd if=/dev/zero bs=1M count=1 of=$@ ###### TEST DATA ####### |