* 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
This commit is contained in:
Catena cyber 2018-10-06 04:49:08 -04:00 committed by Lioncash
parent b62e892b20
commit 86be817717
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
18 changed files with 773 additions and 2 deletions

View file

@ -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

View file

@ -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

22
tests/fuzz/Makefile Normal file
View file

@ -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 $@

View file

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 4096

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

View file

@ -0,0 +1,56 @@
#include <unicorn/unicorn.h>
// 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;
}

21
tests/fuzz/gentargets.sh Normal file
View file

@ -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

49
tests/fuzz/onefile.c Normal file
View file

@ -0,0 +1,49 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
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;
}