Skip to content

Commit

Permalink
Integration of llvm libFuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Sep 28, 2017
1 parent 7f6aeb0 commit 7a0dc28
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 38 deletions.
101 changes: 92 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ option(LIEF_LSAN "Enable Leak sanitizer" OFF)
option(LIEF_TSAN "Enable Thread sanitizer" OFF)
option(LIEF_USAN "Enable undefined sanitizer" OFF)

# Fuzzer
option(LIEF_FUZZING "Fuzz LIEF" OFF)

# CCACHE
# ======
Expand Down Expand Up @@ -228,6 +230,63 @@ ExternalProject_Add(lief_easyloggingpp
ExternalProject_get_property(lief_easyloggingpp SOURCE_DIR)
set(ELG_SOURCE_DIR "${SOURCE_DIR}/src")

# Fuzzing
# ~~~~~~~
set(FUZZING_FLAGS -fno-omit-frame-pointer -g -O1)
set(FUZZING_LINKER_FLAGS)

list(APPEND FUZZING_FLAGS -fsanitize=address -fsanitize-coverage=trace-pc-guard)
list(APPEND FUZZING_LINKER_FLAGS -fsanitize=address -fsanitize-coverage=trace-pc-guard)

set(LIBFUZZER_SRC_FILES)
if (LIEF_FUZZING)
message(STATUS "Fuzzing Enabled")

set(LIBFUZZER_URL "http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer")
ExternalProject_Add(lief_libfuzzer
SVN_REPOSITORY ${LIBFUZZER_URL}
CONFIGURE_COMMAND ""
UPDATE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND "")

ExternalProject_get_property(lief_libfuzzer SOURCE_DIR)
set(LIBFUZZER_SOURCE_DIR "${SOURCE_DIR}")

set(LIBFUZZER_SRC_FILES
"${LIBFUZZER_SOURCE_DIR}/FuzzerSHA1.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerUtilLinux.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerIO.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerMain.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerShmemWindows.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerUtilWindows.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerUtil.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsDlsym.cpp"
#${LIBFUZZER_SOURCE_DIR}/afl/afl_driver.cpp
"${LIBFUZZER_SOURCE_DIR}/FuzzerShmemPosix.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerUtilDarwin.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerIOWindows.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsDlsymWin.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerCrossOver.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerDriver.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWeak.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerUtilPosix.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtFunctionsWeakAlias.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerIOPosix.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerMerge.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerTracePC.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerMutate.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerExtraCounters.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerLoop.cpp"
"${LIBFUZZER_SOURCE_DIR}/FuzzerClangCounters.cpp"
)
list(APPEND LIBLIEF_SOURCE_FILES ${LIBFUZZER_SRC_FILES})

set_source_files_properties(${LIBFUZZER_SRC_FILES} PROPERTIES GENERATED TRUE)


add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/fuzzing")
endif()


# LIEF Source definition
Expand All @@ -242,6 +301,7 @@ set(LIBLIEF_SOURCE_FILES
"${mbedtls_src_crypto}"
"${mbedtls_src_x509}"
"${mbedtls_src_tls}"
"${LIBFUZZER_SRC_FILES}"
"${CMAKE_CURRENT_SOURCE_DIR}/src/logging.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/exception.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/iostream.cpp"
Expand Down Expand Up @@ -290,6 +350,8 @@ set(LIEF_INCLUDE_FILES
${LIEF_VISITOR_INCLUDE_FILES}
)



source_group("Header Files" FILES ${LIEF_INC_FILES})
source_group("Source Files" FILES ${LIBLIEF_SOURCE_FILES})

Expand Down Expand Up @@ -395,15 +457,18 @@ add_dependencies(LIB_LIEF_SHARED lief_mbed_tls)
set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED PROPERTY CXX_STANDARD 11)
set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED PROPERTY CXX_STANDARD_REQUIRED ON)
set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED PROPERTY POSITION_INDEPENDENT_CODE ON)
set(SANITIZER_FLAGS -fno-omit-frame-pointer -g -O1)


# ASAN - LSAN - TSAN - USAN
# ~~~~~~~~~~~~~~~~~~~~~~~~~
set(SANITIZER_FLAGS -fno-omit-frame-pointer -g -O1)
if (LIEF_ASAN)
message(STATUS "Address sanitizer enabled")
list(APPEND SANITIZER_FLAGS -fsanitize=address)

set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED APPEND PROPERTY LINK_FLAGS -fsanitize=address)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address")
target_link_libraries(LIB_LIEF_STATIC INTERFACE asan)
target_link_libraries(LIB_LIEF_SHARED INTERFACE asan)
endif()


Expand All @@ -412,8 +477,9 @@ if (LIEF_LSAN)
list(APPEND SANITIZER_FLAGS -fsanitize=leak)

set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED APPEND PROPERTY LINK_FLAGS -fsanitize=leak)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=leak")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=leak")

target_link_libraries(LIB_LIEF_STATIC INTERFACE lsan)
target_link_libraries(LIB_LIEF_SHARED INTERFACE lsan)
endif()


Expand All @@ -422,8 +488,9 @@ if (LIEF_TSAN)
list(APPEND SANITIZER_FLAGS -fsanitize=thread)

set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED APPEND PROPERTY LINK_FLAGS -fsanitize=thread)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread")

target_link_libraries(LIB_LIEF_STATIC INTERFACE tsan)
target_link_libraries(LIB_LIEF_SHARED INTERFACE tsan)
endif()


Expand All @@ -432,8 +499,9 @@ if (LIEF_USAN)
list(APPEND SANITIZER_FLAGS -fsanitize=undefined)

set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED APPEND PROPERTY LINK_FLAGS -fsanitize=undefined)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=undefined")

target_link_libraries(LIB_LIEF_STATIC INTERFACE ubsan)
target_link_libraries(LIB_LIEF_SHARED INTERFACE ubsan)
endif()

if (LIEF_ASAN OR LIEF_LSAN OR LIEF_TSAN OR LIEF_USAN)
Expand All @@ -443,6 +511,21 @@ if (LIEF_ASAN OR LIEF_LSAN OR LIEF_TSAN OR LIEF_USAN)
endif()


# Fuzzing
# ~~~~~~~
if (LIEF_FUZZING)
set_property(TARGET LIB_LIEF_STATIC LIB_LIEF_SHARED APPEND PROPERTY LINK_FLAGS ${FUZZING_LINKER_FLAGS})

target_compile_options(LIB_LIEF_STATIC PRIVATE ${FUZZING_FLAGS})
target_compile_options(LIB_LIEF_SHARED PRIVATE ${FUZZING_FLAGS})

target_link_libraries(LIB_LIEF_STATIC asan pthread)
target_link_libraries(LIB_LIEF_SHARED asan pthread)

add_dependencies(LIB_LIEF_STATIC lief_libfuzzer)
add_dependencies(LIB_LIEF_SHARED lief_libfuzzer)
endif()

CHECK_CXX_COMPILER_FLAG("-Weverything" HAS_WARN_EVERY)
CHECK_CXX_COMPILER_FLAG("-Wno-expansion-to-defined" HAS_NO_EXPANSION_TO_DEFINED)

Expand Down
28 changes: 0 additions & 28 deletions api/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,34 +137,6 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(pyLIEF PRIVATE ${PYLIEF_COMPILE_FLAGS})
endif()


if (LIEF_ASAN)
set_property(TARGET pyLIEF APPEND PROPERTY LINK_FLAGS -fsanitize=address)
set(PYLIEF_DEPS_LIBRARIES ${PYLIEF_DEPS_LIBRARIES} asan)
endif()


if (LIEF_LSAN)
set_property(TARGET pyLIEF APPEND PROPERTY LINK_FLAGS -fsanitize=leak)
set(PYLIEF_DEPS_LIBRARIES ${PYLIEF_DEPS_LIBRARIES} lsan)
endif()


if (LIEF_TSAN)
set_property(TARGET pyLIEF APPEND PROPERTY LINK_FLAGS -fsanitize=thread)
set(PYLIEF_DEPS_LIBRARIES ${PYLIEF_DEPS_LIBRARIES} tsan)
endif()


if (LIEF_USAN)
#set_property(TARGET pyLIEF APPEND PROPERTY LINK_FLAGS -fsanitize=undefined)
set(PYLIEF_DEPS_LIBRARIES ${PYLIEF_DEPS_LIBRARIES} ubsan)
endif()

#if (LIEF_ASAN OR LIEF_LSAN OR LIEF_TSAN OR LIEF_USAN)
# target_compile_options(pyLIEF PRIVATE ${SANITIZER_FLAGS})
#endif()

set_target_properties(pyLIEF PROPERTIES PREFIX "" OUTPUT_NAME "_pylief")
add_dependencies(pyLIEF lief_pybind11)

Expand Down
86 changes: 86 additions & 0 deletions fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
set(LIEF_FUZZER_SRC
elf_fuzzer.cpp
pe_fuzzer.cpp
macho_fuzzer.cpp
)

foreach(fuzzer ${LIEF_FUZZER_SRC})
string(REGEX REPLACE ".cpp\$" "" output "${fuzzer}")
add_executable("${output}" "${fuzzer}")
add_executable("${output}_shared" "${fuzzer}")

# Don't use default include dir
set_property(TARGET "${output}" "${output}_shared" PROPERTY INCLUDE_DIRECTORIES "")

set_property(TARGET "${output}" "${output}_shared" PROPERTY CXX_STANDARD 11)
set_property(TARGET "${output}" "${output}_shared" PROPERTY CXX_STANDARD_REQUIRED ON)

target_link_libraries("${output}" PUBLIC LIB_LIEF_STATIC)
target_link_libraries("${output}_shared" PUBLIC LIB_LIEF_SHARED)

endforeach()


# Corpus from lief-samples
set(SAMPLES_GIT_URL "https://github.com/lief-project/samples.git" CACHE STRING "URL to tests samples")
set(SAMPLES_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/corpus")
set(SAMPLES_TAG master)

ExternalProject_Add(lief_fuzzer_corpus
PREFIX ${SAMPLES_PREFIX}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
GIT_REPOSITORY ${SAMPLES_GIT_URL}
GIT_TAG ${SAMPLES_TAG}
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
)

ExternalProject_Get_Property(lief_fuzzer_corpus source_dir)
set(LIEF_CORUPUS_DIRECTORY "${source_dir}" CACHE INTERNAL "Path to LIEF samples")
message(STATUS "Samples directory: ${LIEF_CORUPUS_DIRECTORY}")



# ELF
# ===
set(ELF_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/elf-output)

add_custom_target(build-elf-fuzz-output
COMMAND ${CMAKE_COMMAND} -E make_directory ${ELF_WORKING_DIR})

add_custom_target("fuzz-elf"
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/elf_fuzzer ${LIEF_CORUPUS_DIRECTORY}/ELF -detect_leaks=1 -print_final_stats=1
DEPENDS elf_fuzzer LIB_LIEF_STATIC build-elf-fuzz-output lief_fuzzer_corpus
WORKING_DIRECTORY ${ELF_WORKING_DIR}
COMMENT "Run ELF fuzzer")


# PE
# ==
set(PE_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/pe-output)

add_custom_target(build-pe-fuzz-output
COMMAND ${CMAKE_COMMAND} -E make_directory ${PE_WORKING_DIR})

add_custom_target("fuzz-pe"
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/pe_fuzzer ${LIEF_CORUPUS_DIRECTORY}/PE -detect_leaks=1 -print_final_stats=1
DEPENDS pe_fuzzer LIB_LIEF_STATIC build-pe-fuzz-output lief_fuzzer_corpus
WORKING_DIRECTORY ${PE_WORKING_DIR}
COMMENT "Run PE fuzzer")

# MachO
# =====
set(MACHO_WORKING_DIR ${CMAKE_CURRENT_BINARY_DIR}/macho-output)

add_custom_target(build-macho-fuzz-output
COMMAND ${CMAKE_COMMAND} -E make_directory ${MACHO_WORKING_DIR})

add_custom_target("fuzz-macho"
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/macho_fuzzer ${LIEF_CORUPUS_DIRECTORY}/MachO -detect_leaks=1 -print_final_stats=1
DEPENDS macho_fuzzer LIB_LIEF_STATIC build-macho-fuzz-output lief_fuzzer_corpus
WORKING_DIRECTORY ${MACHO_WORKING_DIR}
COMMENT "Run MachO fuzzer")



13 changes: 13 additions & 0 deletions fuzzing/elf_fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <LIEF/LIEF.hpp>
#include <vector>
#include <memory>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
std::vector<uint8_t> raw = {data, data + size};
try {
std::unique_ptr<LIEF::ELF::Binary> b{LIEF::ELF::Parser::parse(raw)};
} catch (const LIEF::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}
17 changes: 17 additions & 0 deletions fuzzing/macho_fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <LIEF/LIEF.hpp>
#include <vector>
#include <memory>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
std::vector<uint8_t> raw = {data, data + size};
std::vector<LIEF::MachO::Binary*> binaries;
try {
binaries = LIEF::MachO::Parser::parse(raw);
} catch (const LIEF::exception& e) {
std::cout << e.what() << std::endl;
}
for (LIEF::MachO::Binary* b: binaries) {
delete b;
}
return 0;
}
13 changes: 13 additions & 0 deletions fuzzing/pe_fuzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <LIEF/LIEF.hpp>
#include <vector>
#include <memory>

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
std::vector<uint8_t> raw = {data, data + size};
try {
std::unique_ptr<LIEF::PE::Binary> b{LIEF::PE::Parser::parse(raw)};
} catch (const LIEF::exception& e) {
std::cout << e.what() << std::endl;
}
return 0;
}
1 change: 0 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ message(STATUS "Samples directory: ${LIEF_SAMPLES_DIRECTORY}")

# Tests options
# =============
option(LIEF_FUZZING "Fuzz LIEF" OFF)

if (NOT LIEF_ELF OR NOT LIEF_PE OR NOT LIEF_MACHO)
message(FATAL_ERROR "Tests require all LIEF's modules activated" )
Expand Down

0 comments on commit 7a0dc28

Please sign in to comment.