1
0
mirror of https://github.com/bitdefender/bddisasm.git synced 2024-12-22 22:18:09 +00:00

bdshemu_fuzz: Update build scripts

This commit is contained in:
Ionel-Cristinel ANICHITEI 2023-04-05 11:06:10 +03:00
parent 3beaac8ae2
commit d16f1d8ba3
4 changed files with 116 additions and 196 deletions

View File

@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16)
option(BDD_INCLUDE_TOOL "Include the disasmtool executable" ON) option(BDD_INCLUDE_TOOL "Include the disasmtool executable" ON)
option(BDD_INCLUDE_ISAGENERATOR "Include the isagenerator target (if a python interpreter is found)" ON) option(BDD_INCLUDE_ISAGENERATOR "Include the isagenerator target (if a python interpreter is found)" ON)
option(BDD_INCLUDE_FUZZERS "Include the bdshemu fuzzer" OFF)
option(BDD_USE_EXTERNAL_VSNPRINTF "Expect nd_vsnprintf_s implementation from the integrator" OFF) option(BDD_USE_EXTERNAL_VSNPRINTF "Expect nd_vsnprintf_s implementation from the integrator" OFF)
option(BDD_USE_EXTERNAL_MEMSET "Expect nd_memset implementation from the integrator" OFF) option(BDD_USE_EXTERNAL_MEMSET "Expect nd_memset implementation from the integrator" OFF)
@ -54,9 +55,7 @@ else ()
-Wno-unused-function -Wno-unused-function
-Wno-multichar -Wno-multichar
-Wno-incompatible-pointer-types -Wno-incompatible-pointer-types
-Wno-discarded-qualifiers
-Wnull-dereference -Wnull-dereference
-Wduplicated-cond
-Werror=format-security -Werror=format-security
-Werror=implicit-function-declaration -Werror=implicit-function-declaration
-pipe -pipe
@ -70,6 +69,12 @@ else ()
-gdwarf-4 -gdwarf-4
-grecord-gcc-switches -grecord-gcc-switches
-march=westmere) -march=westmere)
if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
list(APPEND BDDISASM_COMMON_COMPILE_OPTIONS
-Wduplicated-cond
-Wno-discarded-qualifiers)
endif ()
endif () endif ()
set(BDDISASM_PUBLIC_HEADERS set(BDDISASM_PUBLIC_HEADERS
@ -200,6 +205,11 @@ if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_ISAGENERATO
add_subdirectory(isagenerator) add_subdirectory(isagenerator)
endif () endif ()
# If this is the master project (and if the user requested it) add the fuzzer.
if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_FUZZERS)
add_subdirectory(bdshemu_fuzz)
endif ()
# If this is the master project add install and package targets. # If this is the master project add install and package targets.
if (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) if (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
set(BDDISASM_INSTALL_CMAKEDIR set(BDDISASM_INSTALL_CMAKEDIR

View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.16)
option(BDD_FUZZ_WITH_LOGS "Enable logging for the fuzzer" OFF)
project(bdshemu_fuzzer LANGUAGES C)
add_executable(shfuzzx86 bdshemu_fuzzer.c)
target_link_libraries(shfuzzx86 PRIVATE bddisasm::bdshemu)
target_compile_definitions(shfuzzx86 PRIVATE FUZZ_X86)
add_executable(shfuzzx64 bdshemu_fuzzer.c)
target_link_libraries(shfuzzx64 PRIVATE bddisasm::bdshemu)
target_compile_definitions(shfuzzx64 PRIVATE FUZZ_X64)
if (BDD_FUZZ_WITH_LOGS)
target_compile_definitions(shfuzzx86 PRIVATE ENABLE_LOGGING)
target_compile_definitions(shfuzzx64 PRIVATE ENABLE_LOGGING)
endif (BDD_FUZZ_WITH_LOGS)
add_custom_target(shfuzz DEPENDS shfuzzx86 shfuzzx64)

View File

@ -1,73 +0,0 @@
# Look for afl-fuzz. If it is in path we assume that afl-gcc/afl-clang/afl-clang-fast is present as well.
ifeq (, $(shell which afl-fuzz))
$(error "It looks like AFL is not in your path. AFL is available on GitHub: https://github.com/google/AFL")
endif
# Try to figure out which compiler we should use, afl-clang-fast being the preferred choice.
ifeq (, $(AFL_COMPILER))
# If AFL_COMPILER is not set, check if afl-clang-fast is available.
ifeq (, $(shell which afl-clang-fast))
# If it is not, try to figure out if we should use afl-gcc or afl-clang.
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
AFL_COMPILER = afl-gcc
else
AFL_COMPILER = afl-clang
endif
else
# If it is available, use it.
AFL_COMPILER = afl-clang-fast
endif
endif
ROOT_DIR := $(realpath ..)
DISASM_SRC := $(ROOT_DIR)/bddisasm
DISASM_INC := $(DISASM_SRC)/include
SHEMU_SRC := $(ROOT_DIR)/bdshemu
PUBLIC_INC := $(ROOT_DIR)/inc
SHEMU_INC := $(PUBLIC_INC)/bdshemu
FUZZER_SRC := $(ROOT_DIR)/bdshemu_fuzz
ALL_SRC := $(shell find $(DISASM_SRC)/*.c -type f)
ALL_SRC += $(shell find $(SHEMU_SRC)/*.c -type f)
ALL_SRC += $(shell find $(FUZZER_SRC)/*.c -type f)
ALL_INC := $(shell find $(DISASM_INC)/*.h -type f)
ALL_INC += $(shell find $(PUBLIC_INC)/*.h -type f)
ALL_INC += $(shell find $(SHEMU_INC)/*.h -type f)
# Enable qui ck and dirty mode, if needed.
ifeq ($(DIRTY),y)
AFL_ARGS := -d
endif
ifdef AFL_MEMORY
AFL_ARGS := -m $(AFL_MEMORY)
endif
CFLAGS := -std=c11 -fpic -fno-strict-aliasing -maes \
-D_REENTRANT -fstack-protector -ffunction-sections -fdata-sections \
-DNDEBUG -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -Ofast -g3
ifeq ($(LOG),y)
PREDEFS := -DENABLE_LOGGING
endif
# Build shfuzz with AFL instrumentation.
shfuzz: $(ALL_SRC) $(ALL_INC)
@echo "Using $(AFL_COMPILER) as a compiler"
@$(AFL_COMPILER) $(PREDEFS) $(CFLAGS) -I$(DISASM_INC) -I$(PUBLIC_INC) -I$(SHEMU_INC) $(ALL_SRC) -o shfuzz
@echo "Done!"
# Run the tests in 32-bit mode.
.PHONY: fuzz32
fuzz32: shfuzz
@afl-fuzz -i ./in-32 -o ./out-32 $(AFL_ARGS) ./shfuzz @@ 32
# Run the tests in 64-bit mode.
.PHONY: fuzz64
fuzz64: shfuzz
@afl-fuzz -i ./in-64 -o ./out-64 $(AFL_ARGS) ./shfuzz @@ 64
.PHONY: clean
clean:
@rm -f ./shfuzz

View File

@ -2,82 +2,43 @@
* Copyright (c) 2020 Bitdefender * Copyright (c) 2020 Bitdefender
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#endif
#include <limits.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "bddisasm.h" #include "bddisasm.h"
#include "bdshemu.h" #include "bdshemu.h"
#pragma clang optimize off
#pragma GCC optimize("O0")
#ifdef ENABLE_LOGGING #ifdef ENABLE_LOGGING
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) #define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else #else
#define LOG(fmt, ...) #define LOG(fmt, ...)
#endif // ENABLE_LOGGING #endif // ENABLE_LOGGING
#ifndef __AFL_LOOP
#warning "Persistent mode will not work (you are probably not using afl-clang-fast)"
#endif
int nd_vsnprintf_s(
char *buffer,
size_t sizeOfBuffer,
size_t count,
const char *format,
va_list argptr
)
{
return vsnprintf(buffer, sizeOfBuffer, format, argptr);
}
void *nd_memset(void *s, int c, size_t n)
{
return memset(s, c, n);
}
uint8_t *read_file(const char *fpath, size_t *size)
{
uint8_t *buffer;
FILE *fd = fopen(fpath, "rb");
if (fd == NULL)
{
LOG("[-] Failed to open \"%s\"\n", fpath);
return NULL;
}
fseek(fd, 0ull, SEEK_END);
*size = ftell(fd);
rewind(fd);
buffer = malloc(*size);
if (buffer == NULL)
{
LOG("[-] Failed to allocate %zu bytes\n", *size);
}
else
{
fread(buffer, *size, 1, fd);
}
fclose(fd);
return buffer;
}
static bool gUseLog;
void ShemuLog(char *data) void ShemuLog(char *data)
{ {
if (gUseLog) LOG("%s", data);
{
LOG("%s", data);
}
} }
void run_shemu(uint8_t *Data, size_t Size, uint8_t Def) #ifdef FUZZ_X86
#define DEF_CODE ND_CODE_32
#define FUZZER_TYPE "x86"
#else
#define DEF_CODE ND_CODE_64
#define FUZZER_TYPE "x64"
#endif // FUZZ_X86
void run_shemu(uint8_t *Data, size_t Size)
{ {
// More or less copy pasted from disasmtool // More or less copy pasted from disasmtool
@ -119,7 +80,7 @@ void run_shemu(uint8_t *Data, size_t Size, uint8_t Def)
ctx.Segments.Gs.Selector = 0x30; ctx.Segments.Gs.Selector = 0x30;
ctx.Segments.Gs.Base = 0x7FFF0000; ctx.Segments.Gs.Base = 0x7FFF0000;
ctx.Mode = Def; ctx.Mode = DEF_CODE;
ctx.Ring = 3; ctx.Ring = 3;
ctx.TibBase = ctx.Mode == ND_CODE_32 ? ctx.Segments.Fs.Base : ctx.Segments.Gs.Base; ctx.TibBase = ctx.Mode == ND_CODE_32 ? ctx.Segments.Fs.Base : ctx.Segments.Gs.Base;
ctx.MaxInstructionsCount = 4096; ctx.MaxInstructionsCount = 4096;
@ -134,85 +95,87 @@ void run_shemu(uint8_t *Data, size_t Size, uint8_t Def)
free(ctx.Stack); free(ctx.Stack);
} }
void run_test(uint8_t *Data, size_t Size, uint8_t Def) #if defined(__AFL_FUZZ_TESTCASE_LEN)
{ #include <unistd.h>
run_shemu(Data, Size, Def);
}
int8_t arch_to_def_code(const char *arch) // See https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md
{ __AFL_FUZZ_INIT();
uint32_t a = strtoul(arch, NULL, 0);
switch (a) int main()
{
__AFL_INIT();
uint8_t *buffer = __AFL_FUZZ_TESTCASE_BUF;
while (__AFL_LOOP(UINT_MAX))
{ {
case 16: size_t size = __AFL_FUZZ_TESTCASE_LEN;
return ND_CODE_16; run_shemu(buffer, size);
case 32:
return ND_CODE_32;
case 64:
return ND_CODE_64;
default:
LOG("[-] Unknown arch: \"%s\"\n", arch);
return -1;
} }
return 0;
}
#elif defined(__clang__)
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
// Shemu will write into the shellcode buffer, so copy it to a new buffer first.
uint8_t *buffer = malloc(Size);
if (!buffer) return 1;
memcpy(buffer, Data, Size);
run_shemu(buffer, Size);
free(buffer);
return 0;
}
#else
uint8_t *read_file(const char *fpath, size_t *size)
{
uint8_t *buffer;
FILE *fd = fopen(fpath, "rb");
if (fd == NULL)
{
LOG("[-] Failed to open \"%s\"\n", fpath);
return NULL;
}
fseek(fd, 0ull, SEEK_END);
*size = ftell(fd);
rewind(fd);
buffer = malloc(*size);
if (buffer == NULL)
{
LOG("[-] Failed to allocate %zu bytes\n", *size);
}
else
{
fread(buffer, *size, 1, fd);
}
fclose(fd);
return buffer;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
size_t size = 0; if (argc < 2)
uint8_t *buffer;
int8_t defCode;
if (argc < 3)
{ {
LOG("[-] Missing arguments: <file path> <16|32|64> [activate shemu print]\n"); LOG("Missing file argument\n");
abort(); abort();
} }
defCode = arch_to_def_code(argv[2]); size_t size;
if (defCode == -1) uint8_t *buffer = read_file(argv[1], &size);
if (!buffer)
{ {
LOG("[-] read_file failed for \"%s\"\n", argv[1]);
abort(); abort();
} }
if (argc >= 4) run_shemu(buffer, size);
{ free(buffer);
LOG("[+] Will activate ShemuLog\n");
gUseLog = true;
}
else
{
gUseLog = false;
}
LOG("[+] Using def code/data = %d\n", defCode);
// __AFL_LOOP is defined only when compiling with afl-clang-fast and allows us to use
// AFL's persistent mode. We still want to be able to compile and run even if we are
// using afl-gcc or afl-clang, but there is no reason to actually have a loop here
// if we are not using persistent mode.
#ifdef __AFL_LOOP
while (__AFL_LOOP(1000))
#endif // __AFL_LOOP
{
LOG("[+] Reading data from \"%s\"\n", argv[1]);
buffer = read_file(argv[1], &size);
if (buffer == NULL)
{
abort();
}
LOG("[+] Read %zu bytes at %p (range: [%p, %p))\n", size, buffer, buffer, buffer + size);
run_test(buffer, size, (uint8_t)defCode);
free(buffer);
}
LOG("[+] Done!\n");
return 0; return 0;
} }
#endif // defined(__AFL_FUZZ_TESTCASE_LEN)