about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvanhauser-thc <vh@thc.org>2021-12-29 11:43:21 +0100
committervanhauser-thc <vh@thc.org>2021-12-29 11:43:21 +0100
commit1a25ccb61829105628e096ad7afb68100bfda753 (patch)
treecd85ae89a6e3d3804c322ba0f4320a10e913baf9
parent0792cab5661271250218f6b83b2298e491191e67 (diff)
downloadafl++-1a25ccb61829105628e096ad7afb68100bfda753.tar.gz
readme for nyx
-rw-r--r--nyx_mode/README.md155
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
 ```
-