diff options
Diffstat (limited to 'unicorn_mode')
23 files changed, 194 insertions, 192 deletions
diff --git a/unicorn_mode/README.md b/unicorn_mode/README.md index 0f28cf96..ce87a2e9 100644 --- a/unicorn_mode/README.md +++ b/unicorn_mode/README.md @@ -1,74 +1,81 @@ # Unicorn-based binary-only instrumentation for afl-fuzz -The idea and much of the original implementation comes from Nathan Voss <njvoss299@gmail.com>. +The idea and much of the original implementation comes from Nathan Voss +<njvoss299@gmail.com>. The port to AFL++ is by Dominik Maier <mail@dmnk.co>. -The CompareCoverage and NeverZero counters features are by Andrea Fioraldi <andreafioraldi@gmail.com>. +The CompareCoverage and NeverZero counters features are by Andrea Fioraldi +<andreafioraldi@gmail.com>. ## 1) Introduction -The code in ./unicorn_mode allows you to build the -(Unicorn Engine)[https://github.com/unicorn-engine/unicorn] with AFL++ support. -This means, you can run anything that can be emulated in unicorn and obtain instrumentation -output for black-box, closed-source binary code snippets. This mechanism -can be then used by afl-fuzz to stress-test targets that couldn't be built -with afl-cc or used in QEMU mode. +The code in [unicorn_mode/](./) allows you to build the +[Unicorn Engine](https://github.com/unicorn-engine/unicorn) with AFL++ support. +This means, you can run anything that can be emulated in unicorn and obtain +instrumentation output for black-box, closed-source binary code snippets. This +mechanism can be then used by afl-fuzz to stress-test targets that couldn't be +built with afl-cc or used in QEMU mode. -There is a significant performance penalty compared to native AFL, -but at least we're able to use AFL++ on these binaries, right? +There is a significant performance penalty compared to native AFL, but at least +we're able to use AFL++ on these binaries, right? ## 2) How to use -First, you will need a working harness for your target in unicorn, using Python, C, or Rust. -For some pointers for more advanced emulation, take a look at [BaseSAFE](https://github.com/fgsect/BaseSAFE) and [Qiling](https://github.com/qilingframework/qiling). +First, you will need a working harness for your target in unicorn, using Python, +C, or Rust. -### Building AFL++'s Unicorn Mode +For some pointers for more advanced emulation, take a look at +[BaseSAFE](https://github.com/fgsect/BaseSAFE) and +[Qiling](https://github.com/qilingframework/qiling). -First, make AFL++ as usual. -Once that completes successfully you need to build and add in the Unicorn Mode -features: +### Building AFL++'s Unicorn mode + +First, make AFL++ as usual. Once that completes successfully, you need to build +and add in the Unicorn mode features: ``` cd unicorn_mode ./build_unicorn_support.sh ``` -NOTE: This script checks out a Unicorn Engine fork as submodule that has been tested -and is stable-ish, based on the unicorn engine `next` branch. - -Building Unicorn will take a little bit (~5-10 minutes). Once it completes -it automatically compiles a sample application and verifies that it works. - -### Fuzzing with Unicorn Mode - -To use unicorn-mode effectively you need to prepare the following: - - * Relevant binary code to be fuzzed - * Knowledge of the memory map and good starting state - * Folder containing sample inputs to start fuzzing with - + Same ideas as any other AFL++ inputs - + Quality/speed of results will depend greatly on the quality of starting - samples - + See AFL's guidance on how to create a sample corpus - * Unicornafl-based test harness in Rust, C, or Python, which: - + Adds memory map regions - + Loads binary code into memory - + Calls uc.afl_fuzz() / uc.afl_start_forkserver - + Loads and verifies data to fuzz from a command-line specified file - + AFL++ will provide mutated inputs by changing the file passed to - the test harness - + Presumably the data to be fuzzed is at a fixed buffer address - + If input constraints (size, invalid bytes, etc.) are known they - should be checked in the place_input handler. If a constraint - fails, just return false from the handler. AFL++ will treat the input as 'uninteresting' and move on. - + Sets up registers and memory state for beginning of test - + Emulates the interesting code from beginning to end - + If a crash is detected, the test harness must 'crash' by - throwing a signal (SIGSEGV, SIGKILL, SIGABORT, etc.), or indicate a crash in the crash validation callback. - -Once you have all those things ready to go you just need to run afl-fuzz in -'unicorn-mode' by passing in the '-U' flag: +NOTE: This script checks out a Unicorn Engine fork as submodule that has been +tested and is stable-ish, based on the unicorn engine `next` branch. + +Building Unicorn will take a little bit (~5-10 minutes). Once it completes, it +automatically compiles a sample application and verifies that it works. + +### Fuzzing with Unicorn mode + +To use unicorn-mode effectively, you need to prepare the following: + +* Relevant binary code to be fuzzed +* Knowledge of the memory map and good starting state +* Folder containing sample inputs to start fuzzing with + * Same ideas as any other AFL++ inputs + * Quality/speed of results will depend greatly on the quality of starting + samples + * See AFL's guidance on how to create a sample corpus +* Unicornafl-based test harness in Rust, C, or Python, which: + * Adds memory map regions + * Loads binary code into memory + * Calls uc.afl_fuzz() / uc.afl_start_forkserver + * Loads and verifies data to fuzz from a command-line specified file + * AFL++ will provide mutated inputs by changing the file passed to the + test harness + * Presumably the data to be fuzzed is at a fixed buffer address + * If input constraints (size, invalid bytes, etc.) are known, they + should be checked in the place_input handler. If a constraint fails, + just return false from the handler. AFL++ will treat the input as + 'uninteresting' and move on. + * Sets up registers and memory state to start testing + * Emulates the interesting code from beginning to end + * If a crash is detected, the test harness must 'crash' by throwing a signal + (SIGSEGV, SIGKILL, SIGABORT, etc.), or indicate a crash in the crash + validation callback. + +Once you have all those things ready to go, you just need to run afl-fuzz in +`unicorn-mode` by passing in the `-U` flag: ``` afl-fuzz -U -m none -i /path/to/inputs -o /path/to/results -- ./test_harness @@ @@ -78,39 +85,45 @@ The normal afl-fuzz command line format applies to everything here. Refer to AFL's main documentation for more info about how to use afl-fuzz effectively. For a much clearer vision of what all of this looks like, refer to the sample -provided in the 'unicorn_mode/samples' directory. There is also a blog post that +provided in the [samples/](./samples/) directory. There is also a blog post that uses slightly older concepts, but describes the general ideas, at: [https://medium.com/@njvoss299/afl-unicorn-fuzzing-arbitrary-binary-code-563ca28936bf](https://medium.com/@njvoss299/afl-unicorn-fuzzing-arbitrary-binary-code-563ca28936bf) -The ['helper_scripts'](./helper_scripts) directory also contains several helper scripts that allow you -to dump context from a running process, load it, and hook heap allocations. For details -on how to use this check out the follow-up blog post to the one linked above. +The [helper_scripts/](./helper_scripts/) directory also contains several helper +scripts that allow you to dump context from a running process, load it, and hook +heap allocations. For details on how to use this, check out the follow-up blog +post to the one linked above: + +[https://hackernoon.com/afl-unicorn-part-2-fuzzing-the-unfuzzable-bea8de3540a5](https://hackernoon.com/afl-unicorn-part-2-fuzzing-the-unfuzzable-bea8de3540a5) -A example use of AFL-Unicorn mode is discussed in the paper Unicorefuzz: +An example use of AFL-Unicorn mode is discussed in the paper Unicorefuzz: [https://www.usenix.org/conference/woot19/presentation/maier](https://www.usenix.org/conference/woot19/presentation/maier) ## 3) Options -As for the QEMU-based instrumentation, unicornafl comes with a sub-instruction based instrumentation similar in purpose to laf-intel. +As for the QEMU-based instrumentation, unicornafl comes with a sub-instruction +based instrumentation similar in purpose to laf-intel. -The options that enable Unicorn CompareCoverage are the same used for QEMU. -This will split up each multi-byte compare to give feedback for each correct byte. -`AFL_COMPCOV_LEVEL=1` is to instrument comparisons with only immediate values. +The options that enable Unicorn CompareCoverage are the same used for QEMU. This +will split up each multi-byte compare to give feedback for each correct byte: -`AFL_COMPCOV_LEVEL=2` instruments all comparison instructions. +* `AFL_COMPCOV_LEVEL=1` to instrument comparisons with only immediate values. +* `AFL_COMPCOV_LEVEL=2` to instrument all comparison instructions. -Comparison instructions are currently instrumented only for the x86, x86_64 and ARM targets. +Comparison instructions are currently instrumented only for the x86, x86_64, and +ARM targets. ## 4) Gotchas, feedback, bugs -Running the build script builds Unicornafl and its python bindings and installs -them on your system. -This installation will leave any existing Unicorn installations untouched. -If you want to use unicornafl instead of unicorn in a script, -replace all `unicorn` imports with `unicornafl` inputs, everything else should "just work". -If you use 3rd party code depending on unicorn, you can use unicornafl monkeypatching: -Before importing anything that depends on unicorn, do: +Running the build script builds unicornafl and its Python bindings and installs +them on your system. This installation will leave any existing Unicorn +installations untouched. + +If you want to use unicornafl instead of unicorn in a script, replace all +`unicorn` imports with `unicornafl` inputs, everything else should "just work". +If you use 3rd party code depending on unicorn, you can use unicornafl +monkeypatching. Before importing anything that depends on unicorn, do: ```python import unicornafl @@ -119,20 +132,30 @@ unicornafl.monkeypatch() This will replace all unicorn imports with unicornafl inputs. -5) Examples +## 5) Examples + +Apart from reading the documentation in `afl.c` and the Python bindings of +unicornafl, the best documentation are the [samples/](./samples). -Apart from reading the documentation in `afl.c` and the python bindings of unicornafl, the best documentation are the [samples/](./samples). The following examples exist at the time of writing: -- c: A simple example how to use the c bindings -- compcov_x64: A python example that uses compcov to traverse hard-to-reach blocks -- persistent: A c example using persistent mode for maximum speed, and resetting the target state between each iteration -- simple: A simple python example -- speedtest/c: The c harness for an example target, used to compare c, python, and rust bindings and fix speed issues -- speedtest/python: Fuzzing the same target in python -- speedtest/rust: Fuzzing the same target using a rust harness - -Usually, the place to look at is the `harness` in each folder. The source code in each harness is pretty well documented. -Most harnesses also have the `afl-fuzz` commandline, or even offer a `make fuzz` Makefile target. -Targets in these folders, if x86, can usually be made using `make target` in each folder or get shipped pre-built (plus their source). -Especially take a look at the [speedtest documentation](./samples/speedtest/README.md) to see how the languages compare. \ No newline at end of file +- c: A simple example on how to use the C bindings +- compcov_x64: A Python example that uses compcov to traverse hard-to-reach + blocks +- persistent: A C example using persistent mode for maximum speed, and resetting + the target state between each iteration +- simple: A simple Python example +- speedtest/c: The C harness for an example target, used to compare C, Python, + and Rust bindings and fix speed issues +- speedtest/python: Fuzzing the same target in Python +- speedtest/rust: Fuzzing the same target using a Rust harness + +Usually, the place to look at is the `harness` in each folder. The source code +in each harness is pretty well documented. Most harnesses also have the +`afl-fuzz` commandline, or even offer a `make fuzz` Makefile target. Targets in +these folders, if x86, can usually be made using `make target` in each folder or +get shipped pre-built (plus their source). + +Especially take a look at the +[speedtest documentation](./samples/speedtest/README.md) to see how the +languages compare. \ No newline at end of file diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 8b9c9fc0..4697a492 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -7b0c61f25042ebed910b88da2ca42778b858b852 +46879845 diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 340ac77c..74f9e174 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -180,8 +180,7 @@ sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null git checkout "$UNICORNAFL_VERSION" || exit 1 echo "[*] making sure afl++ header files match" -cp "../../include/config.h" "." || exit 1 -cp "../../include/types.h" "." || exit 1 +cp "../../include/config.h" "./include" || exit 1 echo "[*] Configuring Unicorn build..." @@ -213,7 +212,7 @@ echo "[*] Unicornafl bindings installed successfully." # Compile the sample, run it, verify that it works! echo "[*] Testing unicornafl python functionality by running a sample test harness" -cd ../samples/simple || echo "Cannot cd" +cd ../samples/python_simple || echo "Cannot cd" # Run afl-showmap on the sample application. If anything comes out then it must have worked! unset AFL_INST_RATIO diff --git a/unicorn_mode/samples/c/Makefile b/unicorn_mode/samples/c/Makefile index cb491e10..fd6dbe77 100644 --- a/unicorn_mode/samples/c/Makefile +++ b/unicorn_mode/samples/c/Makefile @@ -4,29 +4,28 @@ .POSIX: UNAME_S =$(shell uname -s)# GNU make UNAME_S:sh=uname -s # BSD make -_UNIQ=_QINU_ -LIBDIR = ../../unicornafl +UNICORNAFL_LIB = ../../unicornafl/build +UNICORN_LIB = ../../unicornafl/unicorn/build BIN_EXT = AR_EXT = a # Verbose output? V ?= 0 -CFLAGS += -Wall -Werror -I../../unicornafl/include +CFLAGS += -Wall -Werror -I../../unicornafl/unicorn/include -I../../unicornafl/include -LDFLAGS += -L$(LIBDIR) -lpthread -lm +LDFLAGS += -L$(UNICORNAFL_LIB) -L$(UNICORN_LIB) -lpthread -lm -lunicornafl -lunicorn -lc++ -_LRT = $(_UNIQ)$(UNAME_S:Linux=) -__LRT = $(_LRT:$(_UNIQ)=-lrt) -LRT = $(__LRT:$(_UNIQ)=) +ifeq ($(UNAME), Linux) +# do something Linux-y +LRT = -lrt +else +LRT = +endif LDFLAGS += $(LRT) -_CC = $(_UNIQ)$(CROSS) -__CC = $(_CC:$(_UNIQ)=$(CC)) -MYCC = $(__CC:$(_UNIQ)$(CROSS)=$(CROSS)gcc) - .PHONY: all clean all: harness @@ -34,14 +33,20 @@ all: harness clean: rm -rf *.o harness harness-debug -harness.o: harness.c ../../unicornafl/include/unicorn/*.h - ${MYCC} ${CFLAGS} -O3 -c harness.c +harness.o: harness.c ../../unicornafl/unicorn/include/unicorn/*.h + ${CC} ${CFLAGS} -O3 -c harness.c + +harness-debug.o: harness.c ../../unicornafl/unicorn/include/unicorn/*.h + ${CC} ${CFLAGS} -g -c harness.c -o $@ -harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h - ${MYCC} ${CFLAGS} -g -c harness.c -o $@ +../../unicornafl/build/libunicornafl.a: + cd ../.. && ./build_unicorn_support.sh harness: harness.o - ${MYCC} -L${LIBDIR} harness.o ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@ + ${CC} harness.o ../../unicornafl/build/libunicornafl.a $(LDFLAGS) -o $@ debug: harness-debug.o - ${MYCC} -L${LIBDIR} harness.o ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug + ${CC} harness.o ../../unicornafl/build/libunicornafl.a $(LDFLAGS) -o harness-debug + +fuzz: harness + DYLD_FALLBACK_LIBRARY_PATH="../../unicornafl/unicorn/build" LD_LIBRARY_PATH="../../unicornafl/unicorn/build" ../../../afl-fuzz -m none -i sample_inputs -o out -- ./harness @@ diff --git a/unicorn_mode/samples/c/harness.c b/unicorn_mode/samples/c/harness.c index 4bda6e2d..30972ce7 100644 --- a/unicorn_mode/samples/c/harness.c +++ b/unicorn_mode/samples/c/harness.c @@ -8,7 +8,7 @@ Run under AFL as follows: - $ cd <afl_path>/unicorn_mode/samples/simple/ + $ cd <afl_path>/unicorn_mode/samples/c $ make $ ../../../afl-fuzz -m none -i sample_inputs -o out -- ./harness @@ */ @@ -26,6 +26,7 @@ #include <sys/mman.h> #include <unicorn/unicorn.h> +#include <unicornafl/unicornafl.h> // Path to the file containing the binary to emulate #define BINARY_FILE ("persistent_target_x86_64") @@ -141,7 +142,7 @@ static void mem_map_checked(uc_engine *uc, uint64_t addr, size_t size, uint32_t //printf("SIZE %llx, align: %llx\n", size, ALIGNMENT); uc_err err = uc_mem_map(uc, addr, size, mode); if (err != UC_ERR_OK) { - printf("Error mapping %ld bytes at 0x%lx: %s (mode: %d)\n", size, addr, uc_strerror(err), mode); + printf("Error mapping %ld bytes at 0x%llx: %s (mode: %d)\n", size, (unsigned long long) addr, uc_strerror(err), (int) mode); exit(1); } } @@ -184,7 +185,7 @@ int main(int argc, char **argv, char **envp) { // Map memory. mem_map_checked(uc, BASE_ADDRESS, len, UC_PROT_ALL); - printf("Len: %lx\n", len); + printf("Len: %lx\n", (unsigned long) len); fflush(stdout); // write machine code to be emulated to memory diff --git a/unicorn_mode/samples/compcov_x64/compcov_test_harness.py b/unicorn_mode/samples/compcov_x64/compcov_test_harness.py index f0749d1b..52f0a286 100644 --- a/unicorn_mode/samples/compcov_x64/compcov_test_harness.py +++ b/unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ -10,7 +10,7 @@ Run under AFL as follows: - $ cd <afl_path>/unicorn_mode/samples/simple/ + $ cd <afl_path>/unicorn_mode/samples/python_simple $ AFL_COMPCOV_LEVEL=2 ../../../afl-fuzz -U -m none -i ./sample_inputs -o ./output -- python compcov_test_harness.py @@ """ diff --git a/unicorn_mode/samples/persistent/Makefile b/unicorn_mode/samples/persistent/Makefile index 80a47550..35584416 100644 --- a/unicorn_mode/samples/persistent/Makefile +++ b/unicorn_mode/samples/persistent/Makefile @@ -4,29 +4,28 @@ .POSIX: UNAME_S =$(shell uname -s)# GNU make UNAME_S:sh=uname -s # BSD make -_UNIQ=_QINU_ -LIBDIR = ../../unicornafl +UNICORNAFL_LIB = ../../unicornafl/build +UNICORN_LIB = ../../unicornafl/unicorn/build BIN_EXT = AR_EXT = a # Verbose output? V ?= 0 -CFLAGS += -Wall -Werror -I../../unicornafl/include +CFLAGS += -Wall -Werror -I../../unicornafl/unicorn/include -I../../unicornafl/include -LDFLAGS += -L$(LIBDIR) -lpthread -lm +LDFLAGS += -L$(UNICORNAFL_LIB) -L$(UNICORN_LIB) -lpthread -lm -lunicornafl -lunicorn -lc++ -_LRT = $(_UNIQ)$(UNAME_S) -__LRT = $(_LRT:$(_UNIQ)Linux=-lrt) -LRT = $(__LRT:$(_UNIQ)$(UNAME_S)=) +ifeq ($(UNAME), Linux) +# do something Linux-y +LRT = -lrt +else +LRT = +endif LDFLAGS += $(LRT) -_CC = $(_UNIQ)$(CROSS) -__CC = $(_CC:$(_UNIQ)=$(CC)) -MYCC = $(__CC:$(_UNIQ)$(CROSS)=$(CROSS)gcc) - .PHONY: all clean all: harness @@ -34,20 +33,23 @@ all: harness clean: rm -rf *.o harness harness-debug -harness.o: harness.c ../../unicornafl/include/unicorn/*.h - ${MYCC} ${CFLAGS} -O3 -c harness.c +harness.o: harness.c ../../unicornafl/unicorn/include/unicorn/*.h + ${CC} ${CFLAGS} -O3 -c harness.c -harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h - ${MYCC} ${CFLAGS} -DAFL_DEBUG=1 -g -c harness.c -o $@ +harness-debug.o: harness.c ../../unicornafl/unicorn/include/unicorn/*.h + ${CC} ${CFLAGS} -DAFL_DEBUG=1 -g -c harness.c -o $@ harness: harness.o - ${MYCC} -L${LIBDIR} harness.o ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@ + ${CC} harness.o ../../unicornafl/build/libunicornafl.a $(LDFLAGS) -o $@ debug: harness-debug.o - ${MYCC} -L${LIBDIR} harness-debug.o ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug + ${CC} harness-debug.o ../../unicornafl/build/libunicornafl.a $(LDFLAGS) -o harness-debug + +../../unicornafl/build/libunicornafl.a: + cd ../.. && ./build_unicorn_support.sh fuzz: harness - ../../../afl-fuzz -m none -i sample_inputs -o out -- ./harness @@ + DYLD_FALLBACK_LIBRARY_PATH="../../unicornafl/unicorn/build" LD_LIBRARY_PATH="../../unicornafl/unicorn/build" ../../../afl-fuzz -m none -i sample_inputs -o out -- ./harness @@ debugmake: @echo UNAME_S=$(UNAME_S), _LRT=$(_LRT), __LRT=$(__LRT), LRT=$(LRT) diff --git a/unicorn_mode/samples/persistent/harness.c b/unicorn_mode/samples/persistent/harness.c index eae3f1fc..37b652e0 100644 --- a/unicorn_mode/samples/persistent/harness.c +++ b/unicorn_mode/samples/persistent/harness.c @@ -30,6 +30,7 @@ #include <sys/mman.h> #include <unicorn/unicorn.h> +#include <unicornafl/unicornafl.h> // Path to the file containing the binary to emulate #define BINARY_FILE ("persistent_target_x86_64") diff --git a/unicorn_mode/samples/simple/COMPILE.md b/unicorn_mode/samples/python_simple/COMPILE.md index f7bf5b50..f7bf5b50 100644 --- a/unicorn_mode/samples/simple/COMPILE.md +++ b/unicorn_mode/samples/python_simple/COMPILE.md diff --git a/unicorn_mode/samples/simple/sample_inputs/sample1.bin b/unicorn_mode/samples/python_simple/sample_inputs/sample1.bin index 85df5078..85df5078 100644 --- a/unicorn_mode/samples/simple/sample_inputs/sample1.bin +++ b/unicorn_mode/samples/python_simple/sample_inputs/sample1.bin diff --git a/unicorn_mode/samples/simple/sample_inputs/sample2.bin b/unicorn_mode/samples/python_simple/sample_inputs/sample2.bin index f76dd238..f76dd238 100644 --- a/unicorn_mode/samples/simple/sample_inputs/sample2.bin +++ b/unicorn_mode/samples/python_simple/sample_inputs/sample2.bin Binary files differdiff --git a/unicorn_mode/samples/simple/sample_inputs/sample3.bin b/unicorn_mode/samples/python_simple/sample_inputs/sample3.bin index 6b2aaa76..6b2aaa76 100644 --- a/unicorn_mode/samples/simple/sample_inputs/sample3.bin +++ b/unicorn_mode/samples/python_simple/sample_inputs/sample3.bin diff --git a/unicorn_mode/samples/simple/sample_inputs/sample4.bin b/unicorn_mode/samples/python_simple/sample_inputs/sample4.bin index 71bd63e6..71bd63e6 100644 --- a/unicorn_mode/samples/simple/sample_inputs/sample4.bin +++ b/unicorn_mode/samples/python_simple/sample_inputs/sample4.bin diff --git a/unicorn_mode/samples/simple/sample_inputs/sample5.bin b/unicorn_mode/samples/python_simple/sample_inputs/sample5.bin index aed2973e..aed2973e 100644 --- a/unicorn_mode/samples/simple/sample_inputs/sample5.bin +++ b/unicorn_mode/samples/python_simple/sample_inputs/sample5.bin diff --git a/unicorn_mode/samples/simple/simple_target.bin b/unicorn_mode/samples/python_simple/simple_target.bin index 0095eb6c..0095eb6c 100644 --- a/unicorn_mode/samples/simple/simple_target.bin +++ b/unicorn_mode/samples/python_simple/simple_target.bin Binary files differdiff --git a/unicorn_mode/samples/simple/simple_target.c b/unicorn_mode/samples/python_simple/simple_target.c index 49e1b4d8..49e1b4d8 100644 --- a/unicorn_mode/samples/simple/simple_target.c +++ b/unicorn_mode/samples/python_simple/simple_target.c diff --git a/unicorn_mode/samples/simple/simple_test_harness.py b/unicorn_mode/samples/python_simple/simple_test_harness.py index cd04ad3a..8758192e 100644 --- a/unicorn_mode/samples/simple/simple_test_harness.py +++ b/unicorn_mode/samples/python_simple/simple_test_harness.py @@ -10,7 +10,7 @@ Run under AFL as follows: - $ cd <afl_path>/unicorn_mode/samples/simple/ + $ cd <afl_path>/unicorn_mode/samples/python_simple $ ../../../afl-fuzz -U -m none -i ./sample_inputs -o ./output -- python simple_test_harness.py @@ """ @@ -19,7 +19,7 @@ import os import signal from unicornafl import * -from unicornafl.mips_const import * +from unicorn.mips_const import * # Path to the file containing the binary to emulate BINARY_FILE = os.path.join( @@ -156,7 +156,7 @@ def main(): uc.mem_write(DATA_ADDRESS, input) # Start the fuzzer. - uc.afl_fuzz(args.input_file, place_input_callback, [end_address]) + uc_afl_fuzz(uc=uc, input_file=args.input_file, place_input_callback=place_input_callback, exits=[end_address]) if __name__ == "__main__": diff --git a/unicorn_mode/samples/simple/simple_test_harness_alt.py b/unicorn_mode/samples/python_simple/simple_test_harness_alt.py index 3249b13d..5fb3f82f 100644 --- a/unicorn_mode/samples/simple/simple_test_harness_alt.py +++ b/unicorn_mode/samples/python_simple/simple_test_harness_alt.py @@ -13,7 +13,7 @@ Run under AFL as follows: - $ cd <afl_path>/unicorn_mode/samples/simple/ + $ cd <afl_path>/unicorn_mode/samples/python_simple $ ../../../afl-fuzz -U -m none -i ./sample_inputs -o ./output -- python simple_test_harness_alt.py @@ """ diff --git a/unicorn_mode/samples/speedtest/README.md b/unicorn_mode/samples/speedtest/README.md index bd5ba8d0..f46a5772 100644 --- a/unicorn_mode/samples/speedtest/README.md +++ b/unicorn_mode/samples/speedtest/README.md @@ -5,7 +5,11 @@ to show the raw speed of C, Rust, and Python harnesses. ## Compiling... -Make sure, you built unicornafl first (`../../build_unicorn_support.sh`). +Make sure you built unicornafl first (`../../build_unicorn_support.sh`). +Build the target using the provided Makefile. +This will also run the [./get_offsets.py](./get_offsets.py) script, +which finds some relevant addresses in the target binary using `objdump`, +and dumps them to different files. Then, follow these individual steps: ### Rust @@ -13,7 +17,7 @@ Then, follow these individual steps: ```bash cd rust cargo build --release -../../../afl-fuzz -i ../sample_inputs -o out -- ./target/release/harness @@ +../../../../afl-fuzz -i ../sample_inputs -o out -U -- ./target/release/harness @@ ``` ### C @@ -21,52 +25,16 @@ cargo build --release ```bash cd c make -../../../afl-fuzz -i ../sample_inputs -o out -- ./harness @@ +../../../../afl-fuzz -i ../sample_inputs -o out -U -- ./harness @@ ``` ### python ```bash cd python -../../../afl-fuzz -i ../sample_inputs -o out -U -- python3 ./harness.py @@ +../../../../afl-fuzz -i ../sample_inputs -o out -U -- python3 ./harness.py @@ ``` ## Results TODO: add results here. - -## Compiling speedtest_target.c - -You shouldn't need to compile simple_target.c since a X86_64 binary version is -pre-built and shipped in this sample folder. This file documents how the binary -was built in case you want to rebuild it or recompile it for any reason. - -The pre-built binary (simple_target_x86_64.bin) was built using -g -O0 in gcc. - -Then load the binary and execute the main function directly. - -## Addresses for the harness - -To find the address (in hex) of main, run: - -```bash -objdump -M intel -D target | grep '<main>:' | cut -d" " -f1 -``` - -To find all call sites to magicfn, run: - -```bash -objdump -M intel -D target | grep '<magicfn>$' | cut -d":" -f1 -``` - -For malloc callsites: - -```bash -objdump -M intel -D target | grep '<malloc@plt>$' | cut -d":" -f1 -``` - -And free callsites: - -```bash -objdump -M intel -D target | grep '<free@plt>$' | cut -d":" -f1 -``` \ No newline at end of file diff --git a/unicorn_mode/samples/speedtest/c/Makefile b/unicorn_mode/samples/speedtest/c/Makefile index 46789954..d34f49fa 100644 --- a/unicorn_mode/samples/speedtest/c/Makefile +++ b/unicorn_mode/samples/speedtest/c/Makefile @@ -4,29 +4,28 @@ .POSIX: UNAME_S =$(shell uname -s)# GNU make UNAME_S:sh=uname -s # BSD make -_UNIQ=_QINU_ -LIBDIR = ../../../unicornafl +UNICORNAFL_LIB = ../../../unicornafl/build +UNICORN_LIB = ../../../unicornafl/unicorn/build BIN_EXT = AR_EXT = a # Verbose output? V ?= 0 -CFLAGS += -Wall -Werror -Wextra -Wno-unused-parameter -I../../../unicornafl/include +CFLAGS += -Wall -I../../../unicornafl/unicorn/include -I../../../unicornafl/include -LDFLAGS += -L$(LIBDIR) -lpthread -lm +LDFLAGS += -L$(UNICORNAFL_LIB) -L$(UNICORN_LIB) -lpthread -lm -lunicornafl -lunicorn -lc++ -_LRT = $(_UNIQ)$(UNAME_S:Linux=) -__LRT = $(_LRT:$(_UNIQ)=-lrt) -LRT = $(__LRT:$(_UNIQ)=) +ifeq ($(UNAME), Linux) +# do something Linux-y +LRT = -lrt +else +LRT = +endif LDFLAGS += $(LRT) -_CC = $(_UNIQ)$(CROSS) -__CC = $(_CC:$(_UNIQ)=$(CC)) -MYCC = $(__CC:$(_UNIQ)$(CROSS)=$(CROSS)gcc) - .PHONY: all clean all: ../target harness @@ -38,17 +37,20 @@ afl-fuzz: ../../../../afl-fuzz clean: rm -rf *.o harness harness-debug -harness.o: harness.c ../../../unicornafl/include/unicorn/*.h - ${MYCC} ${CFLAGS} -O3 -c harness.c -o $@ +../../../unicornafl/build/libunicornafl.a: + cd ../../.. && ./build_unicorn_support.sh + +harness.o: harness.c ../../../unicornafl/unicorn/include/unicorn/*.h + ${CC} ${CFLAGS} -O3 -c harness.c -o $@ -harness-debug.o: harness.c ../../../unicornafl/include/unicorn/*.h - ${MYCC} ${CFLAGS} -fsanitize=address -g -Og -c harness.c -o $@ +harness-debug.o: harness.c ../../../unicornafl/unicorn/include/unicorn/*.h + ${CC} ${CFLAGS} -fsanitize=address -g -Og -c harness.c -o $@ harness: harness.o - ${MYCC} -L${LIBDIR} harness.o ../../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@ + ${CC} harness.o $(LDFLAGS) -o $@ harness-debug: harness-debug.o - ${MYCC} -fsanitize=address -g -Og -L${LIBDIR} harness-debug.o ../../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug + ${CC} -fsanitize=address -g -Og harness-debug.o ../../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug ../target: $(MAKE) -C .. diff --git a/unicorn_mode/samples/speedtest/c/harness.c b/unicorn_mode/samples/speedtest/c/harness.c index e8de3d80..184934b9 100644 --- a/unicorn_mode/samples/speedtest/c/harness.c +++ b/unicorn_mode/samples/speedtest/c/harness.c @@ -8,9 +8,9 @@ Run under AFL as follows: - $ cd <afl_path>/unicorn_mode/samples/simple/ + $ cd <afl_path>/unicorn_mode/samples/speedtest/c $ make - $ ../../../afl-fuzz -m none -i sample_inputs -o out -- ./harness @@ + $ ../../../../afl-fuzz -i ../sample_inputs -o out -U -- ./harness @@ */ // This is not your everyday Unicorn. @@ -28,6 +28,7 @@ #include <sys/mman.h> #include <unicorn/unicorn.h> +#include <unicornafl/unicornafl.h> // Path to the file containing the binary to emulate #define BINARY_FILE ("../target") @@ -124,7 +125,7 @@ static void mem_map_checked(uc_engine *uc, uint64_t addr, size_t size, uint32_t //printf("SIZE %llx, align: %llx\n", size, ALIGNMENT); uc_err err = uc_mem_map(uc, addr, size, mode); if (err != UC_ERR_OK) { - printf("Error mapping %ld bytes at 0x%lx: %s (mode: %d)\n", size, addr, uc_strerror(err), mode); + printf("Error mapping %ld bytes at 0x%llx: %s (mode: %d)\n", (unsigned long) size, (unsigned long long) addr, uc_strerror(err), (int) mode); exit(1); } } @@ -306,7 +307,7 @@ int main(int argc, char **argv, char **envp) { exit(-1); } uint64_t start_address; - if(fscanf(f, "%lx", &start_address) == EOF) { + if(fscanf(f, "%llx", (unsigned long long) &start_address) == EOF) { puts("Start address not found in target.offests.main"); exit(-1); } diff --git a/unicorn_mode/samples/speedtest/rust/Cargo.toml b/unicorn_mode/samples/speedtest/rust/Cargo.toml index 9b81be0b..766b2f27 100644 --- a/unicorn_mode/samples/speedtest/rust/Cargo.toml +++ b/unicorn_mode/samples/speedtest/rust/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "unicornafl_harness" +name = "harness" version = "0.1.0" authors = ["Dominik Maier <domenukk@gmail.com>"] edition = "2018" diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl -Subproject 7b0c61f25042ebed910b88da2ca42778b858b85 +Subproject 468798455a9f9790d2da369a18ed49fda3a64e8 |