diff options
author | vanhauser-thc <vh@thc.org> | 2021-12-29 11:43:21 +0100 |
---|---|---|
committer | vanhauser-thc <vh@thc.org> | 2021-12-29 11:43:21 +0100 |
commit | 1a25ccb61829105628e096ad7afb68100bfda753 (patch) | |
tree | cd85ae89a6e3d3804c322ba0f4320a10e913baf9 | |
parent | 0792cab5661271250218f6b83b2298e491191e67 (diff) | |
download | afl++-1a25ccb61829105628e096ad7afb68100bfda753.tar.gz |
readme for nyx
-rw-r--r-- | nyx_mode/README.md | 155 |
1 files changed, 129 insertions, 26 deletions
diff --git a/nyx_mode/README.md b/nyx_mode/README.md index dd0d1aac..17ed365a 100644 --- a/nyx_mode/README.md +++ b/nyx_mode/README.md @@ -1,34 +1,138 @@ -### Fuzzing libxml2 with AFL++ in Nyx-mode +# Nyx Mode -This tutorial is based on the [Fuzzing libxml2 with AFL++](https://aflplus.plus/docs/tutorials/libxml2_tutorial/) tutorial. +Nyx is a full system emulation fuzzing mode that supports snapshotting and +can be used for both source code based instrumentation and binary-only targets. + +It is recommended to be used if the target cannot be fuzzed in persistent mode +(so default fork mode fuzzing is used). + +It is only available on Linux and is currently restricted to x86_x64 however +aarch64 support is in the works (but the host must then run on aarch64 too). + +Underneath it is built upon KVM and QEMU and requires a modern Linux kernel +(5.11+) for fuzzing source code based instrumented targets (e.g. +`afl-clang-fast`). To fuzz binary-only targets, this is done via Intel PT +and requires an Intel processor (6th generation onwards) and a special +5.10 kernel (see [KVM-Nyx](https://github.com/nyx-fuzz/KVM-Nyx)). + +## Building Nyx mode + +1. Install all the packages from [docs/INSTALL.md](../docs/INSTALL.md). + +2. Additionally install the follow packages: + +```shell +apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 +``` + +3. As Nyx is written in Rust, install the newest rust compiler (rust packages + in the Linux distribution are usually too old to be able to build Nyx): + +```shell +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +4. Finally build Nyx mode: + +```shell +./build_nyx_support.sh +``` + +5. Optional, for binary-only fuzzing: setup the required 5.10 kernel, see + [KVM-Nyx](https://github.com/nyx-fuzz/KVM-Nyx). + +## Preparing to fuzz a target with Nyx mode + +Nyx uses full system emulation hence your fuzzing targets have to be especially +packaged. + +**For source code based instrumentation with `afl-clang-fast` for the time +being these must be instrumented to `AFL_LLVM_INSTRUMENT=AFL` to work!** + +With your target ready at hand execute the following command +(note that for binary-only fuzzing with the special 5.10 kernel switch the +option `instrumentation` below with `process_trace`): + +```shell +python3 nyx_mode/packer/packer/nyx_packer.py \ + /PATH/TO/TARGET \ + PACKAGE-DIRECTORY \ + afl \ + instrumentation \ + --fast_reload_mode \ + --purge +``` + +This will create a directory with all necessary files and the Nyx configuration. +The name of the directory will be whatever you choose for PACKAGE-DIRECTORY +above. + +In the final step for the packaging we generate the Nyx configuration: +```shell +python3 nyx_mode/packer/packer/nyx_config_gen.py PACKAGE-DIRECTORY Kernel +``` -#### Initial Setup +## Fuzzing with Nyx mode -Setting up our fork of AFL++ and its Nyx backend is rather simple. But there are some requirements: first, Nyx expects either a recent linux kernel (`>= 5.11`) with KVM or KVM-Nyx to be installed. In both cases, access to the `/dev/kvm` device is required. So, make sure that the permissions are fine. +All the hard parts are done, fuzzing with Nyx mode is easy - just supply +the PACKAGE-DIRECTORY as fuzzing target and specify the `-X` option to afl-fuzz: -To get started, check out our repository and run our setup script to install `libnyx`, Nyx's packer utilities and QEMU-Nyx: +```shell +afl-fuzz -i in -o out -X -- ./PACKAGE-DIRECTORY +``` +Most likely your first run will fail because the Linux modules have to be +specially set up, but afl-fuzz will tell you this on startup and how to +rectify the situation: +``` +sudo modprobe -r kvm-intel # or kvm-amd for AMD processors +sudo modprobe -r kvm +sudo modprobe kvm enable_vmware_backdoor=y +sudo modprobe kvm-intel # or kvm-amd for AMD processors ``` -git clone https://github.com/nyx-fuzz/AFLplusplus-Nyx.git -cd AFLplusplus-Nyx -compile_nyx_mode.sh + +If you want to fuzz in parallel (and you should!), then this has to be done in a +special way: + + * Instead of `-X` (standalone mode) you specify `-Y` (multi processor mode). + * First a Main afl-fuzz instance has to be started with `-M 0` + * Only afterwards can you start Secondary afl-fuzz instances, which must have + an increasing number value, starting at 1, e.g. `-S 1` + +```shell +afl-fuzz -i in -o out -Y -M 0 -- ./PACKAGE-DIRECTORY ``` +```shell +afl-fuzz -i in -o out -Y -S 1 -- ./PACKAGE-DIRECTORY +``` + +```shell +afl-fuzz -i in -o out -Y -S 2 -- ./PACKAGE-DIRECTORY +``` + +## Real-world examples + +### Fuzzing libxml2 with AFL++ in Nyx-mode + +This tutorial is based on the [Fuzzing libxml2 with AFL++](https://aflplus.plus/docs/tutorials/libxml2_tutorial/) tutorial. + ### Preparing libxml2 -This part is basically the same as described in the original tutorial. First, get the latest libxml2 source files by using `git`: +First, get the latest libxml2 source files by using `git`: ``` -git clone https://gitlab.gnome.org/GNOME/libxml2.git +git clone https://gitlab.gnome.org/GNOME/libxml2 cd libxml2 ``` -From there on, you have to use -- at least for now -- our AFL-compiler instead of the AFL++ provided compiler. The reason for this is that we currently don't support all of AFL++'s features. Basically, we don't have full support for collision-free bitmaps yet. So, to continue run the following commands and adjust the path to our compiler (our compiler is located in the `packer` repository): +Remember that currently only classic AFL instrumented is supported! ``` +export AFL_LLVM_INSTRUMENT=AFL ./autogen.sh ./configure --enable-shared=no -make CC=~/AFLplusplus-Nyx/packer/packer/compiler/afl-clang-fast CXX=~/AFLplusplus-Nyx/packer/packer/compiler/afl-clang-fast++ LD=~/AFLplusplus-Nyx/packer/packer/compiler/afl-clang-fast +make CC=afl-clang-fast CXX=afl-clang-fast++ LD=afl-clang-fast ``` #### Nyx share directories @@ -48,13 +152,13 @@ Those tools are all using hypercalls which are defined in `packer/nyx.h`. We wil To turn a given linux target into the Nyx format, you can simply use `nyx_packer.py`. To do so, move to the following directory: ``` -cd ~/AFLplusplus-Nyx/packer/packer +cd nyx_mode/packer/packer ``` And run the tool with the following options to pack `libxml2`: ```. -./nyx_packer.py \ +python3 ./nyx_packer.py \ ~/libxml2/xmllint \ /tmp/nyx_libxml2 \ afl \ @@ -74,17 +178,17 @@ In case you want to fuzz the target only with fast snapshots enabled, you can al Finally, we need to generate a Nyx configuration file. Simply run the following command and you're good to proceed: ``` -./nyx_config_gen.py /tmp/nyx_libxml2/ Kernel +python3 ./nyx_config_gen.py /tmp/nyx_libxml2/ Kernel ``` -### Run AFL++Nyx +### Run Nyx mode -From here on, we are almost done. Move to the AFL++Nyx folder and start the fuzzer with the following arguments: +From here on, we are almost done. Move to the AFL++ top directory and start the fuzzer with the following arguments: -``` -mkdir /tmp/in/ # to create an input folder -echo "AA" >> /tmp/in/A # create an input file to make the fuzzer happy for now - ./afl-fuzz -i /tmp/in/ -o /tmp/out -d -X /tmp/nyx_libxml2/ +```shell +mkdir /tmp/in/ # create an input folder +echo "AAAA" >> /tmp/in/A # create a dummy input file + ./afl-fuzz -i /tmp/in/ -o /tmp/out -X /tmp/nyx_libxml2/ ``` If everything has been successfully set up to this point, you will now be welcomed by the following AFL++ screen: @@ -145,7 +249,7 @@ mkdir /tmp/nyx_custom_agent/ To compile this example, run the following command (remove the `-DNO_PT_NYX` option if you are using KVM-Nyx ): ``` -gcc example.c -DNO_PT_NYX -static -I AFLplusplus/packer/ -o /tmp/nyx_custom_agent/target +gcc example.c -DNO_PT_NYX -static -I ./packer/ -o /tmp/nyx_custom_agent/target ``` Copy both bootstrap scripts into the sharedir: @@ -158,7 +262,7 @@ cp fuzz_no_pt.sh /tmp/nyx_custom_agent Copy all `htools` executable into the sharedir: ``` -cd ~/AFLplusplus-Nyx/packer/packer/linux_x86_64-userspace/ +cd ~/AFLplusplus/packer/packer/linux_x86_64-userspace/ sh compile_64.sh cp bin64/h* /tmp/nyx_custom_agent/ ``` @@ -166,7 +270,6 @@ cp bin64/h* /tmp/nyx_custom_agent/ And finally, generate a Nyx configuration: ``` -cd ~/AFLplusplus-Nyx/packer/packer -./nyx_config_gen.py /tmp/nyx_custom_agent/ Kernel +cd ~/AFLplusplus/packer/packer +python3 ./nyx_config_gen.py /tmp/nyx_custom_agent/ Kernel ``` - |