Fuzzing the AMD Secure Processors ROM bootloader with LibAFL using QEMU full-system emulation
flowchart LR;
VanillaQemu["Vanilla QEMU"];
LibAFLQemu["LibAFL QEMU"];
ASPQEMU["ASP-QEMU"];
VanillaLibAFL["Vanilla LibAFL"];
ASPLibAFL["LibAFL that references ASP QEMU"];
ASPFuzz{{"ASPFuzz"}};
VanillaQemu --> LibAFLQemu;
LibAFLQemu --> ASPQEMU;
ASPQEMU -.-> ASPLibAFL;
VanillaLibAFL --> ASPLibAFL
ASPLibAFL -.-> ASPFuzz;
Install nix and use the flake.nix with nix develop to get a fully reproducible environment
that you can easily share across machines.
Alternatively you can install the following dependencies manually:
- Qemu requirements (Ubuntu:
sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build) - arm-none-eabi-gcc (Ubuntu
sudo apt install gcc-arm-none-eabi) - nettle (Ubuntu:
sudo apt install nettle-dev) - rust
- cargo
- just
-
Navigate to
fuzzer/amd_sp/.cd fuzzer/amd_sp/ -
Pick a YAML file from
yaml/- Fuzz the on-chip bootloader for Ryzen Zen1:
yaml/ryzen_zen1_desktop_parse_asp_flash.yaml - Fuzz the on-chip bootloader for Ryzen Zen+:
yaml/ryzen_zen+_desktop_parse_asp_flash.yaml - Fuzz the on-chip bootloader for Ryzen Zen2:
yaml/ryzen_zen2_desktop_parse_asp_flash.yaml - Fuzz the on-chip bootloader for Ryzen Zen3:
yaml/ryzen_zen3_desktop_parse_asp_flash.yaml - Fuzz the on-chip bootloader for Ryzen ZenTesla:
yaml/ryzen_zentesla_parse_asp_flash.yaml
- Fuzz the on-chip bootloader for Ryzen Zen1:
-
Run the fuzzer
just test -y {yaml_file_path}- single-core
- debug to
runs/{start_data_time}/logs/run.log
just run -y {yaml_file_path}- single-core
- no debug
just perf -y {yaml_file_path}- performance mode
- no debug
-
More configuration options
just run -- -h -
Stop the fuzzer
- Single-core:
CTRL + a->x - Multi-core:
sudo kill -9 $(pidof aspfuzz)
- Single-core:
-
Output
Loadingflowchart LR; Runs["runs/"]; Date["2022-11-16_09:48/"]; Solutions["solutions/"]; Solution1["{solution_hash}"]; Solution2["..."]; Solution1Meta[".{solution_hash}.metadata"]; Inputs["inputs/"]; Logs["logs/"]; DrCov["drcov.log"]; LibAFL["libafl.log"]; Run["(run.log)"]; Config["config.yaml"]; Runs --> Date; Date --> Solutions; Solutions --> Solution1; Solutions --> Solution1Meta; Solutions --> Solution2; Date --> Inputs; Date --> Logs; Logs --> DrCov; Logs --> LibAFL; Logs --> Run; Date --> Config;- Solutions can be found in
runs/{start_data_time}/solutions/. Each solution file is named after the hashed test-case input. The.{solution_hash}.metadatacontain useful metadata for debugging. - The inputs used for the fuzzing campaign can be found under
runs/{start_data_time}/inputs/. - The LibAFL monitor log for the whole campaign is written to
runs/{start_data_time}/logs/libafl.log. - A DrCov trace file is generate for each campaign as
runs/{start_data_time}/logs/drcov.log. - If the campaign was started with
just test, all debug output will be captured inruns/{start_data_time}/logs/run.log. - The yaml config file used for the campaign is stores as
runs/{start_data_time}/config.yaml
- Solutions can be found in
-
Analyze the output
- Generate full flash ROM images from solutions:
script/solution2flashimg.py - Analyze flash images for the known buffer overflow in Zen1&Zen+:
script/known_buffer_overflow.py. - Evalute solution metadata file:
script/metadata_analyser.py - Plot libafl stats:
script/stats2plot.py - Visualize the DrCov coverage: Ghidra with the Lightkeeper plugin