AFLplusplus / AFLplusplus/LibAFL
Full system qemu baremetal for riscv
- 主要言語
- Rust
- スター
- 2.6k
- フォーク
- 481
- 平均マージ
- 2日 30分
- マージ済み PR(30日)
- 16
説明
# Description
I am trying to fuzz the riscv32 baremetal program in qemu full system emulation mode in LibAFL. Currently, I have made following changes to the given Arm example accordingly to match with riscv.
- Changed the `Cargo.toml` file to install qemu riscv32 version.
- Changed the `Justfile` to modify the gcc toolchain for riscv32 and to modify the qemu machine to `sifive_e`
- Then I made changes to the linker file according to `sifive_e` machine.
I was able to successfully build the environment (`just build`). However, when running the fuzzer(`just run`), I am getting following error.
```afluser@860c6ff8fa77:/workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32$ just run
mkdir -p "/workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target"
qemu-img create -f qcow2 /workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/dummy.qcow2 32M
Formatting '/workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/dummy.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=33554432 lazy_refcounts=off refcount_bits=16
riscv32-unknown-elf-gcc -ggdb -ffreestanding -nostartfiles -lgcc -T example/sifive_e.ld -D "TARGET_BREAKPOINT" -I /workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/release/include example/main.c example/startup.c -o /workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/example.elf
cargo build --profile release --no-default-features --features std,breakpoint --target-dir /workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target
Finished `release` profile [optimized + debuginfo] target(s) in 0.11s
/workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/release/qemu_baremetal -icount shift=auto,align=off,sleep=off -machine sifive_e -monitor null -kernel /workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/example.elf -drive if=none,format=qcow2,file=/workspaces/wolfboot-fuzzer/LibAFL/fuzzers/full_system/qemu_riscv32/target/dummy.qcow2 -serial null -nographic -snapshot -S
FUZZ_INPUT @ 0x80000000
main address = 0x20010306
Breakpoint address = 0x20010200
Devices = ["timer", "cpu_common", "cpu", "riscv_sifive_plic", "riscv_mtimer", "sifive_soc.gpio", "riscv.sifive.uart", "riscv.sifive.uart"]
[Objective #1] (GLOBAL) run time: 0h-0m-3s, clients: 1, corpus: 0, objectives: 1, executions: 0, exec/sec: 0.000
(CLIENT) corpus: 0, objectives: 1, executions: 0, exec/sec: 0.000
We imported 0 inputs from disk.
thread 'main' panicked at src/fuzzer_breakpoint.rs:217:14:
called `Result::unwrap()` on an `Err` value: Empty("No entries in corpus. This often implies the target is not properly instrumented.", ErrorBacktrace)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
[Objective #1] (GLOBAL) run time: 0h-0m-6s, clients: 1, corpus: 0, objectives: 2, executions: 0, exec/sec: 0.000
(CLIENT) corpus: 0, objectives: 2, executions: 0, exec/sec: 0.000
thread 'main' panicked at /workspaces/wolfboot-fuzzer/LibAFL/libafl/src/events/llmp/restarting.rs:886:21:
Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: 101)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Fuzzing stopped by user. Good bye.
```
## Questions
1. It seems like the problem is with the initial corpus. As stated in the above output, it could not import corpus. I copied the corpus directory from the qemu_baremetal example. I am having a problem understanding the corpus directory. Do I need to create a new corpus for my version?
2. I have gone through the README file in the example directory to understand the fuzzing flow. However, I still do not have an idea of how exactly full system fuzzing is achieved in LibAFL. Can you give me a brief explanation on this work?
## Modified files
`Cargo.toml`
```
[package]
name = "qemu_baremetal"
version = "0.15.1"
authors = [
"Andrea Fioraldi ",
"Dominik Maier ",
"Romain Malmain ",
]
edition = "2021"
[features]
default = ["std", "low_level"]
std = []
low_level = [
] # The low-level way to interact with LibAFL QEMU, with direct calls to QEMU's functions
breakpoint = [] # Uses the command system, with breakpoints
sync_exit = [] # Uses the command system, with sync exit.
shared = ["libafl_qemu/shared"]
[profile.release]
incremental = true
debug = true
lto = "fat"
codegen-units = 1
[dependencies]
libafl = { path = "../../../libafl" }
libafl_bolts = { path = "../../../libafl_bolts" }
libafl_targets = { path = "../../../libafl_targets" }
libafl_qemu = { path = "../../../libafl_qemu", features = [
"riscv32",
"systemmode",
], default-features = false }
env_logger = "0.11.5"
log = { version = "0.4.22", features = ["release_max_level_info"] }
[build-dependencies]
libafl_qemu_build = { path = "../../../libafl_qemu/libafl_qemu_build" }
```
`Justfile`
```import "../../../just/libafl-qemu.just"
FUZZER_NAME := "qemu_baremetal"
KERNEL := TARGET_DIR / "example.elf"
DUMMY_IMG := TARGET_DIR / "dummy.qcow2"
target_dir:
mkdir -p "{{TARGET_DIR}}"
image: target_dir
qemu-img create -f qcow2 {{DUMMY_IMG}} 32M
target flavor: image target_dir
riscv32-unknown-elf-gcc -ggdb -ffreestanding -nostartfiles -lgcc \
-T example/sifive_e.ld \
-D "TARGET_{{ uppercase(flavor) }}" \
-I {{BUILD_DIR / "include"}} \
example/main.c \
example/startup.c \
-o {{TARGET_DIR}}/example.elf
build flavor="breakpoint": target_dir
cargo build \
--profile {{PROFILE}} \
--no-default-features \
--features std,{{flavor}} \
--target-dir {{TARGET_DIR}}
run flavor="breakpoint": (target flavor) (build flavor)
{{BUILD_DIR / "qemu_baremetal"}} \
-icount shift=auto,align=off,sleep=off \
-machine sifive_e \
-monitor null \
-kernel {{KERNEL}} \
-drive if=none,format=qcow2,file={{DUMMY_IMG}} \
-serial null \
-nographic \
-snapshot \
-S
test_flavor flavor: (target flavor) (build flavor)
#!/bin/bash
export KERNEL={{ KERNEL }}
export TARGET_DIR={{ TARGET_DIR }}
TMP_DIR=$(mktemp -d)
timeout 20s {{ FUZZER }} \
-icount shift=auto,align=off,sleep=off \
-machine sifive_e \
-monitor null \
-kernel {{ KERNEL }} -serial null \
-drive if=none,format=qcow2,file={{ DUMMY_IMG }} \
-nographic \
-snapshot \
-S | tee "$TMP_DIR/fuzz.log" 2>&1 || true
if [ -z "$(grep 'Objective' $TMP_DIR/fuzz.log)" ]; then
echo "qemu_baremetal ${FEATURE}: Fuzzer did not find the objective in $TMP_DIR/fuzz.log"
exit 1
else
echo "qemu_baremetal ${FEATURE}: Objective found."
fi
test: (test_flavor "low_level") (test_flavor "breakpoint") (test_flavor "sync_exit")
clean:
cargo clean
```
Linker File
```
OUTPUT_ARCH( "riscv" )
ENTRY( _reset )
MEMORY
{
FLASH(rxai!w) : ORIGIN = 0x20010000, LENGTH = 65536
RAM(wxa!ri) : ORIGIN = 0x80000000, LENGTH = 16K
}
SECTIONS
{
.text :
{
_start_text = .;
KEEP(*(.init)) /* Only for _reset, relocates IV to 0x200 */
. = ORIGIN(FLASH) + 0x200;
_start_vector = .;
KEEP(*(.isr_vector))
*(.text*)
*(.rodata*)
*(.srodata*)
. = ALIGN(4);
_end_text = .;
} > FLASH
_stored_data = .;
.data : AT (_stored_data)
{
. = ALIGN(4096);
_start_data = .;
KEEP(*(.ramcode*))
. = ALIGN(4);
*(.data*)
. = ALIGN(4);
_global_pointer = . + 0x800;
*(.sdata*)
. = ALIGN(4);
_end_data = .;
} > RAM
.bss (NOLOAD) :
{
_start_bss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_end_bss = .;
_end = .;
} > RAM
}
PROVIDE(_start_heap = _end);
PROVIDE(_end_stack = ORIGIN(RAM) + (LENGTH(RAM)) );
```
`startup.c`
```c
extern void main(void);
typedef unsigned int uint32_t;
extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;
__attribute__((optimize("O0"))) __attribute__((naked)) void _reset(void) {
/* jump to board initialisation */
void _start(void);
_start();
}
void _start(void) {
main();
}
```
Thank you for your time.
コントリビューションガイド
評価
この issue はまだ評価されていません。