From 50e0f80d1ed803f12b184e8c7fc8b6ece3795ab3 Mon Sep 17 00:00:00 2001 From: Romain Malmain Date: Sat, 30 Mar 2024 17:04:37 +0100 Subject: [PATCH] Refactoring of qemu_systemmode fuzzers (#1980) * Added backdoors to portable header file. * fix arm macros. * copy `libafl_qemu.h` in target directory. * Merged all qemu_systemmode examples into one, settable with features. Automatic building using `Makefile.toml` * fix typo. * added test of QEMU systemmode fuzzers. * replace test by build for now. --- .github/workflows/build_and_test.yml | 2 +- fuzzers/qemu_systemmode/Cargo.toml | 6 +- fuzzers/qemu_systemmode/Makefile.toml | 181 +++++++++++++++ fuzzers/qemu_systemmode/README.md | 35 +-- fuzzers/qemu_systemmode/build.rs | 15 ++ fuzzers/qemu_systemmode/example/build.sh | 2 - fuzzers/qemu_systemmode/example/main.c | 10 + .../src/fuzzer_breakpoint.rs} | 0 .../src/{fuzzer.rs => fuzzer_classic.rs} | 0 .../src/fuzzer_sync_exit.rs} | 0 fuzzers/qemu_systemmode/src/main.rs | 19 +- .../qemu_systemmode_breakpoints/.gitignore | 1 - .../qemu_systemmode_breakpoints/Cargo.toml | 21 -- fuzzers/qemu_systemmode_breakpoints/README.md | 26 --- .../qemu_systemmode_breakpoints/corpus/random | 1 - .../qemu_systemmode_breakpoints/corpus/zero | Bin 5 -> 0 bytes .../example/build.sh | 2 - .../example/main.c | 33 --- .../example/mps2_m3.ld | 143 ------------ .../example/startup.c | 107 --------- .../qemu_systemmode_breakpoints/src/main.rs | 13 -- .../qemu_systemmode_sync_backdoor/.gitignore | 1 - .../qemu_systemmode_sync_backdoor/Cargo.toml | 21 -- .../qemu_systemmode_sync_backdoor/README.md | 26 --- .../corpus/random | 1 - .../qemu_systemmode_sync_backdoor/corpus/zero | Bin 5 -> 0 bytes .../example/build.sh | 2 - .../example/main.c | 37 --- .../example/mps2_m3.ld | 143 ------------ .../example/startup.c | 107 --------- .../qemu_systemmode_sync_backdoor/src/main.rs | 13 -- libafl_qemu/build_linux.rs | 11 +- libafl_qemu/runtime/libafl_exit.h | 176 -------------- ...ibafl_exit_windows.asm => libafl_qemu.asm} | 0 libafl_qemu/runtime/libafl_qemu.h | 216 ++++++++++++++++++ 35 files changed, 472 insertions(+), 899 deletions(-) create mode 100644 fuzzers/qemu_systemmode/Makefile.toml create mode 100644 fuzzers/qemu_systemmode/build.rs delete mode 100755 fuzzers/qemu_systemmode/example/build.sh rename fuzzers/{qemu_systemmode_breakpoints/src/fuzzer.rs => qemu_systemmode/src/fuzzer_breakpoint.rs} (100%) rename fuzzers/qemu_systemmode/src/{fuzzer.rs => fuzzer_classic.rs} (100%) rename fuzzers/{qemu_systemmode_sync_backdoor/src/fuzzer.rs => qemu_systemmode/src/fuzzer_sync_exit.rs} (100%) delete mode 100644 fuzzers/qemu_systemmode_breakpoints/.gitignore delete mode 100644 fuzzers/qemu_systemmode_breakpoints/Cargo.toml delete mode 100644 fuzzers/qemu_systemmode_breakpoints/README.md delete mode 100644 fuzzers/qemu_systemmode_breakpoints/corpus/random delete mode 100644 fuzzers/qemu_systemmode_breakpoints/corpus/zero delete mode 100755 fuzzers/qemu_systemmode_breakpoints/example/build.sh delete mode 100644 fuzzers/qemu_systemmode_breakpoints/example/main.c delete mode 100644 fuzzers/qemu_systemmode_breakpoints/example/mps2_m3.ld delete mode 100644 fuzzers/qemu_systemmode_breakpoints/example/startup.c delete mode 100644 fuzzers/qemu_systemmode_breakpoints/src/main.rs delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/.gitignore delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/Cargo.toml delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/README.md delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/corpus/random delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/corpus/zero delete mode 100755 fuzzers/qemu_systemmode_sync_backdoor/example/build.sh delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/example/main.c delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/example/mps2_m3.ld delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/example/startup.c delete mode 100644 fuzzers/qemu_systemmode_sync_backdoor/src/main.rs delete mode 100644 libafl_qemu/runtime/libafl_exit.h rename libafl_qemu/runtime/{libafl_exit_windows.asm => libafl_qemu.asm} (100%) create mode 100644 libafl_qemu/runtime/libafl_qemu.h diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index b83e269f6f..1d1da3ae84 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -373,7 +373,7 @@ jobs: directory: ${{ runner.temp }}/llvm version: 17 - name: Install deps - run: sudo apt update && sudo apt install nasm ninja-build gcc-arm-linux-gnueabi g++-arm-linux-gnueabi gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-mipsel-linux-gnu g++-mipsel-linux-gnu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-i386-cross libc6-dev libc6-dev-i386 lib32gcc-11-dev lib32stdc++-11-dev libgtk-3-dev pax-utils libz3-dev + run: sudo apt update && sudo apt install nasm ninja-build gcc-arm-linux-gnueabi g++-arm-linux-gnueabi gcc-aarch64-linux-gnu g++-aarch64-linux-gnu gcc-mipsel-linux-gnu g++-mipsel-linux-gnu gcc-powerpc-linux-gnu g++-powerpc-linux-gnu libc6-dev-i386-cross libc6-dev libc6-dev-i386 lib32gcc-11-dev lib32stdc++-11-dev libgtk-3-dev pax-utils libz3-dev qemu-utils - name: pip install run: python3 -m pip install msgpack jinja2 find_libpython # Note that nproc needs to have coreutils installed on macOS, so the order of CI commands matters. diff --git a/fuzzers/qemu_systemmode/Cargo.toml b/fuzzers/qemu_systemmode/Cargo.toml index c0dea615da..9800ed3e7e 100644 --- a/fuzzers/qemu_systemmode/Cargo.toml +++ b/fuzzers/qemu_systemmode/Cargo.toml @@ -5,9 +5,13 @@ authors = ["Andrea Fioraldi ", "Dominik Maier &1 || true + +if [ -z "$(grep 'Objective' $TMP_DIR/fuzz.log)" ]; then + echo "Fuzzer did not find the objective in $TMP_DIR/fuzz.log" + exit 1 +else + echo "Objective found." +fi +''' + +[tasks.build_classic] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=classic", + "-e", "TARGET_DEFINE=TARGET_CLASSIC", + "build_fuzzer", +] + +[tasks.test_classic] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=classic", + "test_fuzzer", +] + +[tasks.build_breakpoint] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=breakpoint", + "-e", "TARGET_DEFINE=TARGET_BREAKPOINT", + "build_fuzzer", +] + +[tasks.test_breakpoint] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=breakpoint", + "test_fuzzer", +] + +[tasks.build_sync_exit] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=sync_exit", + "-e", "TARGET_DEFINE=TARGET_SYNC_EXIT", + "build_fuzzer", +] + +[tasks.test_sync_exit] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=sync_exit", + "test_fuzzer", +] + +[tasks.classic] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=classic", + "-e", "TARGET_DEFINE=TARGET_CLASSIC", + "run_fuzzer", +] + +[tasks.breakpoint] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=breakpoint", + "-e", "TARGET_DEFINE=TARGET_BREAKPOINT", + "run_fuzzer", +] + +[tasks.sync_exit] +command = "cargo" +args = [ + "make", + "-e", "FEATURE=sync_exit", + "-e", "TARGET_DEFINE=TARGET_SYNC_EXIT", + "run_fuzzer", +] + +[tasks.test] +clear = true +run_task = { name = ["build"] } +# run_task = { name = ["test_classic", "test_breakpoint", "test_sync_exit"] } + +[tasks.build] +clear = true +run_task = { name = ["build_classic", "build_breakpoint", "build_sync_exit"] } + +[tasks.run] +alias="classic" + +[tasks.clean] +clear = true +script_runner="@shell" +script=''' +rm -rf ${CARGO_MAKE_CRATE_TARGET_DIRECTORY} +cargo clean +''' diff --git a/fuzzers/qemu_systemmode/README.md b/fuzzers/qemu_systemmode/README.md index 14098dc09c..cbc9266d53 100644 --- a/fuzzers/qemu_systemmode/README.md +++ b/fuzzers/qemu_systemmode/README.md @@ -2,25 +2,28 @@ This folder contains an example fuzzer for the qemu systemmode, using LLMP for fast multi-process fuzzing and crash detection. -## Build +It comes in three flavours (can be set through features): -To build this example, run - -```bash -cargo build --release -cd example; sh build.sh; cd .. -``` - -This will build the the fuzzer (src/fuzzer.rs) and a small example binary based on FreeRTOS, which can run under a qemu emulation target. +-`classic`: The low-level way to interact with QEMU. +-`breakpoint`: Interaction with QEMU using the command system, leveraging breakpoints. +-`sync_exit`: Interaction with QEMU using the command system, leveraging sync exits. ## Run -Since the instrumentation is based on snapshtos QEMU needs a virtual drive (even if it is unused...). -Create on and then run the fuzzer: ```bash -# create an image -qemu-img create -f qcow2 dummy.qcow2 32M -# run the fuzzer -KERNEL=./example/example.elf target/release/qemu_systemmode -icount shift=auto,align=off,sleep=off -machine mps2-an385 -monitor null -kernel ./example/example.elf -serial null -nographic -snapshot -drive if=none,format=qcow2,file=dummy.qcow2 -S +cargo make run ``` -Currently the ``KERNEL`` variable is needed because the fuzzer does not parse QEMUs arguments to find the binary. \ No newline at end of file + +It is also possible to run the fuzzer with the other features: + +```bash +cargo make +``` + +With feature being `classic`, `breakpoint` or `sync_exit`. + +This will build the desired fuzzer (src/fuzzer_.rs) and a small example binary based on FreeRTOS, which can run under a qemu emulation target. +Since the instrumentation is based on snapshots, QEMU needs a virtual drive (even if it is unused...). +Thus, the makefile creates a dummy QCOW2 image `dummy.qcow2` (can be found in the `target directory`). +Currently the ``KERNEL`` variable is needed because the fuzzer does not parse QEMUs arguments to find the binary. +It is automatically set in the build script. \ No newline at end of file diff --git a/fuzzers/qemu_systemmode/build.rs b/fuzzers/qemu_systemmode/build.rs new file mode 100644 index 0000000000..c7d7735ddc --- /dev/null +++ b/fuzzers/qemu_systemmode/build.rs @@ -0,0 +1,15 @@ +#[macro_export] +macro_rules! assert_unique_feature { + () => {}; + ($first:tt $(,$rest:tt)*) => { + $( + #[cfg(all(not(any(doc, feature = "clippy")), feature = $first, feature = $rest))] + compile_error!(concat!("features \"", $first, "\" and \"", $rest, "\" cannot be used together")); + )* + assert_unique_feature!($($rest),*); + } +} + +fn main() { + assert_unique_feature!("classic", "breakpoint", "sync_exit"); +} diff --git a/fuzzers/qemu_systemmode/example/build.sh b/fuzzers/qemu_systemmode/example/build.sh deleted file mode 100755 index ceb387b19a..0000000000 --- a/fuzzers/qemu_systemmode/example/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -arm-none-eabi-gcc -ggdb -ffreestanding -nostartfiles -lgcc -T mps2_m3.ld -mcpu=cortex-m3 main.c startup.c -o example.elf \ No newline at end of file diff --git a/fuzzers/qemu_systemmode/example/main.c b/fuzzers/qemu_systemmode/example/main.c index 13777fb35a..9ffb41732e 100644 --- a/fuzzers/qemu_systemmode/example/main.c +++ b/fuzzers/qemu_systemmode/example/main.c @@ -1,8 +1,15 @@ +#ifdef TARGET_SYNC_EXIT +#include "libafl_qemu.h" +#endif + int __attribute__((noinline)) BREAKPOINT() { for (;;) {} } int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) { +#ifdef TARGET_SYNC_EXIT + LIBAFL_EXIT_START_PHYS((unsigned int) Data, Size); +#endif if (Data[3] == 0) { while (1) {} } // cause a timeout @@ -19,6 +26,9 @@ int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) { } } } +#ifdef TARGET_SYNC_EXIT + LIBAFL_EXIT_END(LIBAFL_EXIT_END_OK); +#endif return BREAKPOINT(); } unsigned int FUZZ_INPUT[] = { diff --git a/fuzzers/qemu_systemmode_breakpoints/src/fuzzer.rs b/fuzzers/qemu_systemmode/src/fuzzer_breakpoint.rs similarity index 100% rename from fuzzers/qemu_systemmode_breakpoints/src/fuzzer.rs rename to fuzzers/qemu_systemmode/src/fuzzer_breakpoint.rs diff --git a/fuzzers/qemu_systemmode/src/fuzzer.rs b/fuzzers/qemu_systemmode/src/fuzzer_classic.rs similarity index 100% rename from fuzzers/qemu_systemmode/src/fuzzer.rs rename to fuzzers/qemu_systemmode/src/fuzzer_classic.rs diff --git a/fuzzers/qemu_systemmode_sync_backdoor/src/fuzzer.rs b/fuzzers/qemu_systemmode/src/fuzzer_sync_exit.rs similarity index 100% rename from fuzzers/qemu_systemmode_sync_backdoor/src/fuzzer.rs rename to fuzzers/qemu_systemmode/src/fuzzer_sync_exit.rs diff --git a/fuzzers/qemu_systemmode/src/main.rs b/fuzzers/qemu_systemmode/src/main.rs index bc1e80f767..8ca48d6eb6 100644 --- a/fuzzers/qemu_systemmode/src/main.rs +++ b/fuzzers/qemu_systemmode/src/main.rs @@ -1,10 +1,23 @@ //! A libfuzzer-like fuzzer using qemu for binary-only coverage -#[cfg(target_os = "linux")] -mod fuzzer; +#[cfg(all(target_os = "linux", feature = "classic"))] +mod fuzzer_classic; + +#[cfg(all(target_os = "linux", feature = "breakpoint"))] +mod fuzzer_breakpoint; + +#[cfg(all(target_os = "linux", feature = "sync_exit"))] +mod fuzzer_sync_exit; #[cfg(target_os = "linux")] pub fn main() { - fuzzer::fuzz(); + #[cfg(feature = "classic")] + fuzzer_classic::fuzz(); + + #[cfg(feature = "breakpoint")] + fuzzer_breakpoint::fuzz(); + + #[cfg(feature = "sync_exit")] + fuzzer_sync_exit::fuzz(); } #[cfg(not(target_os = "linux"))] diff --git a/fuzzers/qemu_systemmode_breakpoints/.gitignore b/fuzzers/qemu_systemmode_breakpoints/.gitignore deleted file mode 100644 index b511ae114b..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.qcow2 diff --git a/fuzzers/qemu_systemmode_breakpoints/Cargo.toml b/fuzzers/qemu_systemmode_breakpoints/Cargo.toml deleted file mode 100644 index 45fc940353..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "qemu_systemmode_breakpoints" -version = "0.11.1" -authors = ["Andrea Fioraldi ", "Dominik Maier ", "Romain Malmain "] -edition = "2021" - -[features] -default = ["std"] -std = [] - -[profile.release] -incremental = true -debug = true -lto = "fat" -codegen-units = 1 - -[dependencies] -libafl = { path = "../../libafl/" } -libafl_bolts = { path = "../../libafl_bolts/" } -libafl_qemu = { path = "../../libafl_qemu/", features = ["arm", "systemmode"] } -env_logger = "*" diff --git a/fuzzers/qemu_systemmode_breakpoints/README.md b/fuzzers/qemu_systemmode_breakpoints/README.md deleted file mode 100644 index 14098dc09c..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Qemu systemmode with launcher - -This folder contains an example fuzzer for the qemu systemmode, using LLMP for fast multi-process fuzzing and crash detection. - -## Build - -To build this example, run - -```bash -cargo build --release -cd example; sh build.sh; cd .. -``` - -This will build the the fuzzer (src/fuzzer.rs) and a small example binary based on FreeRTOS, which can run under a qemu emulation target. - -## Run - -Since the instrumentation is based on snapshtos QEMU needs a virtual drive (even if it is unused...). -Create on and then run the fuzzer: -```bash -# create an image -qemu-img create -f qcow2 dummy.qcow2 32M -# run the fuzzer -KERNEL=./example/example.elf target/release/qemu_systemmode -icount shift=auto,align=off,sleep=off -machine mps2-an385 -monitor null -kernel ./example/example.elf -serial null -nographic -snapshot -drive if=none,format=qcow2,file=dummy.qcow2 -S -``` -Currently the ``KERNEL`` variable is needed because the fuzzer does not parse QEMUs arguments to find the binary. \ No newline at end of file diff --git a/fuzzers/qemu_systemmode_breakpoints/corpus/random b/fuzzers/qemu_systemmode_breakpoints/corpus/random deleted file mode 100644 index 25175d51d3..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/corpus/random +++ /dev/null @@ -1 +0,0 @@ -yJv lpZGօrsY˗CMRպ}S7;Io76l1ޘ1R^Όp>G&_|1;ro4ƯUE<`L"6VƷk4/"tf7Fގd]ܮ%|8#wNUn8%4o˗ diff --git a/fuzzers/qemu_systemmode_breakpoints/corpus/zero b/fuzzers/qemu_systemmode_breakpoints/corpus/zero deleted file mode 100644 index 112363ac1917b417ffbd7f376ca786a1e5fa7490..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5 McmZQzU|`?^000jF3jhEB diff --git a/fuzzers/qemu_systemmode_breakpoints/example/build.sh b/fuzzers/qemu_systemmode_breakpoints/example/build.sh deleted file mode 100755 index ceb387b19a..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/example/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -arm-none-eabi-gcc -ggdb -ffreestanding -nostartfiles -lgcc -T mps2_m3.ld -mcpu=cortex-m3 main.c startup.c -o example.elf \ No newline at end of file diff --git a/fuzzers/qemu_systemmode_breakpoints/example/main.c b/fuzzers/qemu_systemmode_breakpoints/example/main.c deleted file mode 100644 index 13777fb35a..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/example/main.c +++ /dev/null @@ -1,33 +0,0 @@ -int __attribute__((noinline)) BREAKPOINT() { - for (;;) {} -} - -int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) { - if (Data[3] == 0) { - while (1) {} - } // cause a timeout - for (int i = 0; i < Size; i++) { - // if (Data[i] > 0xFFd0 && Data[i] < 0xFFFF) {return 1;} // cause qemu to - // crash - for (int j = i + 1; j < Size; j++) { - if (Data[j] == 0) { continue; } - if (Data[j] > Data[i]) { - int tmp = Data[i]; - Data[i] = Data[j]; - Data[j] = tmp; - if (Data[i] <= 100) { j--; } - } - } - } - return BREAKPOINT(); -} -unsigned int FUZZ_INPUT[] = { - 101, 201, 700, 230, 860, 234, 980, 200, 340, 678, 230, 134, 900, - 236, 900, 123, 800, 123, 658, 607, 246, 804, 567, 568, 207, 407, - 246, 678, 457, 892, 834, 456, 878, 246, 699, 854, 234, 844, 290, - 125, 324, 560, 852, 928, 910, 790, 853, 345, 234, 586, -}; - -int main() { - LLVMFuzzerTestOneInput(FUZZ_INPUT, 50); -} diff --git a/fuzzers/qemu_systemmode_breakpoints/example/mps2_m3.ld b/fuzzers/qemu_systemmode_breakpoints/example/mps2_m3.ld deleted file mode 100644 index adfc15ed78..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/example/mps2_m3.ld +++ /dev/null @@ -1,143 +0,0 @@ -/* - * FreeRTOS V202112.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -MEMORY -{ - RAM (xrw) : ORIGIN = 0x00000000, LENGTH = 4M - /* Originally */ - /* FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 4M */ - /* RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4M */ -} -ENTRY(Reset_Handler) - -_Min_Heap_Size = 0x300000 ; /* Required amount of heap. */ -_Min_Stack_Size = 0x4000 ; /* Required amount of stack. */ -M_VECTOR_RAM_SIZE = (16 + 48) * 4; -_estack = ORIGIN(RAM) + LENGTH(RAM); - -SECTIONS -{ - - .isr_vector : - { - __vector_table = .; - KEEP(*(.isr_vector)) - . = ALIGN(4); - } > RAM /* FLASH */ - - .text : - { - . = ALIGN(4); - *(.text*) - KEEP (*(.init)) - KEEP (*(.fini)) - KEEP(*(.eh_frame)) - *(.rodata*) - . = ALIGN(4); - _etext = .; - } > RAM /* FLASH */ - - .ARM.extab : - { - . = ALIGN(4); - *(.ARM.extab* .gnu.linkonce.armextab.*) - . = ALIGN(4); - } >RAM /* FLASH */ - - .ARM : - { - . = ALIGN(4); - __exidx_start = .; - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __exidx_end = .; - . = ALIGN(4); - } >RAM /* FLASH */ - - .interrupts_ram : - { - . = ALIGN(4); - __VECTOR_RAM__ = .; - __interrupts_ram_start__ = .; - . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); - __interrupts_ram_end = .; - } > RAM - - _sidata = LOADADDR(.data); - - .data : /* AT ( _sidata ) */ - { - . = ALIGN(4); - _sdata = .; - *(.data*) - . = ALIGN(4); - _edata = .; - } > RAM /* RAM AT > FLASH */ - - .uninitialized (NOLOAD): - { - . = ALIGN(32); - __uninitialized_start = .; - *(.uninitialized) - KEEP(*(.keep.uninitialized)) - . = ALIGN(32); - __uninitialized_end = .; - } > RAM - - .bss : - { - . = ALIGN(4); - _sbss = .; - __bss_start__ = _sbss; - *(.bss*) - *(COMMON) - . = ALIGN(4); - _ebss = .; - __bss_end__ = _ebss; - } >RAM - - .heap : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - _heap_bottom = .; - . = . + _Min_Heap_Size; - _heap_top = .; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Set stack top to end of RAM, and stack limit move down by - * size of stack_dummy section */ - __StackTop = ORIGIN(RAM) + LENGTH(RAM); - __StackLimit = __StackTop - _Min_Stack_Size; - PROVIDE(__stack = __StackTop); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= _heap_top, "region RAM overflowed with stack") -} - diff --git a/fuzzers/qemu_systemmode_breakpoints/example/startup.c b/fuzzers/qemu_systemmode_breakpoints/example/startup.c deleted file mode 100644 index 36be3cf55a..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/example/startup.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * FreeRTOS V202112.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -typedef unsigned int uint32_t; - -extern int main(); - -extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; - -/* Prevent optimization so gcc does not replace code with memcpy */ -__attribute__((optimize("O0"))) __attribute__((naked)) void Reset_Handler( - void) { - /* set stack pointer */ - __asm volatile("ldr r0, =_estack"); - __asm volatile("mov sp, r0"); - - /* copy .data section from flash to RAM */ - // Not needed for this example, see linker script - // for( uint32_t * src = &_sidata, * dest = &_sdata; dest < &_edata; ) - // { - // *dest++ = *src++; - // } - - /* zero out .bss section */ - for (uint32_t *dest = &_sbss; dest < &_ebss;) { - *dest++ = 0; - } - - /* jump to board initialisation */ - void _start(void); - _start(); -} - -const uint32_t *isr_vector[] __attribute__((section(".isr_vector"))) = { - (uint32_t *)&_estack, - (uint32_t *)&Reset_Handler, /* Reset -15 */ - 0, /* NMI_Handler -14 */ - 0, /* HardFault_Handler -13 */ - 0, /* MemManage_Handler -12 */ - 0, /* BusFault_Handler -11 */ - 0, /* UsageFault_Handler -10 */ - 0, /* reserved */ - 0, /* reserved */ - 0, /* reserved */ - 0, /* reserved -6 */ - 0, /* SVC_Handler -5 */ - 0, /* DebugMon_Handler -4 */ - 0, /* reserved */ - 0, /* PendSV handler -2 */ - 0, /* SysTick_Handler -1 */ - 0, /* uart0 receive 0 */ - 0, /* uart0 transmit */ - 0, /* uart1 receive */ - 0, /* uart1 transmit */ - 0, /* uart 2 receive */ - 0, /* uart 2 transmit */ - 0, /* GPIO 0 combined interrupt */ - 0, /* GPIO 2 combined interrupt */ - 0, /* Timer 0 */ - 0, /* Timer 1 */ - 0, /* Dial Timer */ - 0, /* SPI0 SPI1 */ - 0, /* uart overflow 1, 2,3 */ - 0, /* Ethernet 13 */ -}; - -__attribute__((naked)) void exit(__attribute__((unused)) int status) { - /* Force qemu to exit using ARM Semihosting */ - __asm volatile( - "mov r1, r0\n" - "cmp r1, #0\n" - "bne .notclean\n" - "ldr r1, =0x20026\n" /* ADP_Stopped_ApplicationExit, a clean exit */ - ".notclean:\n" - "movs r0, #0x18\n" /* SYS_EXIT */ - "bkpt 0xab\n" - "end: b end\n"); -} - -void _start(void) { - main(); - exit(0); -} diff --git a/fuzzers/qemu_systemmode_breakpoints/src/main.rs b/fuzzers/qemu_systemmode_breakpoints/src/main.rs deleted file mode 100644 index bc1e80f767..0000000000 --- a/fuzzers/qemu_systemmode_breakpoints/src/main.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! A libfuzzer-like fuzzer using qemu for binary-only coverage -#[cfg(target_os = "linux")] -mod fuzzer; - -#[cfg(target_os = "linux")] -pub fn main() { - fuzzer::fuzz(); -} - -#[cfg(not(target_os = "linux"))] -pub fn main() { - panic!("qemu-user and libafl_qemu is only supported on linux!"); -} diff --git a/fuzzers/qemu_systemmode_sync_backdoor/.gitignore b/fuzzers/qemu_systemmode_sync_backdoor/.gitignore deleted file mode 100644 index b511ae114b..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.qcow2 diff --git a/fuzzers/qemu_systemmode_sync_backdoor/Cargo.toml b/fuzzers/qemu_systemmode_sync_backdoor/Cargo.toml deleted file mode 100644 index 2a1455ee8c..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "qemu_systemmode_sync_backdoor" -version = "0.11.1" -authors = ["Andrea Fioraldi ", "Dominik Maier ", "Romain Malmain "] -edition = "2021" - -[features] -default = ["std"] -std = [] - -[profile.release] -incremental = true -debug = true -lto = "fat" -codegen-units = 1 - -[dependencies] -libafl = { path = "../../libafl/" } -libafl_bolts = { path = "../../libafl_bolts/" } -libafl_qemu = { path = "../../libafl_qemu/", features = ["arm", "systemmode"] } -env_logger = "*" diff --git a/fuzzers/qemu_systemmode_sync_backdoor/README.md b/fuzzers/qemu_systemmode_sync_backdoor/README.md deleted file mode 100644 index 14098dc09c..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Qemu systemmode with launcher - -This folder contains an example fuzzer for the qemu systemmode, using LLMP for fast multi-process fuzzing and crash detection. - -## Build - -To build this example, run - -```bash -cargo build --release -cd example; sh build.sh; cd .. -``` - -This will build the the fuzzer (src/fuzzer.rs) and a small example binary based on FreeRTOS, which can run under a qemu emulation target. - -## Run - -Since the instrumentation is based on snapshtos QEMU needs a virtual drive (even if it is unused...). -Create on and then run the fuzzer: -```bash -# create an image -qemu-img create -f qcow2 dummy.qcow2 32M -# run the fuzzer -KERNEL=./example/example.elf target/release/qemu_systemmode -icount shift=auto,align=off,sleep=off -machine mps2-an385 -monitor null -kernel ./example/example.elf -serial null -nographic -snapshot -drive if=none,format=qcow2,file=dummy.qcow2 -S -``` -Currently the ``KERNEL`` variable is needed because the fuzzer does not parse QEMUs arguments to find the binary. \ No newline at end of file diff --git a/fuzzers/qemu_systemmode_sync_backdoor/corpus/random b/fuzzers/qemu_systemmode_sync_backdoor/corpus/random deleted file mode 100644 index 25175d51d3..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/corpus/random +++ /dev/null @@ -1 +0,0 @@ -yJv lpZGօrsY˗CMRպ}S7;Io76l1ޘ1R^Όp>G&_|1;ro4ƯUE<`L"6VƷk4/"tf7Fގd]ܮ%|8#wNUn8%4o˗ diff --git a/fuzzers/qemu_systemmode_sync_backdoor/corpus/zero b/fuzzers/qemu_systemmode_sync_backdoor/corpus/zero deleted file mode 100644 index 112363ac1917b417ffbd7f376ca786a1e5fa7490..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5 McmZQzU|`?^000jF3jhEB diff --git a/fuzzers/qemu_systemmode_sync_backdoor/example/build.sh b/fuzzers/qemu_systemmode_sync_backdoor/example/build.sh deleted file mode 100755 index e3ca03467f..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/example/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -arm-none-eabi-gcc -ggdb -ffreestanding -nostartfiles -lgcc -T mps2_m3.ld -mcpu=cortex-m3 -I../../../libafl_qemu/runtime main.c startup.c -o example.elf \ No newline at end of file diff --git a/fuzzers/qemu_systemmode_sync_backdoor/example/main.c b/fuzzers/qemu_systemmode_sync_backdoor/example/main.c deleted file mode 100644 index ed6779ca25..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/example/main.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "libafl_exit.h" - -int __attribute__((noinline)) BREAKPOINT() { - for (;;) {} -} - -int LLVMFuzzerTestOneInput(unsigned int *Data, unsigned int Size) { - LIBAFL_EXIT_START_PHYS((unsigned int) Data, Size); - // if (Data[3] == 0) { - // while (1) {} - // } // cause a timeout - for (int i = 0; i < Size; i++) { - // if (Data[i] > 0xFFd0 && Data[i] < 0xFFFF) {return 1;} // cause qemu to - // crash - for (int j = i + 1; j < Size; j++) { - if (Data[j] == 0) { continue; } - if (Data[j] > Data[i]) { - int tmp = Data[i]; - Data[i] = Data[j]; - Data[j] = tmp; - if (Data[i] <= 100) { j--; } - } - } - } - LIBAFL_EXIT_END(LIBAFL_EXIT_END_OK); - return BREAKPOINT(); -} -unsigned int FUZZ_INPUT[] = { - 101, 201, 700, 230, 860, 234, 980, 200, 340, 678, 230, 134, 900, - 236, 900, 123, 800, 123, 658, 607, 246, 804, 567, 568, 207, 407, - 246, 678, 457, 892, 834, 456, 878, 246, 699, 854, 234, 844, 290, - 125, 324, 560, 852, 928, 910, 790, 853, 345, 234, 586, -}; - -int main() { - LLVMFuzzerTestOneInput(FUZZ_INPUT, 50); -} diff --git a/fuzzers/qemu_systemmode_sync_backdoor/example/mps2_m3.ld b/fuzzers/qemu_systemmode_sync_backdoor/example/mps2_m3.ld deleted file mode 100644 index adfc15ed78..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/example/mps2_m3.ld +++ /dev/null @@ -1,143 +0,0 @@ -/* - * FreeRTOS V202112.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -MEMORY -{ - RAM (xrw) : ORIGIN = 0x00000000, LENGTH = 4M - /* Originally */ - /* FLASH (xr) : ORIGIN = 0x00000000, LENGTH = 4M */ - /* RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 4M */ -} -ENTRY(Reset_Handler) - -_Min_Heap_Size = 0x300000 ; /* Required amount of heap. */ -_Min_Stack_Size = 0x4000 ; /* Required amount of stack. */ -M_VECTOR_RAM_SIZE = (16 + 48) * 4; -_estack = ORIGIN(RAM) + LENGTH(RAM); - -SECTIONS -{ - - .isr_vector : - { - __vector_table = .; - KEEP(*(.isr_vector)) - . = ALIGN(4); - } > RAM /* FLASH */ - - .text : - { - . = ALIGN(4); - *(.text*) - KEEP (*(.init)) - KEEP (*(.fini)) - KEEP(*(.eh_frame)) - *(.rodata*) - . = ALIGN(4); - _etext = .; - } > RAM /* FLASH */ - - .ARM.extab : - { - . = ALIGN(4); - *(.ARM.extab* .gnu.linkonce.armextab.*) - . = ALIGN(4); - } >RAM /* FLASH */ - - .ARM : - { - . = ALIGN(4); - __exidx_start = .; - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __exidx_end = .; - . = ALIGN(4); - } >RAM /* FLASH */ - - .interrupts_ram : - { - . = ALIGN(4); - __VECTOR_RAM__ = .; - __interrupts_ram_start__ = .; - . += M_VECTOR_RAM_SIZE; - . = ALIGN(4); - __interrupts_ram_end = .; - } > RAM - - _sidata = LOADADDR(.data); - - .data : /* AT ( _sidata ) */ - { - . = ALIGN(4); - _sdata = .; - *(.data*) - . = ALIGN(4); - _edata = .; - } > RAM /* RAM AT > FLASH */ - - .uninitialized (NOLOAD): - { - . = ALIGN(32); - __uninitialized_start = .; - *(.uninitialized) - KEEP(*(.keep.uninitialized)) - . = ALIGN(32); - __uninitialized_end = .; - } > RAM - - .bss : - { - . = ALIGN(4); - _sbss = .; - __bss_start__ = _sbss; - *(.bss*) - *(COMMON) - . = ALIGN(4); - _ebss = .; - __bss_end__ = _ebss; - } >RAM - - .heap : - { - . = ALIGN(8); - PROVIDE ( end = . ); - PROVIDE ( _end = . ); - _heap_bottom = .; - . = . + _Min_Heap_Size; - _heap_top = .; - . = . + _Min_Stack_Size; - . = ALIGN(8); - } >RAM - - /* Set stack top to end of RAM, and stack limit move down by - * size of stack_dummy section */ - __StackTop = ORIGIN(RAM) + LENGTH(RAM); - __StackLimit = __StackTop - _Min_Stack_Size; - PROVIDE(__stack = __StackTop); - - /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= _heap_top, "region RAM overflowed with stack") -} - diff --git a/fuzzers/qemu_systemmode_sync_backdoor/example/startup.c b/fuzzers/qemu_systemmode_sync_backdoor/example/startup.c deleted file mode 100644 index 36be3cf55a..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/example/startup.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * FreeRTOS V202112.00 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * https://www.FreeRTOS.org - * https://github.com/FreeRTOS - * - */ - -typedef unsigned int uint32_t; - -extern int main(); - -extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; - -/* Prevent optimization so gcc does not replace code with memcpy */ -__attribute__((optimize("O0"))) __attribute__((naked)) void Reset_Handler( - void) { - /* set stack pointer */ - __asm volatile("ldr r0, =_estack"); - __asm volatile("mov sp, r0"); - - /* copy .data section from flash to RAM */ - // Not needed for this example, see linker script - // for( uint32_t * src = &_sidata, * dest = &_sdata; dest < &_edata; ) - // { - // *dest++ = *src++; - // } - - /* zero out .bss section */ - for (uint32_t *dest = &_sbss; dest < &_ebss;) { - *dest++ = 0; - } - - /* jump to board initialisation */ - void _start(void); - _start(); -} - -const uint32_t *isr_vector[] __attribute__((section(".isr_vector"))) = { - (uint32_t *)&_estack, - (uint32_t *)&Reset_Handler, /* Reset -15 */ - 0, /* NMI_Handler -14 */ - 0, /* HardFault_Handler -13 */ - 0, /* MemManage_Handler -12 */ - 0, /* BusFault_Handler -11 */ - 0, /* UsageFault_Handler -10 */ - 0, /* reserved */ - 0, /* reserved */ - 0, /* reserved */ - 0, /* reserved -6 */ - 0, /* SVC_Handler -5 */ - 0, /* DebugMon_Handler -4 */ - 0, /* reserved */ - 0, /* PendSV handler -2 */ - 0, /* SysTick_Handler -1 */ - 0, /* uart0 receive 0 */ - 0, /* uart0 transmit */ - 0, /* uart1 receive */ - 0, /* uart1 transmit */ - 0, /* uart 2 receive */ - 0, /* uart 2 transmit */ - 0, /* GPIO 0 combined interrupt */ - 0, /* GPIO 2 combined interrupt */ - 0, /* Timer 0 */ - 0, /* Timer 1 */ - 0, /* Dial Timer */ - 0, /* SPI0 SPI1 */ - 0, /* uart overflow 1, 2,3 */ - 0, /* Ethernet 13 */ -}; - -__attribute__((naked)) void exit(__attribute__((unused)) int status) { - /* Force qemu to exit using ARM Semihosting */ - __asm volatile( - "mov r1, r0\n" - "cmp r1, #0\n" - "bne .notclean\n" - "ldr r1, =0x20026\n" /* ADP_Stopped_ApplicationExit, a clean exit */ - ".notclean:\n" - "movs r0, #0x18\n" /* SYS_EXIT */ - "bkpt 0xab\n" - "end: b end\n"); -} - -void _start(void) { - main(); - exit(0); -} diff --git a/fuzzers/qemu_systemmode_sync_backdoor/src/main.rs b/fuzzers/qemu_systemmode_sync_backdoor/src/main.rs deleted file mode 100644 index bc1e80f767..0000000000 --- a/fuzzers/qemu_systemmode_sync_backdoor/src/main.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! A libfuzzer-like fuzzer using qemu for binary-only coverage -#[cfg(target_os = "linux")] -mod fuzzer; - -#[cfg(target_os = "linux")] -pub fn main() { - fuzzer::fuzz(); -} - -#[cfg(not(target_os = "linux"))] -pub fn main() { - panic!("qemu-user and libafl_qemu is only supported on linux!"); -} diff --git a/libafl_qemu/build_linux.rs b/libafl_qemu/build_linux.rs index 620d3e8a04..61f3130f31 100644 --- a/libafl_qemu/build_linux.rs +++ b/libafl_qemu/build_linux.rs @@ -14,10 +14,12 @@ pub fn build() { }) }; + let libafl_qemu_hdr_name = "libafl_qemu.h"; + let build_libqasan = cfg!(all(feature = "build_libqasan", not(feature = "hexagon"))); let exit_hdr_dir = PathBuf::from("runtime"); - let exit_hdr = exit_hdr_dir.join("libafl_exit.h"); + let libafl_qemu_hdr = exit_hdr_dir.join(libafl_qemu_hdr_name); println!("cargo:rustc-cfg=emulation_mode=\"{emulation_mode}\""); println!("cargo:rerun-if-env-changed=EMULATION_MODE"); @@ -72,6 +74,11 @@ pub fn build() { target_dir.pop(); target_dir.pop(); target_dir.pop(); + let include_dir = target_dir.join("include"); + + fs::create_dir_all(&include_dir).expect("Could not create include dir"); + + fs::copy(libafl_qemu_hdr.clone(), include_dir.join(libafl_qemu_hdr_name)).expect("Could not copy libafl_qemu.h to out directory."); let binding_file = out_dir_path_buf.join("backdoor_bindings.rs"); bindgen::Builder::default() @@ -83,7 +90,7 @@ pub fn build() { is_global: true, is_bitfield: true, }) - .header(exit_hdr.display().to_string()) + .header(libafl_qemu_hdr.display().to_string()) .generate() .expect("Exit bindings generation failed.") .write_to_file(binding_file) diff --git a/libafl_qemu/runtime/libafl_exit.h b/libafl_qemu/runtime/libafl_exit.h deleted file mode 100644 index 885290dbbe..0000000000 --- a/libafl_qemu/runtime/libafl_exit.h +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef LIBAFL_EXIT_H -#define LIBAFL_EXIT_H - -#define STRINGIFY(s) #s -#define XSTRINGIFY(s) STRINGIFY(s) - -// Target Specific imports / definitions -#ifdef _WIN32 - #include - #include - -typedef UINT64 libafl_word; - #define LIBAFL_CALLING_CONVENTION __fastcall - -#else - #ifdef __x86_64__ - #include - -typedef uint64_t libafl_word; - #define LIBAFL_CALLING_CONVENTION __attribute__(()) - #endif - - #ifdef __arm__ - #include - -typedef uint32_t libafl_word; - #define LIBAFL_CALLING_CONVENTION __attribute__(()) - #endif -#endif - -#define LIBAFL_EXIT_OPCODE 0x66f23a0f -#define LIBAFL_EXIT_VERSION_NUMBER 0111 // TODO: find a nice way to set it. - -typedef enum LibaflExit { - LIBAFL_EXIT_START_VIRT = 0, - LIBAFL_EXIT_START_PHYS = 1, - LIBAFL_EXIT_INPUT_VIRT = 2, - LIBAFL_EXIT_INPUT_PHYS = 3, - LIBAFL_EXIT_END = 4, - LIBAFL_EXIT_SAVE = 5, - LIBAFL_EXIT_LOAD = 6, - LIBAFL_EXIT_VERSION = 7, - LIBAFL_EXIT_VADDR_FILTER_ALLOW = 8, -} LibaflExit; - -typedef enum LibaflExitEndStatus { - LIBAFL_EXIT_END_UNKNOWN = 0, - LIBAFL_EXIT_END_OK = 1, - LIBAFL_EXIT_END_CRASH = 2, -} LibaflExitEndParams; - -#ifdef _WIN32 - #ifdef __cplusplus -extern "C" { - #endif -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call0(libafl_word action); -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call1(libafl_word action, - libafl_word arg1); -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call2(libafl_word action, - libafl_word arg1, - libafl_word arg2); - #ifdef __cplusplus -} - #endif -#else - - #ifdef __x86_64__ -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call0(libafl_word action) { - libafl_word ret; - __asm__ volatile ( - "mov %1, %%rax\n" - ".dword " XSTRINGIFY(LIBAFL_EXIT_OPCODE) "\n" - "mov %%rax, %0\n" - : "=g"(ret) - : "g"(action) - : "%rax" - ); - return ret; -} - -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call1(libafl_word action, - libafl_word arg1) { - libafl_word ret; - __asm__ volatile ( - "mov %1, %%rax\n" - "mov %2, %%rdi\n" - ".dword " XSTRINGIFY(LIBAFL_EXIT_OPCODE) "\n" - "mov %%rax, %0\n" - : "=g"(ret) - : "g"(action), "g"(arg1) - : "%rax", "%rdi" - ); - return ret; -} - -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call2(libafl_word action, - libafl_word arg1, - libafl_word arg2) { - libafl_word ret; - __asm__ volatile ( - "mov %1, %%rax\n" - "mov %2, %%rdi\n" - "mov %3, %%rsi\n" - ".dword " XSTRINGIFY(LIBAFL_EXIT_OPCODE) "\n" - "mov %%rax, %0\n" - : "=g"(ret) - : "g"(action), "g"(arg1), "g"(arg2) - : "%rax", "%rdi", "%rsi" - ); - return ret; -} - #endif - - #ifdef __arm__ -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call0(libafl_word action) { - libafl_word ret; - __asm__ volatile ( - "mov r0, %1\n" - ".word " XSTRINGIFY(LIBAFL_EXIT_OPCODE) "\n" - "mov %0, r0\n" - : "=r"(ret) - : "r"(action) - : "r0" - ); - return ret; -} - -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call1(libafl_word action, - libafl_word arg1) { - libafl_word ret; - __asm__ volatile ( - "mov r0, %1\n" - "mov r1, %2\n" - ".word " XSTRINGIFY(LIBAFL_EXIT_OPCODE) "\n" - "mov %0, r0\n" - : "=r"(ret) - : "r"(action), "r"(arg1) - : "r0", "r1" - ); - return ret; -} - -libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call2(libafl_word action, - libafl_word arg1, - libafl_word arg2) { - libafl_word ret; - __asm__ volatile ( - "mov r0, %1\n" - "mov r1, %2\n" - "mov r2, %3\n" - ".word " XSTRINGIFY(LIBAFL_EXIT_OPCODE) "\n" - "mov %0, r0\n" - : "=r"(ret) - : "r"(action), "r"(arg1), "r"(arg2) - : "r0", "r1", "r2" - ); - return ret; -} - #endif - -#endif - -#define LIBAFL_EXIT_START_VIRT(buf_vaddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_START_VIRT, buf_vaddr, max_len) -#define LIBAFL_EXIT_START_PHYS(buf_paddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_START_PHYS, buf_paddr, max_len) -#define LIBAFL_EXIT_INPUT_VIRT(buf_vaddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_INPUT_VIRT, buf_vaddr, max_len) -#define LIBAFL_EXIT_INPUT_PHYS(buf_paddr, max_len) \ - _libafl_exit_call2(LIBAFL_EXIT_INPUT_PHYS, buf_paddr, max_len) -#define LIBAFL_EXIT_END(status) _libafl_exit_call1(LIBAFL_EXIT_END, status) -#define LIBAFL_EXIT_SAVE() _libafl_exit_call0(LIBAFL_EXIT_SAVE) -#define LIBAFL_EXIT_LOAD() _libafl_exit_call0(LIBAFL_EXIT_LOAD) -#define LIBAFL_EXIT_VERSION() _libafl_exit_call0(LIBAFL_EXIT_VERSION_NUMBER) - -#endif \ No newline at end of file diff --git a/libafl_qemu/runtime/libafl_exit_windows.asm b/libafl_qemu/runtime/libafl_qemu.asm similarity index 100% rename from libafl_qemu/runtime/libafl_exit_windows.asm rename to libafl_qemu/runtime/libafl_qemu.asm diff --git a/libafl_qemu/runtime/libafl_qemu.h b/libafl_qemu/runtime/libafl_qemu.h new file mode 100644 index 0000000000..0ef008e8f6 --- /dev/null +++ b/libafl_qemu/runtime/libafl_qemu.h @@ -0,0 +1,216 @@ +#ifndef LIBAFL_EXIT_H +#define LIBAFL_EXIT_H + +/** + * LibAFL QEMU header file. + * + * This file is a portable header file used to build target harnesses more + * conveniently. Its main purpose is to generate ready-to-use calls to + * communicate with the fuzzer. The list of commands is available at the bottom + * of this file. The rest mostly consists of macros generating the code used by + * the commands. + */ + +/* === The private part starts here === */ + +/* This part should not be useful for most people. Callable commands are + * available at the end of this file. */ + +#define STRINGIFY(s) #s +#define XSTRINGIFY(s) STRINGIFY(s) + +// Target Specific imports / definitions +#ifdef _WIN32 + #include + #include + +typedef UINT64 libafl_word; + #define LIBAFL_CALLING_CONVENTION __fastcall + +#else + #ifdef __x86_64__ + #include + +typedef uint64_t libafl_word; + #define LIBAFL_CALLING_CONVENTION __attribute__(()) + #endif + + #ifdef __arm__ + #include + +typedef uint32_t libafl_word; + #define LIBAFL_CALLING_CONVENTION __attribute__(()) + #endif +#endif + +#define LIBAFL_EXIT_OPCODE 0x66f23a0f +#define LIBAFL_BACKDOOR_OPCODE 0x44f23a0f + +#define LIBAFL_EXIT_VERSION_NUMBER 0111 // TODO: find a nice way to set it. + +typedef enum LibaflExit { + LIBAFL_EXIT_START_VIRT = 0, + LIBAFL_EXIT_START_PHYS = 1, + LIBAFL_EXIT_INPUT_VIRT = 2, + LIBAFL_EXIT_INPUT_PHYS = 3, + LIBAFL_EXIT_END = 4, + LIBAFL_EXIT_SAVE = 5, + LIBAFL_EXIT_LOAD = 6, + LIBAFL_EXIT_VERSION = 7, + LIBAFL_EXIT_VADDR_FILTER_ALLOW = 8, +} LibaflExit; + +typedef enum LibaflExitEndStatus { + LIBAFL_EXIT_END_UNKNOWN = 0, + LIBAFL_EXIT_END_OK = 1, + LIBAFL_EXIT_END_CRASH = 2, +} LibaflExitEndParams; + +#ifdef _WIN32 + #ifdef __cplusplus +extern "C" { + #endif +libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call0(libafl_word action); +libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call1(libafl_word action, + libafl_word arg1); +libafl_word LIBAFL_CALLING_CONVENTION _libafl_exit_call2(libafl_word action, + libafl_word arg1, + libafl_word arg2); + #ifdef __cplusplus +} + #endif +#else + + #ifdef __x86_64__ + #define LIBAFL_DEFINE_FUNCTIONS(name, opcode) \ + libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call0( \ + libafl_word action) { \ + libafl_word ret; \ + __asm__ volatile ( \ + "mov %1, %%rax\n" \ + ".dword " XSTRINGIFY(opcode) "\n" \ + "mov %%rax, %0\n" \ + : "=g"(ret) \ + : "g"(action) \ + : "%rax" \ + ); \ + return ret; \ + } \ + \ + libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call1( \ + libafl_word action, libafl_word arg1) { \ + libafl_word ret; \ + __asm__ volatile ( \ + "mov %1, %%rax\n" \ + "mov %2, %%rdi\n" \ + ".dword " XSTRINGIFY(opcode) "\n" \ + "mov %%rax, %0\n" \ + : "=g"(ret) \ + : "g"(action), "g"(arg1) \ + : "%rax", "%rdi" \ + ); \ + return ret; \ + } \ + \ + libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call2( \ + libafl_word action, libafl_word arg1, libafl_word arg2) { \ + libafl_word ret; \ + __asm__ volatile ( \ + "mov %1, %%rax\n" \ + "mov %2, %%rdi\n" \ + "mov %3, %%rsi\n" \ + ".dword " XSTRINGIFY(opcode) "\n" \ + "mov %%rax, %0\n" \ + : "=g"(ret) \ + : "g"(action), "g"(arg1), "g"(arg2) \ + : "%rax", "%rdi", "%rsi" \ + ); \ + return ret; \ + } + #endif + + #ifdef __arm__ + #define LIBAFL_DEFINE_FUNCTIONS(name, opcode) \ + libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call0( \ + libafl_word action) { \ + libafl_word ret; \ + __asm__ volatile ( \ + "mov r0, %1\n" \ + ".word " XSTRINGIFY(opcode) "\n" \ + "mov %0, r0\n" \ + : "=r"(ret) \ + : "r"(action) \ + : "r0" \ + ); \ + return ret; \ + } \ + \ + libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call1( \ + libafl_word action, libafl_word arg1) { \ + libafl_word ret; \ + __asm__ volatile ( \ + "mov r0, %1\n" \ + "mov r1, %2\n" \ + ".word " XSTRINGIFY(opcode) "\n" \ + "mov %0, r0\n" \ + : "=r"(ret) \ + : "r"(action), "r"(arg1) \ + : "r0", "r1" \ + ); \ + return ret; \ + } \ + \ + libafl_word LIBAFL_CALLING_CONVENTION _libafl_##name##_call2( \ + libafl_word action, libafl_word arg1, libafl_word arg2) { \ + libafl_word ret; \ + __asm__ volatile ( \ + "mov r0, %1\n" \ + "mov r1, %2\n" \ + "mov r2, %3\n" \ + ".word " XSTRINGIFY(opcode) "\n" \ + "mov %0, r0\n" \ + : "=r"(ret) \ + : "r"(action), "r"(arg1), "r"(arg2) \ + : "r0", "r1", "r2" \ + ); \ + return ret; \ + } + #endif + +#endif + +// Generates sync exit functions +LIBAFL_DEFINE_FUNCTIONS(exit, LIBAFL_EXIT_OPCODE) + +// Generates backdoor functions +LIBAFL_DEFINE_FUNCTIONS(backdoor, LIBAFL_BACKDOOR_OPCODE) + +/* === The private part ends here === */ + +/* === The public part starts here === */ + +/* Commands */ + +#define LIBAFL_EXIT_START_VIRT(buf_vaddr, max_len) \ + _libafl_exit_call2(LIBAFL_EXIT_START_VIRT, buf_vaddr, max_len) + +#define LIBAFL_EXIT_START_PHYS(buf_paddr, max_len) \ + _libafl_exit_call2(LIBAFL_EXIT_START_PHYS, buf_paddr, max_len) + +#define LIBAFL_EXIT_INPUT_VIRT(buf_vaddr, max_len) \ + _libafl_exit_call2(LIBAFL_EXIT_INPUT_VIRT, buf_vaddr, max_len) + +#define LIBAFL_EXIT_INPUT_PHYS(buf_paddr, max_len) \ + _libafl_exit_call2(LIBAFL_EXIT_INPUT_PHYS, buf_paddr, max_len) + +#define LIBAFL_EXIT_END(status) _libafl_exit_call1(LIBAFL_EXIT_END, status) + +#define LIBAFL_EXIT_SAVE() _libafl_exit_call0(LIBAFL_EXIT_SAVE) + +#define LIBAFL_EXIT_LOAD() _libafl_exit_call0(LIBAFL_EXIT_LOAD) + +#define LIBAFL_EXIT_VERSION() _libafl_exit_call0(LIBAFL_EXIT_VERSION_NUMBER) + +/* === The public part ends here === */ + +#endif \ No newline at end of file