diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 7d675281..00000000 --- a/.gitattributes +++ /dev/null @@ -1,7 +0,0 @@ -*.ispm filter=lfs diff=lfs merge=lfs -text -*.tar.gz filter=lfs diff=lfs merge=lfs -text -*.ext2 filter=lfs diff=lfs merge=lfs -text -*.fs filter=lfs diff=lfs merge=lfs -text -*.craff filter=lfs diff=lfs merge=lfs -text -Image filter=lfs diff=lfs merge=lfs -text -*.elf filter=lfs diff=lfs merge=lfs -text \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 725791e5..a7c76d15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ crate-type = ["cdylib", "rlib"] test = false [dependencies] -anyhow = { version = "1.0.86" } +anyhow = { version = "1.0.88" } libafl = { git = "https://github.com/AFLplusplus/LibAFL", rev = "0f26f6ea32aa74ee526636558842ec06bbfb49bb", default-features = false, features = [ "std", "derive", @@ -57,7 +57,7 @@ yaxpeax-x86 = { version = "2.0.0", default-features = false, features = [ "use-serde", "fmt", ] } -typed-builder = "0.19.1" +typed-builder = "0.20.0" raw-cstr = "0.1.4" goblin = "0.8.2" yaxpeax-riscv = { git = "https://github.com/DrChat/yaxpeax-riscv", version = "0.1.0", features = [ @@ -66,8 +66,8 @@ yaxpeax-riscv = { git = "https://github.com/DrChat/yaxpeax-riscv", version = "0. crc32fast = "1.4.2" simics = "0.1.1" indoc = "2.0.5" -serde = { version = "1.0.203", features = ["derive"] } -serde_json = "1.0.117" +serde = { version = "1.0.210", features = ["derive"] } +serde_json = "1.0.128" versions = { version = "6.2.0", features = ["serde"] } ffi = "0.1.1" num-traits = "0.2.19" diff --git a/README.md b/README.md index 543013d0..562b6138 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ find out if TSSFS can fuzz your code. ## Quick Start The fastest way to start using TSFFS is with our [dockerfile](Dockerfile). To set up -TSFFS locally instead, read the [documentation](./docs/src/SUMMARY.md). +TSFFS locally instead, read the [documentation](https://intel.github.io/tsffs). To start +using TSFFS right away: ```sh git clone https://github.com/intel/tsffs @@ -40,8 +41,8 @@ Then, run the provided example target and fuzzing configuration: ## Documentation & Setup -Documentation for setup & usage of this project lives in the [docs](./docs/src/SUMMARY.md) -directory of this repository. +Documentation for setup & usage of this project lives online at +[intel.github.io/tsffs](https://intel.github.io/tsffs). ## Capabilities diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index b24b65dd..31435bf4 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -79,3 +79,4 @@ - [Refreshing Build Environment](developer/refresh.md) - [Building Against A Specific SIMICS Version](developer/specific-simics-version.md) - [Debugging TSFFS](developer/debugging.md) + - [Releasing](developer/release.md) diff --git a/docs/src/developer/release.md b/docs/src/developer/release.md new file mode 100644 index 00000000..9773651f --- /dev/null +++ b/docs/src/developer/release.md @@ -0,0 +1,9 @@ +# Releasing TSFFS + +1. Run check script: `./check.sh` + - This will report issues with formatting (C and Python formatting can be ignored + for releases, markdown and Rust issues should be fixed) + - This will perform most checks done in CI including dependencies + - Any dependencies that are outdated or flag vulnerabilities in audits should be + updated + - Any code which has breaking changes (very rare) should be fixed diff --git a/docs/src/documentation/README.md b/docs/src/documentation/README.md index 178f4075..d9faf335 100644 --- a/docs/src/documentation/README.md +++ b/docs/src/documentation/README.md @@ -3,11 +3,11 @@ Documentation for the public distribution of SIMICS and all the crates which make up TSFFS are provided here. -- [SIMICS Documentation](https://intel.github.io/tsffs/simics/) -- [Crate Documentation](https://intel.github.io/tsffs/crates/) - - [tsffs](https://intel.github.io/tsffs/crates/tsffs/) - - [simics](https://intel.github.io/tsffs/crates/simics) - - [simics-macro](https://intel.github.io/tsffs/crates/simics_macro) - - [simics-codegen](https://intel.github.io/tsffs/crates/simics_codegen) - - [simics-api-sys](https://intel.github.io/tsffs/crates/simics_api_sys) - - [ispm-wrapper](https://intel.github.io/tsffs/crates/ispm_wrapper) +- [SIMICS Documentation](https://intel.github.io/simulator-bindings/simics/index.html) +- [Crate Documentation](https://intel.github.io/simulator-bindings/crates/index.html) + - [tsffs](https://intel.github.io/tsffs/crates/tsffs/index.html) + - [simics](https://intel.github.io/simulator-bindings/crates/simics/index.html) + - [simics-macro](https://intel.github.io/simulator-bindings/crates/simics_macro/index.html) + - [simics-codegen](https://intel.github.io/simulator-bindings/crates/simics_codegen/index.html) + - [simics-api-sys](https://intel.github.io/simulator-bindings/crates/simics_api_sys/index.html) + - [ispm-wrapper](https://intel.github.io/simulator-bindings/crates/ispm_wrapper/index.html) diff --git a/docs/src/tutorials/README.md b/docs/src/tutorials/README.md index c4ccb70d..66cc3995 100644 --- a/docs/src/tutorials/README.md +++ b/docs/src/tutorials/README.md @@ -2,7 +2,7 @@ We have several tutorials for harnessing and fuzzing various target software. -- [Fuzzing an EDK2 UEFI Application](edk2-uefi/README.md) -- [Fuzzing a Kernel Module](kernel-module/README.md) -- [Fuzzing a Custom BIOS](edk2-simics-platform-bios/README.md) -- [Fuzzing a Windows Kernel Mode Driver](windows-kernel/README.md) \ No newline at end of file +- [Fuzzing an EDK2 UEFI Application](edk2-uefi) +- [Fuzzing a Kernel Module](kernel-module) +- [Fuzzing a Custom BIOS](edk2-simics-platform-bios) +- [Fuzzing a Windows Kernel Mode Driver](windows-kernel) \ No newline at end of file diff --git a/examples/manual-example/minimal_boot_disk.craff b/examples/manual-example/minimal_boot_disk.craff index 2488b728..8f121f53 100644 Binary files a/examples/manual-example/minimal_boot_disk.craff and b/examples/manual-example/minimal_boot_disk.craff differ diff --git a/examples/rsrc/minimal_boot_disk.craff b/examples/rsrc/minimal_boot_disk.craff index 2488b728..8f121f53 100644 Binary files a/examples/rsrc/minimal_boot_disk.craff and b/examples/rsrc/minimal_boot_disk.craff differ diff --git a/examples/tutorials/risc-v-kernel/Dockerfile b/examples/tutorials/risc-v-kernel/Dockerfile index f09a6a70..13d34570 100644 --- a/examples/tutorials/risc-v-kernel/Dockerfile +++ b/examples/tutorials/risc-v-kernel/Dockerfile @@ -4,6 +4,7 @@ FROM ubuntu:22.04 AS buildroot SHELL ["/bin/bash", "-o", "pipefail", "-c"] ENV DEBIAN_FRONTEND=noninteractive +ENV FORCE_UNSAFE_CONFIGURE=1 RUN apt-get -y update && \ apt-get -y install \ diff --git a/examples/tutorials/risc-v-kernel/src/tsffs.h b/examples/tutorials/risc-v-kernel/src/tsffs.h index 95b604fd..77df053c 100644 --- a/examples/tutorials/risc-v-kernel/src/tsffs.h +++ b/examples/tutorials/risc-v-kernel/src/tsffs.h @@ -1,7 +1,7 @@ // Copyright (C) 2024 Intel Corporation // SPDX-License-Identifier: Apache-2.0 -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) #ifdef __i386__ // Copyright (C) 2024 Intel Corporation // SPDX-License-Identifier: Apache-2.0 @@ -2591,6 +2591,289 @@ #define FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION (1) #endif // FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +#ifdef __cplusplus + +#include + +/// HARNESS_START +/// +/// Signal the fuzzer to start the fuzzing loop at the point this macro is +/// called. The default "index" of 0 will be used. If you need multiple start +/// harnesses compiled into the same binary, you can use the +/// `HARNESS_START_INDEX` macro to specify different indices, then enable them +/// at runtime by configuring the fuzzer. +/// +/// When this macro is called: +/// +/// - A snapshot will be taken and saved +/// - The buffer pointed to by `buffer` will be saved and used as the testcase +/// buffer. Each +/// fuzzing iteration, a new test case will be written to this buffer. +/// - The size of the buffer pointed to by `size_ptr` will be saved as the +/// maximum testcase size. Each fuzzing iteration, the actual size of the +/// current testcase will be written to `*size_ptr`. +/// +/// # Arguments +/// +/// - `buffer`: The pointer to the testcase buffer +/// - `size_ptr`: The pointer to the size of the testcase buffer +/// +/// # Example +/// +/// ``` +/// unsigned char buffer[1024]; +/// size_t size; +/// HARNESS_START(buffer, &size); +/// ``` +extern "C" void HARNESS_START(void *buffer, void *size_ptr); + +/// HARNESS_START_INDEX +/// +/// Signal the fuzzer to start the fuzzing loop at the point this macro is +/// called. The index specified by `start_index` will be used. If you need +/// multiple start harnesses compiled into the same binary, you can use this +/// macro to specify different indices, then enable them at runtime by +/// configuring the fuzzer. +/// +/// When this macro is called: +/// +/// - A snapshot will be taken and saved +/// - The buffer pointed to by `buffer` will be saved and used as the testcase +/// buffer. Each +/// fuzzing iteration, a new test case will be written to this buffer. +/// - The size of the buffer pointed to by `size_ptr` will be saved as the +/// maximum testcase size. Each fuzzing iteration, the actual size of the +/// current testcase will be written to `*size_ptr`. +/// +/// # Arguments +/// +/// - `start_index`: The index to use for this start harness +/// - `buffer`: The pointer to the testcase buffer +/// - `size_ptr`: The pointer to the size of the testcase buffer +/// +/// # Example +/// +/// ``` +/// unsigned char buffer[1024]; +/// size_t size; +/// HARNESS_START_INDEX(0x0001U, buffer, &size); +/// ``` +extern "C" void HARNESS_START_INDEX(size_t start_index, void *buffer, void *size_ptr); + +/// HARNESS_START_WITH_MAXIMUM_SIZE +/// +/// Signal the fuzzer to start the fuzzing loop at the point this macro is +/// called. The default "index" of 0 will be used. If you need multiple start +/// harnesses compiled into the same binary, you can use the +/// `HARNESS_START_WITH_MAXIMUM_SIZE_INDEX` macro to specify different indices, +/// then enable them at runtime by configuring the fuzzer. +/// +/// When this macro is called: +/// +/// - A snapshot will be taken and saved +/// - The buffer pointed to by `buffer` will be saved and used as the testcase +/// buffer. Each +/// fuzzing iteration, a new test case will be written to this buffer. +/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing +/// test cases will be truncated to this size before being written to the +/// buffer. +/// +/// # Arguments +/// +/// - `buffer`: The pointer to the testcase buffer +/// - `max_size`: The maximum size of the testcase buffer +/// +/// # Example +/// +/// ``` +/// unsigned char buffer[1024]; +/// HARNESS_START_WITH_MAXIMUM_SIZE(buffer, 1024); +/// ``` +extern "C" void HARNESS_START_WITH_MAXIMUM_SIZE(void *buffer, size_t max_size); + +/// HARNESS_START_WITH_MAXIMUM_SIZE_INDEX +/// +/// Signal the fuzzer to start the fuzzing loop at the point this macro is +/// called. The index specified by `start_index` will be used. If you need +/// multiple start harnesses compiled into the same binary, you can use this +/// macro to specify different indices, then enable them at runtime by +/// configuring the fuzzer. +/// +/// When this macro is called: +/// +/// - A snapshot will be taken and saved +/// - The buffer pointed to by `buffer` will be saved and used as the testcase +/// buffer. Each +/// fuzzing iteration, a new test case will be written to this buffer. +/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing +/// test cases will be truncated to this size before being written to the +/// buffer. +/// +/// # Arguments +/// +/// - `start_index`: The index to use for this start harness +/// - `buffer`: The pointer to the testcase buffer +/// - `max_size`: The maximum size of the testcase buffer +/// +/// # Example +/// +/// ``` +/// unsigned char buffer[1024]; +/// HARNESS_START_WITH_MAXIMUM_SIZE_INDEX(0x0001U, buffer, 1024); +/// ``` +extern "C" void HARNESS_START_WITH_MAXIMUM_SIZE_INDEX(size_t start_index, void *buffer, + size_t max_size); + +/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR +/// +/// Signal the fuzzer to start the fuzzing loop at the point this macro is +/// called. The default "index" of 0 will be used. If you need multiple start +/// harnesses compiled into the same binary, you can use the +/// `HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX` macro to specify different +/// indices, then enable them at runtime by configuring the fuzzer. +/// +/// When this macro is called: +/// +/// - A snapshot will be taken and saved +/// - The buffer pointed to by `buffer` will be saved and used as the testcase +/// buffer. Each +/// fuzzing iteration, a new test case will be written to this buffer. +/// - The address `size_ptr` will be saved. Each fuzzing iteration, the actual +/// size of the current testcase will be written to `*size_ptr`. +/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing +/// test cases will be truncated to this size before being written to the +/// buffer. +/// +/// # Arguments +/// +/// - `buffer`: The pointer to the testcase buffer +/// - `size_ptr`: The pointer to the size of the testcase buffer +/// - `max_size`: The maximum size of the testcase buffer +/// +/// # Example +/// +/// ``` +/// unsigned char buffer[1024]; +/// size_t size; +/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR(buffer, &size, 1024); +/// ``` +extern "C" void HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR(void *buffer, void *size_ptr, + size_t max_size); + +/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX +/// +/// Signal the fuzzer to start the fuzzing loop at the point this macro is +/// called. The index specified by `start_index` will be used. If you need +/// multiple start harnesses compiled into the same binary, you can use this +/// macro to specify different indices, then enable them at runtime by +/// configuring the fuzzer. +/// +/// When this macro is called: +/// +/// - A snapshot will be taken and saved +/// - The buffer pointed to by `buffer` will be saved and used as the testcase +/// buffer. Each +/// fuzzing iteration, a new test case will be written to this buffer. +/// - The address `size_ptr` will be saved. Each fuzzing iteration, the actual +/// size of the current testcase will be written to `*size_ptr`. +/// - The `max_size` value will be saved as the maximum testcase size. Fuzzing +/// test cases will be truncated to this size before being written to the +/// buffer. +/// +/// # Arguments +/// +/// - `start_index`: The index to use for this start harness +/// - `buffer`: The pointer to the testcase buffer +/// - `size_ptr`: The pointer to the size of the testcase buffer +/// - `max_size`: The maximum size of the testcase buffer +/// +/// # Example +/// +/// ``` +/// unsigned char buffer[1024]; +/// size_t size; +/// HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX(0x0001U, buffer, &size, 1024); +/// ``` +extern "C" void HARNESS_START_WITH_MAXIMUM_SIZE_AND_PTR_INDEX(size_t start_index, + void *buffer, void *size_ptr, + size_t max_size); + +/// HARNESS_STOP +/// +/// Signal the fuzzer to stop and reset to the beginning of the fuzzing loop +/// with a "normal" stop status, indicating no solution has occurred. The +/// default index of 0 will be used. If you need to differentiate between +/// multiple stop harnesses compiled into the same binary, you can use the +/// `HARNESS_STOP_INDEX` macro to specify different indices, then enable them at +/// runtime by configuring the fuzzer. +/// +/// # Example +/// +/// ``` +/// HARNESS_STOP(); +/// ``` +extern "C" void HARNESS_STOP(void); + +/// HARNESS_STOP_INDEX +/// +/// Signal the fuzzer to stop and reset to the beginning of the fuzzing loop +/// with a "normal" stop status, indicating no solution has occurred. The index +/// specified by `stop_index` will be used. If you need to differentiate between +/// multiple stop harnesses compiled into the same binary, you can use this +/// macro to specify different indices, then enable them at runtime by +/// configuring the fuzzer. +/// +/// # Arguments +/// +/// - `stop_index`: The index to use for this stop harness +/// +/// # Example +/// +/// ``` +/// HARNESS_STOP_INDEX(0x0001U); +/// ``` +extern "C" void HARNESS_STOP_INDEX(size_t stop_index); + +/// HARNESS_ASSERT +/// +/// Signal the fuzzer that a custom assertion has occurred, and the fuzzer +/// should stop the current fuzzing iteration and reset to the beginning of the +/// fuzzing loop with a "solution" stop status. The default index of 0 will be +/// used. If you need to differentiate between multiple assertion harnesses +/// compiled into the same binary, you can use the `HARNESS_ASSERT_INDEX` macro +/// to specify different indices, then enable them at runtime by configuring the +/// fuzzer. +/// +/// # Example +/// +/// ``` +/// HARNESS_ASSERT(); +/// ``` +extern "C" void HARNESS_ASSERT(void); + +/// HARNESS_ASSERT_INDEX +/// +/// Signal the fuzzer that a custom assertion has occurred, and the fuzzer +/// should stop the current fuzzing iteration and reset to the beginning of the +/// fuzzing loop with a "solution" stop status. The index specified by +/// `assert_index` will be used. If you need to differentiate between multiple +/// assertion harnesses compiled into the same binary, you can use this macro to +/// specify different indices, then enable them at runtime by configuring the +/// fuzzer. +/// +/// # Arguments +/// +/// - `assert_index`: The index to use for this assertion harness +/// +/// # Example +/// +/// ``` +/// HARNESS_ASSERT_INDEX(0x0001U); +/// ``` +extern "C" void HARNESS_ASSERT_INDEX(size_t assert_index); + +#else // __cplusplus + #include /// HARNESS_START @@ -2869,6 +3152,7 @@ void HARNESS_ASSERT(void); /// HARNESS_ASSERT_INDEX(0x0001U); /// ``` void HARNESS_ASSERT_INDEX(size_t assert_index); +#endif // __cplusplus #endif // TSFFS_H #else diff --git a/scripts/check.sh b/scripts/check.sh index 99b89a96..af449eab 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -10,6 +10,16 @@ if ! command -v fd &>/dev/null; then exit 1 fi +if ! command -v cargo-outdated &>/dev/null; then + echo "cargo outdated must be installed! Install with 'cargo install cargo-outdated'" + exit 1 +fi + +if ! command -v cargo-audit &>/dev/null; then + echo "cargo audit must be installed! Install with 'cargo install cargo-audit'" + exit 1 +fi + if ! command -v flake8 &>/dev/null; then echo "flake8 must be installed! Install with 'python3 -m pip install flake8'" exit 1 @@ -102,4 +112,17 @@ echo "=================" echo "Running gitleaks..." echo "=================" -gitleaks detect \ No newline at end of file +gitleaks detect + +echo "=================" +echo "Checking for out of date dependencies..." +echo "=================" + +cargo outdated -R --exit-code 1 + + +echo "=================" +echo "Checking for vulnerable dependencies..." +echo "=================" + +cargo audit \ No newline at end of file diff --git a/tests/rsrc/minimal_boot_disk.craff b/tests/rsrc/minimal_boot_disk.craff index 2488b728..8f121f53 100644 Binary files a/tests/rsrc/minimal_boot_disk.craff and b/tests/rsrc/minimal_boot_disk.craff differ