cd <path_of_miragefuzz>
docker build . -t <image-name>
docker run --name <container-name> -it --privileged --net=host <image-name> /bin/bash
After all the dependent library and environment are satisfied (please refer to Dockerfile).
cd <path_of_miragefuzz>
./build.sh
Build the project normally, but the full LLVM bitcode representing the PUT target is required.
Use the tool wllvm, as its document.
While compiling the project in LTO mode, the save-temps plugin of ld-gold linker could save the
bitcodes of each compiling stages for each compile targets.
- Preresquite: LTO support && ld-gold linker: please refer the Dockerfile.
- then compiler should support LTO (clang/llvm 11+)
/usr/lib/bfd-pluginsshould containslibLTO.soandLLVMgold.so
- Usage:
CFLAGS='-flto -fuse-ld=gold -Wl,-plugin-opt=save-temps' CXXFLAGS='-flto -fuse-ld=gold -Wl,-plugin-opt=save-temps'
After the full LLVM bitcode representing the PUT target is obtained, use the driver mirage-ins to process it.
mirage-ins <bitcode-path>
If normal, there will be three different bitcodes in the same directory
<bitcode-name>.source.bc: the bitcode representing the source target<bitcode-name>.phantom.bc: the bitcode representing the phantom target<bitcode-name>.taint.bc: the bitcode representing the taint target, used for DTA
Eventually, we need to compile these three bitcodes into executable files manually.
- eg:
clang -o jhead.source jhead.source.bc build/runtime/libsource-rt.a -lmWe need to link the related libraries into the binary during the compilation. (This is really important to obtain the correct binary for fuzzing. Otherwise, there could be functionality issues since some important libraries are not included!) - For source target, we need to link
libsource-rt.ainmirageproject :<build-dir>/libsource-rt.a - For phantom target, we need to link
libphantom-rt.ainmirageproject andudis86:<build-dir>/libphantom-rt.a -ludis86 - For taint target, we need to link
libdta-rt.ainmirageproject andudis86:<build-dir>/libdta-rt.a -ludis86 - Some static or dynamic libraries that the original PUT depends on are also required. For example,
libm.sois required forjhead.
Finally, fuzz all the things!
As mentioned in the paper, for a fuzzing task, miragefuzz requires at least two fuzz processes to cooperate with each other.
The first fuzz process, namely source fuzzing, needs the SOURCE executable generated by <bitcode>.source.bc.
The second fuzz process, namely phantom fuzzing, needs the PHANTOM executable generated by <bitcode>.phantom.bc.
Moreover, both of them requires the third exeuctable, which is generated by <bitcode>.taint.bc , to do taint analysis.
For source fuzzing:
mirage-fuzz -i <init-seeds-dir> -o <out-dir> -S source -D <pin-mode-target> <source-mode-target> [argvs]
For phantom fuzzing:
mirage-fuzz -E -i <init-seeds-dir> -o <out-dir> -S source -D <pin-mode-target> <phantom-mode-target> [argvs]
Note that both source fuzzing and phantom fuzzing share the same out-dir.
In the real fuzzing scene, it is recommended to add a third fuzzing process.
For this additional fuzzing process, the AFL MODE target is recommended because of the lower runtime cost of instrumentation and the more efficient detection of bugs with LLVM Sanitizer.
- SOURCE MODE target
- PHANTOM MODE target
- AFL MODE target, and optional ASAN/MSAN instrumention to augment bug detection.
For source fuzzing:
mirage-fuzz -i <init-seeds-dir> -o <out-dir> -S source -D <pin-mode-target> <source-mode-target> [argvs]
For phantom fuzzing:
mirage-fuzz -E -i <init-seeds-dir> -o <out-dir> -S phantom -D <pin-mode-target> <phantom-mode-target> [argvs]
For the third fuzzing process:
mirage-fuzz -i <init-seeds-dir> -o <out-dir> -S afl <afl-mode-target> [argvs]
Note that all the three fuzzing processes share the same out-dir.
In fact, as miragefuzz is built based on afl-fuzz, miragefuzz can be used like afl-fuzz.