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:
parent
3beaac8ae2
commit
d16f1d8ba3
@ -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
|
||||||
|
20
bdshemu_fuzz/CMakeLists.txt
Normal file
20
bdshemu_fuzz/CMakeLists.txt
Normal 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)
|
@ -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
|
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user