From 86be8177173ea4d56f2b19300d36cd7ea05f8486 Mon Sep 17 00:00:00 2001 From: Catena cyber <35799796+catenacyber@users.noreply.github.com> Date: Sat, 6 Oct 2018 04:49:08 -0400 Subject: [PATCH] Fuzz * Integration with oss-fuzz * Use CFLAGS even for linking as for fuzzing with asan * Do not abort on uc_emu_start error * Redirect fuzz output somewhere else than stdout * Use uc_open for every fuzz instance * Avoids timeouts from infinite loops Limiting the number of instructions * Moving fuzz to tests directory --- Makefile | 5 +++ samples/Makefile | 4 +-- tests/fuzz/Makefile | 22 ++++++++++++ tests/fuzz/fuzz_emu.options | 2 ++ tests/fuzz/fuzz_emu_arm64_arm.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_arm64_armbe.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_arm_arm.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_arm_armbe.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_arm_thumb.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_m68k_be.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_mips_32be.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_mips_32le.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_sparc_32be.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_x86_16.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_x86_32.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/fuzz_emu_x86_64.c | 56 +++++++++++++++++++++++++++++++ tests/fuzz/gentargets.sh | 21 ++++++++++++ tests/fuzz/onefile.c | 49 +++++++++++++++++++++++++++ 18 files changed, 773 insertions(+), 2 deletions(-) create mode 100644 tests/fuzz/Makefile create mode 100644 tests/fuzz/fuzz_emu.options create mode 100644 tests/fuzz/fuzz_emu_arm64_arm.c create mode 100644 tests/fuzz/fuzz_emu_arm64_armbe.c create mode 100644 tests/fuzz/fuzz_emu_arm_arm.c create mode 100644 tests/fuzz/fuzz_emu_arm_armbe.c create mode 100644 tests/fuzz/fuzz_emu_arm_thumb.c create mode 100644 tests/fuzz/fuzz_emu_m68k_be.c create mode 100644 tests/fuzz/fuzz_emu_mips_32be.c create mode 100644 tests/fuzz/fuzz_emu_mips_32le.c create mode 100644 tests/fuzz/fuzz_emu_sparc_32be.c create mode 100644 tests/fuzz/fuzz_emu_x86_16.c create mode 100644 tests/fuzz/fuzz_emu_x86_32.c create mode 100644 tests/fuzz/fuzz_emu_x86_64.c create mode 100644 tests/fuzz/gentargets.sh create mode 100644 tests/fuzz/onefile.c diff --git a/Makefile b/Makefile index c1c5b1f9..69f4fb41 100644 --- a/Makefile +++ b/Makefile @@ -265,6 +265,11 @@ endif $(PKGCFGF): $(generate-pkgcfg) + +.PHONY: fuzz +fuzz: all + $(MAKE) -C tests/fuzz all + .PHONY: test test: all $(MAKE) -C tests/unit test diff --git a/samples/Makefile b/samples/Makefile index 7c161e56..5b4b28de 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -135,12 +135,12 @@ endif define link-dynamic - $(CC) $< $(LDFLAGS) -o $@ + $(CC) $< ${CFLAGS} $(LDFLAGS) -o $@ endef define link-static - $(CC) $< $(ARCHIVE) $(LDFLAGS) -o $(call staticname,$@) + $(CC) $< $(ARCHIVE) ${CFLAGS} $(LDFLAGS) -o $(call staticname,$@) endef diff --git a/tests/fuzz/Makefile b/tests/fuzz/Makefile new file mode 100644 index 00000000..1e286ed2 --- /dev/null +++ b/tests/fuzz/Makefile @@ -0,0 +1,22 @@ +CFLAGS += -L ../../ -I ../../include + +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S), Linux) +LDFLAGS += -lrt -pthread +endif + +LDFLAGS += -lunicorn + + +ALL_TESTS_SOURCES = $(wildcard fuzz*.c) +ALL_TESTS = $(ALL_TESTS_SOURCES:%.c=%) + +.PHONY: all +all: ${ALL_TESTS} + +.PHONY: clean +clean: + rm -rf ${ALL_TESTS} + +fuzz%: fuzz%.c + $(CC) $(CFLAGS) $^ onefile.c $(LDFLAGS) -o $@ \ No newline at end of file diff --git a/tests/fuzz/fuzz_emu.options b/tests/fuzz/fuzz_emu.options new file mode 100644 index 00000000..9fda93fc --- /dev/null +++ b/tests/fuzz/fuzz_emu.options @@ -0,0 +1,2 @@ +[libfuzzer] +max_len = 4096 diff --git a/tests/fuzz/fuzz_emu_arm64_arm.c b/tests/fuzz/fuzz_emu_arm64_arm.c new file mode 100644 index 00000000..9e694e8d --- /dev/null +++ b/tests/fuzz/fuzz_emu_arm64_arm.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_arm64_armbe.c b/tests/fuzz/fuzz_emu_arm64_armbe.c new file mode 100644 index 00000000..716bf861 --- /dev/null +++ b/tests/fuzz/fuzz_emu_arm64_armbe.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_arm_arm.c b/tests/fuzz/fuzz_emu_arm_arm.c new file mode 100644 index 00000000..ca393175 --- /dev/null +++ b/tests/fuzz/fuzz_emu_arm_arm.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_arm_armbe.c b/tests/fuzz/fuzz_emu_arm_armbe.c new file mode 100644 index 00000000..aadd3858 --- /dev/null +++ b/tests/fuzz/fuzz_emu_arm_armbe.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_arm_thumb.c b/tests/fuzz/fuzz_emu_arm_thumb.c new file mode 100644 index 00000000..d50dd6a2 --- /dev/null +++ b/tests/fuzz/fuzz_emu_arm_thumb.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_m68k_be.c b/tests/fuzz/fuzz_emu_m68k_be.c new file mode 100644 index 00000000..cd2bf597 --- /dev/null +++ b/tests/fuzz/fuzz_emu_m68k_be.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_mips_32be.c b/tests/fuzz/fuzz_emu_mips_32be.c new file mode 100644 index 00000000..dbe31411 --- /dev/null +++ b/tests/fuzz/fuzz_emu_mips_32be.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_mips_32le.c b/tests/fuzz/fuzz_emu_mips_32le.c new file mode 100644 index 00000000..02786ce3 --- /dev/null +++ b/tests/fuzz/fuzz_emu_mips_32le.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_sparc_32be.c b/tests/fuzz/fuzz_emu_sparc_32be.c new file mode 100644 index 00000000..8d3209c0 --- /dev/null +++ b/tests/fuzz/fuzz_emu_sparc_32be.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_x86_16.c b/tests/fuzz/fuzz_emu_x86_16.c new file mode 100644 index 00000000..3e5c6c47 --- /dev/null +++ b/tests/fuzz/fuzz_emu_x86_16.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_X86, UC_MODE_16, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_x86_32.c b/tests/fuzz/fuzz_emu_x86_32.c new file mode 100644 index 00000000..d1e33053 --- /dev/null +++ b/tests/fuzz/fuzz_emu_x86_32.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/fuzz_emu_x86_64.c b/tests/fuzz/fuzz_emu_x86_64.c new file mode 100644 index 00000000..f4f63cb5 --- /dev/null +++ b/tests/fuzz/fuzz_emu_x86_64.c @@ -0,0 +1,56 @@ +#include + + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +uc_engine *uc; +int initialized = 0; +FILE * outfile = NULL; + + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + uc_err err; + + if (initialized == 0) { + if (outfile == NULL) { + // we compute the output + outfile = fopen("/dev/null", "w"); + if (outfile == NULL) { + printf("failed opening /dev/null\n"); + abort(); + return 0; + } + } + + initialized = 1; + } + + // Not global as we must reset this structure + // Initialize emulator in supplied mode + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); + if (err != UC_ERR_OK) { + printf("Failed on uc_open() with error returned: %u\n", err); + abort(); + } + + // map 4MB memory for this emulation + uc_mem_map(uc, ADDRESS, 4 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, Data, Size)) { + printf("Failed to write emulation code to memory, quit!\n"); + abort(); + } + + // emulate code in infinite time & 4096 instructions + // avoid timeouts with infinite loops + err=uc_emu_start(uc, ADDRESS, ADDRESS + Size, 0, 0x1000); + if (err) { + fprintf(outfile, "Failed on uc_emu_start() with error returned %u: %s\n", err, uc_strerror(err)); + } + + uc_close(uc); + + return 0; +} diff --git a/tests/fuzz/gentargets.sh b/tests/fuzz/gentargets.sh new file mode 100644 index 00000000..92385051 --- /dev/null +++ b/tests/fuzz/gentargets.sh @@ -0,0 +1,21 @@ +#/bin/sh +# generates all fuzz targets for different architectures from the template in fuzz_emu_x86_32.c + +sed 's/UC_MODE_32/UC_MODE_64/' fuzz_emu_x86_32.c > fuzz_emu_x86_64.c +sed 's/UC_MODE_32/UC_MODE_16/' fuzz_emu_x86_32.c > fuzz_emu_x86_16.c + +sed 's/UC_ARCH_X86/UC_ARCH_SPARC/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN/' > fuzz_emu_sparc_32be.c +#sed 's/UC_ARCH_X86/UC_ARCH_SPARC/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN/' > fuzz_emu_sparc_64be.c + +sed 's/UC_ARCH_X86/UC_ARCH_M68K/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_BIG_ENDIAN/' > fuzz_emu_m68k_be.c + +sed 's/UC_ARCH_X86/UC_ARCH_MIPS/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN/' > fuzz_emu_mips_32le.c +sed 's/UC_ARCH_X86/UC_ARCH_MIPS/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN/' > fuzz_emu_mips_32be.c + +sed 's/UC_ARCH_X86/UC_ARCH_ARM64/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_ARM/' > fuzz_emu_arm64_arm.c +sed 's/UC_ARCH_X86/UC_ARCH_ARM64/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_ARM + UC_MODE_BIG_ENDIAN/' > fuzz_emu_arm64_armbe.c + +sed 's/UC_ARCH_X86/UC_ARCH_ARM/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_ARM/' > fuzz_emu_arm_arm.c +sed 's/UC_ARCH_X86/UC_ARCH_ARM/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_THUMB/' > fuzz_emu_arm_thumb.c +sed 's/UC_ARCH_X86/UC_ARCH_ARM/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_ARM + UC_MODE_BIG_ENDIAN/' > fuzz_emu_arm_armbe.c +#sed 's/UC_ARCH_X86/UC_ARCH_ARM/' fuzz_emu_x86_32.c | sed 's/UC_MODE_32/UC_MODE_THUMB + UC_MODE_BIG_ENDIAN/' > fuzz_emu_arm_thumbbe.c diff --git a/tests/fuzz/onefile.c b/tests/fuzz/onefile.c new file mode 100644 index 00000000..3146cc07 --- /dev/null +++ b/tests/fuzz/onefile.c @@ -0,0 +1,49 @@ +#include +#include +#include + +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); + +int main(int argc, char** argv) +{ + FILE * fp; + uint8_t *Data; + size_t Size; + + if (argc != 2) { + return 1; + } + //opens the file, get its size, and reads it into a buffer + fp = fopen(argv[1], "rb"); + if (fp == NULL) { + return 2; + } + if (fseek(fp, 0L, SEEK_END) != 0) { + fclose(fp); + return 2; + } + Size = ftell(fp); + if (Size == (size_t) -1) { + fclose(fp); + return 2; + } + if (fseek(fp, 0L, SEEK_SET) != 0) { + fclose(fp); + return 2; + } + Data = malloc(Size); + if (Data == NULL) { + fclose(fp); + return 2; + } + if (fread(Data, Size, 1, fp) != 1) { + fclose(fp); + return 2; + } + + //lauch fuzzer + LLVMFuzzerTestOneInput(Data, Size); + fclose(fp); + return 0; +} +