Skip to content

Commit

Permalink
bdshemu_fuzz: Update build scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
ianichitei committed Apr 5, 2023
1 parent 3beaac8 commit d16f1d8
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 187 deletions.
14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16)

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_FUZZERS "Include the bdshemu fuzzer" 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)

Expand Down Expand Up @@ -54,9 +55,7 @@ else ()
-Wno-unused-function
-Wno-multichar
-Wno-incompatible-pointer-types
-Wno-discarded-qualifiers
-Wnull-dereference
-Wduplicated-cond
-Werror=format-security
-Werror=implicit-function-declaration
-pipe
Expand All @@ -70,6 +69,12 @@ else ()
-gdwarf-4
-grecord-gcc-switches
-march=westmere)

if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
list(APPEND BDDISASM_COMMON_COMPILE_OPTIONS
-Wduplicated-cond
-Wno-discarded-qualifiers)
endif ()
endif ()

set(BDDISASM_PUBLIC_HEADERS
Expand Down Expand Up @@ -200,6 +205,11 @@ if ((${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME}) AND BDD_INCLUDE_ISAGENERATO
add_subdirectory(isagenerator)
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 (${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
set(BDDISASM_INSTALL_CMAKEDIR
Expand Down
20 changes: 20 additions & 0 deletions bdshemu_fuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
73 changes: 0 additions & 73 deletions bdshemu_fuzz/Makefile

This file was deleted.

187 changes: 75 additions & 112 deletions bdshemu_fuzz/bdshemu_fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,82 +2,43 @@
* Copyright (c) 2020 Bitdefender
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "bddisasm.h"
#include "bdshemu.h"

#pragma clang optimize off
#pragma GCC optimize("O0")

#ifdef ENABLE_LOGGING
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#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)
{
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

Expand Down Expand Up @@ -119,7 +80,7 @@ void run_shemu(uint8_t *Data, size_t Size, uint8_t Def)
ctx.Segments.Gs.Selector = 0x30;
ctx.Segments.Gs.Base = 0x7FFF0000;

ctx.Mode = Def;
ctx.Mode = DEF_CODE;
ctx.Ring = 3;
ctx.TibBase = ctx.Mode == ND_CODE_32 ? ctx.Segments.Fs.Base : ctx.Segments.Gs.Base;
ctx.MaxInstructionsCount = 4096;
Expand All @@ -134,85 +95,87 @@ void run_shemu(uint8_t *Data, size_t Size, uint8_t Def)
free(ctx.Stack);
}

void run_test(uint8_t *Data, size_t Size, uint8_t Def)
{
run_shemu(Data, Size, Def);
}
#if defined(__AFL_FUZZ_TESTCASE_LEN)
#include <unistd.h>

// See https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.md
__AFL_FUZZ_INIT();

int8_t arch_to_def_code(const char *arch)
int main()
{
uint32_t a = strtoul(arch, NULL, 0);
__AFL_INIT();

switch (a)
uint8_t *buffer = __AFL_FUZZ_TESTCASE_BUF;
while (__AFL_LOOP(UINT_MAX))
{
case 16:
return ND_CODE_16;
size_t size = __AFL_FUZZ_TESTCASE_LEN;
run_shemu(buffer, size);
}

case 32:
return ND_CODE_32;
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.

case 64:
return ND_CODE_64;
uint8_t *buffer = malloc(Size);
if (!buffer) return 1;

default:
LOG("[-] Unknown arch: \"%s\"\n", arch);
return -1;
}
}
memcpy(buffer, Data, Size);
run_shemu(buffer, Size);

int main(int argc, char **argv)
free(buffer);
return 0;
}
#else
uint8_t *read_file(const char *fpath, size_t *size)
{
size_t size = 0;
uint8_t *buffer;
int8_t defCode;

if (argc < 3)
FILE *fd = fopen(fpath, "rb");
if (fd == NULL)
{
LOG("[-] Missing arguments: <file path> <16|32|64> [activate shemu print]\n");
abort();
LOG("[-] Failed to open \"%s\"\n", fpath);
return NULL;
}

defCode = arch_to_def_code(argv[2]);
if (defCode == -1)
{
abort();
}
fseek(fd, 0ull, SEEK_END);
*size = ftell(fd);
rewind(fd);

if (argc >= 4)
buffer = malloc(*size);
if (buffer == NULL)
{
LOG("[+] Will activate ShemuLog\n");
gUseLog = true;
LOG("[-] Failed to allocate %zu bytes\n", *size);
}
else
{
gUseLog = false;
fread(buffer, *size, 1, fd);
}

LOG("[+] Using def code/data = %d\n", defCode);
fclose(fd);
return buffer;
}

// __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
int main(int argc, char **argv)
{
if (argc < 2)
{
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);
LOG("Missing file argument\n");
abort();
}

free(buffer);
size_t size;
uint8_t *buffer = read_file(argv[1], &size);
if (!buffer)
{
LOG("[-] read_file failed for \"%s\"\n", argv[1]);
abort();
}

LOG("[+] Done!\n");
run_shemu(buffer, size);
free(buffer);

return 0;
}
#endif // defined(__AFL_FUZZ_TESTCASE_LEN)

0 comments on commit d16f1d8

Please sign in to comment.