aboutsummaryrefslogtreecommitdiff
path: root/unicorn_mode
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-12-07 15:18:32 +0100
committerGitHub <noreply@github.com>2021-12-07 15:18:32 +0100
commit1f6c72ea1baea69b2dc5b3a68bfacbc00652bc66 (patch)
treea5a7ed81710c1dec50f0aa661b53c0cd884a4da2 /unicorn_mode
parent5469112db90741cb06c0979313938d83e63f793f (diff)
parentbb506de0b809f97a4221ee1b6e040dcb5f9ca56a (diff)
downloadafl++-1f6c72ea1baea69b2dc5b3a68bfacbc00652bc66.tar.gz
Merge pull request #1191 from llzmb/docs_quality_assurance
Docs content - quality assurance
Diffstat (limited to 'unicorn_mode')
-rw-r--r--unicorn_mode/README.md45
-rw-r--r--unicorn_mode/samples/c/COMPILE.md3
-rw-r--r--unicorn_mode/samples/persistent/COMPILE.md4
-rw-r--r--unicorn_mode/samples/speedtest/README.md15
4 files changed, 37 insertions, 30 deletions
diff --git a/unicorn_mode/README.md b/unicorn_mode/README.md
index d2b7d16f..ee4a7b22 100644
--- a/unicorn_mode/README.md
+++ b/unicorn_mode/README.md
@@ -8,10 +8,11 @@ The CompareCoverage and NeverZero counters features are by Andrea Fioraldi <andr
## 1) Introduction
-The code in ./unicorn_mode allows you to build the (Unicorn Engine)[https://github.com/unicorn-engine/unicorn] with AFL support.
+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
+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,
@@ -25,7 +26,7 @@ For some pointers for more advanced emulation, take a look at [BaseSAFE](https:/
### Building AFL++'s Unicorn Mode
First, make AFL++ as usual.
-Once that completes successfully you need to build and add in the Unicorn Mode
+Once that completes successfully you need to build and add in the Unicorn Mode
features:
```
@@ -33,10 +34,10 @@ 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.
+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
+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
@@ -46,25 +47,24 @@ 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
+ + 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
+ + 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
+ + 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.
+ + 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
+ + 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
@@ -77,14 +77,13 @@ afl-fuzz -U -m none -i /path/to/inputs -o /path/to/results -- ./test_harness @@
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, please refer to the
-sample provided in the 'unicorn_mode/samples' directory. There is also a blog
-post that uses slightly older concepts, but describes the general ideas, at:
+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
+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
+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.
@@ -105,8 +104,8 @@ Comparison instructions are currently instrumented only for the x86, x86_64 and
## 4) Gotchas, feedback, bugs
-Running the build script builds Unicornafl and its python bindings and installs
-them on your system.
+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".
diff --git a/unicorn_mode/samples/c/COMPILE.md b/unicorn_mode/samples/c/COMPILE.md
index 7da140f7..e5265071 100644
--- a/unicorn_mode/samples/c/COMPILE.md
+++ b/unicorn_mode/samples/c/COMPILE.md
@@ -6,6 +6,7 @@ This shows a simple harness for unicornafl in C
The target can be built using the `make` command.
Just make sure you have built unicorn support first:
+
```bash
cd /path/to/afl/unicorn_mode
./build_unicorn_support.sh
@@ -19,4 +20,4 @@ was built in case you want to rebuild it or recompile it for any reason.
The pre-built binary (persistent_target_x86_64) was built using -g -O0 in gcc.
-We then load the binary and execute the main function directly.
+Then load the binary and execute the main function directly.
diff --git a/unicorn_mode/samples/persistent/COMPILE.md b/unicorn_mode/samples/persistent/COMPILE.md
index 9f2ae718..5e607aef 100644
--- a/unicorn_mode/samples/persistent/COMPILE.md
+++ b/unicorn_mode/samples/persistent/COMPILE.md
@@ -3,7 +3,7 @@
This shows a simple persistent harness for unicornafl in C.
In contrast to the normal c harness, this harness manually resets the unicorn
state on each new input.
-Thanks to this, we can rerun the test case in unicorn multiple times, without
+Thanks to this, you can rerun the test case in unicorn multiple times, without
the need to fork again.
## Compiling sample.c
@@ -25,4 +25,4 @@ was built in case you want to rebuild it or recompile it for any reason.
The pre-built binary (persistent_target_x86_64.bin) was built using -g -O0 in
gcc.
-We then load the binary and we execute the main function directly. \ No newline at end of file
+Then load the binary and execute the main function directly. \ No newline at end of file
diff --git a/unicorn_mode/samples/speedtest/README.md b/unicorn_mode/samples/speedtest/README.md
index 3c1184a2..bd5ba8d0 100644
--- a/unicorn_mode/samples/speedtest/README.md
+++ b/unicorn_mode/samples/speedtest/README.md
@@ -35,7 +35,6 @@ cd python
TODO: add results here.
-
## Compiling speedtest_target.c
You shouldn't need to compile simple_target.c since a X86_64 binary version is
@@ -44,22 +43,30 @@ 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.
-We then load the binary and execute the main function directly.
+Then load the binary and execute the main function directly.
+
+## Addresses for the harness
-## 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