diff options
author | van Hauser <vh@thc.org> | 2022-01-11 12:20:35 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-11 12:20:35 +0100 |
commit | 10dae419d6e3ebc38f53840c5abfe98e9c901217 (patch) | |
tree | 352576e19c8a504c40ea58dbb141056762901a69 | |
parent | 74a8f145e09d0361d8f576eb3f2e8881b6116f18 (diff) | |
parent | d2715336a54635bb6e617a2e739c0ad5fe51d28d (diff) | |
download | afl++-10dae419d6e3ebc38f53840c5abfe98e9c901217.tar.gz |
Merge pull request #1236 from AFLplusplus/dev
push to stable
171 files changed, 2514 insertions, 859 deletions
diff --git a/.custom-format.py b/.custom-format.py index 346e4b07..7ac63396 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -6,7 +6,7 @@ # Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com> # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35051a20..886148df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,24 +7,47 @@ on: branches: [ stable, dev ] jobs: - build: + linux: runs-on: '${{ matrix.os }}' strategy: matrix: os: [ubuntu-20.04, ubuntu-18.04] + env: + AFL_SKIP_CPUFREQ: 1 + AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 steps: - uses: actions/checkout@v2 - name: debug - run: apt-cache search plugin-dev | grep gcc- ; echo ; apt-cache search clang-format- | grep clang-format- + run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format- - name: update run: sudo apt-get update && sudo apt-get upgrade -y - name: install packages run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build - name: compiler installed - run: gcc -v ; echo ; clang -v + run: gcc -v; echo; clang -v - name: install gcc plugin run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev - name: build afl++ run: make distrib ASAN_BUILD=1 - name: run tests - run: sudo -E ./afl-system-config ; export AFL_SKIP_CPUFREQ=1 ; make tests + run: sudo -E ./afl-system-config; make tests + macos: + runs-on: macOS-latest + env: + AFL_MAP_SIZE: 65536 + AFL_SKIP_CPUFREQ: 1 + AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1 + steps: + - uses: actions/checkout@v2 + - name: install + run: brew install make gcc + - name: fix install + run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v + - name: build + run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1 + - name: frida + run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake + - name: run tests + run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests + - name: force frida test for MacOS + run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr diff --git a/.gitmodules b/.gitmodules index 6569c0b1..8ba1c39d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,12 @@ [submodule "coresight_mode/coresight-trace"] path = coresight_mode/coresight-trace url = https://github.com/RICSecLab/coresight-trace.git +[submodule "nyx_mode/libnyx"] + path = nyx_mode/libnyx + url = https://github.com/nyx-fuzz/libnyx.git +[submodule "nyx_mode/QEMU-Nyx"] + path = nyx_mode/QEMU-Nyx + url = https://github.com/nyx-fuzz/qemu-nyx.git +[submodule "nyx_mode/packer"] + path = nyx_mode/packer + url = https://github.com/nyx-fuzz/packer.git diff --git a/GNUmakefile b/GNUmakefile index 673d2bf8..527cdcfc 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -345,9 +345,9 @@ performance-test: source-only help: @echo "HELP --- the following make targets exist:" @echo "==========================================" - @echo "all: just the main afl++ binaries" - @echo "binary-only: everything for binary-only fuzzing: qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap" - @echo "source-only: everything for source code fuzzing: gcc_plugin, libdislocator, libtokencap" + @echo "all: the main afl++ binaries and llvm/gcc instrumentation" + @echo "binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode, qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap" + @echo "source-only: everything for source code fuzzing: nyx_mode, libdislocator, libtokencap" @echo "distrib: everything (for both binary-only and source code fuzzing)" @echo "man: creates simple man pages from the help option of the programs" @echo "install: installs everything you have compiled with the build option above" @@ -564,7 +564,7 @@ all_done: test_build .PHONY: clean clean: - rm -rf $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM + rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM -$(MAKE) -f GNUmakefile.llvm clean -$(MAKE) -f GNUmakefile.gcc_plugin clean $(MAKE) -C utils/libdislocator clean @@ -617,6 +617,9 @@ ifneq "$(SYS)" "Darwin" ifeq "$(ARCH)" "aarch64" -$(MAKE) -C coresight_mode endif +ifeq "$(SYS)" "Linux" + -cd nyx_mode && ./build_nyx_support.sh +endif -cd qemu_mode && sh ./build_qemu_support.sh -cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh endif @@ -634,6 +637,9 @@ ifneq "$(SYS)" "Darwin" ifeq "$(ARCH)" "aarch64" -$(MAKE) -C coresight_mode endif +ifeq "$(SYS)" "Linux" + -cd nyx_mode && ./build_nyx_support.sh +endif -cd qemu_mode && sh ./build_qemu_support.sh -cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh endif @@ -647,6 +653,9 @@ endif $(MAKE) -C utils/libdislocator $(MAKE) -C utils/libtokencap # -$(MAKE) -C utils/plot_ui +ifeq "$(SYS)" "Linux" + -cd nyx_mode && ./build_nyx_support.sh +endif %.8: % @echo .TH $* 8 $(BUILD_DATE) "afl++" > $@ @@ -684,6 +693,7 @@ install: all $(MANPAGES) @if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi @if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi @if [ -f afl-frida-trace.so ]; then install -m 755 afl-frida-trace.so $${DESTDIR}$(HELPER_PATH); fi + @if [ -f libnyx.so ]; then install -m 755 libnyx.so $${DESTDIR}$(HELPER_PATH); fi @if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi @if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi @if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi @@ -706,7 +716,7 @@ endif .PHONY: uninstall uninstall: -cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto* - -cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt + -cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt -rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries -sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f" -cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES) diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin index ed2725d7..63b22017 100644 --- a/GNUmakefile.gcc_plugin +++ b/GNUmakefile.gcc_plugin @@ -11,7 +11,7 @@ # from Laszlo Szekeres. # # Copyright 2015 Google Inc. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 21724696..62b928e4 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,14 @@ terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details. Here is some information to get you started: +* For an overview of the AFL++ documentation and a very helpful graphical + guide please visit [docs/README.md](docs/README.md) +* To get you started with tutorials, go to + [docs/tutorials.md](docs/tutorials.md). * For releases, see the [Releases tab](https://github.com/AFLplusplus/AFLplusplus/releases) and - [branches](#branches). Also take a look at the list of + [branches](#branches). The best branches to use are however `stable` or + `dev` - depending on your risk appetite. Also take a look at the list of [important changes in AFL++](docs/important_changes.md) and the list of [features](docs/features.md). * If you want to use AFL++ for your academic work, check the @@ -40,8 +45,6 @@ Here is some information to get you started: `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus). -* To get you started with tutorials, go to - [docs/tutorials.md](docs/tutorials.md). ## Building and installing AFL++ @@ -57,7 +60,8 @@ This image is automatically generated when a push to the stable repo happens (see [branches](#branches)). You will find your target source code in `/src` in the container. -To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md). +To build AFL++ yourself - which we recommend - continue at +[docs/INSTALL.md](docs/INSTALL.md). ## Quick start: Fuzzing with AFL++ @@ -115,20 +119,24 @@ Step-by-step quick start: You can generate cores or use gdb directly to follow up the crashes. +6. We cannot stress this enough - if you want to fuzz effectively, read the + [docs/fuzzing_in_depth.md](docs/fuzzing_in_depth.md) document! + ## Contact Questions? Concerns? Bug reports? -* The contributors can be reached via +* The contributors can be reached via (e.g. by creating an issue): [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus). * Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important question missing, submit it via [https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions). -* There is a mailing list for the AFL/AFL++ project +* Best: join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server. +* There is a (not really used) mailing list for the AFL/AFL++ project ([browse archive](https://groups.google.com/group/afl-users)). To compare notes with other users or to get notified about major new features, send an - email to <afl-users+subscribe@googlegroups.com>. -* Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server. + email to <afl-users+subscribe@googlegroups.com>, but note that this is not + managed by us. ## Branches @@ -141,7 +149,7 @@ The following branches exist: stability * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state of AFL++ - bleeding edge and you might catch a checkout which does not compile - or has a bug. *We only accept PRs in dev!!* + or has a bug. **We only accept PRs (push requests) for the 'dev' branch!** * (any other): experimental branches to work on specific features or testing new functionality or changes. @@ -243,4 +251,4 @@ presented at WOOT'20: } ``` -</details> \ No newline at end of file +</details> diff --git a/afl-whatsup b/afl-whatsup index c9abbe91..160a8c74 100755 --- a/afl-whatsup +++ b/afl-whatsup @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2015 Google Inc. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/custom_mutators/gramatron/build_gramatron_mutator.sh b/custom_mutators/gramatron/build_gramatron_mutator.sh index b6654632..677e4548 100755 --- a/custom_mutators/gramatron/build_gramatron_mutator.sh +++ b/custom_mutators/gramatron/build_gramatron_mutator.sh @@ -11,7 +11,7 @@ # Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co> # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION index 87f607cd..4743e7c2 100644 --- a/custom_mutators/grammar_mutator/GRAMMAR_VERSION +++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION @@ -1 +1 @@ -eedf07d +6ca490c diff --git a/custom_mutators/grammar_mutator/build_grammar_mutator.sh b/custom_mutators/grammar_mutator/build_grammar_mutator.sh index b6cef66f..452cb0e1 100755 --- a/custom_mutators/grammar_mutator/build_grammar_mutator.sh +++ b/custom_mutators/grammar_mutator/build_grammar_mutator.sh @@ -14,7 +14,7 @@ # <andreafioraldi@gmail.com> # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator -Subproject b79d51a8daccbd7a693f9b6765c81ead14f28e2 +Subproject 6ca490c66b949db20d8c861ebc8fb2e6ca725ea diff --git a/docs/Changelog.md b/docs/Changelog.md index 1daa9a75..c4786bf3 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. e.g. "unique crashes" -> "saved crashes", "total paths" -> "corpus count", "current path" -> "current item". This might need changing custom scripting! + - Nyx mode (full system emulation with snapshot capability) has been + added - thanks to @schumilo and @eqv! - new binary-only fuzzing mode: coresight_mode for aarch64 CPUs :) thanks to RICSecLab submitting! - if instrumented libaries are dlopen()'ed after the forkserver you @@ -57,6 +59,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - added AFL_USE_TSAN thread sanitizer support - llvm and LTO mode modified to work with new llvm 14-dev (again. again.) - fix for AFL_REAL_LD + - more -z defs filtering - make -v without options work - added the very good grammar mutator "GramaTron" to the custom_mutators diff --git a/docs/FAQ.md b/docs/FAQ.md index f1cffe00..3d3dce20 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -180,6 +180,27 @@ If you find an interesting or important question missing, submit it via [best_practices.md#improving-stability](best_practices.md#improving-stability). </p></details> +<details> + <summary id="what-are-power-schedules">What are power schedules?</summary><p> + + Not every item in our queue/corpus is the same, some are more interesting, + others provide little value. + A power schedule measures how "interesting" a value is, and depending on + the calculated value spends more or less time mutating it. + + AFL++ comes with several power schedules, initially ported from [AFLFast](https://github.com/mboehme/aflfast) + however modified to be more effective and several more modes added. + + The most effective modes are '-p fast` (default) and `-p explore`. + + If you fuzz with several parallel afl-fuzz instances, then it is beneficial + to assign a different schedule to each instance, however the majority should + be `fast` and `explore`. + + It does not make sense to explain the details of the calculation and + reasoning behind all of the schedules. If you are interested, read the source + code and the AFLFast paper. + ## Troubleshooting <details> diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 906d3f8e..efec0d8b 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -33,10 +33,10 @@ sudo make install It is recommended to install the newest available gcc, clang and llvm-dev possible in your distribution! -Note that "make distrib" also builds instrumentation, QEMU mode, unicorn_mode -and more. If you just want plain AFL++, then do "make all". However, compiling -and using at least instrumentation is highly recommended for much better results -- hence in this case choose: +Note that "make distrib" also builds FRIDA mode, QEMU mode, unicorn_mode +and more. If you just want plain AFL++, then do "make all". If you want +some assisting tooling compiled but are not interested in binary-only targets +then instead choose: ```shell make source-only @@ -44,11 +44,11 @@ make source-only These build targets exist: -* all: just the main AFL++ binaries -* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, - libdislocator, libtokencap -* source-only: everything for source code fuzzing: instrumentation, - libdislocator, libtokencap +* all: the main afl++ binaries and llvm/gcc instrumentation +* binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode, + qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap +* source-only: everything for source code fuzzing: nyx_mode, libdislocator, + libtokencap * distrib: everything (for both binary-only and source code fuzzing) * man: creates simple man pages from the help option of the programs * install: installs everything you have compiled with the build options above @@ -86,32 +86,35 @@ e.g.: `make ASAN_BUILD=1` ## MacOS X on x86 and arm64 (M1) -MacOS X should work, but there are some gotchas due to the idiosyncrasies of the -platform. On top of this, we have limited release testing capabilities and -depend mostly on user feedback. +MacOS has some gotchas due to the idiosyncrasies of the platform. To build AFL, install llvm (and perhaps gcc) from brew and follow the general instructions for Linux. If possible, avoid Xcode at all cost. -`brew install wget git make cmake llvm gdb` +```shell +brew install wget git make cmake llvm gdb coreutils +``` Be sure to setup `PATH` to point to the correct clang binaries and use the -freshly installed clang, clang++ and gmake, e.g.: +freshly installed clang, clang++, gmake and coreutils, e.g.: -``` -export PATH="/usr/local/Cellar/llvm/12.0.1/bin/:$PATH" +```shell +export +PATH="/usr/local/Cellar/llvm/13.0.0_2/bin/:/usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:$PATH" export CC=clang export CXX=clang++ gmake cd frida_mode gmake cd .. -gmake install +sudo gmake install ``` `afl-gcc` will fail unless you have GCC installed, but that is using outdated -instrumentation anyway. You don't want that. Note that `afl-clang-lto`, -`afl-gcc-fast` and `qemu_mode` are not working on MacOS. +instrumentation anyway. `afl-clang` might fail too depending on your PATH +setup. But you don't want neither, you want `afl-clang-fast` anyway :) +Note that `afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on +MacOS. The crash reporting daemon that comes by default with MacOS X will cause problems with fuzzing. You need to turn it off: @@ -133,7 +136,7 @@ and definitely don't look POSIX-compliant. This means two things: User emulation mode of QEMU does not appear to be supported on MacOS X, so black-box instrumentation mode (`-Q`) will not work. However, Frida mode (`-O`) -should work on x86 and arm64 MacOS boxes. +works on both x86 and arm64 MacOS boxes. MacOS X supports SYSV shared memory used by AFL's instrumentation, but the default settings aren't usable with AFL++. The default settings on 10.14 seem to @@ -169,4 +172,4 @@ sysctl kern.sysv.shmall=98304 See [http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html) -for documentation for these settings and how to make them permanent. \ No newline at end of file +for documentation for these settings and how to make them permanent. diff --git a/docs/env_variables.md b/docs/env_variables.md index dc79bf9e..76a64bd2 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -105,7 +105,8 @@ fairly broad use of environment variables instead: within your program at a certain point (such as at the end of an `__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will cause an abort if any memory is leaked (you can combine this with the - `LSAN_OPTIONS=...` suppression option to suppress some known leaks). + `__AFL_LSAN_OFF();` and `__AFL_LSAN_ON();` macros to avoid checking for + memory leaks from memory allocated between these two calls. - `AFL_USE_MSAN=1` - activates the memory sanitizer (uninitialized memory) - `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race conditions @@ -283,12 +284,24 @@ mode. TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all ``` - - GCC_PLUGIN mode only: Setting `AFL_GCC_INSTRUMENT_FILE` with a filename will - only instrument those files that match the names listed in this file (one - filename per line). See + - GCC_PLUGIN mode only: Setting `AFL_GCC_INSTRUMENT_FILE` or + `AFL_GCC_ALLOWLIST` with a filename will only instrument those files + that match the names listed in this file (one filename per line). + + Setting `AFL_GCC_DENYLIST` or `AFL_GCC_BLOCKLIST` + with a file name and/or function will only skip those files that match + the names listed in the specified file. See [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) for more information. + Setting `AFL_GCC_OUT_OF_LINE=1` will instruct afl-gcc-fast to instrument the + code with calls to an injected subroutine instead of the much more efficient + inline instrumentation. + + Setting `AFL_GCC_SKIP_NEVERZERO=1` will not implement the skip zero test. + If the target performs only a few loops, then this will give a small + performance boost. + ## 4) Settings for afl-fuzz The main fuzzer binary accepts several options that disable a couple of sanity diff --git a/docs/features.md b/docs/features.md index 431d9eb1..628f9383 100644 --- a/docs/features.md +++ b/docs/features.md @@ -4,20 +4,56 @@ AFL++ supports llvm from 3.8 up to version 12, very fast binary fuzzing with QEMU 5.1 with laf-intel and redqueen, FRIDA mode, unicorn mode, gcc plugin, full *BSD, Mac OS, Solaris and Android support and much, much, much more. -| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) |unicorn_mode(10) |coresight_mode(11)| -| -------------------------|:-------:|:---------:|:----------:|:----------------:|:----------------:|:----------------:|:----------------:| -| Threadsafe counters | | x(3) | | | | | | -| NeverZero | x86[_64]| x(1) | x | x | x | x | | -| Persistent Mode | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | -| LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | | -| CmpLog | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | | | -| Selective Instrumentation| | x | x | x | x | | | -| Non-Colliding Coverage | | x(4) | | | (x)(5) | | | -| Ngram prev_loc Coverage | | x(6) | | | | | | -| Context Coverage | | x(6) | | | | | | -| Auto Dictionary | | x(7) | | | | | | -| Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | | | -| Shared Memory Test cases | | x | x | x86[_64]/arm64 | x | x | | +| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) |unicorn_mode(10) |nyx_mode(12)|coresight_mode(11)| +| ------------------------------|:-------:|:---------:|:----------:|:----------------:|:----------------:|:----------------:|:----------:|:----------------:| +| Threadsafe counters [A] | | x(3) | | | | | x | | +| NeverZero [B] | x86[_64]| x(1) | x | x | x | x | | | +| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | | +| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | | +| CmpLog [E] | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | | | | +| Selective Instrumentation [F] | | x | x | x | x | | | | +| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | | +| Ngram prev_loc Coverage [H] | | x(6) | | | | | | | +| Context Coverage [I] | | x(6) | | | | | | | +| Auto Dictionary [J] | | x(7) | | | | | | | +| Snapshot Support (K) | | (x)(8) | (x)(8) | | (x)(5) | | x | | +| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | | + +A. Default is not thread-safe coverage counter updates for better performance, + see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md) +B. On wrapping coverage counters (255 + 1) skip the 0 value and jump to 1 + instead. This has shown to give better coverage data and is the default; + see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md) +C. Instead of forking, reiterate the fuzz target function in a loop (like + `LLVMFuzzerTestOneInput`. Great speed increase but only work with target + functions that does not keep state, leak memory or exit; + see [instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md) +D. Split any non-8-bit comparison to 8 bit comparison; + see [instrumentation/README.laf-intel.md](../instrumentation/README.laf-intel.md) +E. CmpLog is our enhanced [Redqueen](https://www.ndss-symposium.org/ndss-paper/redqueen-fuzzing-with-input-to-state-correspondence/) + implementation, see see [instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md) +F. Similar and compatible to clang 13+ sancov sanitize-coverage-allow/deny but + for all llvm versions and all our compile modes, only instrument what should + be instrumented, for more speed, directed fuzzing and less instability; + see [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) +G. Vanilla AFL uses coverage where edges could collide to the same coverage + bytes the larger the target is. Our default instrumentation in LTO and + afl-clang-fast (PCGUARD) uses non-colliding coverage that also makes it + faster. Vanilla AFL style is available with `AFL_LLVM_INSTRUMENT=AFL`; + see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md) +H.+I. Alternative coverage based on previous edges (NGRAM) or depending on the + caller (CTX), based on + [https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf](https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf); + see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md) +J. An LTO feature that creates a fuzzing dictionary based on comparisons found + during compilation/instrumentation. Automatic feature :) + See [instrumentation/README.lto.md](../instrumentation/README.lto.md) +K. The snapshot feature requires a kernel module that was a lot of work to get + right and maintained so it is no longer supported. We have + [nyx_mode](../nyx_mode/README.md) instead. +L. Faster fuzzing and less kernel syscall overhead by in-memory fuzz testcase + delivery, see + [instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md) 1. default for LLVM >= 9.0, environment variable for older version due an efficiency bug in previous llvm versions @@ -34,6 +70,7 @@ QEMU 5.1 with laf-intel and redqueen, FRIDA mode, unicorn mode, gcc plugin, full 10. QEMU/Unicorn is only supported on Linux 11. Coresight mode is only available on AARCH64 Linux with a CPU with Coresight extension +12. Nyx mode is only supported on Linux and currently restricted to x86_x64 Among others, the following features and patches have been integrated: diff --git a/docs/fuzzing_binary-only_targets.md b/docs/fuzzing_binary-only_targets.md index 5434a22c..855d7756 100644 --- a/docs/fuzzing_binary-only_targets.md +++ b/docs/fuzzing_binary-only_targets.md @@ -12,11 +12,10 @@ fuzzed with AFL++. ## TL;DR: -QEMU mode in persistent mode is the fastest - if the stability is high enough. -Otherwise, try RetroWrite, Dyninst, and if these fail, too, then try standard -QEMU mode with `AFL_ENTRYPOINT` to where you need it. - -If your target is a library, then use FRIDA mode. +FRIDA mode and QEMU mode in persistent mode are the fastest - if persistent mode +is possible and the stability is high enough. +Otherwise, try Zafl, RetroWrite, Dyninst, and if these fail, too, then try +standard FRIDA/QEMU mode with `AFL_ENTRYPOINT` to where you need it. If your target is non-linux, then use unicorn_mode. @@ -92,7 +91,7 @@ For more information, see ### FRIDA mode In FRIDA mode, you can fuzz binary-only targets as easily as with QEMU mode. -FRIDA mode is sometimes faster and sometimes slower than QEMU mode. It is also +FRIDA mode is most of the times slightly faster than QEMU mode. It is also newer, lacks COMPCOV, and has the advantage that it works on MacOS (both intel and M1). @@ -100,7 +99,7 @@ To build FRIDA mode: ```shell cd frida_mode -make +gmake ``` For additional instructions and caveats, see @@ -126,6 +125,16 @@ to check out our sister project libafl which supports Frida, too: [https://github.com/AFLplusplus/LibAFL](https://github.com/AFLplusplus/LibAFL). Working examples already exist :-) +### Nyx mode + +Nyx is a full system emulation fuzzing environment with snapshot support that +is built upon KVM and QEMU. +It is only available on Linux and currently restricted to x86_x64. + +For binary-only fuzzing a special 5.10 kernel is required. + +See [nyx_mode/README.md](../nyx_mode/README.md) + ### Unicorn Unicorn is a fork of QEMU. The instrumentation is, therefore, very similar. In diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index b280ca0a..446c4466 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -55,7 +55,7 @@ tasks, fuzzing may put a strain on your hardware and on the OS. In particular: ### a) Selecting the best AFL++ compiler for instrumenting the target AFL++ comes with a central compiler `afl-cc` that incorporates various different -kinds of compiler targets and and instrumentation options. The following +kinds of compiler targets and instrumentation options. The following evaluation flow will help you to select the best possible. It is highly recommended to have the newest llvm version possible installed, @@ -101,7 +101,7 @@ You can select the mode for the afl-cc compiler by one of the following methods: afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++, afl-gcc-fast, afl-g++-fast (recommended!). * Using the environment variable `AFL_CC_COMPILER` with `MODE`. -* Passing --afl-MODE command line options to the compiler via +* Passing --afl-`MODE` command line options to the compiler via `CFLAGS`/`CXXFLAGS`/`CPPFLAGS`. `MODE` can be one of the following: @@ -141,20 +141,42 @@ options are available: [instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md). If you use LTO, LLVM, or GCC_PLUGIN mode -(afl-clang-fast/afl-clang-lto/afl-gcc-fast), you have the option to selectively -only instrument parts of the target that you are interested in: - -* To instrument only those parts of the target that you are interested in, - create a file with all the filenames of the source code that should be - instrumented. For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if a mode - other than DEFAULT/PCGUARD is used or you have llvm > 10.0.0 - just put one - filename or function per line (no directory information necessary for - filenames), and either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or** - `export AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per default - to instrument unless noted (DENYLIST) or not perform instrumentation unless - requested (ALLOWLIST). **NOTE:** During optimization functions might be - inlined and then would not match! See - [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md). +(afl-clang-fast/afl-clang-lto/afl-gcc-fast), you have the option to +selectively instrument _parts_ of the target that you are interested in. +For afl-clang-fast you have to use an llvm version newer than 10.0.0 or a mode +other than DEFAULT/PCGUARD. + +This step can be done either by explicitly including parts to be instrumented +or by explicitly excluding parts from instrumentation. + +* To instrument _only specified parts_ + create a file (eg `allowlist.txt`) with all the filenames and/or functions of + the source code that should be instrumented and then: + + 1. just put one filename or function (prefixing with `fun: `) per line (no + directory information necessary for filenames) in the file `allowlist.txt`. + Example: +``` +foo.cpp # will match foo/foo.cpp, bar/foo.cpp, barfoo.cpp etc. +fun: foo_func # will match the function foo_func +``` + + 2. set `export AFL_LLVM_ALLOWLIST=allowlist.txt` to enable selective positive + instrumentation. + +* Similarly to _exclude_ specified parts from instrumentation + create a file (eg `denylist.txt`) with all the filenames of the source code + that should be skipped during instrumentation and then + + 1. same as above just put one filename or function per line in the file + `denylist.txt` + + 2. set `export AFL_LLVM_DENYLIST=denylist.txt` to enable selective negative + instrumentation. + +**NOTE:** During optimization functions might be +inlined and then would not match the list! See +[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md). There are many more options and modes available, however, these are most of the time less effective. See: @@ -173,26 +195,26 @@ allows you to find bugs that would not necessarily result in a crash. Note that sanitizers have a huge impact on CPU (= less executions per second) and RAM usage. Also, you should only run one afl-fuzz instance per sanitizer -type. This is enough because a use-after-free bug will be picked up, e.g., by -ASAN (address sanitizer) anyway when syncing to other fuzzing instances, so not -all fuzzing instances need to be instrumented with ASAN. +type. This is enough because e.g. a use-after-free bug will be picked up by +ASAN (address sanitizer) anyway after syncing test cases from other fuzzing +instances, so running more than one address sanitized target would be a waste. The following sanitizers have built-in support in AFL++: * ASAN = Address SANitizer, finds memory corruption vulnerabilities like use-after-free, NULL pointer dereference, buffer overruns, etc. Enabled with `export AFL_USE_ASAN=1` before compiling. -* MSAN = Memory SANitizer, finds read access to uninitialized memory, e.g., a +* MSAN = Memory SANitizer, finds read accesses to uninitialized memory, e.g., a local variable that is defined and read before it is even set. Enabled with `export AFL_USE_MSAN=1` before compiling. * UBSAN = Undefined Behavior SANitizer, finds instances where - by the C and C++ standards - undefined behavior happens, e.g., adding two signed integers - together where the result is larger than a signed integer can hold. Enabled + where the result is larger than what a signed integer can hold. Enabled with `export AFL_USE_UBSAN=1` before compiling. * CFISAN = Control Flow Integrity SANitizer, finds instances where the control flow is found to be illegal. Originally this was rather to prevent return - oriented programming exploit chains from functioning. In fuzzing, this is - mostly reduced to detecting type confusion vulnerabilities - which is, + oriented programming (ROP) exploit chains from functioning. In fuzzing, this + is mostly reduced to detecting type confusion vulnerabilities - which is, however, one of the most important and dangerous C++ memory corruption classes! Enabled with `export AFL_USE_CFISAN=1` before compiling. * TSAN = Thread SANitizer, finds thread race conditions. Enabled with `export @@ -201,7 +223,10 @@ The following sanitizers have built-in support in AFL++: security issue, but for developers this can be very valuable. Note that unlike the other sanitizers above this needs `__AFL_LEAK_CHECK();` added to all areas of the target source code where you find a leak check necessary! Enabled with - `export AFL_USE_LSAN=1` before compiling. + `export AFL_USE_LSAN=1` before compiling. To ignore the memory-leaking check + for certain allocations, `__AFL_LSAN_OFF();` can be used before memory is + allocated, and `__AFL_LSAN_ON();` afterwards. Memory allocated between these + two macros will not be checked for memory leaks. It is possible to further modify the behavior of the sanitizers at run-time by setting `ASAN_OPTIONS=...`, `LSAN_OPTIONS` etc. - the available parameters can @@ -261,7 +286,8 @@ Then build the target. (Usually with `make`.) 3. In case the configure/build system complains about AFL++'s compiler and aborts, then set `export AFL_NOOPT=1` which will then just behave like the - real compiler. This option has to be unset again before building the target! + real compiler and run the configure step separately. + For building the target afterwards this option has to be unset again! #### configure @@ -334,7 +360,7 @@ afl-clang-fast++ -fsanitize=fuzzer -o harness harness.cpp targetlib.a ``` You can even use advanced libfuzzer features like `FuzzedDataProvider`, -`LLVMFuzzerMutate()` etc. and they will work! +`LLVMFuzzerInitialize()` etc. and they will work! The generated binary is fuzzed with afl-fuzz like any other fuzz target. @@ -373,22 +399,23 @@ produce a new path/coverage in the target: 1. Put all files from [step a](#a-collecting-inputs) into one directory, e.g., INPUTS. 2. Run afl-cmin: - * If the target program is to be called by fuzzing as `bin/target -d - INPUTFILE`, set the INPUTFILE argument that the target program would read - from as `@@`: + * If the target program is to be called by fuzzing as `bin/target + INPUTFILE`, replace the INPUTFILE argument that the target program would read + from with `@@`: ``` - afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -d @@ + afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -someopt @@ ``` - * If the target reads from stdin instead, just omit the `@@` as this is the - default: + * If the target reads from stdin (standard input) instead, just omit the `@@` + as this is the default: ``` - afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -d + afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -someopt ``` -This step is highly recommended! +This step is highly recommended, because afterwards the testcase corpus is not +bloated with duplicates anymore, which would slow down the fuzzing progress! ### c) Minimizing all corpus files @@ -400,7 +427,7 @@ however, it is a long process as this has to be done for every file: mkdir input cd INPUTS_UNIQUE for i in *; do - afl-tmin -i "$i" -o "../input/$i" -- bin/target -d @@ + afl-tmin -i "$i" -o "../input/$i" -- bin/target -someopt @@ done ``` @@ -421,7 +448,7 @@ In this final step, fuzz the target. There are not that many important options to run the target - unless you want to use many CPU cores/threads for the fuzzing, which will make the fuzzing much more useful. -If you just use one CPU for fuzzing, then you are fuzzing just for fun and not +If you just use one instance for fuzzing, then you are fuzzing just for fun and not seriously :-) ### a) Running afl-fuzz @@ -449,13 +476,13 @@ hence all you need is to specify the seed input directory with the result of step [2a) Collecting inputs](#a-collecting-inputs): ``` -afl-fuzz -i input -o output -- bin/target -d @@ +afl-fuzz -i input -o output -- bin/target -someopt @@ ``` Note that the directory specified with `-o` will be created if it does not exist. -It can be valuable to run afl-fuzz in a screen or tmux shell so you can log off, +It can be valuable to run afl-fuzz in a `screen` or `tmux` shell so you can log off, or afl-fuzz is not aborted if you are running it in a remote ssh session where the connection fails in between. Only do that though once you have verified that your fuzzing setup works! Run it like `screen -dmS afl-main -- afl-fuzz -M @@ -469,27 +496,32 @@ If you need to stop and re-start the fuzzing, use the same command line options mode!) and switch the input directory with a dash (`-`): ``` -afl-fuzz -i - -o output -- bin/target -d @@ +afl-fuzz -i - -o output -- bin/target -someopt @@ ``` Adding a dictionary is helpful. See the directory [dictionaries/](../dictionaries/) if something is already included for your data format, and tell afl-fuzz to load that dictionary by adding `-x -dictionaries/FORMAT.dict`. With afl-clang-lto, you have an autodictionary -generation for which you need to do nothing except to use afl-clang-lto as the -compiler. You also have the option to generate a dictionary yourself, see -[utils/libtokencap/README.md](../utils/libtokencap/README.md). +dictionaries/FORMAT.dict`. +With `afl-clang-lto`, you have an autodictionary generation for which you need +to do nothing except to use afl-clang-lto as the compiler. +With `afl-clang-fast` you can set +`AFL_LLVM_DICT2FILE=/full/path/to/new/file.dic` to automatically generate a +dictionary during target compilation. +You also have the option to generate a dictionary yourself during an independant +run of the target, see [utils/libtokencap/README.md](../utils/libtokencap/README.md). +Finally you can also write a dictionary file manually, of course. afl-fuzz has a variety of options that help to workaround target quirks like -specific locations for the input file (`-f`), performing deterministic fuzzing -(`-D`) and many more. Check out `afl-fuzz -h`. +very specific locations for the input file (`-f`), performing deterministic +fuzzing (`-D`) and many more. Check out `afl-fuzz -h`. We highly recommend that you set a memory limit for running the target with `-m` which defines the maximum memory in MB. This prevents a potential out-of-memory problem for your system plus helps you detect missing `malloc()` failure handling in the target. Play around with various `-m` values until you find one that safely works for all your input seeds (if you have good ones and then -double or quadruple that. +double or quadruple that). By default, afl-fuzz never stops fuzzing. To terminate AFL++, press Control-C or send a signal SIGINT. You can limit the number of executions or approximate @@ -558,7 +590,8 @@ All other secondaries should be used like this: * a quarter to a third with the MOpt mutator enabled: `-L 0` * run with a different power schedule, recommended are: `fast (default), explore, coe, lin, quad, exploit and rare` which you can set - with, e.g., `-p explore` + with the `-p` option, e.g., `-p explore`. See the [FAQ](FAQ.md#what-are-power-schedules) + for details. * a few instances should use the old queue cycling with `-Z` Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases @@ -601,7 +634,7 @@ Now there are three strategies on how you can sync between the servers: * regularly (~4h): this ensures that all fuzzing campaigns on the servers "see" the same thing. It is like fuzzing on a huge server. * in intervals of 1/10th of the overall expected runtime of the fuzzing you - sync. This tries a bit to combine both. have some individuality of the paths + sync. This tries a bit to combine both. Have some individuality of the paths each campaign on a server explores, on the other hand if one gets stuck where another found progress this is handed over making it unstuck. @@ -844,8 +877,8 @@ normal fuzzing campaigns as these are much shorter runnings. 1. Always: * LTO has a much longer compile time which is diametrical to short fuzzing - hence use afl-clang-fast instead. - * If you compile with CMPLOG, then you can save fuzzing time and reuse that - compiled target for both the `-c` option and the main fuzz target. This + * If you compile with CMPLOG, then you can save compilation time and reuse that + compiled target with the `-c` option and as the main fuzz target. This will impact the speed by ~15% though. * `AFL_FAST_CAL` - enables fast calibration, this halves the time the saturated corpus needs to be loaded. @@ -876,7 +909,7 @@ and ## The End -Check out the [FAQ](FAQ.md) if it maybe answers your question (that you might +Check out the [FAQ](FAQ.md). Maybe it answers your question (that you might not even have known you had ;-) ). This is basically all you need to know to professionally run fuzzing campaigns. @@ -885,4 +918,4 @@ covered. Note that there are also a lot of tools out there that help fuzzing with AFL++ (some might be deprecated or unsupported), see -[third_party_tools.md](third_party_tools.md). \ No newline at end of file +[third_party_tools.md](third_party_tools.md). diff --git a/docs/ideas.md b/docs/ideas.md index 52b07c26..e2360ab2 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -19,17 +19,17 @@ Mentor: vanhauser-thc ## WASM Instrumentation Currently, AFL++ can be used for source code fuzzing and traditional binaries. -With the rise of WASM as compile target, however, a novel way of instrumentation +With the rise of WASM as a compile target, however, a novel way of instrumentation needs to be implemented for binaries compiled to Webassembly. This can either be done by inserting instrumentation directly into the WASM AST, or by patching -feedback into a WASM VMs of choice, similar to the current Unicorn +feedback into a WASM VM of choice, similar to the current Unicorn instrumentation. Mentor: any ## Support other programming languages -Other programming languages also use llvm hence they could (easily?) supported +Other programming languages also use llvm hence they could be (easily?) supported for fuzzing, e.g., mono, swift, go, kotlin native, fortran, ... GCC also supports: Objective-C, Fortran, Ada, Go, and D (according to @@ -54,4 +54,4 @@ Mentor: domenukk ## Your idea! Finally, we are open to proposals! Create an issue at -https://github.com/AFLplusplus/AFLplusplus/issues and let's discuss :-) \ No newline at end of file +https://github.com/AFLplusplus/AFLplusplus/issues and let's discuss :-) diff --git a/docs/important_changes.md b/docs/important_changes.md index d5e67f75..040a086d 100644 --- a/docs/important_changes.md +++ b/docs/important_changes.md @@ -5,12 +5,13 @@ changes. ## From version 3.00 onwards -With AFL++ 3.13-3.20, we introduce FRIDA mode (`-O`) to have an alternative for -binary-only fuzzing. It is slower than QEMU mode but works on MacOS, Android, -iOS etc. +With AFL++ 4.00, we introduced the following changes from previous behaviors: + * the complete documentation was overhauled and restructured thanks to @llzmb! + * a new CMPLOG target format requires recompiling CMPLOG targets for use + with afl++ 4.0 onwards + * better naming for several fields in the UI With AFL++ 3.15, we introduced the following changes from previous behaviors: - * Also -M main mode does not do deterministic fuzzing by default anymore * afl-cmin and afl-showmap -Ci now descent into subdirectories like afl-fuzz -i does (but note that afl-cmin.bash does not) @@ -20,7 +21,7 @@ With AFL++ 3.14, we introduced the following changes from previous behaviors: however, does not) With AFL++ 3.10, we introduced the following changes from previous behaviors: - * The '+' feature of the '-t' option now means to auto-calculate the timeout + * The '+' feature of the '-t' option now means to auto-calculate the timeout with the value given being the maximum timeout. The original meaning of "skipping timeouts instead of abort" is now inherent to the -t option. @@ -55,4 +56,4 @@ behaviors and defaults: * -M mains do not perform trimming * examples/ got renamed to utils/ * libtokencap/ libdislocator/ and qdbi_mode/ were moved to utils/ - * afl-cmin/afl-cmin.bash now search first in PATH and last in AFL_PATH \ No newline at end of file + * afl-cmin/afl-cmin.bash now search first in PATH and last in AFL_PATH diff --git a/docs/resources/grafana-afl++.json b/docs/resources/grafana-afl++.json index 7afe89b1..910129a8 100644 --- a/docs/resources/grafana-afl++.json +++ b/docs/resources/grafana-afl++.json @@ -424,7 +424,7 @@ "steppedLine": false, "targets": [ { - "expr": "fuzzing{type=\"unique_crashes\"}", + "expr": "fuzzing{type=\"saved_crashes\"}", "interval": "", "legendFormat": "", "refId": "A" @@ -519,7 +519,7 @@ "steppedLine": false, "targets": [ { - "expr": "fuzzing{type=\"unique_hangs\"}", + "expr": "fuzzing{type=\"saved_hangs\"}", "interval": "", "legendFormat": "", "refId": "A" diff --git a/docs/resources/screenshot.png b/docs/resources/screenshot.png index 7b4dd7e4..75b88287 100644 --- a/docs/resources/screenshot.png +++ b/docs/resources/screenshot.png Binary files differdiff --git a/docs/tutorials.md b/docs/tutorials.md index ed8a7eec..0a44602d 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -9,6 +9,7 @@ Here are some good write-ups to show how to effectively use AFL++: * [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP) * [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP) * [https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1) +* [https://mmmds.pl/fuzzing-map-parser-part-1-teeworlds/](https://mmmds.pl/fuzzing-map-parser-part-1-teeworlds/) If you do not want to follow a tutorial but rather try an exercise type of training, then we can highly recommend the following: @@ -18,13 +19,13 @@ training, then we can highly recommend the following: If you are interested in fuzzing structured data (where you define what the structure is), these links have you covered: -* Superion for AFL++: - [https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator) * libprotobuf for AFL++: [https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator) * libprotobuf raw: [https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator) * libprotobuf for old AFL++ API: [https://github.com/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator) +* Superion for AFL++: + [https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator) If you find other good ones, please send them to us :-) \ No newline at end of file diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 5303fd1a..254c82db 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -118,16 +118,15 @@ GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.x GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)" GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME) +ifdef FRIDA_SOURCE +GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gumjs-1.0.a +else GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gumjs.a +endif GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gumjs.h FRIDA_DIR:=$(PWD)build/frida-source/ FRIDA_MAKEFILE:=$(FRIDA_DIR)Makefile -FRIDA_GUM:=$(FRIDA_DIR)build/frida-linux-x86_64/lib/libfrida-gumjs-1.0.a -FRIDA_GUM_DEVKIT_DIR:=$(FRIDA_DIR)build/gum-devkit/ -FRIDA_GUM_DEVKIT_HEADER:=$(FRIDA_GUM_DEVKIT_DIR)frida-gumjs.h -FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar -FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL:=$(FRIDA_DIR)build/$(GUM_DEVKIT_FILENAME) AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o @@ -142,14 +141,20 @@ AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(BUILD_DIR)frida_hook.so AFLPP_QEMU_DRIVER_HOOK_SRC:=$(HOOK_DIR)qemu_hook.c AFLPP_QEMU_DRIVER_HOOK_OBJ:=$(BUILD_DIR)qemu_hook.so +ifneq "$(shell uname)" "Darwin" +ADDR_DIR:=$(PWD)addr/ +ADDR_SRC:=$(ADDR_DIR)addr.c +ADDR_BIN:=$(BUILD_DIR)addr +endif + BIN2C:=$(BUILD_DIR)bin2c BIN2C_SRC:=$(PWD)util/bin2c.c -.PHONY: all 32 clean format hook $(FRIDA_GUM) +.PHONY: all 32 clean format hook addr $(FRIDA_GUM) ############################## ALL ############################################# -all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) +all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN) 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all @@ -160,41 +165,98 @@ $(BUILD_DIR): $(OBJ_DIR): | $(BUILD_DIR) mkdir -p $@ -############################# FRIDA ############################################ +############################# DEVKIT ########################################### + +$(FRIDA_BUILD_DIR): | $(BUILD_DIR) + mkdir -p $@ +ifdef FRIDA_SOURCE $(FRIDA_MAKEFILE): | $(BUILD_DIR) git clone --recursive https://github.com/frida/frida.git $(FRIDA_DIR) -$(FRIDA_GUM): $(FRIDA_MAKEFILE) +.PHONY: $(GUM_DEVIT_LIBRARY) + +$(GUM_DEVIT_LIBRARY): $(FRIDA_MAKEFILE) cd $(FRIDA_DIR) && make gum-linux-$(ARCH) -$(FRIDA_GUM_DEVKIT_HEADER): $(FRIDA_GUM) - $(FRIDA_DIR)releng/devkit.py frida-gumjs linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/ +$(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR) + echo "#include <stdio.h>" > $@ + echo "#include <unistd.h>" >> $@ + echo "#include <gum/gumreturnaddress.h>" >> $@ + echo "#include <gum/gumbacktracer.h>" >> $@ + echo "#include <gum/gumsymbolutil.h>" >> $@ + echo "#include <gum/gumstalker.h>" >> $@ + echo "#include <gum/gumlibc.h>" >> $@ + echo "#include <gumjs/gumscriptbackend.h>" >> $@ + +ifeq "$(ARCH)" "arm64" + +CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-linux-$(ARCH)/include/frida-1.0 \ + -I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/glib-2.0/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/glib-2.0/include/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/capstone/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/json-glib-1.0/ \ + +TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsoup-2.4.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsqlite3.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libtcc.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libquickjs.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libcapstone.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind-*.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libffi.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libdwarf.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libelf.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgio-2.0.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgobject-2.0.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libglib-2.0.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/liblzma.a \ + $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libz.a \ -$(FRIDA_GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_HEADER) - cd $(FRIDA_GUM_DEVKIT_DIR) && tar cvf $(FRIDA_GUM_DEVKIT_TARBALL) . +else -$(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL): $(FRIDA_GUM_DEVKIT_TARBALL) - xz -k -f -0 $(FRIDA_GUM_DEVKIT_TARBALL) +CFLAGS+=-I $(FRIDA_DIR)build/frida-linux-$(ARCH)/include/frida-1.0 \ + -I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/glib-2.0/ \ + -I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/glib-2.0/include/ \ + -I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/capstone/ \ + -I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/json-glib-1.0/ \ + +TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsoup-2.4.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsqlite3.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libtcc.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libquickjs.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libcapstone.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind-*.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libffi.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libdwarf.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libelf.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgio-2.0.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgobject-2.0.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libglib-2.0.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/liblzma.a \ + $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libz.a \ + +endif -############################# DEVKIT ########################################### -$(FRIDA_BUILD_DIR): | $(BUILD_DIR) - mkdir -p $@ -ifdef FRIDA_SOURCE -$(GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL)| $(FRIDA_BUILD_DIR) - cp -v $< $@ else $(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR) wget -O $@ $(GUM_DEVKIT_URL) || curl -L -o $@ $(GUM_DEVKIT_URL) -endif $(GUM_DEVIT_LIBRARY): $(GUM_DEVKIT_TARBALL) tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR) $(GUM_DEVIT_HEADER): $(GUM_DEVKIT_TARBALL) tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR) +endif + + ############################## AFL ############################################# $(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC) @@ -235,7 +297,7 @@ $(JS_OBJ): $(JS_SRC) GNUmakefile ############################# SOURCE ########################################### define BUILD_SOURCE -$(2): $(1) $(INCLUDES) GNUmakefile | $(OBJ_DIR) +$(2): $(1) $(INCLUDES) $(GUM_DEVIT_HEADER) | $(OBJ_DIR) $(TARGET_CC) \ $(CFLAGS) \ -I $(ROOT)include \ @@ -256,6 +318,7 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL $(GUM_DEVIT_LIBRARY) \ $(AFL_COMPILER_RT_OBJ) \ $(AFL_PERFORMANCE_OBJ) \ + $(TRACE_LDFLAGS) \ $(LDFLAGS) \ $(LDSCRIPT) \ -o $@ \ @@ -272,13 +335,30 @@ $(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR) hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) +############################# ADDR ############################################# +$(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR) + -$(TARGET_CC) \ + $(CFLAGS) \ + -Werror \ + -Wall \ + -Wextra \ + -Wpointer-arith \ + -z noexecstack \ + -Wl,--gc-sections \ + -Wl,--exclude-libs,ALL \ + -ldl \ + -lrt \ + $< -o $@ + +addr: $(ADDR_BIN) + ############################# CLEAN ############################################ clean: rm -rf $(BUILD_DIR) ############################# FORMAT ########################################### format: - cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) | xargs -L1 ./.custom-format.py -i + cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) $(ADDR_BIN ) | xargs -L1 ./.custom-format.py -i cd $(ROOT) && echo $(INCLUDES) | xargs -L1 ./.custom-format.py -i ############################# RUN ############################################# diff --git a/frida_mode/README.md b/frida_mode/README.md index 08f6b891..e5b46baf 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -176,9 +176,6 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage instrumentation (the default where available). Required to use `AFL_FRIDA_INST_TRACE`. -* `AFL_FRIDA_INST_NO_BACKPATCH` - Disable backpatching. At the end of executing - each block, control will return to FRIDA to identify the next block to - execute. * `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will report instrumented blocks back to the parent so that it can also instrument them and they be inherited by the next child on fork, implies @@ -227,6 +224,9 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent * `AFL_FRIDA_STALKER_IC_ENTRIES` - Configure the number of inline cache entries stored along-side branch instructions which provide a cache to avoid having to call back into FRIDA to find the next block. Default is 32. +* `AFL_FRIDA_STALKER_NO_BACKPATCH` - Disable backpatching. At the end of executing + each block, control will return to FRIDA to identify the next block to + execute. * `AFL_FRIDA_STATS_FILE` - Write statistics information about the code being instrumented to the given file name. The statistics are written only for the child process when new block is instrumented (when the @@ -307,6 +307,7 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent core dump of the instrumented target. Note that in order to capture the core dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz` killing the process whilst it is being dumped. +* `AFL_FRIDA_VERBOSE` - Enable verbose output from FRIDA mode. ## FASAN - FRIDA Address Sanitizer mode @@ -376,4 +377,4 @@ Should you encounter problems with FRIDA mode, refer to The next features to be added are Aarch32 support as well as looking at potential performance improvements. The intention is to achieve feature parity with QEMU mode in due course. Contributions are welcome, but please get in touch -to ensure that efforts are deconflicted. \ No newline at end of file +to ensure that efforts are deconflicted. diff --git a/frida_mode/Scripting.md b/frida_mode/Scripting.md index ad86fdd3..8634860b 100644 --- a/frida_mode/Scripting.md +++ b/frida_mode/Scripting.md @@ -390,7 +390,7 @@ Consider the [following](test/js/test2.c) test code... -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: @@ -782,7 +782,7 @@ class Afl { Afl.jsApiWrite(STDOUT_FILENO, buf, log.length); } /** - * See `AFL_FRIDA_INST_NO_BACKPATCH`. + * See `AFL_FRIDA_STALKER_NO_BACKPATCH`. */ static setBackpatchDisable() { Afl.jsApiSetBackpatchDisable(); @@ -995,4 +995,4 @@ class Afl { return Afl.module.getExportByName(name); } } -``` \ No newline at end of file +``` diff --git a/frida_mode/addr/addr.c b/frida_mode/addr/addr.c new file mode 100644 index 00000000..371f69d4 --- /dev/null +++ b/frida_mode/addr/addr.c @@ -0,0 +1,39 @@ +#include <errno.h> +#include <link.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/personality.h> + +#define UNUSED_PARAMETER(x) (void)(x) + +int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) +{ + UNUSED_PARAMETER (size); + + ElfW(Addr) * base = data; + + if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; } + return 0; +} + +int main (int argc, char** argv, char** envp) { + UNUSED_PARAMETER (argc); + + ElfW(Addr) base = 0; + + int persona = personality(ADDR_NO_RANDOMIZE); + if (persona == -1) { + + printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno); + return 1; + } + + if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); } + + dl_iterate_phdr(phdr_callback, &base); + + printf("%p\n", (void *)base); + if (base == 0) { return 1; } + + return 0; +} diff --git a/frida_mode/frida.map b/frida_mode/frida.map index 5276db91..d059bdb6 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -37,6 +37,7 @@ js_api_set_stderr; js_api_set_stdout; js_api_set_traceable; + js_api_set_verbose; local: *; diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index a5d52616..abb89c9f 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -5,14 +5,13 @@ #include "config.h" -extern char * instrument_debug_filename; -extern char * instrument_coverage_filename; -extern gboolean instrument_tracing; -extern gboolean instrument_optimize; -extern gboolean instrument_unique; -extern __thread guint64 instrument_previous_pc; -extern guint64 instrument_hash_zero; -extern char * instrument_coverage_unstable_filename; +extern char * instrument_debug_filename; +extern char * instrument_coverage_filename; +extern gboolean instrument_tracing; +extern gboolean instrument_optimize; +extern gboolean instrument_unique; +extern guint64 instrument_hash_zero; +extern char * instrument_coverage_unstable_filename; extern gboolean instrument_use_fixed_seed; extern guint64 instrument_fixed_seed; @@ -20,6 +19,8 @@ extern guint64 instrument_fixed_seed; extern uint8_t *__afl_area_ptr; extern uint32_t __afl_map_size; +extern __thread guint64 *instrument_previous_pc_addr; + void instrument_config(void); void instrument_init(void); @@ -51,7 +52,7 @@ void instrument_coverage_unstable(guint64 edge, guint64 previous_rip, guint64 previous_end, guint64 current_rip, guint64 current_end); -void instrument_on_fork(); +void instrument_on_fork(void); guint64 instrument_get_offset_hash(GumAddress current_rip); diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h index 4dc05f20..bd37687c 100644 --- a/frida_mode/include/util.h +++ b/frida_mode/include/util.h @@ -8,9 +8,12 @@ #define UNUSED_PARAMETER(x) (void)(x) #define IGNORED_RETURN(x) (void)!(x) +extern gboolean util_verbose; + guint64 util_read_address(char *key, guint64 default_value); guint64 util_read_num(char *key, guint64 default_value); gboolean util_output_enabled(void); +gboolean util_verbose_enabled(void); gsize util_rotate(gsize val, gsize shift, gsize size); gsize util_log2(gsize val); @@ -19,7 +22,8 @@ gsize util_log2(gsize val); \ if (!util_output_enabled()) { break; } \ \ - OKF(x); \ + SAYF(cLGN "[F] " cRST x); \ + SAYF(cRST "\n"); \ \ } while (0) @@ -37,5 +41,15 @@ gsize util_log2(gsize val); \ } while (0) +#define FVERBOSE(x...) \ + do { \ + \ + if (!util_verbose_enabled()) { break; } \ + \ + SAYF(cGRA "[F] " x); \ + SAYF(cRST "\n"); \ + \ + } while (0) + #endif diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c index 884bec53..cad409ee 100644 --- a/frida_mode/src/asan/asan.c +++ b/frida_mode/src/asan/asan.c @@ -9,21 +9,15 @@ gboolean asan_initialized = FALSE; void asan_config(void) { - if (getenv("AFL_USE_FASAN") != NULL) { - - FOKF("Frida ASAN mode enabled"); - asan_enabled = TRUE; - - } else { - - FOKF("Frida ASAN mode disabled"); - - } + if (getenv("AFL_USE_FASAN") != NULL) { asan_enabled = TRUE; } } void asan_init(void) { + FOKF(cBLU "Instrumentation" cRST " - " cGRN "asan:" cYEL " [%c]", + asan_enabled ? 'X' : ' '); + if (asan_enabled) { asan_arch_init(); diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c index 443baa1d..355df0b7 100644 --- a/frida_mode/src/cmplog/cmplog.c +++ b/frida_mode/src/cmplog/cmplog.c @@ -54,7 +54,7 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) { static void cmplog_get_ranges(void) { - FOKF("CMPLOG - Collecting ranges"); + FVERBOSE("CMPLOG - Collecting ranges"); cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100); gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges); @@ -68,18 +68,21 @@ void cmplog_config(void) { void cmplog_init(void) { - FOKF("CMPLOG - Enabled [%c]", __afl_cmp_map == NULL ? ' ' : 'X'); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cmplog:" cYEL " [%c]", + __afl_cmp_map == NULL ? ' ' : 'X'); if (__afl_cmp_map == NULL) { return; } cmplog_get_ranges(); + FVERBOSE("Cmplog Ranges"); + for (guint i = 0; i < cmplog_ranges->len; i++) { GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i); - FOKF("CMPLOG Range - %3u: 0x%016" G_GINT64_MODIFIER - "X - 0x%016" G_GINT64_MODIFIER "X", - i, range->base_address, range->base_address + range->size); + FVERBOSE("\t%3u: 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER + "X", + i, range->base_address, range->base_address + range->size); } diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index de645fdb..995f765f 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -24,7 +24,7 @@ gboolean entry_run = FALSE; static void entry_launch(void) { - FOKF("Entry point reached"); + FVERBOSE("Entry point reached"); __afl_manual_init(); /* Child here */ @@ -69,8 +69,8 @@ void entry_config(void) { void entry_init(void) { - FOKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point); - FOKF("dumpable: [%c]", traceable ? 'X' : ' '); + FVERBOSE("Entry Point: 0x%016" G_GINT64_MODIFIER "X", entry_point); + FVERBOSE("Dumpable: [%c]", traceable ? 'X' : ' '); if (dlopen(NULL, RTLD_NOW) == NULL) { FFATAL("Failed to dlopen: %d", errno); } @@ -94,7 +94,7 @@ static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) { void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) { UNUSED_PARAMETER(output); - FOKF("AFL_ENTRYPOINT reached"); + FVERBOSE("AFL_ENTRYPOINT reached"); if (persistent_start == 0) { diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 8ee21f5b..46ed1a34 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -32,12 +32,13 @@ char * instrument_coverage_unstable_filename = NULL; static GumStalkerTransformer *transformer = NULL; -__thread guint64 instrument_previous_pc = 0; - static GumAddress previous_rip = 0; static GumAddress previous_end = 0; static u8 * edges_notified = NULL; +__thread guint64 instrument_previous_pc; +__thread guint64 *instrument_previous_pc_addr = NULL; + typedef struct { GumAddress address; @@ -105,8 +106,14 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context, guint16 current_end = ctx->end; guint64 current_pc = instrument_get_offset_hash(current_rip); guint64 edge; + if (instrument_previous_pc_addr == NULL) { - edge = current_pc ^ instrument_previous_pc; + instrument_previous_pc_addr = &instrument_previous_pc; + *instrument_previous_pc_addr = instrument_hash_zero; + + } + + edge = current_pc ^ *instrument_previous_pc_addr; instrument_increment_map(edge); @@ -136,7 +143,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context, previous_end = current_end; gsize map_size_pow2 = util_log2(__afl_map_size); - instrument_previous_pc = util_rotate(current_pc, 1, map_size_pow2); + *instrument_previous_pc_addr = util_rotate(current_pc, 1, map_size_pow2); } @@ -274,14 +281,19 @@ void instrument_init(void) { if (!instrument_is_coverage_optimize_supported()) instrument_optimize = false; - FOKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' '); - FOKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' '); - FOKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' '); - FOKF("Instrumentation - fixed seed [%c] [0x%016" G_GINT64_MODIFIER "x]", + FOKF(cBLU "Instrumentation" cRST " - " cGRN "optimize:" cYEL " [%c]", + instrument_optimize ? 'X' : ' '); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "tracing:" cYEL " [%c]", + instrument_tracing ? 'X' : ' '); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "unique:" cYEL " [%c]", + instrument_unique ? 'X' : ' '); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "fixed seed:" cYEL + " [%c] [0x%016" G_GINT64_MODIFIER "x]", instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed); - FOKF("Instrumentation - unstable coverage [%c] [%s]", - instrument_coverage_unstable_filename == NULL ? ' ' : 'X', - instrument_coverage_unstable_filename); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage:" cYEL " [%s]", + instrument_coverage_unstable_filename == NULL + ? " " + : instrument_coverage_unstable_filename); if (instrument_tracing && instrument_optimize) { @@ -366,15 +378,16 @@ void instrument_init(void) { } - FOKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]", + FOKF(cBLU "Instrumentation" cRST " - " cGRN "seed:" cYEL + " [0x%016" G_GINT64_MODIFIER "x]", instrument_hash_seed); instrument_hash_zero = instrument_get_offset_hash(0); - instrument_coverage_optimize_init(); - instrument_debug_init(); - instrument_coverage_init(); asan_init(); cmplog_init(); + instrument_coverage_init(); + instrument_coverage_optimize_init(); + instrument_debug_init(); } @@ -387,7 +400,11 @@ GumStalkerTransformer *instrument_get_transformer(void) { void instrument_on_fork() { - instrument_previous_pc = instrument_hash_zero; + if (instrument_previous_pc_addr != NULL) { + + *instrument_previous_pc_addr = instrument_hash_zero; + + } } diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 0f635458..57b60317 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -1,50 +1,118 @@ +#include <stddef.h> + #include "frida-gumjs.h" #include "config.h" #include "instrument.h" +#include "ranges.h" +#include "stalker.h" +#include "util.h" + +#define G_MININT33 ((gssize)0xffffffff00000000) +#define G_MAXINT33 ((gssize)0x00000000ffffffff) + +#define PAGE_MASK (~(GUM_ADDRESS(0xfff))) +#define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x)) #if defined(__aarch64__) -static GumAddress current_log_impl = GUM_ADDRESS(0); +__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE]; + + #pragma pack(push, 1) +typedef struct { + + // cur_location = (block_address >> 4) ^ (block_address << 8); + // shared_mem[cur_location ^ prev_location]++; + // prev_location = cur_location >> 1; + + // stp x0, x1, [sp, #-160] + // adrp x0, 0x7fb7738000 + // ldr x1, [x0] + // mov x0, #0x18b8 + // eor x0, x1, x0 + // adrp x1, 0x7fb7d73000 + // add x0, x1, x0 + // ldrb w1, [x0] + // add w1, w1, #0x1 + // add x1, x1, x1, lsr #8 + // strb w1, [x0] + // adrp x0, 0x7fb7738000 + // mov x1, #0xc5c + // str x1, [x0] + // ldp x0, x1, [sp, #-160] + // b 0x7fb6f0dee4 + // ldp x16, x17, [sp], #144 + + uint32_t stp_x0_x1; /* stp x0, x1, [sp, #-0xa0] */ + + uint32_t adrp_x0_prev_loc1; /* adrp x0, #0xXXXX */ + uint32_t ldr_x1_ptr_x0; /* ldr x1, [x0] */ + + uint32_t mov_x0_curr_loc; /* movz x0, #0xXXXX */ + uint32_t eor_x0_x1_x0; /* eor x0, x1, x0 */ + uint32_t adrp_x1_area_ptr; /* adrp x1, #0xXXXX */ + uint32_t add_x0_x1_x0; /* add x0, x1, x0 */ + + uint32_t ldrb_w1_x0; /* ldrb w1, [x0] */ + uint32_t add_w1_w1_1; /* add w1, w1, #1 */ + uint32_t add_w1_w1_w1_lsr_8; /* add x1, x1, x1, lsr #8 */ + + uint32_t strb_w1_ptr_x0; /* strb w1, [x0] */ + + uint32_t adrp_x0_prev_loc2; /* adrp x0, #0xXXXX */ + uint32_t mov_x1_curr_loc_shr_1; /* movz x1, #0xXXXX */ + uint32_t str_x1_ptr_x0; /* str x1, [x0] */ + + uint32_t ldp_x0_x1; /* ldp x0, x1, [sp, #-0xa0] */ + + uint32_t b_imm8; /* br #8 */ + uint32_t restoration_prolog; /* ldp x16, x17, [sp], #0x90 */ -static const guint8 afl_log_code[] = { +} afl_log_code_asm_t; - // __afl_area_ptr[current_pc ^ previous_pc]++; - // previous_pc = current_pc ROR 1; - 0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]! - 0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]! + #pragma pack(pop) - // x0 = current_pc - 0x21, 0x02, 0x00, 0x58, // ldr x1, #0x44, =&__afl_area_ptr - 0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr) +typedef union { - 0x22, 0x02, 0x00, 0x58, // ldr x2, #0x44, =&previous_pc - 0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc) + afl_log_code_asm_t code; + uint8_t bytes[0]; - // __afl_area_ptr[current_pc ^ previous_pc]++; - 0x42, 0x00, 0x00, 0xca, // eor x2, x2, x0 - 0x23, 0x68, 0x62, 0xf8, // ldr x3, [x1, x2] - 0x63, 0x04, 0x00, 0x91, // add x3, x3, #1 - 0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr - 0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2] +} afl_log_code; - // previous_pc = current_pc ROR 1; - 0xe4, 0x07, 0x40, 0x8b, // add x4, xzr, x0, LSR #1 - 0xe0, 0xff, 0x00, 0x8b, // add x0, xzr, x0, LSL #63 - 0x80, 0xc0, 0x40, 0x8b, // add x0, x4, x0, LSR #48 +static const afl_log_code_asm_t template = + { - 0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc - 0x40, 0x00, 0x00, 0xf9, // str x0, [x2] + .stp_x0_x1 = 0xa93607e0, - 0xE3, 0x13, 0xc1, 0xA8, // ldp x3, x4, [sp], #0x10 - 0xE1, 0x0B, 0xc1, 0xA8, // ldp x1, x2, [sp], #0x10 - 0xC0, 0x03, 0x5F, 0xD6, // ret + .adrp_x0_prev_loc1 = 0x90000000, + .ldr_x1_ptr_x0 = 0xf9400001, - // &afl_area_ptr_ptr - // &afl_prev_loc_ptr + .mov_x0_curr_loc = 0xd2800000, + .eor_x0_x1_x0 = 0xca000020, -}; + .adrp_x1_area_ptr = 0x90000001, + .add_x0_x1_x0 = 0x8b000020, + + .ldrb_w1_x0 = 0x39400001, + + .add_w1_w1_1 = 0x11000421, + .add_w1_w1_w1_lsr_8 = 0x8b412021, + + .strb_w1_ptr_x0 = 0x39000001, + + .adrp_x0_prev_loc2 = 0x90000000, + .mov_x1_curr_loc_shr_1 = 0xd2800001, + .str_x1_ptr_x0 = 0xf9000001, + + .ldp_x0_x1 = 0xa97607e0, + + .b_imm8 = 0x14000002, + .restoration_prolog = 0xa8c947f0, + +} + +; gboolean instrument_is_coverage_optimize_supported(void) { @@ -52,50 +120,111 @@ gboolean instrument_is_coverage_optimize_supported(void) { } +static gboolean instrument_coverage_in_range(gssize offset) { + + return (offset >= G_MININT33 && offset <= G_MAXINT33); + +} + +static void instrument_patch_ardp(guint32 *patch, GumAddress insn, + GumAddress target) { + + if (!PAGE_ALIGNED(target)) { FATAL("Target not page aligned"); } + + gssize distance = target - (GUM_ADDRESS(insn) & PAGE_MASK); + if (!instrument_coverage_in_range(distance)) { + + FATAL("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target, + distance); + + } + + guint32 imm_low = ((distance >> 12) & 0x3) << 29; + guint32 imm_high = ((distance >> 14) & 0x7FFFF) << 5; + *patch |= imm_low; + *patch |= imm_high; + +} + void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output) { - guint64 current_pc = instr->address; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); + afl_log_code code = {0}; GumArm64Writer *cw = output->writer.arm64; + guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); + gsize map_size_pow2; + gsize area_offset_ror; + GumAddress code_addr = 0; - if (current_log_impl == 0 || - !gum_arm64_writer_can_branch_directly_between(cw, cw->pc, - current_log_impl) || - !gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128, - current_log_impl)) { + if (instrument_previous_pc_addr == NULL) { - gconstpointer after_log_impl = cw->code + 1; + GumAddressSpec spec = {.near_address = cw->code, + .max_distance = 1ULL << 30}; - gum_arm64_writer_put_b_label(cw, after_log_impl); + instrument_previous_pc_addr = gum_memory_allocate_near( + &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + FVERBOSE("code_addr: %p", cw->code); - current_log_impl = cw->pc; - gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code)); + } - uint8_t **afl_area_ptr_ptr = &__afl_area_ptr; - uint64_t *afl_prev_loc_ptr = &instrument_previous_pc; - gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr, - sizeof(afl_area_ptr_ptr)); - gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr, - sizeof(afl_prev_loc_ptr)); + // gum_arm64_writer_put_brk_imm(cw, 0x0); - gum_arm64_writer_put_label(cw, after_log_impl); + code_addr = cw->pc; - } + code.code = template; + + /* + * Given our map is allocated on a 64KB boundary and our map is a multiple of + * 64KB in size, then it should also end on a 64 KB boundary. It is followed + * by our previous_pc, so this too should be 64KB aligned. + */ + g_assert(PAGE_ALIGNED(instrument_previous_pc_addr)); + g_assert(PAGE_ALIGNED(__afl_area_ptr)); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE), - GUM_INDEX_PRE_ADJUST); - gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset); - gum_arm64_writer_put_bl_imm(cw, current_log_impl); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE, - GUM_INDEX_POST_ADJUST); + instrument_patch_ardp( + &code.code.adrp_x0_prev_loc1, + code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1), + GUM_ADDRESS(instrument_previous_pc_addr)); + + code.code.mov_x0_curr_loc |= area_offset << 5; + + instrument_patch_ardp( + &code.code.adrp_x1_area_ptr, + code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr), + GUM_ADDRESS(__afl_area_ptr)); + + map_size_pow2 = util_log2(__afl_map_size); + area_offset_ror = util_rotate(area_offset, 1, map_size_pow2); + + instrument_patch_ardp( + &code.code.adrp_x0_prev_loc2, + code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2), + GUM_ADDRESS(instrument_previous_pc_addr)); + + code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5); + + gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); } void instrument_coverage_optimize_init(void) { + char *shm_env = getenv(SHM_ENV_VAR); + FVERBOSE("SHM_ENV_VAR: %s", shm_env); + + if (shm_env == NULL) { + + FWARNF("SHM_ENV_VAR not set, using dummy for debugging purposes"); + + __afl_area_ptr = area_ptr_dummy; + memset(area_ptr_dummy, '\0', sizeof(area_ptr_dummy)); + + } + + FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); + } void instrument_flush(GumStalkerOutput *output) { diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c index c1984eb2..098e7269 100644 --- a/frida_mode/src/instrument/instrument_coverage.c +++ b/frida_mode/src/instrument/instrument_coverage.c @@ -659,17 +659,17 @@ void instrument_coverage_config(void) { void instrument_coverage_normal_init(void) { - FOKF("Coverage - enabled [%c]", - instrument_coverage_filename == NULL ? ' ' : 'X'); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "coverage:" cYEL " [%s]", + instrument_coverage_filename == NULL ? " " + : instrument_coverage_filename); if (instrument_coverage_filename == NULL) { return; } - FOKF("Coverage - file [%s]", instrument_coverage_filename); - char *path = g_canonicalize_filename(instrument_coverage_filename, g_get_current_dir()); - FOKF("Coverage - path [%s]", path); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "coverage path:" cYEL " [%s]", + path); normal_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); @@ -718,7 +718,7 @@ void instrument_coverage_unstable_find_output(void) { GDir *dir = g_dir_open(fds_name, 0, NULL); - FOKF("Coverage Unstable - fds: %s", fds_name); + FVERBOSE("Coverage Unstable - fds: %s", fds_name); for (const gchar *filename = g_dir_read_name(dir); filename != NULL; filename = g_dir_read_name(dir)) { @@ -782,18 +782,24 @@ void instrument_coverage_unstable_find_output(void) { } - FOKF("Fuzzer stats: %s", unstable_coverage_fuzzer_stats); + FVERBOSE("Fuzzer stats: %s", unstable_coverage_fuzzer_stats); } void instrument_coverage_unstable_init(void) { + FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage:" cYEL " [%s]", + instrument_coverage_unstable_filename == NULL + ? " " + : instrument_coverage_unstable_filename); if (instrument_coverage_unstable_filename == NULL) { return; } char *path = g_canonicalize_filename(instrument_coverage_unstable_filename, g_get_current_dir()); - FOKF("Coverage - unstable path [%s]", instrument_coverage_unstable_filename); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage path:" cYEL + " [%s]", + path == NULL ? " " : path); unstable_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); diff --git a/frida_mode/src/instrument/instrument_debug.c b/frida_mode/src/instrument/instrument_debug.c index 9c95857f..592ab673 100644 --- a/frida_mode/src/instrument/instrument_debug.c +++ b/frida_mode/src/instrument/instrument_debug.c @@ -35,6 +35,10 @@ static void instrument_debug(char *format, ...) { static void instrument_disasm(guint8 *start, guint8 *end, GumStalkerOutput *output) { +#if !defined(__arm__) + UNUSED_PARAMETER(output); +#endif + csh capstone; cs_err err; cs_mode mode; @@ -50,9 +54,7 @@ static void instrument_disasm(guint8 *start, guint8 *end, if (output->encoding == GUM_INSTRUCTION_SPECIAL) { mode |= CS_MODE_THUMB; } #endif - err = cs_open(GUM_DEFAULT_CS_ARCH, - CS_MODE_THUMB | GUM_DEFAULT_CS_MODE | GUM_DEFAULT_CS_ENDIAN, - &capstone); + err = cs_open(GUM_DEFAULT_CS_ARCH, mode, &capstone); g_assert(err == CS_ERR_OK); size = GPOINTER_TO_SIZE(end) - GPOINTER_TO_SIZE(start); @@ -96,19 +98,15 @@ void instrument_debug_config(void) { void instrument_debug_init(void) { - FOKF("Instrumentation debugging - enabled [%c]", - instrument_debug_filename == NULL ? ' ' : 'X'); - - if (instrument_debug_filename == NULL) { return; } - - FOKF("Instrumentation debugging - file [%s]", instrument_debug_filename); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "debugging:" cYEL " [%s]", + instrument_debug_filename == NULL ? " " : instrument_debug_filename); if (instrument_debug_filename == NULL) { return; } char *path = g_canonicalize_filename(instrument_debug_filename, g_get_current_dir()); - FOKF("Instrumentation debugging - path [%s]", path); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "path:" cYEL " [%s]", path); debugging_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index b51cb697..0ea4f7f0 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -323,7 +323,7 @@ void instrument_coverage_optimize_init(void) { gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low, &low_address); - FOKF("Low address: %p", low_address); + FVERBOSE("Low address: %p", low_address); if (low_address == 0 || GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) { @@ -335,7 +335,7 @@ void instrument_coverage_optimize_init(void) { ranges_print_debug_maps(); char *shm_env = getenv(SHM_ENV_VAR); - FOKF("SHM_ENV_VAR: %s", shm_env); + FVERBOSE("SHM_ENV_VAR: %s", shm_env); if (shm_env == NULL) { @@ -359,8 +359,7 @@ void instrument_coverage_optimize_init(void) { } - FOKF("__afl_area_ptr: %p", __afl_area_ptr); - FOKF("instrument_previous_pc: %p", &instrument_previous_pc); + FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); } @@ -439,6 +438,18 @@ void instrument_coverage_optimize(const cs_insn * instr, gsize map_size_pow2; gsize area_offset_ror; GumAddress code_addr = 0; + if (instrument_previous_pc_addr == NULL) { + + GumAddressSpec spec = {.near_address = cw->code, + .max_distance = 1ULL << 30}; + + instrument_previous_pc_addr = gum_memory_allocate_near( + &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + FVERBOSE("code_addr: %p", cw->code); + + } instrument_coverage_suppress_init(); @@ -462,7 +473,7 @@ void instrument_coverage_optimize(const cs_insn * instr, *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror); gssize prev_loc_value = - GPOINTER_TO_SIZE(&instrument_previous_pc) - + GPOINTER_TO_SIZE(instrument_previous_pc_addr) - (code_addr + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) + sizeof(code.code.mov_prev_loc_curr_loc_shr1)); gssize prev_loc_value_offset = @@ -478,7 +489,7 @@ void instrument_coverage_optimize(const cs_insn * instr, *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value; gssize prev_loc_value2 = - GPOINTER_TO_SIZE(&instrument_previous_pc) - + GPOINTER_TO_SIZE(instrument_previous_pc_addr) - (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) + sizeof(code.code.mov_eax_prev_loc)); gssize prev_loc_value_offset2 = diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index ad837e2d..c4e93324 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -153,6 +153,19 @@ void instrument_coverage_optimize(const cs_insn * instr, gsize map_size_pow2; gsize area_offset_ror; + if (instrument_previous_pc_addr == NULL) { + + GumAddressSpec spec = {.near_address = cw->code, + .max_distance = 1ULL << 30}; + + instrument_previous_pc_addr = gum_memory_allocate_near( + &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + FVERBOSE("code_addr: %p", cw->code); + + } + code.code = template; instrument_coverage_suppress_init(); @@ -170,7 +183,7 @@ void instrument_coverage_optimize(const cs_insn * instr, sizeof(code.code.mov_eax_prev_loc) - sizeof(gint); *((gint *)&code.bytes[prev_loc_value_offset2]) = - (gint)GPOINTER_TO_SIZE(&instrument_previous_pc); + (gint)GPOINTER_TO_SIZE(instrument_previous_pc_addr); gssize curr_loc_shr_1_offset = offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) + @@ -187,7 +200,7 @@ void instrument_coverage_optimize(const cs_insn * instr, sizeof(guint32); *((gint *)&code.bytes[prev_loc_value_offset]) = - (gint)GPOINTER_TO_SIZE(&instrument_previous_pc); + (gint)GPOINTER_TO_SIZE(instrument_previous_pc_addr); gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) + sizeof(code.code.xor_eax_curr_loc) - diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 215fbdaf..52e9e45c 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -63,7 +63,7 @@ class Afl { Afl.jsApiWrite(STDOUT_FILENO, buf, log.length); } /** - * See `AFL_FRIDA_INST_NO_BACKPATCH`. + * See `AFL_FRIDA_STALKER_NO_BACKPATCH`. */ static setBackpatchDisable() { Afl.jsApiSetBackpatchDisable(); @@ -268,6 +268,12 @@ class Afl { static setTraceable() { Afl.jsApiSetTraceable(); } + /** + * See `AFL_FRIDA_VERBOSE` + */ + static setVerbose() { + Afl.jsApiSetVerbose(); + } static jsApiGetFunction(name, retType, argTypes) { const addr = Afl.module.getExportByName(name); return new NativeFunction(addr, retType, argTypes); @@ -315,6 +321,7 @@ Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "v Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]); Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]); Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []); +Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []); Afl.jsApiWrite = new NativeFunction( /* tslint:disable-next-line:no-null-keyword */ Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]); diff --git a/frida_mode/src/js/js.c b/frida_mode/src/js/js.c index 5f477388..1ca2237f 100644 --- a/frida_mode/src/js/js.c +++ b/frida_mode/src/js/js.c @@ -55,7 +55,10 @@ static gchar *js_get_script() { } else { - FOKF("Loaded AFL script: %s, %" G_GSIZE_MODIFIER "d bytes", filename, + FOKF(cBLU "Javascript" cRST " - " cGRN "script:" cYEL " [%s]", + filename == NULL ? " " : filename); + FOKF(cBLU "Javascript" cRST " - " cGRN "size: " cYEL "%" G_GSIZE_MODIFIER + "d bytes", length); gchar *source = g_malloc0(api_js_len + length + 1); @@ -74,7 +77,7 @@ static void js_print_script(gchar *source) { for (size_t i = 0; split[i] != NULL; i++) { - FOKF("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]); + FVERBOSE("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]); } diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 5021b531..94ec8842 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -262,3 +262,9 @@ __attribute__((visibility("default"))) void js_api_set_js_main_hook( } +__attribute__((visibility("default"))) void js_api_set_verbose(void) { + + util_verbose = TRUE; + +} + diff --git a/frida_mode/src/lib/lib.c b/frida_mode/src/lib/lib.c index 48d2ea2a..39480ce9 100644 --- a/frida_mode/src/lib/lib.c +++ b/frida_mode/src/lib/lib.c @@ -93,17 +93,18 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) { } - FOKF("Image preferred load address 0x%016" G_GSIZE_MODIFIER "x", - preferred_base); + FVERBOSE("\tpreferred load address: 0x%016" G_GSIZE_MODIFIER "x", + preferred_base); shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff); shstrtab = &shdr[hdr->e_shstrndx]; shstr = (char *)hdr + shstrtab->sh_offset; - FOKF("shdr: %p", shdr); - FOKF("shstrtab: %p", shstrtab); - FOKF("shstr: %p", shstr); + FVERBOSE("\tshdr: %p", shdr); + FVERBOSE("\tshstrtab: %p", shstrtab); + FVERBOSE("\tshstr: %p", shstr); + FVERBOSE("Sections:"); for (size_t i = 0; i < hdr->e_shnum; i++) { curr = &shdr[i]; @@ -111,21 +112,23 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) { if (curr->sh_name == 0) continue; section_name = &shstr[curr->sh_name]; - FOKF("Section: %2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER - "X size: 0x%016" G_GSIZE_MODIFIER "X %s", - i, curr->sh_addr, curr->sh_size, section_name); + FVERBOSE("\t%2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER + "X size: 0x%016" G_GSIZE_MODIFIER "X %s", + i, curr->sh_addr, curr->sh_size, section_name); if (memcmp(section_name, text_name, sizeof(text_name)) == 0 && text_base == 0) { text_base = lib_details->base_address + curr->sh_addr - preferred_base; text_limit = text_base + curr->sh_size; - FOKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base); - FOKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit); } } + FVERBOSE(".text\n"); + FVERBOSE("\taddr: 0x%016" G_GINT64_MODIFIER "X", text_base); + FVERBOSE("\tlimit: 0x%016" G_GINT64_MODIFIER "X", text_limit); + } static void lib_get_text_section(lib_details_t *details) { @@ -141,7 +144,7 @@ static void lib_get_text_section(lib_details_t *details) { if (len == (off_t)-1) { FFATAL("Failed to lseek %s", details->path); } - FOKF("len: %ld", len); + FVERBOSE("\tlength: %ld", len); hdr = (Elf_Ehdr *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0); if (hdr == MAP_FAILED) { FFATAL("Failed to map %s", details->path); } @@ -162,8 +165,10 @@ void lib_init(void) { lib_details_t lib_details; gum_process_enumerate_modules(lib_find_exe, &lib_details); - FOKF("Executable: 0x%016" G_GINT64_MODIFIER "x - %s", - lib_details.base_address, lib_details.path); + FVERBOSE("Image"); + FVERBOSE("\tbase: 0x%016" G_GINT64_MODIFIER "x", + lib_details.base_address); + FVERBOSE("\tpath: %s", lib_details.path); lib_get_text_section(&lib_details); } diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c index 3bdb8c10..65c1d937 100644 --- a/frida_mode/src/lib/lib_apple.c +++ b/frida_mode/src/lib/lib_apple.c @@ -20,7 +20,7 @@ static gboolean lib_get_main_module(const GumModuleDetails *details, details->path, mach_task_self(), details->range->base_address, GUM_DARWIN_MODULE_FLAGS_NONE, NULL); - FOKF("Found main module: %s", module->name); + FVERBOSE("Found main module: %s", module->name); *ret = module; @@ -35,21 +35,23 @@ gboolean lib_get_text_section(const GumDarwinSectionDetails *details, static size_t idx = 0; char text_name[] = "__text"; - FOKF("Section: %2lu - base: 0x%016" G_GINT64_MODIFIER - "X size: 0x%016" G_GINT64_MODIFIER "X %s", - idx++, details->vm_address, details->vm_address + details->size, - details->section_name); + FVERBOSE("\t%2lu - base: 0x%016" G_GINT64_MODIFIER + "X size: 0x%016" G_GINT64_MODIFIER "X %s", + idx++, details->vm_address, details->vm_address + details->size, + details->section_name); if (memcmp(details->section_name, text_name, sizeof(text_name)) == 0 && text_base == 0) { text_base = details->vm_address; text_limit = details->vm_address + details->size; - FOKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base); - FOKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit); } + FVERBOSE(".text\n"); + FVERBOSE("\taddr: 0x%016" G_GINT64_MODIFIER "X", text_base); + FVERBOSE("\tlimit: 0x%016" G_GINT64_MODIFIER "X", text_limit); + return TRUE; } @@ -62,6 +64,8 @@ void lib_init(void) { GumDarwinModule *module = NULL; gum_darwin_enumerate_modules(mach_task_self(), lib_get_main_module, &module); + + FVERBOSE("Sections:"); gum_darwin_module_enumerate_sections(module, lib_get_text_section, NULL); } diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index 1be63bc4..d8521300 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -111,11 +111,13 @@ static void afl_print_cmdline(void) { int idx = 0; + FVERBOSE("Command Line"); + for (ssize_t i = 0; i < bytes_read; i++) { if (i == 0 || buffer[i - 1] == '\0') { - FOKF("AFL - COMMANDLINE: argv[%d] = %s", idx++, &buffer[i]); + FVERBOSE("\targv[%d] = %s", idx++, &buffer[i]); } @@ -131,7 +133,7 @@ static void afl_print_cmdline(void) { for (idx = 0; idx < nargv; idx++) { - FOKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]); + FVERBOSE("\targv[%d] = %s", idx, argv[idx]); } @@ -161,11 +163,12 @@ static void afl_print_env(void) { int idx = 0; + FVERBOSE("ENVIRONMENT"); for (ssize_t i = 0; i < bytes_read; i++) { if (i == 0 || buffer[i - 1] == '\0') { - FOKF("AFL - ENVIRONMENT %3d: %s", idx++, &buffer[i]); + FVERBOSE("\t%3d: %s", idx++, &buffer[i]); } @@ -179,6 +182,13 @@ static void afl_print_env(void) { __attribute__((visibility("default"))) void afl_frida_start(void) { + FOKF(cRED "**********************"); + FOKF(cRED "* " cYEL "******************" cRED " *"); + FOKF(cRED "* " cYEL "* " cGRN "**************" cYEL " *" cRED " *"); + FOKF(cRED "* " cYEL "* " cGRN "* FRIDA MODE *" cYEL " *" cRED " *"); + FOKF(cRED "* " cYEL "* " cGRN "**************" cYEL " *" cRED " *"); + FOKF(cRED "* " cYEL "******************" cRED " *"); + FOKF(cRED "**********************"); afl_print_cmdline(); afl_print_env(); @@ -255,9 +265,9 @@ static void intercept_main(void) { static void intercept_main(void) { mach_port_t task = mach_task_self(); - FOKF("Task Id: %u", task); + FVERBOSE("Task Id: %u", task); GumAddress entry = gum_darwin_find_entrypoint(task); - FOKF("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry); + FVERBOSE("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry); void *main = GSIZE_TO_POINTER(entry); main_fn = main; intercept_hook(main, on_main, NULL); diff --git a/frida_mode/src/output.c b/frida_mode/src/output.c index f570fe91..66208992 100644 --- a/frida_mode/src/output.c +++ b/frida_mode/src/output.c @@ -18,7 +18,7 @@ static void output_redirect(int fd, char *filename) { path = g_canonicalize_filename(filename, g_get_current_dir()); - FOKF("Redirect %d -> '%s'", fd, path); + FVERBOSE("Redirect %d -> '%s'", fd, path); int output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); @@ -46,8 +46,10 @@ void output_config(void) { void output_init(void) { - FOKF("Output - StdOut: %s", output_stdout); - FOKF("Output - StdErr: %s", output_stderr); + FOKF(cBLU "Output" cRST " - " cGRN "stdout:" cYEL " [%s]", + output_stdout == NULL ? " " : output_stdout); + FOKF(cBLU "Output" cRST " - " cGRN "stderr:" cYEL " [%s]", + output_stderr == NULL ? " " : output_stderr); output_redirect(STDOUT_FILENO, output_stdout); output_redirect(STDERR_FILENO, output_stderr); diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c index 817d9925..7fd7d351 100644 --- a/frida_mode/src/persistent/persistent.c +++ b/frida_mode/src/persistent/persistent.c @@ -72,13 +72,16 @@ void persistent_config(void) { void persistent_init(void) { - FOKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)", + FOKF(cBLU "Instrumentation" cRST " - " cGRN "persistent mode:" cYEL + " [%c] (0x%016" G_GINT64_MODIFIER "X)", persistent_start == 0 ? ' ' : 'X', persistent_start); - FOKF("Instrumentation - persistent count [%c] (%" G_GINT64_MODIFIER "d)", + FOKF(cBLU "Instrumentation" cRST " - " cGRN "persistent count:" cYEL + " [%c] (%" G_GINT64_MODIFIER "d)", persistent_start == 0 ? ' ' : 'X', persistent_count); - FOKF("Instrumentation - hook [%s]", hook_name); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "hook:" cYEL " [%s]", hook_name); - FOKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)", + FOKF(cBLU "Instrumentation" cRST " - " cGRN "persistent ret:" cYEL + " [%c] (0x%016" G_GINT64_MODIFIER "X)", persistent_ret == 0 ? ' ' : 'X', persistent_ret); if (persistent_hook != NULL) { __afl_sharedmem_fuzzing = 1; } @@ -87,7 +90,7 @@ void persistent_init(void) { void persistent_prologue(GumStalkerOutput *output) { - FOKF("AFL_FRIDA_PERSISTENT_ADDR reached"); + FVERBOSE("AFL_FRIDA_PERSISTENT_ADDR reached"); entry_compiled = TRUE; ranges_exclude(); stalker_trust(); @@ -97,7 +100,7 @@ void persistent_prologue(GumStalkerOutput *output) { void persistent_epilogue(GumStalkerOutput *output) { - FOKF("AFL_FRIDA_PERSISTENT_RET reached"); + FVERBOSE("AFL_FRIDA_PERSISTENT_RET reached"); persistent_epilogue_arch(output); } diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c index c9159ca1..16ecf39c 100644 --- a/frida_mode/src/persistent/persistent_arm64.c +++ b/frida_mode/src/persistent/persistent_arm64.c @@ -89,7 +89,7 @@ static void instrument_persitent_save_regs(GumArm64Writer * cw, /* LR (x30) */ gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, - offsetof(GumCpuContext, x[30])); + offsetof(GumCpuContext, lr)); /* PC & Adjusted SP (31) */ gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, @@ -189,7 +189,7 @@ static void instrument_persitent_restore_regs(GumArm64Writer * cw, /* LR (x30) */ gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, - offsetof(GumCpuContext, x[30])); + offsetof(GumCpuContext, lr)); /* Adjusted SP (31) (use x1 as clobber)*/ gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, @@ -236,7 +236,13 @@ static void instrument_exit(GumArm64Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - instrument_previous_pc = instrument_hash_zero; + if (instrument_previous_pc_addr == NULL) { + + FATAL("instrument_previous_pc_addr uninitialized"); + + } + + *instrument_previous_pc_addr = instrument_hash_zero; return ret; } @@ -264,8 +270,7 @@ static void persistent_prologue_hook(GumArm64Writer * cw, gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); - gum_arm64_writer_put_and_reg_reg_imm(cw, ARM64_REG_X2, ARM64_REG_X2, - G_MAXULONG); + gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_W2, ARM64_REG_W2); gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X1, GUM_ADDRESS(&__afl_fuzz_ptr)); @@ -324,7 +329,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - FOKF("Persistent loop reached"); + FVERBOSE("Persistent loop reached"); instrument_persitent_save_regs(cw, &saved_regs); diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index 8cbde633..56141787 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -173,7 +173,13 @@ static void instrument_exit(GumX86Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - instrument_previous_pc = instrument_hash_zero; + if (instrument_previous_pc_addr == NULL) { + + FATAL("instrument_previous_pc_addr uninitialized"); + + } + + *instrument_previous_pc_addr = instrument_hash_zero; return ret; } @@ -269,7 +275,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - FOKF("Persistent loop reached"); + FVERBOSE("Persistent loop reached"); /* Pop the return value */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8); diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index 5425b01b..76c25334 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -130,7 +130,13 @@ static void instrument_exit(GumX86Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - instrument_previous_pc = instrument_hash_zero; + if (instrument_previous_pc_addr == NULL) { + + FATAL("instrument_previous_pc_addr uninitialized"); + + } + + *instrument_previous_pc_addr = instrument_hash_zero; return ret; } @@ -210,7 +216,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - FOKF("Persistent loop reached"); + FVERBOSE("Persistent loop reached"); /* Pop the return value */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4); diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index 8c9ce94d..fa0288cc 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -178,8 +178,10 @@ static void prefetch_hook_fork(void) { void prefetch_init(void) { - FOKF("Instrumentation - prefetch [%c]", prefetch_enable ? 'X' : ' '); - FOKF("Instrumentation - prefetch_backpatch [%c]", + FOKF(cBLU "Instrumentation" cRST " - " cGRN "prefetch:" cYEL " [%c]", + prefetch_enable ? 'X' : ' '); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "prefetch_backpatch:" cYEL + " [%c]", prefetch_backpatch ? 'X' : ' '); if (!prefetch_enable) { return; } diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 9844c74c..84803453 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -122,10 +122,10 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details, if (!g_str_has_suffix(details->path, ctx->suffix)) { return true; }; - FOKF("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER - "x-0x%016" G_GINT64_MODIFIER "x %s", - ctx->suffix, details->range->base_address, - details->range->base_address + details->range->size, details->path); + FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER + "x-0x%016" G_GINT64_MODIFIER "x %s", + ctx->suffix, details->range->base_address, + details->range->base_address + details->range->size, details->path); *ctx->range = *details->range; ctx->done = true; @@ -158,9 +158,9 @@ static void convert_token(gchar *token, GumMemoryRange *range) { } - FOKF("Converted token: %s -> 0x%016" G_GINT64_MODIFIER - "x-0x%016" G_GINT64_MODIFIER "x\n", - token, range->base_address, range->base_address + range->size); + FVERBOSE("Converted token: %s -> 0x%016" G_GINT64_MODIFIER + "x-0x%016" G_GINT64_MODIFIER "x\n", + token, range->base_address, range->base_address + range->size); } @@ -192,24 +192,24 @@ static gboolean print_ranges_callback(const GumRangeDetails *details, if (details->file == NULL) { - FOKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER - "X %c%c%c", - details->range->base_address, - details->range->base_address + details->range->size, - details->protection & GUM_PAGE_READ ? 'R' : '-', - details->protection & GUM_PAGE_WRITE ? 'W' : '-', - details->protection & GUM_PAGE_EXECUTE ? 'X' : '-'); + FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER + "X %c%c%c", + details->range->base_address, + details->range->base_address + details->range->size, + details->protection & GUM_PAGE_READ ? 'R' : '-', + details->protection & GUM_PAGE_WRITE ? 'W' : '-', + details->protection & GUM_PAGE_EXECUTE ? 'X' : '-'); } else { - FOKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER - "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)", - details->range->base_address, - details->range->base_address + details->range->size, - details->protection & GUM_PAGE_READ ? 'R' : '-', - details->protection & GUM_PAGE_WRITE ? 'W' : '-', - details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', - details->file->path, details->file->offset); + FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER + "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)", + details->range->base_address, + details->range->base_address + details->range->size, + details->protection & GUM_PAGE_READ ? 'R' : '-', + details->protection & GUM_PAGE_WRITE ? 'W' : '-', + details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', + details->file->path, details->file->offset); } @@ -219,14 +219,14 @@ static gboolean print_ranges_callback(const GumRangeDetails *details, static void print_ranges(char *key, GArray *ranges) { - FOKF("Range: %s Length: %d", key, ranges->len); + FVERBOSE("Range: [%s], Length: %d", key, ranges->len); for (guint i = 0; i < ranges->len; i++) { GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i); GumAddress curr_limit = curr->base_address + curr->size; - FOKF("Range: %s Idx: %3d - 0x%016" G_GINT64_MODIFIER - "x-0x%016" G_GINT64_MODIFIER "x", - key, i, curr->base_address, curr_limit); + FVERBOSE("\t%3d - 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER + "x", + i, curr->base_address, curr_limit); } @@ -248,7 +248,7 @@ static GArray *collect_module_ranges(void) { result = g_array_new(false, false, sizeof(GumMemoryRange)); gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, collect_module_ranges_callback, result); - print_ranges("Modules", result); + print_ranges("modules", result); return result; } @@ -348,7 +348,7 @@ static GArray *collect_libs_ranges(void) { g_array_append_val(result, range); - print_ranges("AFL_INST_LIBS", result); + print_ranges("libs", result); return result; @@ -382,7 +382,7 @@ static GArray *collect_jit_ranges(void) { } - print_ranges("JIT", result); + print_ranges("jit", result); return result; } @@ -564,6 +564,7 @@ static GArray *merge_ranges(GArray *a) { void ranges_print_debug_maps(void) { + FVERBOSE("Maps"); gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL); } @@ -590,16 +591,15 @@ void ranges_init(void) { GArray * step4; GArray * step5; - FOKF("Ranges - Instrument jit [%c]", ranges_inst_jit ? 'X' : ' '); - FOKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' '); + FOKF(cBLU "Ranges" cRST " - " cGRN "instrument jit:" cYEL " [%c]", + ranges_inst_jit ? 'X' : ' '); + FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]", + ranges_inst_libs ? 'X' : ' '); + FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]", + ranges_inst_libs ? 'X' : ' '); - print_ranges("AFL_FRIDA_INST_RANGES", include_ranges); - print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges); - - FOKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' '); - - print_ranges("AFL_FRIDA_INST_RANGES", include_ranges); - print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges); + print_ranges("include", include_ranges); + print_ranges("exclude", exclude_ranges); module_ranges = collect_module_ranges(); libs_ranges = collect_libs_ranges(); @@ -673,7 +673,7 @@ void ranges_exclude() { GumMemoryRange *r; GumStalker * stalker = stalker_get(); - FOKF("Excluding ranges"); + FVERBOSE("Excluding ranges"); for (guint i = 0; i < ranges->len; i++) { diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c index 9d8fdd5d..984a3990 100644 --- a/frida_mode/src/seccomp/seccomp.c +++ b/frida_mode/src/seccomp/seccomp.c @@ -25,7 +25,8 @@ void seccomp_config(void) { void seccomp_init(void) { - FOKF("Seccomp - file [%s]", seccomp_filename); + FOKF(cBLU "Seccomp" cRST " - " cGRN "file:" cYEL " [%s]", + seccomp_filename == NULL ? " " : seccomp_filename); if (seccomp_filename == NULL) { return; } diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c index f7aaf78b..c86e753f 100644 --- a/frida_mode/src/seccomp/seccomp_callback.c +++ b/frida_mode/src/seccomp/seccomp_callback.c @@ -124,7 +124,7 @@ void seccomp_callback_initialize(void) { path = g_canonicalize_filename(seccomp_filename, g_get_current_dir()); - FOKF("Seccomp - path [%s]", path); + FVERBOSE("Seccomp - path [%s]", path); fd = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c index 1d050303..075d793a 100644 --- a/frida_mode/src/seccomp/seccomp_filter.c +++ b/frida_mode/src/seccomp/seccomp_filter.c @@ -258,7 +258,7 @@ void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) { if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0) { if (errno == ENOENT) { continue; } - FOKF("SECCOMP_IOCTL_NOTIF_SEND"); + FVERBOSE("SECCOMP_IOCTL_NOTIF_SEND"); continue; } diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c index caa16b3f..3a421867 100644 --- a/frida_mode/src/stalker.c +++ b/frida_mode/src/stalker.c @@ -93,10 +93,12 @@ static gboolean stalker_exclude_self(const GumRangeDetails *details, void stalker_init(void) { - FOKF("Instrumentation - backpatch [%c]", backpatch_enable ? 'X' : ' '); - - FOKF("Stalker - ic_entries [%u]", stalker_ic_entries); - FOKF("Stalker - adjacent_blocks [%u]", stalker_adjacent_blocks); + FOKF(cBLU "Stalker" cRST " - " cGRN "backpatch:" cYEL " [%c]", + backpatch_enable ? 'X' : ' '); + FOKF(cBLU "Stalker" cRST " - " cGRN "ic_entries:" cYEL " [%u]", + stalker_ic_entries); + FOKF(cBLU "Stalker" cRST " - " cGRN "adjacent_blocks:" cYEL " [%u]", + stalker_adjacent_blocks); #if !(defined(__x86_64__) || defined(__i386__)) if (getenv("AFL_FRIDA_STALKER_IC_ENTRIES") != NULL) { diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c index 83ecf89a..39aca0db 100644 --- a/frida_mode/src/stats/stats.c +++ b/frida_mode/src/stats/stats.c @@ -329,8 +329,11 @@ void stats_config(void) { void stats_init(void) { - FOKF("Stats - file [%s]", stats_filename); - FOKF("Stats - interval [%" G_GINT64_MODIFIER "u]", stats_interval); + FOKF(cBLU "Stats" cRST " - " cGRN "file:" cYEL " [%s]", + stats_filename == NULL ? " " : stats_filename); + FOKF(cBLU "Stats" cRST " - " cGRN "interval:" cYEL " [%" G_GINT64_MODIFIER + "u]", + stats_interval); if (getenv("AFL_FRIDA_STATS_INTERVAL") != NULL && getenv("AFL_FRIDA_STATS_FILE") == NULL) { @@ -347,7 +350,8 @@ void stats_init(void) { char *path = g_canonicalize_filename(stats_filename, g_get_current_dir()); - FOKF("Stats - path [%s]", path); + FOKF(cBLU "Stats" cRST " - " cGRN "path:" cYEL " [%s]", + path == NULL ? " " : path); stats_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); diff --git a/frida_mode/src/util.c b/frida_mode/src/util.c index 6f52b6cb..90c10917 100644 --- a/frida_mode/src/util.c +++ b/frida_mode/src/util.c @@ -1,5 +1,7 @@ #include "util.h" +gboolean util_verbose = FALSE; + guint64 util_read_address(char *key, guint64 default_value) { char *value_str = getenv(key); @@ -66,7 +68,7 @@ guint64 util_read_num(char *key, guint64 default_value) { errno = 0; - guint64 value = g_ascii_strtoull(value_str, NULL, 10); + guint64 value = g_ascii_strtoull(value_str, &end_ptr, 10); if (errno != 0) { @@ -87,12 +89,13 @@ guint64 util_read_num(char *key, guint64 default_value) { gboolean util_output_enabled(void) { static gboolean initialized = FALSE; - static gboolean enabled = TRUE; + static gboolean enabled = FALSE; if (!initialized) { initialized = TRUE; - if (getenv("AFL_DEBUG_CHILD") == NULL) { enabled = FALSE; } + if (getenv("AFL_DEBUG_CHILD") != NULL) { enabled = TRUE; } + if (util_verbose_enabled()) { enabled = TRUE; } } @@ -100,6 +103,21 @@ gboolean util_output_enabled(void) { } +gboolean util_verbose_enabled(void) { + + static gboolean initialized = FALSE; + + if (!initialized) { + + initialized = TRUE; + if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; } + + } + + return util_verbose; + +} + gsize util_rotate(gsize val, gsize shift, gsize size) { if (shift == 0) { return val; } diff --git a/frida_mode/test/bloaty/GNUmakefile b/frida_mode/test/bloaty/GNUmakefile index 7ef4fe81..8e767fae 100644 --- a/frida_mode/test/bloaty/GNUmakefile +++ b/frida_mode/test/bloaty/GNUmakefile @@ -34,20 +34,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all clean frida hook diff --git a/frida_mode/test/bloaty/get_symbol_addr.py b/frida_mode/test/bloaty/get_symbol_addr.py deleted file mode 100755 index 1c46e010..00000000 --- a/frida_mode/test/bloaty/get_symbol_addr.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 -import argparse -from elftools.elf.elffile import ELFFile - -def process_file(file, symbol, base): - with open(file, 'rb') as f: - elf = ELFFile(f) - symtab = elf.get_section_by_name('.symtab') - mains = symtab.get_symbol_by_name(symbol) - if len(mains) != 1: - print ("Failed to find main") - return 1 - - main_addr = mains[0]['st_value'] - main = base + main_addr - print ("0x%016x" % main) - return 0 - -def hex_value(x): - return int(x, 16) - -def main(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-f', '--file', dest='file', type=str, - help='elf file name', required=True) - parser.add_argument('-s', '--symbol', dest='symbol', type=str, - help='symbol name', required=True) - parser.add_argument('-b', '--base', dest='base', type=hex_value, - help='elf base address', required=True) - - args = parser.parse_args() - return process_file (args.file, args.symbol, args.base) - -if __name__ == "__main__": - ret = main() - exit(ret) diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c index c7a05ac5..7e564a61 100644 --- a/frida_mode/test/deferred/testinstr.c +++ b/frida_mode/test/deferred/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c index bd605c52..196b1d84 100644 --- a/frida_mode/test/entry_point/testinstr.c +++ b/frida_mode/test/entry_point/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c index 5e26fc46..334f6518 100644 --- a/frida_mode/test/exe/testinstr.c +++ b/frida_mode/test/exe/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/freetype2/GNUmakefile b/frida_mode/test/freetype2/GNUmakefile index f7a50de2..8c35d5de 100644 --- a/frida_mode/test/freetype2/GNUmakefile +++ b/frida_mode/test/freetype2/GNUmakefile @@ -47,6 +47,7 @@ endif TEST_DATA_DIR:=$(BUILD_DIR)in/ TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed +AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat FRIDA_OUT:=$(BUILD_DIR)frida-out QEMU_OUT:=$(BUILD_DIR)qemu-out @@ -62,20 +63,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all clean frida hook @@ -154,6 +157,9 @@ $(TEST_DATA_DIR): | $(TRT_DIR) cp $(TRT_DIR)fonts/TestGLYFOne.ttf $@ $(TEST_DATA_FILE): | $(TEST_DATA_DIR) + echo "hi" > $@ + +$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) dd if=/dev/zero bs=1048576 count=1 of=$@ ###### TEST DATA ####### @@ -161,7 +167,7 @@ $(TEST_DATA_FILE): | $(TEST_DATA_DIR) clean: rm -rf $(BUILD_DIR) -frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) +frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT) AFL_FRIDA_PERSISTENT_CNT=1000000 \ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ @@ -174,9 +180,9 @@ frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) -O \ -V 30 \ -- \ - $(TEST_BIN) $(TEST_DATA_FILE) + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) +qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT) AFL_QEMU_PERSISTENT_CNT=1000000 \ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ @@ -189,4 +195,4 @@ qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) -Q \ -V 30 \ -- \ - $(TEST_BIN) $(TEST_DATA_FILE) + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) diff --git a/frida_mode/test/freetype2/get_symbol_addr.py b/frida_mode/test/freetype2/get_symbol_addr.py deleted file mode 100755 index 1c46e010..00000000 --- a/frida_mode/test/freetype2/get_symbol_addr.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 -import argparse -from elftools.elf.elffile import ELFFile - -def process_file(file, symbol, base): - with open(file, 'rb') as f: - elf = ELFFile(f) - symtab = elf.get_section_by_name('.symtab') - mains = symtab.get_symbol_by_name(symbol) - if len(mains) != 1: - print ("Failed to find main") - return 1 - - main_addr = mains[0]['st_value'] - main = base + main_addr - print ("0x%016x" % main) - return 0 - -def hex_value(x): - return int(x, 16) - -def main(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-f', '--file', dest='file', type=str, - help='elf file name', required=True) - parser.add_argument('-s', '--symbol', dest='symbol', type=str, - help='symbol name', required=True) - parser.add_argument('-b', '--base', dest='base', type=hex_value, - help='elf base address', required=True) - - args = parser.parse_args() - return process_file (args.file, args.symbol, args.base) - -if __name__ == "__main__": - ret = main() - exit(ret) diff --git a/frida_mode/test/jpeg/GNUmakefile b/frida_mode/test/jpeg/GNUmakefile index ca5101cb..a8242081 100644 --- a/frida_mode/test/jpeg/GNUmakefile +++ b/frida_mode/test/jpeg/GNUmakefile @@ -46,19 +46,11 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) -endif - -ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) -endif - -ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) -endif +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) .PHONY: all clean frida hook diff --git a/frida_mode/test/jpeg/get_symbol_addr.py b/frida_mode/test/jpeg/get_symbol_addr.py deleted file mode 100755 index 1c46e010..00000000 --- a/frida_mode/test/jpeg/get_symbol_addr.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 -import argparse -from elftools.elf.elffile import ELFFile - -def process_file(file, symbol, base): - with open(file, 'rb') as f: - elf = ELFFile(f) - symtab = elf.get_section_by_name('.symtab') - mains = symtab.get_symbol_by_name(symbol) - if len(mains) != 1: - print ("Failed to find main") - return 1 - - main_addr = mains[0]['st_value'] - main = base + main_addr - print ("0x%016x" % main) - return 0 - -def hex_value(x): - return int(x, 16) - -def main(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-f', '--file', dest='file', type=str, - help='elf file name', required=True) - parser.add_argument('-s', '--symbol', dest='symbol', type=str, - help='symbol name', required=True) - parser.add_argument('-b', '--base', dest='base', type=hex_value, - help='elf base address', required=True) - - args = parser.parse_args() - return process_file (args.file, args.symbol, args.base) - -if __name__ == "__main__": - ret = main() - exit(ret) diff --git a/frida_mode/test/js/test.c b/frida_mode/test/js/test.c index bbda5ccf..f6778b6f 100644 --- a/frida_mode/test/js/test.c +++ b/frida_mode/test/js/test.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/js/test2.c b/frida_mode/test/js/test2.c index d16f35fc..9e9cdbb4 100644 --- a/frida_mode/test/js/test2.c +++ b/frida_mode/test/js/test2.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile index f8dc3db7..1bf9cd7f 100644 --- a/frida_mode/test/libpcap/GNUmakefile +++ b/frida_mode/test/libpcap/GNUmakefile @@ -55,20 +55,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) ifeq "$(ARCH)" "arm64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all clean qemu frida hook diff --git a/frida_mode/test/libxml/GNUmakefile b/frida_mode/test/libxml/GNUmakefile index 1d675187..6fc87585 100644 --- a/frida_mode/test/libxml/GNUmakefile +++ b/frida_mode/test/libxml/GNUmakefile @@ -42,21 +42,11 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) - -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) -endif - -ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) -endif - -ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) -endif +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) .PHONY: all clean frida hook @@ -134,7 +124,7 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ $(TEST_DATA_FILE): | $(TEST_DATA_DIR) - dd if=/dev/zero bs=1048576 count=1 of=$@ + echo "hi" > $@ ###### ####### diff --git a/frida_mode/test/libxml/get_symbol_addr.py b/frida_mode/test/libxml/get_symbol_addr.py deleted file mode 100755 index 1c46e010..00000000 --- a/frida_mode/test/libxml/get_symbol_addr.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 -import argparse -from elftools.elf.elffile import ELFFile - -def process_file(file, symbol, base): - with open(file, 'rb') as f: - elf = ELFFile(f) - symtab = elf.get_section_by_name('.symtab') - mains = symtab.get_symbol_by_name(symbol) - if len(mains) != 1: - print ("Failed to find main") - return 1 - - main_addr = mains[0]['st_value'] - main = base + main_addr - print ("0x%016x" % main) - return 0 - -def hex_value(x): - return int(x, 16) - -def main(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-f', '--file', dest='file', type=str, - help='elf file name', required=True) - parser.add_argument('-s', '--symbol', dest='symbol', type=str, - help='symbol name', required=True) - parser.add_argument('-b', '--base', dest='base', type=hex_value, - help='elf base address', required=True) - - args = parser.parse_args() - return process_file (args.file, args.symbol, args.base) - -if __name__ == "__main__": - ret = main() - exit(ret) diff --git a/frida_mode/test/libxslt/GNUmakefile b/frida_mode/test/libxslt/GNUmakefile new file mode 100644 index 00000000..655e652b --- /dev/null +++ b/frida_mode/test/libxslt/GNUmakefile @@ -0,0 +1,177 @@ +PWD:=$(shell pwd)/ +ROOT:=$(PWD)../../../ +BUILD_DIR:=$(PWD)build/ + +AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so +AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so + +LIBFUZZER_LIB:=/usr/lib/llvm-12/lib/libFuzzer.a + +LIBXSLT_GIT_REPO:=https://gitlab.gnome.org/GNOME/libxslt.git +LIBXSLT_DIR:=$(BUILD_DIR)libxslt/ +LIBXSLT_LIB:=$(LIBXSLT_DIR)libxslt/.libs/libxslt.a + +LIBZXML2_GIT_REPO:=https://gitlab.gnome.org/GNOME/libxml2.git +LIBXML2_DIR:=$(BUILD_DIR)libxml2/ +LIBXML2_LIB:=$(LIBXML2_DIR).libs/libxml2.a + +TEST_BIN:=$(BUILD_DIR)test +XPATH_XML:=$(BUILD_DIR)xpath.xml + +ifeq "$(shell uname)" "Darwin" +TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie +endif + +TEST_DATA_DIR:=$(BUILD_DIR)in/ +TEST_DATA_SRC:=$(LIBXSLT_DIR)tests/testdata/fuzz_corpus/ +DUMMY_DATA_FILE:=$(BUILD_DIR)default_seed + +FRIDA_OUT:=$(BUILD_DIR)frida-out +QEMU_OUT:=$(BUILD_DIR)qemu-out + +ifndef ARCH + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + ARCH:=arm64 +endif + +ifeq "$(ARCH)" "i686" + ARCH:=x86 +endif +endif + +ADDR_BIN:=$(ROOT)frida_mode/build/addr +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh + +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) + +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) +endif + +ifeq "$(ARCH)" "x86_64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +endif + +ifeq "$(ARCH)" "x86" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +endif + +.PHONY: all clean frida hook + +all: $(TEST_BIN) + make -C $(ROOT)frida_mode/ + +32: + CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +########## LIBXML2 ####### + +$(LIBXML2_DIR): | $(BUILD_DIR) + git clone --depth 1 $(LIBZXML2_GIT_REPO) $@ + +$(LIBXML2_LIB): | $(LIBXML2_DIR) + cd $(LIBXML2_DIR) && ./autogen.sh \ + --disable-shared \ + --without-c14n \ + --without-legacy \ + --without-push \ + --without-python \ + --without-reader \ + --without-regexps \ + --without-sax1 \ + --without-schemas \ + --without-schematron \ + --without-valid \ + --without-writer \ + --without-zlib \ + --without-lzma + cd $(LIBXML2_DIR) && make -j$(nproc) V=1 + +libxml2: $(LIBXML2_LIB) + +########## LIBZXSLT ####### + +$(LIBXSLT_DIR): | $(BUILD_DIR) + git clone --depth 1 $(LIBXSLT_GIT_REPO) $@ + +$(LIBXSLT_LIB): | $(LIBXSLT_DIR) $(LIBXML2_DIR) + cd $(LIBXSLT_DIR) && ./autogen.sh \ + --with-libxml-src=../libxml2 \ + --disable-shared \ + --without-python \ + --with-crypto \ + --without-debug \ + --without-debugger \ + --without-profiler + cd $(LIBXSLT_DIR) && make -j$(nproc) V=1 + +libxslt: $(LIBXSLT_LIB) + +$(TEST_BIN): $(LIBXSLT_LIB) $(LIBXML2_LIB) + clang \ + -o $@ \ + -fsanitize=fuzzer \ + -I $(LIBXSLT_DIR) \ + -I $(LIBXML2_DIR)include \ + $(LIBXSLT_DIR)tests/fuzz/xpath.c \ + $(LIBXSLT_DIR)tests/fuzz/fuzz.c \ + $(LIBXSLT_DIR)libxslt/.libs/libxslt.a \ + $(LIBXSLT_DIR)libexslt/.libs/libexslt.a \ + $(LIBXML2_LIB) \ + -lgcrypt + +test: $(TEST_BIN) + + +########## DUMMY ####### + +$(DUMMY_DATA_FILE): | $(TEST_DATA_DIR) + dd if=/dev/zero bs=1048576 count=1 of=$@ + +###### TEST DATA ####### + +$(TEST_DATA_DIR): | $(LIBXSLT_DIR) $(BUILD_DIR) + cp -av $(LIBXSLT_DIR)tests/fuzz/seed/* $@ + +$(XPATH_XML): | $(LIBXSLT_DIR) + cp $(LIBXSLT_DIR)tests/fuzz/xpath.xml $@ + + +clean: + rm -rf $(BUILD_DIR) + +frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE) $(XPATH_XML) + AFL_FRIDA_PERSISTENT_CNT=1000000 \ + AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -m none \ + -d \ + -O \ + -V 30 \ + -- \ + $(TEST_BIN) $(DUMMY_DATA_FILE) + +qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE) $(XPATH_XML) + AFL_QEMU_PERSISTENT_CNT=1000000 \ + AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ + AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -i $(TEST_DATA_DIR) \ + -o $(QEMU_OUT) \ + -m none \ + -d \ + -Q \ + -V 30 \ + -- \ + $(TEST_BIN) $(DUMMY_DATA_FILE) diff --git a/frida_mode/test/libxslt/Makefile b/frida_mode/test/libxslt/Makefile new file mode 100644 index 00000000..07b139e9 --- /dev/null +++ b/frida_mode/test/libxslt/Makefile @@ -0,0 +1,13 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +32: + @echo trying to use GNU make... + @gmake 32 || echo please install GNUmake + +clean: + @gmake clean + +frida: + @gmake frida diff --git a/frida_mode/test/output/testinstr.c b/frida_mode/test/output/testinstr.c index 5e26fc46..334f6518 100644 --- a/frida_mode/test/output/testinstr.c +++ b/frida_mode/test/output/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/perf/GNUmakefile b/frida_mode/test/perf/GNUmakefile index d65aaa6d..2d7c0239 100644 --- a/frida_mode/test/perf/GNUmakefile +++ b/frida_mode/test/perf/GNUmakefile @@ -14,6 +14,10 @@ FRIDA_OUT:=$(BUILD_DIR)frida-out AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so +AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat +QEMU_OUT:=$(BUILD_DIR)qemu-out +FRIDA_OUT:=$(BUILD_DIR)frida-out + ifndef ARCH ARCH=$(shell uname -m) @@ -26,20 +30,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) ifeq "$(ARCH)" "arm64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif @@ -70,10 +76,13 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ $(TEST_DATA_FILE): | $(TEST_DATA_DIR) + echo "hi" > $@ + +$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) dd if=/dev/zero bs=1048576 count=1 of=$@ -qemu: $(TEST_BIN) $(TEST_DATA_FILE) +qemu: $(TEST_BIN) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT) AFL_QEMU_PERSISTENT_CNT=1000000 \ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ @@ -86,9 +95,9 @@ qemu: $(TEST_BIN) $(TEST_DATA_FILE) -o $(QEMU_OUT) \ -V 10 \ -- \ - $(TEST_BIN) $(TEST_DATA_FILE) + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -frida: $(TEST_BIN) $(TEST_DATA_FILE) +frida: $(TEST_BIN) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT) AFL_FRIDA_PERSISTENT_CNT=1000000 \ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ @@ -98,9 +107,9 @@ frida: $(TEST_BIN) $(TEST_DATA_FILE) -O \ -i $(TEST_DATA_DIR) \ -o $(FRIDA_OUT) \ - -V 10 \ + -t 1000+ \ -- \ - $(TEST_BIN) $(TEST_DATA_FILE) + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) debug: echo $(AFL_FRIDA_PERSISTENT_ADDR) diff --git a/frida_mode/test/perf/perf.c b/frida_mode/test/perf/perf.c index c5881915..f6659b55 100644 --- a/frida_mode/test/perf/perf.c +++ b/frida_mode/test/perf/perf.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/persistent_ret/GNUmakefile b/frida_mode/test/persistent_ret/GNUmakefile index 71f6c693..71f6a124 100644 --- a/frida_mode/test/persistent_ret/GNUmakefile +++ b/frida_mode/test/persistent_ret/GNUmakefile @@ -22,27 +22,16 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh ifeq "$(shell uname)" "Darwin" TEST_BIN_LDFLAGS:=-Wl,-no_pie endif -ARCH=$(shell uname -m) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x0000aaaaaaaaa000) - AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x0000aaaaaaaaa000) -endif - -ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x0000555555554000) - AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x0000555555554000) -endif - -ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x56555000) - AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x56555000) -endif +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main $(AFL_FRIDA_BASE_ADDR)) +AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow $(AFL_FRIDA_BASE_ADDR)) ifeq "$(shell uname)" "Darwin" AFL_PRELOAD=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c index 42e3519a..d383c340 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/png/persistent/GNUmakefile b/frida_mode/test/png/persistent/GNUmakefile index c6526fee..94e2be38 100644 --- a/frida_mode/test/png/persistent/GNUmakefile +++ b/frida_mode/test/png/persistent/GNUmakefile @@ -21,20 +21,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) ifeq "$(ARCH)" "arm64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x0000aaaaaaaaa000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all 32 clean qemu qemu_entry frida frida_entry diff --git a/frida_mode/test/png/persistent/hook/GNUmakefile b/frida_mode/test/png/persistent/hook/GNUmakefile index 5010662b..b6a1ca1a 100644 --- a/frida_mode/test/png/persistent/hook/GNUmakefile +++ b/frida_mode/test/png/persistent/hook/GNUmakefile @@ -32,20 +32,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) ifeq "$(ARCH)" "arm64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(shell uname)" "Darwin" diff --git a/frida_mode/test/proj4/GNUmakefile b/frida_mode/test/proj4/GNUmakefile index 7dffab2e..debc8a88 100644 --- a/frida_mode/test/proj4/GNUmakefile +++ b/frida_mode/test/proj4/GNUmakefile @@ -46,19 +46,11 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) -endif - -ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) -endif - -ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) -endif +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) .PHONY: all clean frida hook diff --git a/frida_mode/test/proj4/get_symbol_addr.py b/frida_mode/test/proj4/get_symbol_addr.py deleted file mode 100755 index 1c46e010..00000000 --- a/frida_mode/test/proj4/get_symbol_addr.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 -import argparse -from elftools.elf.elffile import ELFFile - -def process_file(file, symbol, base): - with open(file, 'rb') as f: - elf = ELFFile(f) - symtab = elf.get_section_by_name('.symtab') - mains = symtab.get_symbol_by_name(symbol) - if len(mains) != 1: - print ("Failed to find main") - return 1 - - main_addr = mains[0]['st_value'] - main = base + main_addr - print ("0x%016x" % main) - return 0 - -def hex_value(x): - return int(x, 16) - -def main(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-f', '--file', dest='file', type=str, - help='elf file name', required=True) - parser.add_argument('-s', '--symbol', dest='symbol', type=str, - help='symbol name', required=True) - parser.add_argument('-b', '--base', dest='base', type=hex_value, - help='elf base address', required=True) - - args = parser.parse_args() - return process_file (args.file, args.symbol, args.base) - -if __name__ == "__main__": - ret = main() - exit(ret) diff --git a/frida_mode/test/re2/GNUmakefile b/frida_mode/test/re2/GNUmakefile index 67b37a89..220e7616 100644 --- a/frida_mode/test/re2/GNUmakefile +++ b/frida_mode/test/re2/GNUmakefile @@ -47,20 +47,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all clean qemu frida hook diff --git a/frida_mode/test/sqlite/GNUmakefile b/frida_mode/test/sqlite/GNUmakefile index 85f213a9..df470af8 100644 --- a/frida_mode/test/sqlite/GNUmakefile +++ b/frida_mode/test/sqlite/GNUmakefile @@ -42,20 +42,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all clean qemu frida hook sqlite diff --git a/frida_mode/test/testinstr/testinstr.c b/frida_mode/test/testinstr/testinstr.c index 5e26fc46..334f6518 100644 --- a/frida_mode/test/testinstr/testinstr.c +++ b/frida_mode/test/testinstr/testinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/unstable/GNUmakefile b/frida_mode/test/unstable/GNUmakefile index 54bbe662..ed91da40 100644 --- a/frida_mode/test/unstable/GNUmakefile +++ b/frida_mode/test/unstable/GNUmakefile @@ -22,20 +22,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(UNSTABLE_BIN) run_test 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(UNSTABLE_BIN) run_test 0x0000aaaaaaaaa000) +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(UNSTABLE_BIN) run_test 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(UNSTABLE_BIN) run_test 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all 32 clean qemu frida diff --git a/frida_mode/test/unstable/unstable.c b/frida_mode/test/unstable/unstable.c index 67d56b73..915e283f 100644 --- a/frida_mode/test/unstable/unstable.c +++ b/frida_mode/test/unstable/unstable.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/frida_mode/test/vorbis/GNUmakefile b/frida_mode/test/vorbis/GNUmakefile index 59ae9a59..9cce6c9e 100644 --- a/frida_mode/test/vorbis/GNUmakefile +++ b/frida_mode/test/vorbis/GNUmakefile @@ -36,8 +36,8 @@ endif TEST_DATA_DIR:=$(BUILD_DIR)in/ TEST_DATA_SRC:=https://github.com/google/fuzzbench/blob/master/benchmarks/vorbis-2017-12-11/seeds/sound.ogg?raw=true TEST_DATA_FILE:=$(TEST_DATA_DIR)sound.ogg -DUMMY_DATA_FILE:=$(BUILD_DIR)default_seed +AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat FRIDA_OUT:=$(BUILD_DIR)frida-out QEMU_OUT:=$(BUILD_DIR)qemu-out @@ -53,20 +53,22 @@ ifeq "$(ARCH)" "i686" endif endif +ADDR_BIN:=$(ROOT)frida_mode/build/addr GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN)) +AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR)) -ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) +ifeq "$(ARCH)" "arm64" + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000) endif ifeq "$(ARCH)" "x86_64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif ifeq "$(ARCH)" "x86" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) endif .PHONY: all clean frida hook @@ -158,18 +160,18 @@ $(TEST_BIN): $(VORBIS_LIB) $(OGG_LIB) $(HARNESS_OBJ) $(DECODE_OBJ) $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ -$(DUMMY_DATA_FILE): | $(TEST_DATA_DIR) +$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) dd if=/dev/zero bs=1048576 count=1 of=$@ ###### TEST DATA ####### -$(TEST_DATA_FILE): +$(TEST_DATA_FILE): $(TEST_DATA_DIR) wget -O $@ $(TEST_DATA_SRC) clean: rm -rf $(BUILD_DIR) -frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE) +frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT) AFL_FRIDA_PERSISTENT_CNT=1000000 \ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ @@ -182,9 +184,9 @@ frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA -O \ -V 30 \ -- \ - $(TEST_BIN) $(DUMMY_DATA_FILE) + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE) +qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT) AFL_QEMU_PERSISTENT_CNT=1000000 \ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ @@ -197,4 +199,4 @@ qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_F -Q \ -V 30 \ -- \ - $(TEST_BIN) $(DUMMY_DATA_FILE) + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) diff --git a/frida_mode/test/vorbis/get_symbol_addr.py b/frida_mode/test/vorbis/get_symbol_addr.py deleted file mode 100755 index 1c46e010..00000000 --- a/frida_mode/test/vorbis/get_symbol_addr.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python3 -import argparse -from elftools.elf.elffile import ELFFile - -def process_file(file, symbol, base): - with open(file, 'rb') as f: - elf = ELFFile(f) - symtab = elf.get_section_by_name('.symtab') - mains = symtab.get_symbol_by_name(symbol) - if len(mains) != 1: - print ("Failed to find main") - return 1 - - main_addr = mains[0]['st_value'] - main = base + main_addr - print ("0x%016x" % main) - return 0 - -def hex_value(x): - return int(x, 16) - -def main(): - parser = argparse.ArgumentParser(description='Process some integers.') - parser.add_argument('-f', '--file', dest='file', type=str, - help='elf file name', required=True) - parser.add_argument('-s', '--symbol', dest='symbol', type=str, - help='symbol name', required=True) - parser.add_argument('-b', '--base', dest='base', type=hex_value, - help='elf base address', required=True) - - args = parser.parse_args() - return process_file (args.file, args.symbol, args.base) - -if __name__ == "__main__": - ret = main() - exit(ret) diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 0473cbf6..57d7b5b5 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -78,7 +78,7 @@ class Afl { } /** - * See `AFL_FRIDA_INST_NO_BACKPATCH`. + * See `AFL_FRIDA_STALKER_NO_BACKPATCH`. */ public static setBackpatchDisable(): void { Afl.jsApiSetBackpatchDisable(); @@ -313,6 +313,13 @@ class Afl { Afl.jsApiSetTraceable(); } + /** + * See `AFL_FRIDA_VERBOSE` + */ + public static setVerbose(): void { + Afl.jsApiSetVerbose(); + } + private static readonly jsApiAddExcludeRange = Afl.jsApiGetFunction( "js_api_add_exclude_range", "void", @@ -480,6 +487,11 @@ class Afl { "void", []); + private static readonly jsApiSetVerbose = Afl.jsApiGetFunction( + "js_api_set_verbose", + "void", + []); + private static readonly jsApiWrite = new NativeFunction( /* tslint:disable-next-line:no-null-keyword */ Module.getExportByName(null, "write"), diff --git a/include/afl-as.h b/include/afl-as.h index 2a2e8ad7..bbbd5582 100644 --- a/include/afl-as.h +++ b/include/afl-as.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e59b3781..e225211f 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index 87bbb1cc..bdf0d87f 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/alloc-inl.h b/include/alloc-inl.h index 0c540330..6c2bafff 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/cmplog.h b/include/cmplog.h index 8778a4b6..c6d2957e 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/common.h b/include/common.h index 6c8e3b3a..896c5fb2 100644 --- a/include/common.h +++ b/include/common.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/config.h b/include/config.h index b787152f..99cacc40 100644 --- a/include/config.h +++ b/include/config.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2021 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/debug.h b/include/debug.h index feb7f52d..31ebd0f2 100644 --- a/include/debug.h +++ b/include/debug.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/envs.h b/include/envs.h index a3ba5e88..3bacc380 100644 --- a/include/envs.h +++ b/include/envs.h @@ -59,7 +59,6 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_JIT", - "AFL_FRIDA_INST_NO_BACKPATCH", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH", @@ -76,11 +75,13 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_PERSISTENT_DEBUG", "AFL_FRIDA_PERSISTENT_HOOK", "AFL_FRIDA_PERSISTENT_RET", - "AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS", + "AFL_FRIDA_STALKER_IC_ENTRIES", + "AFL_FRIDA_STALKER_NO_BACKPATCH", "AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE", + "AFL_FRIDA_VERBOSE", "AFL_FUZZER_ARGS", // oss-fuzz "AFL_GDB", "AFL_GCC_ALLOWLIST", @@ -94,8 +95,8 @@ static char *afl_environment_variables[] = { "AFL_FORKSRV_INIT_TMOUT", "AFL_HARDEN", "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", - "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IGNORE_PROBLEMS", + "AFL_IGNORE_UNKNOWN_ENVS", "AFL_IMPORT_FIRST", "AFL_INST_LIBS", "AFL_INST_RATIO", @@ -193,6 +194,7 @@ static char *afl_environment_variables[] = { "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", + "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT", diff --git a/include/forkserver.h b/include/forkserver.h index 464f208d..48db2e26 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co>> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -33,6 +33,42 @@ #include "types.h" +#ifdef __linux__ +/** + * Nyx related typedefs taken from libnyx.h + */ + +typedef enum NyxReturnValue { + + Normal, + Crash, + Asan, + Timout, + InvalidWriteToPayload, + Error, + IoError, + Abort, + +} NyxReturnValue; + +typedef struct { + + void *(*nyx_new)(const char *sharedir, const char *workdir, + uint32_t worker_id, uint32_t cpu_id, bool create_snapshot); + void (*nyx_shutdown)(void *qemu_process); + void (*nyx_option_set_reload_mode)(void *qemu_process, bool enable); + void (*nyx_option_set_timeout)(void *qemu_process, uint8_t timeout_sec, + uint32_t timeout_usec); + void (*nyx_option_apply)(void *qemu_process); + void (*nyx_set_afl_input)(void *qemu_process, uint8_t *buffer, uint32_t size); + enum NyxReturnValue (*nyx_exec)(void *qemu_process); + uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process); + size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process); + +} nyx_plugin_handler_t; + +#endif + typedef struct afl_forkserver { /* a program that includes afl-forkserver needs to define these */ @@ -121,6 +157,17 @@ typedef struct afl_forkserver { u8 kill_signal; +#ifdef __linux__ + nyx_plugin_handler_t *nyx_handlers; + char * out_dir_path; /* path to the output directory */ + u8 nyx_mode; /* if running in nyx mode or not */ + bool nyx_parent; /* create initial snapshot */ + bool nyx_standalone; /* don't serialize the snapshot */ + void * nyx_runner; /* nyx runner object */ + u32 nyx_id; /* nyx runner id (0 -> master) */ + u32 nyx_bind_cpu_id; /* nyx runner cpu id */ +#endif + } afl_forkserver_t; typedef enum fsrv_run_result { diff --git a/include/hash.h b/include/hash.h index 9bb34ff8..d8fef70c 100644 --- a/include/hash.h +++ b/include/hash.h @@ -15,7 +15,7 @@ Other code written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/list.h b/include/list.h index d49e56da..a6223564 100644 --- a/include/list.h +++ b/include/list.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/sharedmem.h b/include/sharedmem.h index 93080d0f..e646b73f 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h index 7234bbaa..8d2f41ff 100644 --- a/include/snapshot-inl.h +++ b/include/snapshot-inl.h @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/types.h b/include/types.h index bbcc2f81..4a68b1b0 100644 --- a/include/types.h +++ b/include/types.h @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/include/xxhash.h b/include/xxhash.h index 8cf4a345..4f101003 100644 --- a/include/xxhash.h +++ b/include/xxhash.h @@ -1,7 +1,7 @@ /* * xxHash - Extremely Fast Hash algorithm * Header File - * Copyright (C) 2012-2020 Yann Collet + * Copyright (C) 2012-2022 Yann Collet * * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) * diff --git a/instrumentation/README.cmplog.md b/instrumentation/README.cmplog.md index 668c07eb..a2caca4f 100644 --- a/instrumentation/README.cmplog.md +++ b/instrumentation/README.cmplog.md @@ -42,4 +42,4 @@ For example: afl-fuzz -i input -o output -c ./program.cmplog -m none -- ./program.afl @@ ``` -Be sure to use `-m none` because CmpLog can map a lot of pages. \ No newline at end of file +Be careful with the usage of `-m` because CmpLog can map a lot of pages. diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 20f325f3..1b9fdee3 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -3,7 +3,7 @@ ------------------------------------------------ Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -1421,11 +1421,25 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { // we have a problem as we cannot increase the coverage map anymore. if (__afl_already_initialized_forkserver) { - fprintf(stderr, - "[-] FATAL: forkserver is already up, but an instrumented dlopen() " - "library loaded afterwards. You must AFL_PRELOAD such libraries to " - "be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n"); - abort(); + if (!getenv("AFL_IGNORE_PROBLEMS")) { + + fprintf( + stderr, + "[-] FATAL: forkserver is already up, but an instrumented dlopen() " + "library loaded afterwards. You must AFL_PRELOAD such libraries to " + "be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n" + "To ignore this set AFL_IGNORE_PROBLEMS=1.\n"); + abort(); + + } else { + + while (start < stop) { + + *(start++) = 4; + + } + + } } @@ -1462,7 +1476,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (R(100) < inst_ratio) *start = ++__afl_final_loc % __afl_map_size; else - *start = 0; + *start = 4; start++; @@ -1487,7 +1501,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { if (R(100) < inst_ratio) *start = ++__afl_final_loc; else - *start = 0; + *start = 4; start++; diff --git a/instrumentation/afl-gcc-pass.so.cc b/instrumentation/afl-gcc-pass.so.cc index df2b6f2a..734fa170 100644 --- a/instrumentation/afl-gcc-pass.so.cc +++ b/instrumentation/afl-gcc-pass.so.cc @@ -2,7 +2,7 @@ Copyright 2014-2019 Free Software Foundation, Inc Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AdaCore + Copyright 2019-2022 AdaCore Written by Alexandre Oliva <oliva@adacore.com>, based on the AFL LLVM pass by Laszlo Szekeres <lszekeres@google.com> and Michal @@ -901,7 +901,7 @@ struct afl_pass : gimple_opt_pass { static struct plugin_info afl_plugin = { - .version = "20200907", + .version = "20220907", .help = G_("AFL gcc plugin\n\ \n\ Set AFL_QUIET in the environment to silence it.\n\ diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 5e7faba7..39124660 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-llvm-lto-instrumentlist.so.cc b/instrumentation/afl-llvm-lto-instrumentlist.so.cc index bac02977..35ba9c5a 100644 --- a/instrumentation/afl-llvm-lto-instrumentlist.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentlist.so.cc @@ -9,7 +9,7 @@ from afl-as.c are Michal's fault. Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index 18c0294e..899734f8 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -12,7 +12,7 @@ NGRAM previous location coverage comes from Adrian Herrera. Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-instructions-pass.cc b/instrumentation/cmplog-instructions-pass.cc index a2083a33..a0b386d5 100644 --- a/instrumentation/cmplog-instructions-pass.cc +++ b/instrumentation/cmplog-instructions-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-routines-pass.cc b/instrumentation/cmplog-routines-pass.cc index 076d2779..2af01a7a 100644 --- a/instrumentation/cmplog-routines-pass.cc +++ b/instrumentation/cmplog-routines-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/instrumentation/cmplog-switches-pass.cc b/instrumentation/cmplog-switches-pass.cc index 8501d514..068650ce 100644 --- a/instrumentation/cmplog-switches-pass.cc +++ b/instrumentation/cmplog-switches-pass.cc @@ -5,7 +5,7 @@ Written by Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/nyx_mode/LIBNYX_VERSION b/nyx_mode/LIBNYX_VERSION new file mode 100644 index 00000000..1ac5611b --- /dev/null +++ b/nyx_mode/LIBNYX_VERSION @@ -0,0 +1 @@ +ecbcb2d diff --git a/nyx_mode/PACKER_VERSION b/nyx_mode/PACKER_VERSION new file mode 100644 index 00000000..2596e40f --- /dev/null +++ b/nyx_mode/PACKER_VERSION @@ -0,0 +1 @@ +f91742c diff --git a/nyx_mode/QEMU-Nyx b/nyx_mode/QEMU-Nyx new file mode 160000 +Subproject acc90e462b45fab15bb6b28c064e9f78808cb34 diff --git a/nyx_mode/QEMU_NXY_VERSION b/nyx_mode/QEMU_NXY_VERSION new file mode 100644 index 00000000..d2f0328b --- /dev/null +++ b/nyx_mode/QEMU_NXY_VERSION @@ -0,0 +1 @@ +acc90e462b diff --git a/nyx_mode/README.md b/nyx_mode/README.md new file mode 100644 index 00000000..f975c764 --- /dev/null +++ b/nyx_mode/README.md @@ -0,0 +1,275 @@ +# Nyx Mode + +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 following 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. Optionally, for binary-only fuzzing: set up 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 +``` + +## Fuzzing with Nyx mode + +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: + +```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 +``` + +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 + +First, get the latest libxml2 source files by using `git`: + +``` +git clone https://gitlab.gnome.org/GNOME/libxml2 +cd libxml2 +``` + +Remember that currently only classic AFL instrumentation is supported! + +``` +export AFL_LLVM_INSTRUMENT=AFL +./autogen.sh +./configure --enable-shared=no +make CC=afl-clang-fast CXX=afl-clang-fast++ LD=afl-clang-fast +``` + +#### Nyx share directories + +Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Both bootstrap scripts use several tools to communicate with the "outer world": + +- `hcat` - this tool copies a given string to the host +- `hget` - this program requests a file from the host's share directory +- `hget_bulk` - an improved version of `hget`. It is quite useful if you want to transfer huge files. But please keep in mind that this version of `hget` has a much larger startup overhead and won't improve your transfer rates on small files (typically files smaller than 100MB). +- `habort` - this tool basically sends an abort signal to the host (useful if something went wrong during bootstrap) +- `hpush` - a tool to transfer a given file to the host (the transfered file will be put in the `dump/` folder of your Nyx workdir) + +Those tools are all using hypercalls which are defined in `packer/nyx.h`. We will give some more examples later on how to use these hypercalls directly to implement custom fuzzing harnesses. + +### Pack libxml2 into Nyx sharedir format + +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 nyx_mode/packer/packer +``` + + And run the tool with the following options to pack `libxml2`: + +```. +python3 ./nyx_packer.py \ + ~/libxml2/xmllint \ + /tmp/nyx_libxml2 \ + afl \ + instrumentation \ + -args "/tmp/input" \ + -file "/tmp/input" \ + --fast_reload_mode \ + --purge +``` + +In this example, the packer will take `xmllint`, recursively get all dependencies and put both into the specified share directory (`/tmp/nyx_libxml2` in this case). Because we have selected the `afl` option, an `ld_preload`-based agent is also automatically built and put into the sharedir. Another option would be `spec`. Without going into too much detail here, the `spec`mode is only used by Nyx's [spec-fuzzer](https://github.com/nyx-fuzz/spec-fuzzer) implementation. Next, since our target is built with compile-time instrumentations, we must select the `instrumentation` option, otherwise we could also use `processor-trace` option to enable Intel-PT fuzzing on targets without instrumentation. + +To specify that the input generated by the fuzzer is passed as a seperate file to the target, we need to set the `-file` option. Otherwise, the input will be passed over to the target via `stdin`. To specify any required `argv` options you can use the `-args`parameter. + +In case you want to fuzz the target only with fast snapshots enabled, you can also set the `--fast_reload_mode` option to improve performance. + +Finally, we need to generate a Nyx configuration file. Simply run the following command and you're good to proceed: + +``` +python3 ./nyx_config_gen.py /tmp/nyx_libxml2/ Kernel +``` + +### Run Nyx mode + +From here on, we are almost done. Move to the AFL++ top directory and start the fuzzer with the following arguments: + +```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: + +``` + american fuzzy lop ++3.15a {default} (/tmp/nyx_libxml2/) [fast] - NYX +┌─ process timing ────────────────────────────────────┬─ overall results ────┐ +│ run time : 0 days, 0 hrs, 0 min, 14 sec │ cycles done : 0 │ +│ last new find : 0 days, 0 hrs, 0 min, 0 sec │ corpus count : 96 │ +│last saved crash : none seen yet │saved crashes : 0 │ +│ last saved hang : none seen yet │ saved hangs : 0 │ +├─ cycle progress ─────────────────────┬─ map coverage┴──────────────────────┤ +│ now processing : 28.0 (29.2%) │ map density : 2.17% / 3.61% │ +│ runs timed out : 0 (0.00%) │ count coverage : 1.67 bits/tuple │ +├─ stage progress ─────────────────────┼─ findings in depth ─────────────────┤ +│ now trying : havoc │ favored items : 27 (28.12%) │ +│ stage execs : 22.3k/32.8k (68.19%) │ new edges on : 58 (60.42%) │ +│ total execs : 55.9k │ total crashes : 0 (0 saved) │ +│ exec speed : 3810/sec │ total tmouts : 0 (0 saved) │ +├─ fuzzing strategy yields ────────────┴─────────────┬─ item geometry ───────┤ +│ bit flips : disabled (default, enable with -D) │ levels : 3 │ +│ byte flips : disabled (default, enable with -D) │ pending : 95 │ +│ arithmetics : disabled (default, enable with -D) │ pend fav : 27 │ +│ known ints : disabled (default, enable with -D) │ own finds : 95 │ +│ dictionary : n/a │ imported : 0 │ +│havoc/splice : 57/32.8k, 0/0 │ stability : 100.00% │ +│py/custom/rq : unused, unused, unused, unused ├───────────────────────┘ +│ trim/eff : n/a, disabled │ [cpu000: 25%] +└────────────────────────────────────────────────────┘ +``` + +If you want to run the fuzzer in distributed mode, which might be especially useful if you want to keep your memory footprint low, we got you covered. To start an initiating `parent` process, which will also create the snapshot which is later shared across all other `child`s, simply run AFL++Nyx with the following arguments: + +``` +./afl-fuzz -i /tmp/in/ -o /tmp/out -d -Y -M 0 /tmp/nyx_libxml2/ +``` + +To attach other child processes adjust the `-S <id>` and run the following command: + +``` +./afl-fuzz -i /tmp/in/ -o /tmp/out -d -Y -S 1 /tmp/nyx_libxml2/ +``` + +If you want to disable fast snapshots (except for crashes), you can simply set the `NYX_DISABLE_SNAPSHOT_MODE` environment variable. + +### Run AFL++Nyx with a custom agent + +Most of the common use-cases for linux userland targets are already handled by our general purpose [agent](https://github.com/nyx-fuzz/packer/blob/main/packer/linux_x86_64-userspace/src/ld_preload_fuzz.c) implementation. But in case you want to build your own agent, or write a custom harness for a specific target or you just want to implement all the hypercall and shared memory communication on your own, you can use our custom harness example as a starting point for that. You can find the code [here](custom_harness/) + +This custom harness can be statically compiled with by gcc or clang. There is no need to use an AFL compiler, because this agent implements its own very basic coverage tracking by simply setting specific bytes in the "coverage" bitmap after specific branches have been covered. + +To prepare this target, we must first create a new folder that will later become the sharedir. + +```` +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 ./packer/ -o /tmp/nyx_custom_agent/target +``` + +Copy both bootstrap scripts into the sharedir: + +``` +cp fuzz.sh /tmp/nyx_custom_agent +cp fuzz_no_pt.sh /tmp/nyx_custom_agent +``` + +Copy all `htools` executables into the sharedir: + +``` +cd ~/AFLplusplus/packer/packer/linux_x86_64-userspace/ +sh compile_64.sh +cp bin64/h* /tmp/nyx_custom_agent/ +``` + +And finally, generate a Nyx configuration: + +``` +cd ~/AFLplusplus/packer/packer +python3 ./nyx_config_gen.py /tmp/nyx_custom_agent/ Kernel +``` diff --git a/nyx_mode/build_nyx_support.sh b/nyx_mode/build_nyx_support.sh new file mode 100755 index 00000000..8626342d --- /dev/null +++ b/nyx_mode/build_nyx_support.sh @@ -0,0 +1,69 @@ +#!/bin/bash +set -e + +echo "=================================================" +echo " Nyx build script" +echo "=================================================" +echo + +echo "[*] Performing basic sanity checks..." + +if [ ! "`uname -s`" = "Linux" ]; then + + echo "[-] Error: Nyx mode is only available on Linux." + exit 0 + +fi + +echo "[*] Making sure all Nyx is checked out" + +git status 1>/dev/null 2>/dev/null +if [ $? -eq 0 ]; then + git submodule init || exit 1 + echo "[*] initializing QEMU-Nyx submodule" + git submodule update ./QEMU-Nyx 2>/dev/null # ignore errors + echo "[*] initializing packer submodule" + git submodule update ./packer 2>/dev/null # ignore errors + echo "[*] initializing libnyx submodule" + git submodule update ./libnyx 2>/dev/null # ignore errors + +else + echo "[ ] not a git repo..." + exit 1 +fi + +test -d QEMU-Nyx || { echo "[-] Not checked out, please install git or check your internet connection." ; exit 1 ; } +test -d packer || { echo "[-] Not checked out, please install git or check your internet connection." ; exit 1 ; } +test -d libnyx || { echo "[-] Not checked out, please install git or check your internet connection." ; exit 1 ; } + +echo "[*] checking packer init.cpio.gz ..." +if [ ! -f "packer/linux_initramfs/init.cpio.gz" ]; then + cd packer/linux_initramfs/ + sh pack.sh || exit 1 + cd ../../ +fi + +echo "[*] Checking libnyx ..." +if [ ! -f "libnyx/libnyx/target/release/liblibnyx.a" ]; then + cd libnyx/libnyx + cargo build --release || exit 1 + cd ../../ +fi + +echo "[*] Checking QEMU-Nyx ..." +if [ ! -f "QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64" ]; then + cd QEMU-Nyx/ + ./compile_qemu_nyx.sh || exit 1 + cd .. +fi + +echo "[*] Checking libnyx.so ..." +if [ -f "libnyx/libnyx/target/release/liblibnyx.so" ]; then + cp -v libnyx/libnyx/target/release/liblibnyx.so ../libnyx.so || exit 1 +else + echo "[ ] libnyx.so not found..." + exit 1 +fi +echo "[+] All done for nyx_mode, enjoy!" + +exit 0 diff --git a/nyx_mode/custom_harness/example.c b/nyx_mode/custom_harness/example.c new file mode 100644 index 00000000..0b12e60b --- /dev/null +++ b/nyx_mode/custom_harness/example.c @@ -0,0 +1,91 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdbool.h> +#include <inttypes.h> +#include "nyx.h" + +/* this is our "bitmap" that is later shared with the fuzzer (you can also pass the pointer of the bitmap used by compile-time instrumentations in your target) */ +uint8_t* trace_buffer[64*1024] = {0}; + +int main(int argc, char** argv){ + /* if you want to debug code running in Nyx, hprintf() is the way to go. + * Long story short -- it's just a guest-to-hypervisor printf. Hence the name "hprintf" + */ + hprintf("Agent test\n"); + + /* Request information on available (host) capabilites (optional) */ + host_config_t host_config; + kAFL_hypercall(HYPERCALL_KAFL_GET_HOST_CONFIG, (uintptr_t)&host_config); + hprintf("[capablities] host_config.bitmap_size: 0x%"PRIx64"\n", host_config.bitmap_size); + hprintf("[capablities] host_config.ijon_bitmap_size: 0x%"PRIx64"\n", host_config.ijon_bitmap_size); + hprintf("[capablities] host_config.payload_buffer_size: 0x%"PRIx64"x\n", host_config.payload_buffer_size); + + /* Submit agent configuration */ + memset(trace_buffer, 0, 64*1024); // makes sure that the bitmap buffer is already mapped into the guest's memory (alternatively you can use mlock) */ + agent_config_t agent_config = {0}; + agent_config.agent_timeout_detection = 0; /* timeout detection is implemented by the agent (currently not used) */ + agent_config.agent_tracing = 1; /* set this flag to propagade that instrumentation-based fuzzing is availabe */ + agent_config.agent_ijon_tracing = 0; /* set this flag to propagade that IJON extension is implmented agent-wise */ + agent_config.trace_buffer_vaddr = (uintptr_t)trace_buffer; /* trace "bitmap" pointer - required for instrumentation-only fuzzing */ + agent_config.ijon_trace_buffer_vaddr = (uintptr_t)NULL; /* "IJON" buffer pointer */ + agent_config.agent_non_reload_mode = 1; /* non-reload mode is supported (usually because the agent implements a fork-server; currently not used) */ + kAFL_hypercall(HYPERCALL_KAFL_SET_AGENT_CONFIG, (uintptr_t)&agent_config); + + /* Tell hypervisor the virtual address of the payload (input) buffer (call mlock to ensure that this buffer stays in the guest's memory)*/ + kAFL_payload* payload_buffer = mmap((void*)0x4000000ULL, PAYLOAD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + mlock(payload_buffer, (size_t)PAYLOAD_SIZE); + memset(payload_buffer, 0, PAYLOAD_SIZE); + kAFL_hypercall(HYPERCALL_KAFL_GET_PAYLOAD, (uintptr_t)payload_buffer); + hprintf("[init] payload buffer is mapped at %p\n", payload_buffer); + + /* the main fuzzing loop */ + while(1){ + + /* Creates a root snapshot on first execution. Also we requested the next input with this hypercall */ + kAFL_hypercall(HYPERCALL_KAFL_USER_FAST_ACQUIRE, 0); // root snapshot <-- + +#ifdef DEBUG + hprintf("Size: %ld Data: %x %x %x %x\n", payload_buffer->size, + payload_buffer->data[4], + payload_buffer->data[5], + payload_buffer->data[6], + payload_buffer->data[7] + ); +#endif + + uint32_t len = payload_buffer->size; + + /* set a byte to make AFL++ happy (otherwise the fuzzer might refuse to start fuzzing at all) */ + ((uint8_t*)trace_buffer)[0] = 0x1; + + if (len >= 4){ + /* set a byte in the bitmap to guide your fuzzer */ + ((uint8_t*)trace_buffer)[0] = 0x1; + if (payload_buffer->data[0] == '!'){ + ((uint8_t*)trace_buffer)[1] = 0x1; + if (payload_buffer->data[1] == 'N'){ + ((uint8_t*)trace_buffer)[2] = 0x1; + if (payload_buffer->data[2] == 'Y'){ + ((uint8_t*)trace_buffer)[3] = 0x1; + if (payload_buffer->data[3] == 'X'){ + ((uint8_t*)trace_buffer)[4] = 0x1; + /* Notifiy the hypervisor and the fuzzer that a "crash" has occured. Also a string is passed by this hypercall (this is currently not supported by AFL++-Nyx) */ + kAFL_hypercall(HYPERCALL_KAFL_PANIC_EXTENDED, (uintptr_t)"Something went wrong\n"); + } + } + } + } + } + /* this hypercall is used to notify the hypervisor and the fuzzer that a single fuzzing "execution" has finished. + * If the reload-mode is enabled, we will jump back to our root snapshot. + * Otherwise, the hypervisor passes control back to the guest once the bitmap buffer has been "processed" by the fuzzer. + */ + kAFL_hypercall(HYPERCALL_KAFL_RELEASE, 0); + + /* This shouldn't happen if you have enabled the reload mode */ + hprintf("This should never happen :)\n"); + } + + + return 0; +} diff --git a/nyx_mode/custom_harness/fuzz.sh b/nyx_mode/custom_harness/fuzz.sh new file mode 100644 index 00000000..98138f70 --- /dev/null +++ b/nyx_mode/custom_harness/fuzz.sh @@ -0,0 +1,13 @@ +chmod +x hget +cp hget /tmp/ +cd /tmp/ +echo 0 > /proc/sys/kernel/randomize_va_space +echo 0 > /proc/sys/kernel/printk +./hget hcat hcat +./hget habort habort +./hget target target +chmod +x hcat +chmod +x habort +chmod +x target +./target +./habort "Target has terminated without initializing the fuzzing agent ..." diff --git a/nyx_mode/custom_harness/fuzz_no_pt.sh b/nyx_mode/custom_harness/fuzz_no_pt.sh new file mode 100644 index 00000000..b65a6493 --- /dev/null +++ b/nyx_mode/custom_harness/fuzz_no_pt.sh @@ -0,0 +1,13 @@ +chmod +x hget +cp hget /tmp/ +cd /tmp/ +echo 0 > /proc/sys/kernel/randomize_va_space +echo 0 > /proc/sys/kernel/printk +./hget hcat_no_pt hcat +./hget habort_no_pt habort +./hget target target +chmod +x hcat +chmod +x habort +chmod +x target +./target +./habort "Target has terminated without initializing the fuzzing agent ..." diff --git a/nyx_mode/libnyx b/nyx_mode/libnyx new file mode 160000 +Subproject ecbcb2d7234fef0b5e1db8ca6019e6137ee0582 diff --git a/nyx_mode/packer b/nyx_mode/packer new file mode 160000 +Subproject f91742ce6c51eee133b5675edd68f39202785db diff --git a/nyx_mode/update_ref.sh b/nyx_mode/update_ref.sh new file mode 100755 index 00000000..3e94a42b --- /dev/null +++ b/nyx_mode/update_ref.sh @@ -0,0 +1,99 @@ +#/bin/sh + +################################################## +# AFL++ internal tool to update nyx references. +# Usage: ./update_ref.sh +# It will take HEAD of all the repos! +################################################## + +if [ "$NEW_VERSION" = "-h" ]; then + echo "Internal script to update bound qemuafl version." + echo + echo "Usage: ./update_ref.sh" + echo "t will take HEAD of all the repos!" + echo "-h to show this help screen." + exit 1 +fi + +git submodule init && git submodule update || exit 1 + +UC_VERSION_FILE='./LIBNYX_VERSION' +NEW_VERSION="" + +cd ./libnyx || exit 1 +git fetch origin main 1>/dev/null || exit 1 +git stash 1>/dev/null 2>/dev/null +git stash drop 1>/dev/null 2>/dev/null +git checkout main +git pull origin main 1>/dev/null || exit 1 + +NEW_VERSION=$(git rev-parse --short HEAD) + +if [ -z "$NEW_VERSION" ]; then + echo "Error getting version." + exit 1 +fi + +git checkout "$NEW_VERSION" || exit 1 + +cd .. + +rm "$UC_VERSION_FILE" +echo "$NEW_VERSION" > "$UC_VERSION_FILE" + +echo "Done. New XXX version is $NEW_VERSION." + + +UC_VERSION_FILE='./PACKER_VERSION' +NEW_VERSION="" + +cd ./packer || exit 1 +git fetch origin main 1>/dev/null || exit 1 +git stash 1>/dev/null 2>/dev/null +git stash drop 1>/dev/null 2>/dev/null +git checkout main +git pull origin main 1>/dev/null || exit 1 + +NEW_VERSION=$(git rev-parse --short HEAD) + +if [ -z "$NEW_VERSION" ]; then + echo "Error getting version." + exit 1 +fi + +git checkout "$NEW_VERSION" || exit 1 + +cd .. + +rm "$UC_VERSION_FILE" +echo "$NEW_VERSION" > "$UC_VERSION_FILE" + +echo "Done. New XXX version is $NEW_VERSION." + + +UC_VERSION_FILE='./QEMU_NXY_VERSION' +NEW_VERSION="" + +cd ./QEMU-Nyx || exit 1 +git fetch origin qemu-nyx-4.2.0 1>/dev/null || exit 1 +git stash 1>/dev/null 2>/dev/null +git stash drop 1>/dev/null 2>/dev/null +git checkout qemu-nyx-4.2.0 +git pull origin qemu-nyx-4.2.0 1>/dev/null || exit 1 + +NEW_VERSION=$(git rev-parse --short HEAD) + +if [ -z "$NEW_VERSION" ]; then + echo "Error getting version." + exit 1 +fi + +git checkout "$NEW_VERSION" || exit 1 + +cd .. + +rm "$UC_VERSION_FILE" +echo "$NEW_VERSION" > "$UC_VERSION_FILE" + +echo "Done. New XXX version is $NEW_VERSION." + diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 71453a71..86ebb4d4 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -13,7 +13,7 @@ # counters by Andrea Fioraldi <andreafioraldi@gmail.com> # # Copyright 2015, 2016, 2017 Google Inc. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index eba3d80a..309bf5f3 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -5,7 +5,7 @@ Written and maintained by Andrea Fioraldi <andreafioraldi@gmail.com> - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 86278c31..fc868603 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-as.c b/src/afl-as.c index b644b82a..1edc8cca 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-cc.c b/src/afl-cc.c index 442cf265..49000877 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -5,7 +5,7 @@ Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse Copyright 2015, 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -556,7 +556,16 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && !have_c) { u8 *ld_path = NULL; - if (getenv("AFL_REAL_LD")) { ld_path = strdup(getenv("AFL_REAL_LD")); } + if (getenv("AFL_REAL_LD")) { + + ld_path = strdup(getenv("AFL_REAL_LD")); + + } else { + + ld_path = strdup(AFL_REAL_LD); + + } + if (!ld_path || !*ld_path) { ld_path = strdup("ld.lld"); } if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); } #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12 @@ -720,10 +729,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (!strcmp(cur, "-z")) { + if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) { u8 *param = *(argv + 1); - if (!strcmp(param, "defs")) { + if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) { skip_next = 1; continue; @@ -867,7 +876,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-fsanitize=leak"; cc_params[cc_par_cnt++] = "-includesanitizer/lsan_interface.h"; - cc_params[cc_par_cnt++] = "-D__AFL_LEAK_CHECK()=__lsan_do_leak_check()"; + cc_params[cc_par_cnt++] = "-D__AFL_LEAK_CHECK()={if(__lsan_do_recoverable_leak_check() > 0) _exit(23); }"; + cc_params[cc_par_cnt++] = "-D__AFL_LSAN_OFF()=__lsan_disable();"; + cc_params[cc_par_cnt++] = "-D__AFL_LSAN_ON()=__lsan_enable();"; + } diff --git a/src/afl-common.c b/src/afl-common.c index 6c2d0753..7ba3bb74 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -38,13 +38,10 @@ #include "common.h" /* Detect @@ in args. */ -#ifndef __glibc__ - #include <unistd.h> -#endif +#include <unistd.h> #include <limits.h> #include <sys/types.h> #include <sys/stat.h> -#include <unistd.h> #include <fcntl.h> u8 be_quiet = 0; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index b871ea8c..eebbb7c8 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -13,7 +13,7 @@ Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -71,6 +71,17 @@ static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { void afl_fsrv_init(afl_forkserver_t *fsrv) { +#ifdef __linux__ + fsrv->nyx_handlers = NULL; + fsrv->out_dir_path = NULL; + fsrv->nyx_mode = 0; + fsrv->nyx_parent = false; + fsrv->nyx_standalone = false; + fsrv->nyx_runner = NULL; + fsrv->nyx_id = 0xFFFFFFFF; + fsrv->nyx_bind_cpu_id = 0xFFFFFFFF; +#endif + // this structure needs default so we initialize it if this was not done // already fsrv->out_fd = -1; @@ -375,6 +386,82 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, s32 rlen; char *ignore_autodict = getenv("AFL_NO_AUTODICT"); +#ifdef __linux__ + if (unlikely(fsrv->nyx_mode)) { + + if (fsrv->nyx_runner != NULL) { return; } + + if (!be_quiet) { ACTF("Spinning up the NYX backend..."); } + + if (fsrv->out_dir_path == NULL) { FATAL("Nyx workdir path not found..."); } + + char *x = alloc_printf("%s/workdir", fsrv->out_dir_path); + + if (fsrv->nyx_id == 0xFFFFFFFF) { FATAL("Nyx ID is not set..."); } + + if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) { + + FATAL("Nyx CPU ID is not set..."); + + } + + if (fsrv->nyx_parent) { + + fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new( + fsrv->target_path, x, fsrv->nyx_id, fsrv->nyx_bind_cpu_id, + !fsrv->nyx_standalone); + + } else { + + fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new( + fsrv->target_path, x, fsrv->nyx_id, fsrv->nyx_bind_cpu_id, true); + + } + + if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); } + + u32 tmp_map_size = + fsrv->nyx_handlers->nyx_get_bitmap_buffer_size(fsrv->nyx_runner); + fsrv->real_map_size = fsrv->map_size; + fsrv->map_size = (((tmp_map_size + 63) >> 6) << 6); + if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); } + + fsrv->trace_bits = + fsrv->nyx_handlers->nyx_get_bitmap_buffer(fsrv->nyx_runner); + + fsrv->nyx_handlers->nyx_option_set_reload_mode( + fsrv->nyx_runner, getenv("NYX_DISABLE_SNAPSHOT_MODE") == NULL); + fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); + + fsrv->nyx_handlers->nyx_option_set_timeout(fsrv->nyx_runner, 2, 0); + fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); + + /* dry run */ + fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, "INIT", 4); + switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) { + + case Abort: + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + FATAL("Error: Nyx abort occured..."); + break; + case IoError: + FATAL("Error: QEMU-Nyx has died..."); + break; + case Error: + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + FATAL("Error: Nyx runtime error has occured..."); + break; + default: + break; + + } + + return; + + } + +#endif + if (!be_quiet) { ACTF("Spinning up the fork server..."); } #ifdef AFL_PERSISTENT_RECORD @@ -1085,6 +1172,10 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) { fsrv->fsrv_pid = -1; fsrv->child_pid = -1; +#ifdef __linux__ + if (fsrv->nyx_mode) { fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); } +#endif + } /* Get the map size from the target forkserver */ @@ -1101,6 +1192,16 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { +#ifdef __linux__ + if (unlikely(fsrv->nyx_mode)) { + + fsrv->nyx_handlers->nyx_set_afl_input(fsrv->nyx_runner, buf, len); + return; + + } + +#endif + #ifdef AFL_PERSISTENT_RECORD if (unlikely(fsrv->persistent_record)) { @@ -1214,13 +1315,80 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, u32 exec_ms; u32 write_value = fsrv->last_run_timed_out; +#ifdef __linux__ + if (fsrv->nyx_mode) { + + static uint32_t last_timeout_value = 0; + + if (last_timeout_value != timeout) { + + fsrv->nyx_handlers->nyx_option_set_timeout( + fsrv->nyx_runner, timeout / 1000, (timeout % 1000) * 1000); + fsrv->nyx_handlers->nyx_option_apply(fsrv->nyx_runner); + last_timeout_value = timeout; + + } + + enum NyxReturnValue ret_val = + fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner); + + fsrv->total_execs++; + + switch (ret_val) { + + case Normal: + return FSRV_RUN_OK; + case Crash: + case Asan: + return FSRV_RUN_CRASH; + case Timout: + return FSRV_RUN_TMOUT; + case InvalidWriteToPayload: + /* ??? */ + FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing"); + break; + case Abort: + fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner); + FATAL("Error: Nyx abort occured..."); + case IoError: + if (*stop_soon_p) { + + return 0; + + } else { + + FATAL("Error: QEMU-Nyx has died..."); + + } + + break; + case Error: + FATAL("Error: Nyx runtime error has occured..."); + break; + + } + + return FSRV_RUN_OK; + + } + +#endif /* After this memset, fsrv->trace_bits[] are effectively volatile, so we must prevent any earlier operations from venturing into that territory. */ - memset(fsrv->trace_bits, 0, fsrv->map_size); +#ifdef __linux__ + if (!fsrv->nyx_mode) { + + memset(fsrv->trace_bits, 0, fsrv->map_size); + MEM_BARRIER(); + + } +#else + memset(fsrv->trace_bits, 0, fsrv->map_size); MEM_BARRIER(); +#endif /* we have the fork server (or faux server) up and running First, tell it if the previous run timed out. */ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 7a236005..8d044959 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 28a3ae3f..ce8f1a83 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -11,7 +11,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 0f0fe331..535ffdc3 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index e4b83fa5..5449460e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -393,15 +393,14 @@ void bind_to_free_cpu(afl_state_t *afl) { "For this platform we do not have free CPU binding code yet. If possible, please supply a PR to https://github.com/AFLplusplus/AFLplusplus" #endif - size_t cpu_start = 0; + #if !defined(__aarch64__) && !defined(__arm__) && !defined(__arm64__) - #if !defined(__ANDROID__) - - for (i = cpu_start; i < afl->cpu_core_count; i++) { + for (i = 0; i < afl->cpu_core_count; i++) { #else - /* for some reason Android goes backwards */ + /* many ARM devices have performance and efficiency cores, the slower + efficiency cores seem to always come first */ for (i = afl->cpu_core_count - 1; i > -1; i--) { @@ -413,13 +412,15 @@ void bind_to_free_cpu(afl_state_t *afl) { if (bind_cpu(afl, i)) { + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = i; } + #endif /* Success :) */ break; } WARNF("setaffinity failed to CPU %d, trying next CPU", i); - cpu_start++; } @@ -1092,6 +1093,14 @@ void perform_dry_run(afl_state_t *afl) { FATAL("Unable to execute target application ('%s')", afl->argv[0]); case FSRV_RUN_NOINST: +#ifdef __linux__ + if (afl->fsrv.nyx_mode && afl->fsrv.nyx_runner != NULL) { + + afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner); + + } + +#endif FATAL("No instrumentation detected"); case FSRV_RUN_NOBITS: @@ -2445,6 +2454,9 @@ void fix_up_sync(afl_state_t *afl) { x = alloc_printf("%s/%s", afl->out_dir, afl->sync_id); +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { afl->fsrv.out_dir_path = afl->out_dir; } +#endif afl->sync_dir = afl->out_dir; afl->out_dir = x; @@ -2582,6 +2594,28 @@ void check_binary(afl_state_t *afl, u8 *fname) { if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { afl->fsrv.target_path = ck_strdup(fname); +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + /* check if target_path is a nyx sharedir */ + if (stat(afl->fsrv.target_path, &st) || S_ISDIR(st.st_mode)) { + + char *tmp = alloc_printf("%s/config.ron", afl->fsrv.target_path); + if (stat(tmp, &st) || S_ISREG(st.st_mode)) { + + free(tmp); + return; + + } + + } + + FATAL("Directory '%s' not found or is not a nyx share directory", + afl->fsrv.target_path); + + } + +#endif if (stat(afl->fsrv.target_path, &st) || !S_ISREG(st.st_mode) || !(st.st_mode & 0111) || (f_len = st.st_size) < 4) { @@ -2721,6 +2755,9 @@ void check_binary(afl_state_t *afl, u8 *fname) { #endif /* ^!__APPLE__ */ if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode && +#ifdef __linux__ + !afl->fsrv.nyx_mode && +#endif !afl->fsrv.cs_mode && !afl->non_instrumented_mode && !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index e0dfd6b0..51a43dbd 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 426a6507..26a01948 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -2002,7 +2002,7 @@ havoc_stage: /* We essentially just do several thousand runs (depending on perf_score) where we take the input file and make random stacked tweaks. */ -#define MAX_HAVOC_ENTRY 59 /* 55 to 60 */ +#define MAX_HAVOC_ENTRY 64 #define MUTATE_ASCII_DICT 64 u32 r_max, r; @@ -2506,12 +2506,101 @@ havoc_stage: } - // increase from 4 up to 8? - case 52 ... MAX_HAVOC_ENTRY: { + case 52: { - /* Delete bytes. We're making this a bit more likely - than insertion (the next option) in hopes of keeping - files reasonably small. */ + /* Increase byte by 1. */ + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " ADDBYTE_"); + strcat(afl->mutation, afl->m_tmp); +#endif + out_buf[rand_below(afl, temp_len)]++; + break; + + } + + case 53: { + + /* Decrease byte by 1. */ + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SUBBYTE_"); + strcat(afl->mutation, afl->m_tmp); +#endif + out_buf[rand_below(afl, temp_len)]++; + break; + + } + + case 54: { + + /* Flip byte. */ + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " FLIP8_"); + strcat(afl->mutation, afl->m_tmp); +#endif + out_buf[rand_below(afl, temp_len)] ^= 0xff; + break; + + } + + case 55 ... 56: { + + if (temp_len < 4) { break; } + + /* Switch bytes. */ + + u32 to_end, switch_to, switch_len, switch_from; + switch_from = rand_below(afl, temp_len); + do { + + switch_to = rand_below(afl, temp_len); + + } while (switch_from == switch_to); + + if (switch_from < switch_to) { + + switch_len = switch_to - switch_from; + to_end = temp_len - switch_to; + + } else { + + switch_len = switch_from - switch_to; + to_end = temp_len - switch_from; + + } + + switch_len = choose_block_len(afl, MIN(switch_len, to_end)); + +#ifdef INTROSPECTION + snprintf(afl->m_tmp, sizeof(afl->m_tmp), " SWITCH-%s-%u-%u-%u", + "switch", switch_from, switch_to, switch_len); + strcat(afl->mutation, afl->m_tmp); +#endif + u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), switch_len); + if (unlikely(!new_buf)) { PFATAL("alloc"); } + + /* Backup */ + + memcpy(new_buf, out_buf + switch_from, switch_len); + + /* Switch 1 */ + + memcpy(out_buf + switch_from, out_buf + switch_to, switch_len); + + /* Switch 2 */ + + memcpy(out_buf + switch_to, new_buf, switch_len); + + break; + + } + + // MAX_HAVOC_ENTRY = 64 + case 57 ... MAX_HAVOC_ENTRY: { + + /* Delete bytes. */ if (temp_len < 2) { break; } diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 6484768b..65501c8c 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 2d76e4d2..9ca89944 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index e363dffd..1e4b1b3c 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -11,7 +11,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index d730876a..eaa82b19 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -10,7 +10,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 737a49a7..69ffa8cf 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 289f7e09..1170bdb8 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -679,11 +679,29 @@ void show_stats(afl_state_t *afl) { banner_pad = (79 - banner_len) / 2; memset(banner, ' ', banner_pad); - sprintf(banner + banner_pad, - "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "peruvian were-rabbit" - : cYEL "american fuzzy lop", - si, afl->use_banner, afl->power_name); +#ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + sprintf(banner + banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx", + afl->crash_mode ? cPIN "peruvian were-rabbit" + : cYEL "american fuzzy lop", + si, afl->use_banner, afl->power_name); + + } else { + +#endif + sprintf(banner + banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN "peruvian were-rabbit" + : cYEL "american fuzzy lop", + si, afl->use_banner, afl->power_name); + +#ifdef __linux__ + + } + +#endif } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index f59bb47c..1030dfdf 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ #ifdef __APPLE__ #include <sys/qos.h> + #include <pthread/qos.h> #endif #ifdef PROFILING @@ -104,7 +105,7 @@ static void usage(u8 *argv0, int more_help) { " -p schedule - power schedules compute a seed's performance score:\n" " fast(default), explore, exploit, seek, rare, mmopt, " "coe, lin\n" - " quad -- see docs/power_schedules.md\n" + " quad -- see docs/FAQ.md for more information\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" " -t msec - timeout for each run (auto-scaled, default %u ms). " @@ -123,6 +124,10 @@ static void usage(u8 *argv0, int more_help) { " -W - use qemu-based instrumentation with Wine (Wine " "mode)\n" #endif +#if defined(__linux__) + " -X - use VM fuzzing (NYX mode - standalone mode)\n" + " -Y - use VM fuzzing (NYX mode - multiple instances mode)\n" +#endif "\n" "Mutator settings:\n" @@ -384,6 +389,60 @@ static void fasan_check_afl_preload(char *afl_preload) { } + #ifdef __linux__ + #include <dlfcn.h> + +nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) { + + void * handle; + nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t)); + + ACTF("Trying to load libnyx.so plugin..."); + handle = dlopen((char *)libnyx_binary, RTLD_NOW); + if (!handle) { goto fail; } + + plugin->nyx_new = dlsym(handle, "nyx_new"); + if (plugin->nyx_new == NULL) { goto fail; } + + plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown"); + if (plugin->nyx_shutdown == NULL) { goto fail; } + + plugin->nyx_option_set_reload_mode = + dlsym(handle, "nyx_option_set_reload_mode"); + if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; } + + plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout"); + if (plugin->nyx_option_set_timeout == NULL) { goto fail; } + + plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply"); + if (plugin->nyx_option_apply == NULL) { goto fail; } + + plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input"); + if (plugin->nyx_set_afl_input == NULL) { goto fail; } + + plugin->nyx_exec = dlsym(handle, "nyx_exec"); + if (plugin->nyx_exec == NULL) { goto fail; } + + plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer"); + if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; } + + plugin->nyx_get_bitmap_buffer_size = + dlsym(handle, "nyx_get_bitmap_buffer_size"); + if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; } + + OKF("libnyx plugin is ready!"); + return plugin; + +fail: + + FATAL("failed to load libnyx: %s\n", dlerror()); + free(plugin); + return NULL; + +} + + #endif + /* Main entry point */ int main(int argc, char **argv_orig, char **envp) { @@ -440,7 +499,7 @@ int main(int argc, char **argv_orig, char **envp) { while ((opt = getopt( argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > + "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOXYo:p:RQs:S:t:T:UV:Wx:Z")) > 0) { switch (opt) { @@ -844,6 +903,29 @@ int main(int argc, char **argv_orig, char **envp) { afl->use_banner = optarg; break; + #ifdef __linux__ + case 'X': /* NYX mode */ + + if (afl->fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); } + + afl->fsrv.nyx_parent = true; + afl->fsrv.nyx_standalone = true; + afl->fsrv.nyx_mode = 1; + afl->fsrv.nyx_id = 0; + + break; + + case 'Y': /* NYX distributed mode */ + if (afl->fsrv.nyx_mode) { FATAL("Multiple -Y options not supported"); } + afl->fsrv.nyx_mode = 1; + + break; + #else + case 'X': + case 'Y': + FATAL("Nyx mode is only availabe on linux..."); + break; + #endif case 'A': /* CoreSight mode */ #if !defined(__aarch64__) || !defined(__linux__) @@ -1184,6 +1266,16 @@ int main(int argc, char **argv_orig, char **envp) { OKF("NOTE: This is v3.x which changes defaults and behaviours - see " "README.md"); + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + OKF("afl++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)"); + OKF("Nyx is open source, get it at " + "https://github.com/Nyx-Fuzz"); + + } + + #endif if (afl->sync_id && afl->is_main_node && afl->afl_env.afl_custom_mutator_only) { @@ -1226,6 +1318,56 @@ int main(int argc, char **argv_orig, char **envp) { } + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + if (afl->fsrv.nyx_standalone && + strncmp(afl->sync_id, "default", strlen("default")) != 0) { + + FATAL( + "distributed fuzzing is not supported in this Nyx mode (use -Y " + "instead)"); + + } + + if (!afl->fsrv.nyx_standalone) { + + if (afl->is_main_node) { + + if (strncmp("0", afl->sync_id, strlen("0") != 0)) { + + FATAL( + "for Nyx -Y mode, the Main (-M) parameter has to be set to 0 (-M " + "0)"); + + } + + afl->fsrv.nyx_id = 0; + + } + + if (afl->is_secondary_node) { + + long nyx_id = strtol(afl->sync_id, NULL, 10); + + if (nyx_id == 0 || nyx_id == LONG_MAX) { + + FATAL( + "for Nyx -Y mode, the Secondary (-S) parameter has to be a " + "numeric value and >= 1 (e.g. -S 1)"); + + } + + afl->fsrv.nyx_id = nyx_id; + + } + + } + + } + + #endif + if (afl->sync_id) { if (strlen(afl->sync_id) > 24) { @@ -1449,8 +1591,28 @@ int main(int argc, char **argv_orig, char **envp) { afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver; + #ifdef __linux__ + if (!afl->fsrv.nyx_mode) { + + check_crash_handling(); + check_cpu_governor(afl); + + } else { + + u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so"); + afl->fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary); + if (afl->fsrv.nyx_handlers == NULL) { + + FATAL("failed to initialize libnyx.so..."); + + } + + } + + #else check_crash_handling(); check_cpu_governor(afl); + #endif if (getenv("LD_PRELOAD")) { @@ -1934,6 +2096,14 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->pending_not_fuzzed || !valid_seeds) { + #ifdef __linux__ + if (afl->fsrv.nyx_mode) { + + afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner); + + } + + #endif FATAL("We need at least one valid input seed that does not crash!"); } diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index f8466680..539206ce 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c index 1dcdb176..9b58125f 100644 --- a/src/afl-ld-lto.c +++ b/src/afl-ld-lto.c @@ -9,7 +9,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Dominik Maier <domenukk@gmail.com> - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index c1d4ff03..8d58bb3e 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -11,7 +11,7 @@ Andrea Fioraldi <andreafioraldi@gmail.com> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 115f9f2a..3fdbe8fe 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -105,15 +105,8 @@ static sharedmem_t * shm_fuzz; static const u8 count_class_human[256] = { - [0] = 0, - [1] = 1, - [2] = 2, - [3] = 3, - [4] = 4, - [8] = 5, - [16] = 6, - [32] = 7, - [128] = 8 + [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, + [8] = 5, [16] = 6, [32] = 7, [128] = 8 }; diff --git a/src/afl-tmin.c b/src/afl-tmin.c index b5b015ce..1bf4af38 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/test-instr.c b/test-instr.c index eaae50ef..b2caa1fe 100644 --- a/test-instr.c +++ b/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/test/test-basic.sh b/test/test-basic.sh index c39faa74..bec42b4d 100755 --- a/test/test-basic.sh +++ b/test/test-basic.sh @@ -44,10 +44,13 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc CODE=1 } test -e test-compcov.harden && { - grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && { + nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && { $ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working" } || { $ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened" + env | egrep 'AFL|PATH|LLVM' + AFL_DEBUG=1 AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c + nm test-compcov.harden CODE=1 } rm -f test-compcov.harden @@ -159,7 +162,7 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc CODE=1 } test -e test-compcov.harden && { - grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && { + nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && { $ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working" } || { $ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened" diff --git a/test/test-gcc-plugin.sh b/test/test-gcc-plugin.sh index 50d83e40..95ae9c47 100755 --- a/test/test-gcc-plugin.sh +++ b/test/test-gcc-plugin.sh @@ -40,7 +40,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && { } test -e test-compcov.harden.gccpi && test_compcov_binary_functionality ./test-compcov.harden.gccpi && { - grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden.gccpi > /dev/null 2>&1 && { + nm test-compcov.harden.gccpi | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && { $ECHO "$GREEN[+] gcc_plugin hardened mode succeeded and is working" } || { $ECHO "$RED[!] gcc_plugin hardened mode is not hardened" diff --git a/test/test-llvm.sh b/test/test-llvm.sh index aa40c5ed..ddbee378 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -68,24 +68,24 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { ../afl-clang-fast -DTEST_SHARED_OBJECT=1 -z defs -fPIC -shared -o test-instr.so ../test-instr.c > /dev/null 2>&1 test -e test-instr.so && { $ECHO "$GREEN[+] llvm_mode shared object with -z defs compilation succeeded" - test `uname -s` = 'Linux' && LIBS=-ldl : + test `uname -s` = 'Linux' && LIBS=-ldl ../afl-clang-fast -o test-dlopen.plain test-dlopen.c ${LIBS} > /dev/null 2>&1 test -e test-dlopen.plain && { $ECHO "$GREEN[+] llvm_mode test-dlopen compilation succeeded" - echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ./test-dlopen.plain > /dev/null 2>&1 + echo 0 | DYLD_INSERT_LIBRARIES=./test-instr.so LD_PRELOAD=./test-instr.so TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ./test-dlopen.plain > /dev/null 2>&1 if [ $? -ne 0 ]; then $ECHO "$RED[!] llvm_mode test-dlopen exits with an error" CODE=1 fi - echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.0 -r -- ./test-dlopen.plain > /dev/null 2>&1 - TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.1 -r -- ./test-dlopen.plain < /dev/null > /dev/null 2>&1 + echo 0 | AFL_PRELOAD=./test-instr.so TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.0 -r -- ./test-dlopen.plain > /dev/null 2>&1 + AFL_PRELOAD=./test-instr.so TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.1 -r -- ./test-dlopen.plain < /dev/null > /dev/null 2>&1 test -e test-dlopen.plain.0 -a -e test-dlopen.plain.1 && { diff test-dlopen.plain.0 test-dlopen.plain.1 > /dev/null 2>&1 && { $ECHO "$RED[!] llvm_mode test-dlopen instrumentation should be different on different input but is not" CODE=1 } || { $ECHO "$GREEN[+] llvm_mode test-dlopen instrumentation present and working correctly" - TUPLES=`echo 0|TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-dlopen.plain 2>&1 | grep Captur | awk '{print$3}'` + TUPLES=`echo 0|AFL_PRELOAD=./test-instr.so TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-dlopen.plain 2>&1 | grep Captur | awk '{print$3}'` test "$TUPLES" -gt 3 -a "$TUPLES" -lt 12 && { $ECHO "$GREEN[+] llvm_mode test-dlopen run reported $TUPLES instrumented locations which is fine" } || { @@ -110,7 +110,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { CODE=1 } test -e test-compcov.harden && test_compcov_binary_functionality ./test-compcov.harden && { - grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && { + nm test-compcov.harden | grep -Eq 'stack_chk_fail|fstack-protector-all|fortified' > /dev/null 2>&1 && { $ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working" } || { $ECHO "$RED[!] llvm_mode hardened mode is not hardened" diff --git a/test/test-pre.sh b/test/test-pre.sh index e12d95be..b8b286e5 100755 --- a/test/test-pre.sh +++ b/test/test-pre.sh @@ -105,14 +105,14 @@ test -n "$TRAVIS_OS_NAME" && { export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1:symbolize=1 } -export AFL_LLVM_INSTRUMENT=AFL +#export AFL_LLVM_INSTRUMENT=AFL # AFL mode makes dlopen not link on macos # on OpenBSD we need to work with llvm from /usr/local/bin test -e /usr/local/bin/opt && { - export PATH="/usr/local/bin:${PATH}" + test `uname -s` = 'Darwin' || export PATH="/usr/local/bin:${PATH}" } # on MacOS X we prefer afl-clang over afl-gcc, because -# afl-gcc does not work there +# afl-gcc does not work there (it is a symlink from clang) test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && { AFL_GCC=afl-clang } || { diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index f9c0be7f..340ac77c 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -14,7 +14,7 @@ # <andreafioraldi@gmail.com> # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-client.c b/utils/afl_network_proxy/afl-network-client.c index a2451fdc..ceffb1ed 100644 --- a/utils/afl_network_proxy/afl-network-client.c +++ b/utils/afl_network_proxy/afl-network-client.c @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_network_proxy/afl-network-server.c b/utils/afl_network_proxy/afl-network-server.c index 60f174ee..3e5e275d 100644 --- a/utils/afl_network_proxy/afl-network-server.c +++ b/utils/afl_network_proxy/afl-network-server.c @@ -12,7 +12,7 @@ Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_proxy/afl-proxy.c b/utils/afl_proxy/afl-proxy.c index 6006e238..05247c60 100644 --- a/utils/afl_proxy/afl-proxy.c +++ b/utils/afl_proxy/afl-proxy.c @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/afl-untracer.c b/utils/afl_untracer/afl-untracer.c index 2baeb58d..d2cb4bcf 100644 --- a/utils/afl_untracer/afl-untracer.c +++ b/utils/afl_untracer/afl-untracer.c @@ -4,7 +4,7 @@ Written by Marc Heuse <mh@mh-sec.de> - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/afl_untracer/libtestinstr.c b/utils/afl_untracer/libtestinstr.c index 96b1cf21..a3f5acc8 100644 --- a/utils/afl_untracer/libtestinstr.c +++ b/utils/afl_untracer/libtestinstr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/utils/distributed_fuzzing/sync_script.sh b/utils/distributed_fuzzing/sync_script.sh index b28ff6cd..251ae4e6 100755 --- a/utils/distributed_fuzzing/sync_script.sh +++ b/utils/distributed_fuzzing/sync_script.sh @@ -6,7 +6,7 @@ # Originally written by Michal Zalewski # # Copyright 2014 Google Inc. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index dde78f7b..103da9d5 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/libtokencap/libtokencap.so.c b/utils/libtokencap/libtokencap.so.c index 0db044a1..71c30eed 100644 --- a/utils/libtokencap/libtokencap.so.c +++ b/utils/libtokencap/libtokencap.so.c @@ -6,7 +6,7 @@ Originally written by Michal Zalewski Copyright 2016 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/utils/optimin/build_optimin.sh b/utils/optimin/build_optimin.sh index 51d1bd26..aee5d0c3 100755 --- a/utils/optimin/build_optimin.sh +++ b/utils/optimin/build_optimin.sh @@ -11,7 +11,7 @@ # Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co> # # Copyright 2017 Battelle Memorial Institute. All rights reserved. -# Copyright 2019-2020 AFLplusplus Project. All rights reserved. +# Copyright 2019-2022 AFLplusplus Project. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/utils/optimin/src/OptiMin.cpp b/utils/optimin/src/OptiMin.cpp index ce1fb850..b0082d14 100644 --- a/utils/optimin/src/OptiMin.cpp +++ b/utils/optimin/src/OptiMin.cpp @@ -260,7 +260,7 @@ static Error runShowmap(AFLCoverageMap &CovMap, const StringRef Input, if (TargetArgsHasAtAt) { - ShowmapArgs.append({"-A", StdinFile}); + ShowmapArgs.append({"-H", StdinFile}); Redirects[/* stdin */ 0] = "/dev/null"; } else if (InputIsFile) { diff --git a/utils/persistent_mode/test-instr.c b/utils/persistent_mode/test-instr.c index 6da511de..168aa429 100644 --- a/utils/persistent_mode/test-instr.c +++ b/utils/persistent_mode/test-instr.c @@ -3,7 +3,7 @@ -------------------------------------------------------- Originally written by Michal Zalewski Copyright 2014 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2022 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: diff --git a/utils/qbdi_mode/build.sh b/utils/qbdi_mode/build.sh index 2527bd26..29fe0ee4 100755 --- a/utils/qbdi_mode/build.sh +++ b/utils/qbdi_mode/build.sh @@ -52,6 +52,6 @@ ${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g echo "[+] Building afl-fuzz for Android" # build afl-fuzz cd ../.. -${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-*.c src/afl-fuzz.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o utils/qbdi_mode/afl-fuzz -ldl -w +${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz*.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c src/afl-performance.c -o utils/qbdi_mode/afl-fuzz -ldl -lm -w echo "[+] All done. Enjoy!" |