|
| 1 | +SAFL Fuzzer |
| 2 | +================== |
| 3 | + |
| 4 | +## Install |
| 5 | +SAFL is installed in /opt/tsmart-date/. Please configure the `PATH` environment variable in your shell first. |
| 6 | + |
| 7 | +Execute in shell: |
| 8 | + |
| 9 | +```sh |
| 10 | +export PATH="/opt/tsmart-date:$PATH" |
| 11 | +``` |
| 12 | + |
| 13 | +Or you can directly insert the content above in configuration files such as `~/.bashrc`. |
| 14 | + |
| 15 | +## Symbolic execution |
| 16 | + |
| 17 | +### Configure and Build |
| 18 | +You can use SAFL after the installation. SAFL uses symbolic execution to build high-quality seeds as the input for fuzzer, thus the first step is to configure the size of the input. For example, execute the following command when you want 10 bytes: |
| 19 | + |
| 20 | + |
| 21 | +```sh |
| 22 | +~/test/c-ares root@HghDTG |
| 23 | +❯ date-prepare sym 10 |
| 24 | +[*] Toolchain is at /tmp/toolchain |
| 25 | +[+] Saving configuration (symbolic, size is 10) |
| 26 | +``` |
| 27 | + |
| 28 | +Next, let's configure the project before build. Just like normal configuration procedure, you only need to insert `safl-configure` before the command. |
| 29 | + |
| 30 | +```sh |
| 31 | +~/test/c-ares/src heads/master* root@HghDTG |
| 32 | +❯ date-configure ./configure |
| 33 | +[*] Config: sym 10 |
| 34 | +[+] Setting up bitcode toolchain (unfiltered) |
| 35 | +[*] LLVM is at /opt/llvm |
| 36 | +[*] Toolchain is at /tmp/toolchain |
| 37 | +[*] Additional argument(s) to pass: |
| 38 | +[*] CXXFLAGS=-stdlib=libc++ -nostdinc -I/opt/llvm/include/c++/v1 -Qunused-arguments |
| 39 | +[*] LDFLAGS=-stdlib=libc++ -nostdinc -L/opt/llvm/lib -Wl,-rpath,/opt/llvm/lib |
| 40 | +[*] CC=/tmp/toolchain/clang |
| 41 | +[*] CXX=/tmp/toolchain/clang++ |
| 42 | +[+] Running target program |
| 43 | +checking whether to enable maintainer-specific portions of Makefiles... no |
| 44 | +[...] |
| 45 | +config.status: executing libtool commands |
| 46 | +configure: amending ./Makefile |
| 47 | +``` |
| 48 | + |
| 49 | +The next step is compilation. Just like normal configuration procedure, you need to insert `safl-build` before the command. |
| 50 | + |
| 51 | + |
| 52 | +```sh |
| 53 | +❯ date-build make -j |
| 54 | +[*] Config: sym 10 |
| 55 | +[+] Setting up bitcode toolchain |
| 56 | +[*] WLLVM is at /opt/wllvm |
| 57 | +[*] Toolchain is at /tmp/toolchain |
| 58 | +[+] Custom build comand, ignoring |
| 59 | +[+] Running target program |
| 60 | +make all-recursive |
| 61 | +[...] |
| 62 | +make[1]: Leaving directory '/home/hugh/test/c-ares/src' |
| 63 | +``` |
| 64 | + |
| 65 | +After building the library file, you may need to compiler additional test harness. Just like the normal `g++` or `clang` invocation, but you need to insert `safl-build` before the command. |
| 66 | + |
| 67 | +```sh |
| 68 | +~/test/c-ares root@HghDTG |
| 69 | +❯ date-build g++ target.cc -I src -c |
| 70 | +[*] Config: sym 10 |
| 71 | +[+] Setting up bitcode toolchain |
| 72 | +[*] WLLVM is at /opt/wllvm |
| 73 | +[*] Toolchain is at /tmp/toolchain |
| 74 | +[+] C++ compiler intercepted |
| 75 | +[*] Command to execute: |
| 76 | +[*] /tmp/toolchain/clang++ |
| 77 | +[*] -stdlib=libc++ |
| 78 | +[*] -nostdinc++ |
| 79 | +[*] -I/opt/llvm/include/c++/v1 |
| 80 | +[*] -Qunused-arguments |
| 81 | +[*] target.cc |
| 82 | +[*] -I |
| 83 | +[*] src |
| 84 | +[*] -c |
| 85 | +``` |
| 86 | + |
| 87 | +Finally, let's link the object files together! Caveat: SAFL uses a customized driver instead of the built-in version of clang, so you can't link with the standard toolchain. You should use `date-link` instead. |
| 88 | + |
| 89 | +The following example links the test harness `target.o` and library `src/.libs/libcares.a` together into binary `app`, and output the LLVM bitcode file `app.bc`. |
| 90 | + |
| 91 | +```sh |
| 92 | +~/test/c-ares root@HghDTG |
| 93 | +❯ date-link target.o src/.libs/libcares.a |
| 94 | +[*] Config: sym 10 |
| 95 | +[+] Setting up bitcode toolchain |
| 96 | +[*] WLLVM is at /opt/wllvm |
| 97 | +[*] Toolchain is at /tmp/toolchain |
| 98 | +[+] Generating driver, symbolic argument size = 10 |
| 99 | +[*] Command to execute: |
| 100 | +[*] /tmp/toolchain/clang |
| 101 | +[*] -xc |
| 102 | +[*] -c |
| 103 | +[*] -o |
| 104 | +[*] /tmp/toolchain/driver.o |
| 105 | +[*] /tmp/toolchain/driver.c |
| 106 | +[+] Linking objects |
| 107 | +[*] Command to execute: |
| 108 | +[*] /tmp/toolchain/clang++ |
| 109 | +[*] -stdlib=libc++ |
| 110 | +[*] -nostdinc++ |
| 111 | +[*] -I/opt/llvm/include/c++/v1 |
| 112 | +[*] -Qunused-arguments |
| 113 | +[*] -stdlib=libc++ |
| 114 | +[*] -nostdinc++ |
| 115 | +[*] -L/opt/llvm/lib |
| 116 | +[*] -Wl,-rpath,/opt/llvm/lib |
| 117 | +[*] /tmp/toolchain/driver.o |
| 118 | +[*] target.o |
| 119 | +[*] src/.libs/libcares.a |
| 120 | +[*] -o |
| 121 | +[*] app |
| 122 | +[+] Extracting bitcode |
| 123 | +Loading '/tmp/toolchain/.driver.o.bc' |
| 124 | +Loading '/home/hugh/test/c-ares/.target.o.bc' |
| 125 | +Linking in '/home/hugh/test/c-ares/.target.o.bc' |
| 126 | +Loading '/home/hugh/test/c-ares/src/.libcares_la-ares_create_query.o.bc' |
| 127 | +Linking in '/home/hugh/test/c-ares/src/.libcares_la-ares_create_query.o.bc' |
| 128 | +Loading '/home/hugh/test/c-ares/src/.libcares_la-ares_library_init.o.bc' |
| 129 | +Linking in '/home/hugh/test/c-ares/src/.libcares_la-ares_library_init.o.bc' |
| 130 | +Writing bitcode... |
| 131 | +``` |
| 132 | + |
| 133 | +### Start Symbolic execution |
| 134 | +Create a new directory for intermediate files for symbolic execution, then place the linked bitcode here. For example, the following command uses `sym` as the directory. |
| 135 | + |
| 136 | +```sh |
| 137 | +~/test/c-ares root@HghDTG |
| 138 | +❯ mkdir sym && cd sym |
| 139 | + |
| 140 | +~/test/c-ares/sym root@HghDTG |
| 141 | +❯ cp ../app.bc . |
| 142 | +``` |
| 143 | + |
| 144 | +Use command `safl-fuzz` to start symbolic execution. To get better results, you may re-run it several times. |
| 145 | + |
| 146 | +```sh |
| 147 | +~/test/c-ares/sym root@HghDTG |
| 148 | +❯ date-fuzz app |
| 149 | +[*] Config: sym 10 |
| 150 | +[*] Symbolic argument size = 10 |
| 151 | +[*] Application is at app.bc |
| 152 | +[+] Starting symbolic execution |
| 153 | +[*] KLEE cmdline: |
| 154 | +[*] /opt/klee/bin/klee |
| 155 | +[*] -only-output-states-covering-new |
| 156 | +[*] -libc=uclibc |
| 157 | +[*] -posix-runtime |
| 158 | +[*] -simplify-sym-indices |
| 159 | +[*] app.bc |
| 160 | +[*] -sym-arg |
| 161 | +[*] 10 |
| 162 | +KLEE: NOTE: Using klee-uclibc : /opt/klee/lib64/klee/runtime/klee-uclibc.bca |
| 163 | +KLEE: NOTE: Using model: /opt/klee/lib64/klee/runtime/libkleeRuntimePOSIX.bca |
| 164 | +KLEE: output directory is "/home/hugh/test/c-ares/sym/klee-out-0" |
| 165 | +KLEE: Using Z3 solver backend |
| 166 | +[...] |
| 167 | +^CKLEE: ctrl-c detected, requesting interpreter to halt. |
| 168 | +KLEE: halting execution, dumping remaining states |
| 169 | + |
| 170 | +KLEE: done: total instructions = 224686 |
| 171 | +KLEE: done: completed paths = 1371 |
| 172 | +KLEE: done: generated tests = 6 |
| 173 | +``` |
| 174 | + |
| 175 | +### Generate seeds |
| 176 | +Symbolic execution outputs testcases. You need to use `date-test-gen` to convert the testcases into seeds that can be used in fuzzing. The following example generates 6 seeds in `seed` directory. |
| 177 | + |
| 178 | +```sh |
| 179 | +~/test/c-ares/sym root@HghDTG |
| 180 | +❯ ls |
| 181 | +klee-out-0 app.bc klee-last |
| 182 | + |
| 183 | +~/test/c-ares/sym root@HghDTG |
| 184 | +❯ mkdir seed |
| 185 | + |
| 186 | +~/test/c-ares/sym root@HghDTG |
| 187 | +❯ date-test-gen klee-out-*/*.ktest --output seed |
| 188 | + |
| 189 | +~/test/c-ares/sym root@HghDTG |
| 190 | +❯ ls seed |
| 191 | +test000001.symseed test000003.symseed test000005.symseed |
| 192 | +test000002.symseed test000004.symseed test000006.symseed |
| 193 | +``` |
| 194 | + |
| 195 | +These seeds can be used as inputs for fuzzing. |
| 196 | + |
| 197 | +## Fuzz |
| 198 | + |
| 199 | +### Configure and build |
| 200 | +Before fuzzing, please cleanup the build directory and delete the compiled object files and binaries. |
| 201 | + |
| 202 | +```sh |
| 203 | +~/test/c-ares/src heads/master* root@HghDTG |
| 204 | +❯ make clean |
| 205 | +make[1]: Entering directory '/home/hugh/test/c-ares/src' |
| 206 | +[...] |
| 207 | +rm -f *.o |
| 208 | +rm -f *.lo |
| 209 | +make[1]: Leaving directory '/home/hugh/test/c-ares/src' |
| 210 | +``` |
| 211 | + |
| 212 | +Next, reconfigure SAFL to switch to dynamic mode. |
| 213 | + |
| 214 | +```sh |
| 215 | +~/test/c-ares/src heads/master* root@HghDTG |
| 216 | +❯ date-prepare dyn |
| 217 | +[*] Toolchain is at /tmp/toolchain |
| 218 | +[+] Saving configuration (dynamic) |
| 219 | +``` |
| 220 | + |
| 221 | +Execute the same commands as the aforementioned build steps: |
| 222 | + |
| 223 | +```sh |
| 224 | +# Build library |
| 225 | +date-configure ./configure |
| 226 | +date-build make -j |
| 227 | + |
| 228 | +# Build test program |
| 229 | +cd .. |
| 230 | +date-build g++ target.cc -I src -c |
| 231 | +date-link target.o src/.libs/libcares.a |
| 232 | +``` |
| 233 | + |
| 234 | +### Start fuzzing |
| 235 | + |
| 236 | +```sh |
| 237 | +❯ mkdir dyn && cd dyn |
| 238 | +date-fuzz -i ../sym/seed -o out -- ./app |
| 239 | +``` |
| 240 | + |
| 241 | +#### Direct invocation |
| 242 | + |
| 243 | +You need to have `tmux` installed (`sudo apt-get install tmux`), then execute: |
| 244 | + |
| 245 | +```sh |
| 246 | +date-fuzz ./app |
| 247 | +``` |
| 248 | + |
| 249 | +#### AFL customization |
| 250 | +To customize parameters of AFL, add `-afl-mode` at the end of the command: |
| 251 | + |
| 252 | + |
| 253 | +```sh |
| 254 | +date-fuzz -afl-mode -my-afl-parameters ./app |
| 255 | +``` |
| 256 | + |
| 257 | +See [documentation of AFL](http://lcamtuf.coredump.cx/afl/README.txt) for advanced tuning. |
0 commit comments