Compare commits

...

13 Commits
taint ... 2.67c

Author SHA1 Message Date
1c64048d0f 2.67c 2020-08-18 19:56:47 +02:00
0a6084f361 Merge pull request #499 from AFLplusplus/dev
important push to stable
2020-08-17 23:42:45 +02:00
9532499ef5 install libafldrivers 2020-08-16 14:14:24 +02:00
1d56de6c1d fix lto autodict for long strings 2020-08-16 13:29:24 +02:00
266b51a842 final afl-llvm-rt.o.c that takes care of all eventualities 2020-08-16 10:53:38 +02:00
cc1fe2f2d2 skip instrumenting blocks following __afl_loop to improve stability in LTO. not in afl-llvm-pass and instrim because they are outdated, sancov cant be fixed 2020-08-15 22:59:49 +02:00
43214d6b46 more likely 2020-08-15 22:10:28 +02:00
2f28ecd3a5 more unlikely 2020-08-15 20:51:57 +02:00
73a629d6f2 important bugfix for large covmaps 2020-08-15 18:14:44 +02:00
0a251f93e0 increase initial memory sized 2020-08-15 13:34:51 +02:00
1cf4738487 more FAQ 2020-08-15 10:27:40 +02:00
af14acf2c1 Revert "Merge branch 'debug' into dev"
This reverts commit a7537b5511, reversing
changes made to 15e799f7ae.
2020-08-14 14:35:05 +02:00
8044ae28be Merge pull request #496 from AFLplusplus/dev
push to stable
2020-08-12 14:29:34 +02:00
27 changed files with 472 additions and 1228 deletions

View File

@ -521,7 +521,6 @@ clean:
$(MAKE) -C examples/argv_fuzzing clean
$(MAKE) -C qemu_mode/unsigaction clean
$(MAKE) -C qemu_mode/libcompcov clean
test -d qemu_taint/qemu && { cd qemu_taint ; ./clean.sh ; }
rm -rf qemu_mode/qemu-3.1.1
ifeq "$(IN_REPO)" "1"
test -d unicorn_mode/unicornafl && $(MAKE) -C unicorn_mode/unicornafl clean || true
@ -532,7 +531,6 @@ endif
deepclean: clean
rm -rf qemu_mode/qemu-3.1.1.tar.xz
rm -rf qemu_taint/qemu
rm -rf unicorn_mode/unicornafl
git reset --hard >/dev/null 2>&1 || true
@ -590,7 +588,6 @@ install: all $(MANPAGES)
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
if [ -f afl-qemu-taint ]; then install -m 755 afl-qemu-taint $${DESTDIR}$(BIN_PATH); fi
if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
if [ -f afl-clang-fast ]; then $(MAKE) -C llvm_mode install; fi
if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
@ -600,6 +597,8 @@ install: all $(MANPAGES)
if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
if [ -f examples/afl_network_proxy/afl-network-server ]; then $(MAKE) -C examples/afl_network_proxy install; fi
if [ -f libAFLDriver.a ]; then install -m 644 libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
if [ -f libAFLQemuDriver.a ]; then install -m 644 libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi

View File

@ -1,45 +1,12 @@
# qemu_taint variant.
UPDATE: **WORKS NOW** **PLEASE TEST** **:-)**
## HOWTO
cd qemu_taint && ./build_qemu_taint.sh
afl-fuzz -A ...
## CAVEATS
* llvm shmem persistent mode does not and can not not work
* MOpt works but totally ignores the taint information, so disabled here
* custom mutators? dunno if they work or not. depends on how they work.
* not tested with qemu_mode
* there are several debug checks to ensure the data is fine which slows down
fuzzing, if the beta experiment runs fine these will be improved and it
will result in quite a speed gain.
## THE TAINT
taint can be seen in out/taint/
the id:000 mirrors the out/queue entry, except the content it 0x00 for
untainted bytes and '!' for tainted bytes.
If a file has new tainted bytes compared to from which previous entry it
was created then there is a id:000[...].new file where the new bytes are
marked '!'.
the mutation switches between fuzzing all tainted bytes in one cycle and
only new bytes in the other cycle.
# American Fuzzy Lop plus plus (afl++)
<img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ Logo">
![Travis State](https://api.travis-ci.com/AFLplusplus/AFLplusplus.svg?branch=stable)
Release Version: [2.66c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release Version: [2.67c](https://github.com/AFLplusplus/AFLplusplus/releases)
Github Version: 2.66d
Github Version: 2.67d
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

@ -1,191 +0,0 @@
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// Platform detection. Copied from FuzzerInternal.h
#ifdef __linux__
#define LIBFUZZER_LINUX 1
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 0
#elif __APPLE__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 1
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 0
#elif __NetBSD__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 1
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 0
#elif __FreeBSD__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 1
#define LIBFUZZER_OPENBSD 0
#elif __OpenBSD__
#define LIBFUZZER_LINUX 0
#define LIBFUZZER_APPLE 0
#define LIBFUZZER_NETBSD 0
#define LIBFUZZER_FREEBSD 0
#define LIBFUZZER_OPENBSD 1
#else
#error "Support for your platform has not been implemented"
#endif
// libFuzzer interface is thin, so we don't include any libFuzzer headers.
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
// Notify AFL about persistent mode.
static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
int __afl_persistent_loop(unsigned int);
static volatile char suppress_warning2 = AFL_PERSISTENT[0];
// Notify AFL about deferred forkserver.
static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
void __afl_manual_init();
static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
// Input buffer.
static const size_t kMaxAflInputSize = 1024000;
static uint8_t AflInputBuf[kMaxAflInputSize];
// Use this optionally defined function to output sanitizer messages even if
// user asks to close stderr.
__attribute__((weak)) void __sanitizer_set_report_fd(void *);
// Keep track of where stderr content is being written to, so that
// dup_and_close_stderr can use the correct one.
static FILE *output_file = stderr;
// Experimental feature to use afl_driver without AFL's deferred mode.
// Needs to run before __afl_auto_init.
__attribute__((constructor(0))) static void __decide_deferred_forkserver(void) {
if (getenv("AFL_DRIVER_DONT_DEFER")) {
if (unsetenv("__AFL_DEFER_FORKSRV")) {
perror("Failed to unset __AFL_DEFER_FORKSRV");
abort();
}
}
}
// If the user asks us to duplicate stderr, then do it.
static void maybe_duplicate_stderr() {
char *stderr_duplicate_filename =
getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
if (!stderr_duplicate_filename)
return;
FILE *stderr_duplicate_stream =
freopen(stderr_duplicate_filename, "a+", stderr);
if (!stderr_duplicate_stream) {
fprintf(
stderr,
"Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
abort();
}
output_file = stderr_duplicate_stream;
}
// Most of these I/O functions were inspired by/copied from libFuzzer's code.
static void discard_output(int fd) {
FILE *temp = fopen("/dev/null", "w");
if (!temp)
abort();
dup2(fileno(temp), fd);
fclose(temp);
}
static void close_stdout() { discard_output(STDOUT_FILENO); }
// Prevent the targeted code from writing to "stderr" but allow sanitizers and
// this driver to do so.
static void dup_and_close_stderr() {
int output_fileno = fileno(output_file);
int output_fd = dup(output_fileno);
if (output_fd <= 0)
abort();
FILE *new_output_file = fdopen(output_fd, "w");
if (!new_output_file)
abort();
if (!__sanitizer_set_report_fd)
return;
__sanitizer_set_report_fd(reinterpret_cast<void *>(output_fd));
discard_output(output_fileno);
}
// Close stdout and/or stderr if user asks for it.
static void maybe_close_fd_mask() {
char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK");
if (!fd_mask_str)
return;
int fd_mask = atoi(fd_mask_str);
if (fd_mask & 2)
dup_and_close_stderr();
if (fd_mask & 1)
close_stdout();
}
// Define LLVMFuzzerMutate to avoid link failures for targets that use it
// with libFuzzer's LLVMFuzzerCustomMutator.
size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
return 0;
}
int main(int argc, char **argv) {
printf(
"======================= INFO =========================\n"
"This binary is built for AFL-fuzz.\n"
"To run the target function on individual input(s) execute this:\n"
" %s < INPUT_FILE\n"
"To fuzz with afl-fuzz execute this:\n"
" afl-fuzz [afl-flags] %s [-N]\n"
"afl-fuzz will run N iterations before "
"re-spawning the process (default: 1000)\n"
"======================================================\n",
argv[0], argv[0]);
maybe_duplicate_stderr();
maybe_close_fd_mask();
if (LLVMFuzzerInitialize)
LLVMFuzzerInitialize(&argc, &argv);
// Do any other expensive one-time initialization here.
int N = 100000;
if (argc == 2 && argv[1][0] == '-')
N = atoi(argv[1] + 1);
else if(argc == 2 && (N = atoi(argv[1])) > 0)
printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
assert(N > 0);
if (!getenv("AFL_DRIVER_DONT_DEFER"))
__afl_manual_init();
// Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
// on the first execution of LLVMFuzzerTestOneInput is ignored.
uint8_t dummy_input[1] = {0};
LLVMFuzzerTestOneInput(dummy_input, 1);
while (__afl_persistent_loop(N)) {
ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
if (n_read > 0) {
LLVMFuzzerTestOneInput(AflInputBuf, n_read);
}
}
printf("%s: successfully executed input(s)\n", argv[0]);
}

View File

@ -9,9 +9,11 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++2.66d (devel)
### Version ++2.67c (release)
- Support for improved afl++ snapshot module:
https://github.com/AFLplusplus/AFL-Snapshot-LKM
- Due to the instrumentation needing more memory, the initial memory sizes
for -m have been increased
- afl-fuzz:
- added -F option to allow -M main fuzzers to sync to foreign fuzzers,
e.g. honggfuzz or libfuzzer
@ -21,11 +23,11 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
MOpt into the mix
- fixed a bug in redqueen for strings and made deterministic with -s
- llvm_mode:
- now supports llvm 12!
- now supports llvm 12
- support for AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST (previous
AFL_LLVM_WHITELIST and AFL_LLVM_INSTRUMENT_FILE are deprecated and
are matched to AFL_LLVM_ALLOWLIST). The format is compatible to llvm
sancov, and also supports function matching!
sancov, and also supports function matching :)
- added neverzero counting to trace-pc/pcgard
- fixes for laf-intel float splitting (thanks to mark-griffin for
reporting)
@ -33,9 +35,12 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- skipping ctors and ifuncs for instrumentation
- LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR
for a fixed map address (eg. 0x10000)
- LTO: improved stability for persistent mode, no other instrumentation
has that advantage
- LTO: fixed autodict for long strings
- LTO: laf-intel and redqueen/cmplog are now applied at link time
to prevent llvm optimizing away the splits
- LTO: autodictionary mode is a default
- LTO: autodictionary mode is a fixed default now
- LTO: instrim instrumentation disabled, only classic support used
as it is always better
- LTO: env var AFL_LLVM_DOCUMENT_IDS=file will document which edge ID

View File

@ -2,16 +2,39 @@
## Contents
1. [How to improve the fuzzing speed?](#how-to-improve-the-fuzzing-speed)
2. [How do I fuzz a network service?](#how-to-fuzz-a-network-service)
3. [How do I fuzz a GUI program?](#how-to-fuzz-a-gui-program)
4. [What is an edge?](#what-is-an-edge)
5. [Why is my stability below 100%?](#why-is-my-stability-below-100)
6. [How can I improve the stability value](#how-can-i-improve-the-stability-value)
* [What is the difference between afl and afl++?](#what-is-the-difference-between-afl-and-afl)
* [How to improve the fuzzing speed?](#how-to-improve-the-fuzzing-speed)
* [How do I fuzz a network service?](#how-to-fuzz-a-network-service)
* [How do I fuzz a GUI program?](#how-to-fuzz-a-gui-program)
* [What is an edge?](#what-is-an-edge)
* [Why is my stability below 100%?](#why-is-my-stability-below-100)
* [How can I improve the stability value](#how-can-i-improve-the-stability-value)
If you find an interesting or important question missing, submit it via
[https://github.com/AFLplusplus/AFLplusplus/issues](https://github.com/AFLplusplus/AFLplusplus/issues)
## What is the difference between afl and afl++?
American Fuzzy Lop (AFL) was developed by Michał "lcamtuf" Zalewski starting in
2013/2014, and when he left Google end of 2017 he stopped developing it.
At the end of 2019 the Google fuzzing team took over maintance of AFL, however
it is only accepting PR from the community and is not developing enhancements
anymore.
In the second quarter of 2019, 1 1/2 years after no further development of
AFL had happened and it became clear there would be none coming, afl++
was born, where initially first community patches were collected and applied
for bugs and enhancements. Then from various AFL spin-offs - mostly academic
research - features were integrated. This already resulted in a much advanced
AFL.
Until the end of 2019 the afl++ team had grown to four active developers which
then implemented their own research and feature, making it now by far the most
flexible and feature rich guided fuzzer available as open source.
And in independent fuzzing benchmarks it is one of the best fuzzers available,
e.g. [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html)
## How to improve the fuzzing speed
1. use [llvm_mode](docs/llvm_mode/README.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended)
@ -101,15 +124,15 @@ code example above):
```
Every line between two blocks is an `edge`.
## Why is my stability below 100
## Why is my stability below 100%
Stability is measured by how many percent of the edges in the target are
"stable". Sending the same input again and again should take the exact same
path through the target every time. If that is the case, the stability is 100%.
If however randomness happens, e.g. a thread reading from shared memory,
If however randomness happens, e.g. a thread reading other external data,
reaction to timing, etc. then in some of the re-executions with the same data
will result in the edge information being different accross runs.
the result in the edge information will be different accross runs.
Those edges that change are then flagged "unstable".
The more "unstable" edges, the more difficult for afl++ to identify valid new
@ -122,9 +145,25 @@ improve the stability.
## How can I improve the stability value
For fuzzing a 100% stable target that covers all edges is the best.
A 90% stable target that covers all edges is however better than a 100% stable
target that ignores 10% of the edges.
With instability you basically have a partial coverage loss on an edge, with
ignore you have a full loss on that edge.
There are functions that are unstable, but also provide value to coverage, eg
init functions that use fuzz data as input for example.
If however it is a function that has nothing to do with the input data is the
source, e.g. checking jitter, or is a hash map function etc. then it should
not be instrumented.
To be able to make this decision the following process will allow you to
identify the functions with variable edges so you can make this decision.
Four steps are required to do this and requires quite some knowledge of
coding and/or disassembly and it is only effectively possible with
afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation!
afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation.
1. First step: Identify which edge ID numbers are unstable
@ -135,9 +174,9 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation!
2. Second step: Find the responsible function.
a) For LTO instrumented binaries this can be documented during compile
time, just set `export AFL_LLVM_DOCUMENT_IDS=/path/to/afile`.
This file will have one assigned edge ID and the corresponding function
per line.
time, just set `export AFL_LLVM_DOCUMENT_IDS=/path/to/a/file`.
This file will have one assigned edge ID and the corresponding
function per line.
b) For PCGUARD instrumented binaries it is much more difficult. Here you
can either modify the __sanitizer_cov_trace_pc_guard function in
@ -151,6 +190,10 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation!
on start, check to which memory address the edge ID value is written
and set a write breakpoint to that address (`watch 0x.....`).
c) in all other instrumentation types this is not possible. So just
recompile with the the two mentioned above. This is just for
identifying the functions that have unstable edges.
3. Third step: create a text file with the filenames/functions
Identify which source code files contain the functions that you need to
@ -161,6 +204,15 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation!
If PCGUARD is used, then you need to follow this guide (needs llvm 12+!):
[http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation](http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation)
Only deny those functions from instrumentation that provide no value
for coverage - that is if it does not process any fuzz data directly
or indirectly (e.g. hash maps, thread management etc.).
If however a function directly or indirectly handles fuzz data then you
should not put the function in a deny instrumentation list and rather
live with the instability it comes with.
4. Fourth step: recompile the target
Recompile, fuzz it, be happy :)
This link explains this process for [Fuzzbench](https://github.com/google/fuzzbench/issues/677)

View File

@ -16,6 +16,7 @@ aflpp_driver.o: aflpp_driver.c
libAFLDriver.a: aflpp_driver.o
ar ru libAFLDriver.a aflpp_driver.o
cp -vf libAFLDriver.a ../../
debug:
$(LLVM_BINDIR)clang -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c
@ -29,6 +30,7 @@ aflpp_qemu_driver.o: aflpp_qemu_driver.c
libAFLQemuDriver.a: aflpp_qemu_driver.o
ar ru libAFLQemuDriver.a aflpp_qemu_driver.o
cp -vf libAFLQemuDriver.a ../../
aflpp_qemu_driver_hook.so: aflpp_qemu_driver_hook.o
$(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so

View File

@ -106,7 +106,9 @@ If 1, close stdout at startup. If 2 close stderr; if 3 close both.
#error "Support for your platform has not been implemented"
#endif
int __afl_sharedmem_fuzzing = 0;
int __afl_sharedmem_fuzzing = 1;
extern unsigned int * __afl_fuzz_len;
extern unsigned char *__afl_fuzz_ptr;
// libFuzzer interface is thin, so we don't include any libFuzzer headers.
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
@ -272,7 +274,6 @@ int main(int argc, char **argv) {
// Do any other expensive one-time initialization here.
uint8_t dummy_input[64] = {0};
uint8_t buf[1024000];
memcpy(dummy_input, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT));
memcpy(dummy_input + 32, (void *)AFL_DEFER_FORKSVR,
sizeof(AFL_DEFER_FORKSVR));
@ -283,25 +284,17 @@ int main(int argc, char **argv) {
printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
else if (argc > 1) {
if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) {
__afl_sharedmem_fuzzing = 0;
__afl_manual_init();
}
return ExecuteFilesOnyByOne(argc, argv);
}
assert(N > 0);
if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) {
fprintf(stderr, "performing manual init\n");
// if (!getenv("AFL_DRIVER_DONT_DEFER"))
__afl_manual_init();
}
// Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
// on the first execution of LLVMFuzzerTestOneInput is ignored.
LLVMFuzzerTestOneInput(dummy_input, 1);
@ -309,13 +302,25 @@ int main(int argc, char **argv) {
int num_runs = 0;
while (__afl_persistent_loop(N)) {
ssize_t r = read(0, buf, sizeof(buf));
#ifdef _DEBUG
fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
hash64(__afl_fuzz_ptr, *__afl_fuzz_len, 0xa5b35705),
*__afl_fuzz_len);
fprintf(stderr, "RECV:");
for (int i = 0; i < *__afl_fuzz_len; i++)
fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
fprintf(stderr, "\n");
#endif
if (*__afl_fuzz_len) {
if (r > 0) { LLVMFuzzerTestOneInput(buf, r); }
num_runs++;
LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len);
}
printf("%s: successfully executed input(s)\n", argv[0]);
}
printf("%s: successfully executed %d input(s)\n", argv[0], num_runs);
}

View File

@ -134,9 +134,7 @@ extern s32
struct queue_entry {
u8 *fname; /* File name for the test case */
u8 * fname_taint; /* File name for taint data */
u32 len; /* Input length */
struct queue_entry *prev; /* previous queue entry, if any */
u8 cal_failed, /* Calibration failed? */
trim_done, /* Trimmed? */
@ -150,10 +148,7 @@ struct queue_entry {
is_ascii; /* Is the input just ascii text? */
u32 bitmap_size, /* Number of bits set in bitmap */
fuzz_level, /* Number of fuzzing iterations */
taint_bytes_all, /* Number of tainted bytes */
taint_bytes_new, /* Number of new tainted bytes */
taint_bytes_highest; /* highest offset in input */
fuzz_level; /* Number of fuzzing iterations */
u64 exec_us, /* Execution time (us) */
handicap, /* Number of queue cycles behind */
@ -385,8 +380,6 @@ typedef struct afl_state {
char **argv; /* argv if needed */
char **argv_taint; /* argv for taint mode */
/* MOpt:
Lots of globals, but mostly for the status UI and other things where it
really makes no sense to haul them around as function parameters. */
@ -438,9 +431,7 @@ typedef struct afl_state {
*in_bitmap, /* Input bitmap */
*file_extension, /* File extension */
*orig_cmdline, /* Original command line */
*infoexec, /* Command to execute on a new crash */
*taint_input_file, /* fuzz_input_one input file */
*taint_src, *taint_map;
*infoexec; /* Command to execute on a new crash */
u32 hang_tmout; /* Timeout used for hang det (ms) */
@ -451,9 +442,7 @@ typedef struct afl_state {
custom_only, /* Custom mutator only mode */
python_only, /* Python-only mode */
is_main_node, /* if this is the main node */
is_secondary_node, /* if this is a secondary instance */
taint_needs_splode, /* explode fuzz input */
taint_mode;
is_secondary_node; /* if this is a secondary instance */
u32 stats_update_freq; /* Stats update frequency (execs) */
@ -514,8 +503,7 @@ typedef struct afl_state {
useless_at_start, /* Number of useless starting paths */
var_byte_count, /* Bitmap bytes with var behavior */
current_entry, /* Current queue entry ID */
havoc_div, /* Cycle count divisor for havoc */
taint_len, taint_count;
havoc_div; /* Cycle count divisor for havoc */
u64 total_crashes, /* Total number of crashes */
unique_crashes, /* Crashes with unique signatures */
@ -602,9 +590,6 @@ typedef struct afl_state {
char * cmplog_binary;
afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */
/* Taint mode */
afl_forkserver_t taint_fsrv; /* taint mode has its own little forkserver */
/* Custom mutators */
struct custom_mutator *mutator;
@ -856,8 +841,7 @@ struct custom_mutator {
};
void afl_state_init_1(afl_state_t *, uint32_t map_size);
void afl_state_init_2(afl_state_t *, uint32_t map_size);
void afl_state_init(afl_state_t *, uint32_t map_size);
void afl_state_deinit(afl_state_t *);
/* Set stop_soon flag on all childs, kill all childs */
@ -903,7 +887,7 @@ void deinit_py(void *);
void mark_as_det_done(afl_state_t *, struct queue_entry *);
void mark_as_variable(afl_state_t *, struct queue_entry *);
void mark_as_redundant(afl_state_t *, struct queue_entry *, u8);
void add_to_queue(afl_state_t *, u8 *, u8 *, u32, struct queue_entry *, u8);
void add_to_queue(afl_state_t *, u8 *, u32, u8);
void destroy_queue(afl_state_t *);
void update_bitmap_score(afl_state_t *, struct queue_entry *);
void cull_queue(afl_state_t *);
@ -913,9 +897,7 @@ u32 calculate_score(afl_state_t *, struct queue_entry *);
void write_bitmap(afl_state_t *);
u32 count_bits(afl_state_t *, u8 *);
u32 count_bits_len(afl_state_t *, u8 *, u32);
u32 count_bytes(afl_state_t *, u8 *);
u32 count_bytes_len(afl_state_t *, u8 *, u32);
u32 count_non_255_bytes(afl_state_t *, u8 *);
#ifdef WORD_SIZE_64
void simplify_trace(afl_state_t *, u64 *);
@ -993,8 +975,6 @@ void check_if_tty(afl_state_t *);
void setup_signal_handlers(void);
void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int);
void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
u8 *mem, u32 len);
/* CmpLog */

View File

@ -55,7 +55,6 @@ extern u8 *doc_path; /* path to documentation dir */
@returns the path, allocating the string */
u8 *find_binary(u8 *fname);
u8 *find_afl_binary(u8 *fname, u8 *own_loc);
/* Read a bitmap from file fname to memory
This is for the -B option again. */

View File

@ -28,7 +28,7 @@
/* Version string: */
// c = release, d = volatile github dev, e = experimental branch
#define VERSION "++2.66d"
#define VERSION "++2.67c"
/******************************************************
* *
@ -70,21 +70,21 @@
#ifndef __NetBSD__
#ifndef WORD_SIZE_64
#define MEM_LIMIT 25
#else
#define MEM_LIMIT 50
#else
#define MEM_LIMIT 75
#endif /* ^!WORD_SIZE_64 */
#else /* NetBSD's kernel needs more space for stack, see discussion for issue \
#165 */
#define MEM_LIMIT 200
#define MEM_LIMIT 250
#endif
/* Default memory limit when running in QEMU mode (MB): */
#define MEM_LIMIT_QEMU 200
#define MEM_LIMIT_QEMU 250
/* Default memory limit when running in Unicorn mode (MB): */
#define MEM_LIMIT_UNICORN 200
#define MEM_LIMIT_UNICORN 250
/* Number of calibration cycles per every new test case (and for test
cases that show variable behavior): */

View File

@ -123,7 +123,6 @@ static char *afl_environment_variables[] = {
"AFL_SKIP_BIN_CHECK",
"AFL_SKIP_CPUFREQ",
"AFL_SKIP_CRASHES",
"AFL_TAINT_INPUT",
"AFL_TMIN_EXACT",
"AFL_TMPDIR",
"AFL_TOKEN_FILE",

View File

@ -80,8 +80,6 @@ typedef struct afl_forkserver {
u8 qemu_mode; /* if running in qemu mode or not */
u8 taint_mode; /* if running taint analysis or not */
u32 *shmem_fuzz_len; /* length of the fuzzing test case */
u8 *shmem_fuzz; /* allocated memory for fuzzing */

View File

@ -103,6 +103,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
std::vector<std::string> dictionary;
std::vector<CallInst *> calls;
DenseMap<Value *, std::string *> valueMap;
std::vector<BasicBlock *> BlockList;
char * ptr;
FILE * documentFile = NULL;
@ -297,7 +298,7 @@ bool AFLLTOPass::runOnModule(Module &M) {
bool isStrncasecmp = true;
bool isIntMemcpy = true;
bool addedNull = false;
uint8_t optLen = 0;
size_t optLen = 0;
Function *Callee = callInst->getCalledFunction();
if (!Callee) continue;
@ -310,6 +311,24 @@ bool AFLLTOPass::runOnModule(Module &M) {
isStrncasecmp &= !FuncName.compare("strncasecmp");
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
/* we do something different here, putting this BB and the
successors in a block map */
if (!FuncName.compare("__afl_persistent_loop")) {
BlockList.push_back(&BB);
/*
for (succ_iterator SI = succ_begin(&BB), SE =
succ_end(&BB); SI != SE; ++SI) {
BasicBlock *succ = *SI;
BlockList.push_back(succ);
}
*/
}
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
!isStrncasecmp && !isIntMemcpy)
continue;
@ -527,18 +546,27 @@ bool AFLLTOPass::runOnModule(Module &M) {
// add null byte if this is a string compare function and a null
// was not already added
if (addedNull == false && !isMemcmp) {
if (!isMemcmp) {
if (addedNull == false) {
thestring.append("\0", 1); // add null byte
optLen++;
}
// ensure we do not have garbage
size_t offset = thestring.find('\0', 0);
if (offset + 1 < optLen) optLen = offset + 1;
thestring = thestring.substr(0, optLen);
}
if (!be_quiet) {
std::string outstring;
fprintf(stderr, "%s: length %u/%u \"", FuncName.c_str(), optLen,
(unsigned int)thestring.length());
fprintf(stderr, "%s: length %zu/%zu \"", FuncName.c_str(), optLen,
thestring.length());
for (uint8_t i = 0; i < thestring.length(); i++) {
uint8_t c = thestring[i];
@ -603,6 +631,28 @@ bool AFLLTOPass::runOnModule(Module &M) {
uint32_t fs = origBB->getParent()->size();
uint32_t countto;
if (BlockList.size()) {
int skip = 0;
for (uint32_t k = 0; k < BlockList.size(); k++) {
if (origBB == BlockList[k]) {
if (debug)
fprintf(
stderr,
"DEBUG: Function %s skipping BB with/after __afl_loop\n",
F.getName().str().c_str());
skip = 1;
}
}
if (skip) continue;
}
for (succ_iterator SI = succ_begin(origBB), SE = succ_end(origBB);
SI != SE; ++SI) {

View File

@ -107,6 +107,10 @@ struct cmp_map *__afl_cmp_map;
static u8 is_persistent;
/* Are we in sancov mode? */
static u8 _is_sancov;
/* Error reporting to forkserver controller */
void send_forkserver_error(int error) {
@ -190,19 +194,10 @@ static void __afl_map_shm(void) {
if (__afl_final_loc) {
if (__afl_area_ptr && __afl_final_loc &&
__afl_final_loc > MAP_INITIAL_SIZE &&
__afl_area_ptr != __afl_area_initial) {
munmap(__afl_area_ptr, __afl_final_loc);
__afl_area_ptr = __afl_area_initial;
}
if (__afl_final_loc % 8)
__afl_final_loc = (((__afl_final_loc + 7) >> 3) << 3);
__afl_map_size = __afl_final_loc;
if (__afl_final_loc > MAP_SIZE) {
char *ptr;
@ -212,10 +207,12 @@ static void __afl_map_shm(void) {
if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
if (!getenv("AFL_QUIET"))
fprintf(stderr,
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
"be able to run this instrumented program!\n",
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
"to be able to run this instrumented program!\n",
__afl_final_loc);
if (id_str) {
send_forkserver_error(FS_ERROR_MAP_SIZE);
@ -225,9 +222,10 @@ static void __afl_map_shm(void) {
} else {
if (!getenv("AFL_QUIET"))
fprintf(stderr,
"Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
"be able to run this instrumented program!\n",
"Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u "
"to be able to run this instrumented program!\n",
__afl_final_loc);
}
@ -244,13 +242,25 @@ static void __afl_map_shm(void) {
if (getenv("AFL_DEBUG"))
fprintf(stderr,
"DEBUG: id_str %s, __afl_map_addr 0x%llx, MAP_SIZE %u, "
"__afl_final_loc %u, max_size_forkserver %u/0x%x\n",
id_str == NULL ? "<null>" : id_str, __afl_map_addr, MAP_SIZE,
__afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
"DEBUG: id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
"__afl_map_addr 0x%llx, MAP_SIZE %u, __afl_final_loc %u, "
"max_size_forkserver %u/0x%x\n",
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
__afl_area_initial, __afl_map_addr, MAP_SIZE, __afl_final_loc,
FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
if (id_str) {
if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
if (__afl_map_addr)
munmap((void *)__afl_map_addr, __afl_final_loc);
else
free(__afl_area_ptr);
__afl_area_ptr = __afl_area_initial;
}
#ifdef USEMMAP
const char * shm_file_path = id_str;
int shm_fd = -1;
@ -319,11 +329,14 @@ static void __afl_map_shm(void) {
__afl_area_ptr[0] = 1;
} else if (__afl_map_addr) {
} else if ((!__afl_area_ptr || __afl_area_ptr == __afl_area_initial) &&
__afl_map_addr) {
__afl_area_ptr =
mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (__afl_area_ptr == MAP_FAILED) {
fprintf(stderr, "can not aquire mmap for address %p\n",
@ -332,6 +345,14 @@ static void __afl_map_shm(void) {
}
} else if (_is_sancov && __afl_area_ptr != __afl_area_initial) {
free(__afl_area_ptr);
__afl_area_ptr = NULL;
if (__afl_final_loc > MAP_INITIAL_SIZE)
__afl_area_ptr = malloc(__afl_final_loc);
if (!__afl_area_ptr) __afl_area_ptr = __afl_area_initial;
}
id_str = getenv(CMPLOG_SHM_ENV_VAR);
@ -888,29 +909,50 @@ __attribute__((constructor())) void __afl_auto_init(void) {
__attribute__((constructor(CTOR_PRIO))) void __afl_auto_early(void) {
if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
is_persistent = !!getenv(PERSIST_ENV_VAR);
if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
__afl_map_shm();
}
/* preset __afl_area_ptr */
/* preset __afl_area_ptr #2 */
__attribute__((constructor(1))) void __afl_auto_second(void) {
if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
u8 *ptr;
if (__afl_final_loc) {
if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial)
free(__afl_area_ptr);
if (__afl_map_addr)
ptr = (u8 *)mmap((void *)__afl_map_addr, __afl_final_loc,
PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
else
ptr = (u8 *)malloc(__afl_final_loc);
if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
}
}
/* preset __afl_area_ptr #1 - at constructor level 0 global variables have
not been set */
__attribute__((constructor(0))) void __afl_auto_first(void) {
if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
u8 *ptr;
if (__afl_final_loc > MAP_INITIAL_SIZE) {
ptr = (u8 *)malloc(1024000);
ptr = (u8 *)mmap(NULL, __afl_final_loc, PROT_READ | PROT_WRITE, MAP_PRIVATE,
-1, 0);
if (ptr && (ssize_t)ptr != -1) { __afl_area_ptr = ptr; }
}
if (ptr && (ssize_t)ptr != -1) __afl_area_ptr = ptr;
}
@ -978,6 +1020,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
u32 inst_ratio = 100;
char *x;
_is_sancov = 1;
if (getenv("AFL_DEBUG")) {
fprintf(stderr, "Running __sanitizer_cov_trace_pc_guard_init: %p-%p\n",

View File

@ -1,42 +0,0 @@
# qemu_taint
First level taint implementation with qemu for linux user mode
**THIS IS NOT WORKING YET** **WIP**
## What is this for
On new queue entries (newly discovered paths into the target) this tainter
is run with the new input and the data gathered which bytes in the input
file are actually touched.
Only touched bytes are then fuzzed by afl-fuzz
## How to build
./build_qemu_taint.sh
## How to use
Add the -A flag to afl-fuzz
## Caveats
For some targets this is amazing and improves fuzzing a lot, but if a target
copies all input bytes first (e.g. for creating a crc checksum or just to
safely work with the data), then this is not helping at all.
## Future
Two fuzz modes for a queue entry which will be switched back and forth:
1. fuzz all touched bytes
2. fuzz only bytes that are newly touched (compared to the one this queue
entry is based on)
## TODO
* Direct trim: trim to highest touched byte, that is all we need to do
* add 5-25% dummy bytes to the queue entries? (maybe create a 2nd one?)
* Disable trim?

View File

@ -1,7 +0,0 @@
#!/bin/bash
test -d qemu || git clone https://github.com/vanhauser-thc/qemu_taint qemu || exit 1
cd qemu || exit 1
test -d .git && { git stash ; git pull ; }
cp -fv ../../include/config.h ../../include/types.h . || exit 1
./build.sh || exit 1
cp -fv ./afl-qemu-taint ../..

View File

@ -1,3 +0,0 @@
#!/bin/sh
rm -f afl-qemu-taint qemu/afl-qemu-taint ../afl-qemu-taint
test -d qemu && { cd qemu ; ./clean.sh ; }

View File

@ -138,59 +138,12 @@ void argv_cpy_free(char **argv) {
}
u8 *find_afl_binary(u8 *fname, u8 *own_loc) {
u8 *tmp, *rsl, *own_copy, *cp;
tmp = getenv("AFL_PATH");
if (tmp) {
cp = alloc_printf("%s/%s", tmp, fname);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
return cp;
}
if (own_loc) {
own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
cp = alloc_printf("%s/%s", own_copy, fname);
ck_free(own_copy);
if (!access(cp, X_OK)) { return cp; }
} else {
ck_free(own_copy);
}
}
cp = alloc_printf("%s/%s", BIN_PATH, fname);
if (!access(cp, X_OK)) { return cp; }
ck_free(cp);
return NULL;
}
/* Rewrite argv for QEMU. */
char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
u8 * cp = NULL;
u8 * tmp, *cp = NULL, *rsl, *own_copy;
memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
new_argv[argc - 1] = NULL;
@ -200,15 +153,51 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
/* Now we need to actually find the QEMU binary to put in argv[0]. */
cp = find_afl_binary("afl-qemu-trace", own_loc);
tmp = getenv("AFL_PATH");
if (cp) {
if (tmp) {
cp = alloc_printf("%s/afl-qemu-trace", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
*target_path_p = new_argv[0] = cp;
return new_argv;
}
own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
cp = alloc_printf("%s/afl-qemu-trace", own_copy);
ck_free(own_copy);
if (!access(cp, X_OK)) {
*target_path_p = new_argv[0] = cp;
return new_argv;
}
} else {
ck_free(own_copy);
}
if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
if (cp) { ck_free(cp); }
*target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace");
return new_argv;
}
SAYF("\n" cLRD "[-] " cRST
"Oops, unable to find the 'afl-qemu-trace' binary. The binary must be "
"built\n"
@ -236,7 +225,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
u8 * cp = NULL;
u8 * tmp, *cp = NULL, *rsl, *own_copy;
memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
new_argv[argc - 1] = NULL;
@ -245,14 +234,41 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
/* Now we need to actually find the QEMU binary to put in argv[0]. */
cp = find_afl_binary("afl-qemu-trace", own_loc);
tmp = getenv("AFL_PATH");
if (cp) {
if (tmp) {
cp = alloc_printf("%s/afl-qemu-trace", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
ck_free(cp);
cp = find_afl_binary("afl-wine-trace", own_loc);
if (cp) {
cp = alloc_printf("%s/afl-wine-trace", tmp);
if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); }
*target_path_p = new_argv[0] = cp;
return new_argv;
}
own_copy = ck_strdup(own_loc);
rsl = strrchr(own_copy, '/');
if (rsl) {
*rsl = 0;
cp = alloc_printf("%s/afl-qemu-trace", own_copy);
if (cp && !access(cp, X_OK)) {
ck_free(cp);
cp = alloc_printf("%s/afl-wine-trace", own_copy);
if (!access(cp, X_OK)) {
*target_path_p = new_argv[0] = cp;
return new_argv;
@ -261,22 +277,49 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
}
ck_free(own_copy);
} else {
ck_free(own_copy);
}
u8 *ncp = BIN_PATH "/afl-qemu-trace";
if (!access(ncp, X_OK)) {
ncp = BIN_PATH "/afl-wine-trace";
if (!access(ncp, X_OK)) {
*target_path_p = new_argv[0] = ck_strdup(ncp);
return new_argv;
}
}
SAYF("\n" cLRD "[-] " cRST
"Oops, unable to find the afl-qemu-trace and afl-wine-trace binaries.\n"
"The afl-qemu-trace binary must be built separately by following the "
"instructions\n"
"in qemu_mode/README.md. If you already have the binary installed, you "
"may need\n"
"to specify the location via AFL_PATH in the environment.\n\n"
"Oops, unable to find the '%s' binary. The binary must be "
"built\n"
" separately by following the instructions in "
"qemu_mode/README.md. "
"If you\n"
" already have the binary installed, you may need to specify "
"AFL_PATH in the\n"
" environment.\n\n"
" Of course, even without QEMU, afl-fuzz can still work with "
"binaries that are\n"
" instrumented at compile time with afl-gcc. It is also possible to "
"use it as a\n"
" traditional non-instrumented fuzzer by specifying '-n' in the "
"command "
"line.\n");
"line.\n",
ncp);
FATAL("Failed to locate 'afl-qemu-trace' and 'afl-wine-trace'.");
FATAL("Failed to locate '%s'.", ncp);
}

View File

@ -498,21 +498,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
char pid_buf[16];
sprintf(pid_buf, "%d", fsrv->fsrv_pid);
if (fsrv->taint_mode) {
setenv("__AFL_TARGET_PID3", pid_buf, 1);
} else if (fsrv->cmplog_binary) {
if (fsrv->cmplog_binary)
setenv("__AFL_TARGET_PID2", pid_buf, 1);
} else {
else
setenv("__AFL_TARGET_PID1", pid_buf, 1);
}
/* Close the unneeded endpoints. */
close(ctl_pipe[0]);
@ -947,7 +937,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
} else {
s32 fd;
s32 fd = fsrv->out_fd;
if (fsrv->out_file) {
@ -966,7 +956,6 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
} else {
fd = fsrv->out_fd;
lseek(fd, 0, SEEK_SET);
}

View File

@ -177,40 +177,6 @@ u32 count_bits(afl_state_t *afl, u8 *mem) {
}
u32 count_bits_len(afl_state_t *afl, u8 *mem, u32 len) {
u32 *ptr = (u32 *)mem;
u32 i = (len >> 2);
u32 ret = 0;
(void)(afl);
if (len % 4) i++;
while (i--) {
u32 v = *(ptr++);
/* This gets called on the inverse, virgin bitmap; optimize for sparse
data. */
if (v == 0xffffffff) {
ret += 32;
continue;
}
v -= ((v >> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
ret += (((v + (v >> 4)) & 0xF0F0F0F) * 0x01010101) >> 24;
}
return ret;
}
/* Count the number of bytes set in the bitmap. Called fairly sporadically,
mostly to update the status screen or calibrate and examine confirmed
new paths. */
@ -237,32 +203,6 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) {
}
u32 count_bytes_len(afl_state_t *afl, u8 *mem, u32 len) {
u32 *ptr = (u32 *)mem;
u32 i = (len >> 2);
u32 ret = 0;
(void)(afl);
if (len % 4) i++;
while (i--) {
u32 v = *(ptr++);
if (!v) { continue; }
if (v & 0x000000ff) { ++ret; }
if (v & 0x0000ff00) { ++ret; }
if (v & 0x00ff0000) { ++ret; }
if (v & 0xff000000) { ++ret; }
}
return ret;
}
/* Count the number of non-255 bytes set in the bitmap. Used strictly for the
status screen, several calls per second or so. */
@ -655,7 +595,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#endif /* ^!SIMPLE_FILES */
add_to_queue(afl, queue_fn, mem, len, afl->queue_top, 0);
add_to_queue(afl, queue_fn, len, 0);
if (hnb == 2) {

View File

@ -712,7 +712,7 @@ void read_testcases(afl_state_t *afl) {
if (!access(dfn, F_OK)) { passed_det = 1; }
add_to_queue(afl, fn2, NULL, st.st_size, NULL, passed_det);
add_to_queue(afl, fn2, st.st_size, passed_det);
}
@ -771,13 +771,9 @@ void perform_dry_run(afl_state_t *afl) {
close(fd);
res = calibrate_case(afl, q, use_mem, 0, 1);
if (afl->stop_soon) {
ck_free(use_mem);
return;
}
if (afl->stop_soon) { return; }
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
@ -964,10 +960,6 @@ void perform_dry_run(afl_state_t *afl) {
}
/* perform taint gathering on the input seed */
if (afl->taint_mode) perform_taint_run(afl, q, q->fname, use_mem, q->len);
ck_free(use_mem);
q = q->next;
}
@ -1446,10 +1438,6 @@ static void handle_existing_out_dir(afl_state_t *afl) {
u8 *orig_q = alloc_printf("%s/queue", afl->out_dir);
u8 *fnt = alloc_printf("%s/taint", afl->out_dir);
mkdir(fnt, 0755); // ignore errors
ck_free(fnt);
afl->in_dir = alloc_printf("%s/_resume", afl->out_dir);
rename(orig_q, afl->in_dir); /* Ignore errors */
@ -1506,20 +1494,6 @@ static void handle_existing_out_dir(afl_state_t *afl) {
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
ck_free(fn);
if (afl->taint_mode) {
fn = alloc_printf("%s/taint", afl->out_dir);
mkdir(fn, 0755); // ignore errors
u8 *fn2 = alloc_printf("%s/taint/.input", afl->out_dir);
unlink(fn2); // ignore errors
ck_free(fn2);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
ck_free(fn);
}
/* All right, let's do <afl->out_dir>/crashes/id:* and
* <afl->out_dir>/hangs/id:*. */
@ -1747,16 +1721,6 @@ void setup_dirs_fds(afl_state_t *afl) {
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
/* Taint directory if taint_mode. */
if (afl->taint_mode) {
tmp = alloc_printf("%s/taint", afl->out_dir);
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
ck_free(tmp);
}
/* Top-level directory for queue metadata used for session
resume and related tasks. */

View File

@ -95,7 +95,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) {
default:
if (rand_below(afl, 10)) {
if (likely(rand_below(afl, 10))) {
min_value = HAVOC_BLK_MEDIUM;
max_value = HAVOC_BLK_LARGE;
@ -421,7 +421,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (((afl->queue_cur->was_fuzzed > 0 || afl->queue_cur->fuzz_level > 0) ||
!afl->queue_cur->favored) &&
rand_below(afl, 100) < SKIP_TO_NEW_PROB) {
likely(rand_below(afl, 100) < SKIP_TO_NEW_PROB)) {
return 1;
@ -438,11 +438,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (afl->queue_cycle > 1 &&
(afl->queue_cur->fuzz_level == 0 || afl->queue_cur->was_fuzzed)) {
if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) { return 1; }
if (likely(rand_below(afl, 100) < SKIP_NFAV_NEW_PROB)) { return 1; }
} else {
if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) { return 1; }
if (likely(rand_below(afl, 100) < SKIP_NFAV_OLD_PROB)) { return 1; }
}
@ -458,147 +458,6 @@ u8 fuzz_one_original(afl_state_t *afl) {
}
u32 tmp_val = 0;
if (unlikely(afl->taint_mode)) {
tmp_val = afl->queue_cycle % 2; // starts with 1
ret_val = 0;
if (unlikely(afl->queue_cur->cal_failed && !tmp_val)) goto abandon_entry;
if (unlikely(!afl->skip_deterministic && !afl->queue_cur->passed_det &&
!tmp_val))
goto abandon_entry;
if ((!afl->queue_cur->taint_bytes_new ||
afl->queue_cur->taint_bytes_new == afl->queue_cur->len) &&
!tmp_val)
goto abandon_entry;
ret_val = 1;
s32 dst = 0, i;
temp_len = len = afl->queue_cur->len;
s32 j = 0; // tmp
fd = open(afl->queue_cur->fname, O_RDONLY);
afl->taint_src = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (ssize_t)afl->taint_src == -1)
FATAL("unable to open '%s'", afl->queue_cur->fname);
close(fd);
afl->taint_needs_splode = 1;
switch (tmp_val) {
case 1: // fuzz only tainted bytes
// special case: all or nothing tainted. in this case we act like
// nothing is special. this is not the taint you are looking for ...
if (!afl->queue_cur->taint_bytes_all ||
afl->queue_cur->taint_bytes_all == (u32)len) {
orig_in = in_buf = afl->taint_src;
afl->taint_needs_splode = 0;
break;
}
fd = open(afl->taint_input_file, O_RDONLY);
temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_all;
orig_in = in_buf =
mmap(0, len >= MAX_FILE - 65536 ? MAX_FILE : len + 65536,
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (ssize_t)in_buf == -1)
FATAL("unable to open '%s'", afl->taint_input_file);
close(fd);
fd = open(afl->queue_cur->fname_taint, O_RDONLY);
afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if (fd < 0 || (ssize_t)in_buf == -1)
FATAL("unable to open '%s'", afl->queue_cur->fname_taint);
close(fd);
for (i = 0; i < (s32)afl->queue_cur->len && dst < len; i++)
if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
// FIXME DEBUG TODO XXX
for (i = 0; i < (s32)afl->queue_cur->len; i++) {
switch (afl->taint_map[i]) {
case 0x0:
break;
case '!':
j++;
break;
default:
FATAL(
"invalid taint map entry byte 0x%02x at position %d "
"(passed_det:%d)\n",
afl->taint_map[i], i, afl->queue_cur->passed_det);
}
}
if (j != len)
FATAL("different taint values in map vs in queue (%d != %d)", j, len);
break;
case 0: // fuzz only newly tainted bytes
fd = open(afl->taint_input_file, O_RDONLY);
temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_new;
orig_in = in_buf =
mmap(0, len >= MAX_FILE - 65536 ? MAX_FILE : len + 65536,
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (fd < 0 || (ssize_t)in_buf == -1)
FATAL("unable to open '%s'", afl->taint_input_file);
close(fd);
u8 *fn = alloc_printf("%s.new", afl->queue_cur->fname_taint);
if (!fn) FATAL("OOM");
fd = open(fn, O_RDWR);
afl->taint_map = mmap(0, afl->queue_cur->len, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if (fd < 0 || (ssize_t)in_buf == -1)
FATAL("unable to open '%s' for %u bytes", fn, len);
close(fd);
ck_free(fn);
for (i = 0; i < (s32)afl->queue_cur->len && dst < len; i++)
if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
// FIXME DEBUG TODO XXX
for (i = 0; i < (s32)afl->queue_cur->len; i++) {
switch (afl->taint_map[i]) {
case 0x0:
break;
case '!':
j++;
break;
default:
FATAL(
"invalid taint map entry byte 0x%02x at position %d "
"(passed_det:%d)\n",
afl->taint_map[i], i, afl->queue_cur->passed_det);
}
}
if (j != len)
FATAL("different taint values in map vs in queue (%d != %d)", j, len);
break;
}
} else {
/* Map the test case into memory. */
fd = open(afl->queue_cur->fname, O_RDONLY);
@ -621,8 +480,6 @@ u8 fuzz_one_original(afl_state_t *afl) {
close(fd);
}
/* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every
single byte anyway, so it wouldn't give us any performance or memory usage
benefits. */
@ -645,12 +502,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->queue_cur->exec_cksum = 0;
if (unlikely(afl->taint_needs_splode))
res = calibrate_case(afl, afl->queue_cur, afl->taint_src,
afl->queue_cycle - 1, 0);
else
res = calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1,
0);
res =
calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
if (unlikely(res == FSRV_RUN_ERROR)) {
@ -674,7 +527,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
************/
if (unlikely(!afl->non_instrumented_mode && !afl->queue_cur->trim_done &&
!afl->disable_trim && !afl->taint_needs_splode)) {
!afl->disable_trim)) {
u8 res = trim_case(afl, afl->queue_cur, in_buf);
@ -709,28 +562,15 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (unlikely(perf_score == 0)) { goto abandon_entry; }
if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) {
if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
int res;
if (unlikely(afl->taint_needs_splode)) {
if (input_to_state_stage(afl, in_buf, out_buf, len,
afl->queue_cur->exec_cksum)) {
len = afl->queue_cur->len;
memcpy(out_buf, afl->taint_src, len);
res = input_to_state_stage(afl, afl->taint_src, out_buf, len,
afl->queue_cur->exec_cksum);
// just abandon as success
ret_val = 0;
res = 1;
} else {
res = input_to_state_stage(afl, in_buf, out_buf, len,
afl->queue_cur->exec_cksum);
goto abandon_entry;
}
if (unlikely(res)) { goto abandon_entry; }
}
/* Skip right away if -d is given, if it has not been chosen sufficiently
@ -751,8 +591,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
/* Skip deterministic fuzzing if exec path checksum puts this out of scope
for this main instance. */
if (afl->main_node_max && (afl->queue_cur->exec_cksum % afl->main_node_max) !=
afl->main_node_id - 1) {
if (unlikely(afl->main_node_max &&
(afl->queue_cur->exec_cksum % afl->main_node_max) !=
afl->main_node_id - 1)) {
goto custom_mutator_stage;
@ -2291,21 +2132,11 @@ havoc_stage:
u32 clone_from, clone_to, clone_len;
u8 *new_buf;
if (actually_clone) {
if (unlikely(afl->taint_needs_splode)) {
clone_len = choose_block_len(afl, afl->queue_cur->len);
clone_from =
rand_below(afl, afl->queue_cur->len - clone_len + 1);
} else {
if (likely(actually_clone)) {
clone_len = choose_block_len(afl, temp_len);
clone_from = rand_below(afl, temp_len - clone_len + 1);
}
} else {
clone_len = choose_block_len(afl, HAVOC_BLK_XL);
@ -2324,12 +2155,8 @@ havoc_stage:
/* Inserted part */
if (actually_clone) {
if (likely(actually_clone)) {
if (unlikely(afl->taint_needs_splode))
memcpy(new_buf + clone_to, afl->taint_src + clone_from,
clone_len);
else
memcpy(new_buf + clone_to, out_buf + clone_from, clone_len);
} else {
@ -2342,7 +2169,7 @@ havoc_stage:
}
/* Tail */
memmove(new_buf + clone_to + clone_len, out_buf + clone_to,
memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
temp_len - clone_to);
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
@ -2363,52 +2190,19 @@ havoc_stage:
if (temp_len < 2) { break; }
if (unlikely(afl->taint_needs_splode)) {
copy_len = choose_block_len(afl, afl->queue_cur->len - 1);
copy_from = rand_below(afl, afl->queue_cur->len - copy_len + 1);
copy_to = rand_below(afl, temp_len + 1);
} else {
copy_len = choose_block_len(afl, temp_len - 1);
copy_from = rand_below(afl, temp_len - copy_len + 1);
copy_to = rand_below(afl, temp_len - copy_len + 1);
}
if (rand_below(afl, 4)) {
if (likely(rand_below(afl, 4))) {
if (copy_from != copy_to) {
if (unlikely(afl->taint_needs_splode)) {
if (temp_len >= (s32)(copy_to + copy_len)) {
memcpy(out_buf + copy_to, afl->taint_src + copy_from,
copy_len);
} else {
u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
copy_to + copy_len);
memcpy(new_buf, in_buf, copy_to);
memcpy(new_buf + copy_to, afl->taint_src + copy_from,
copy_len);
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
out_buf = new_buf;
temp_len = copy_to + copy_len;
}
} else {
memmove(out_buf + copy_to, out_buf + copy_from, copy_len);
}
}
} else {
memset(out_buf + copy_to,
@ -2671,17 +2465,10 @@ havoc_stage:
splices them together at some offset, then relies on the havoc
code to mutate that blob. */
u32 saved_len;
if (unlikely(afl->taint_needs_splode))
saved_len = afl->taint_len;
else
saved_len = afl->queue_cur->len;
retry_splicing:
if (afl->use_splicing && splice_cycle++ < SPLICE_CYCLES &&
afl->queued_paths > 1 && saved_len > 1) {
afl->queued_paths > 1 && afl->queue_cur->len > 1) {
struct queue_entry *target;
u32 tid, split_at;
@ -2694,7 +2481,7 @@ retry_splicing:
if (in_buf != orig_in) {
in_buf = orig_in;
len = saved_len;
len = afl->queue_cur->len;
}
@ -2765,8 +2552,6 @@ retry_splicing:
ret_val = 0;
goto abandon_entry;
/* we are through with this queue entry - for this iteration */
abandon_entry:
@ -2786,18 +2571,8 @@ abandon_entry:
++afl->queue_cur->fuzz_level;
if (unlikely(afl->taint_needs_splode)) {
munmap(afl->taint_src, afl->queue_cur->len);
munmap(orig_in, afl->taint_len);
munmap(afl->taint_map, afl->queue_cur->len);
} else {
munmap(orig_in, afl->queue_cur->len);
}
return ret_val;
#undef FLIP_BIT
@ -2979,7 +2754,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
orig_perf = perf_score = calculate_score(afl, afl->queue_cur);
if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) {
if (unlikely(afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized)) {
if (input_to_state_stage(afl, in_buf, out_buf, len,
afl->queue_cur->exec_cksum)) {

View File

@ -103,169 +103,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
}
void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
u8 *mem, u32 len) {
u8 * ptr, *fn = fname;
u32 bytes = 0, plen = len;
struct queue_entry *prev = q->prev;
if (plen % 4) plen = plen + 4 - (len % 4);
if ((ptr = strrchr(fname, '/')) != NULL) fn = ptr + 1;
q->fname_taint = alloc_printf("%s/taint/%s", afl->out_dir, fn);
if (q->fname_taint) {
u8 *save = ck_maybe_grow(BUF_PARAMS(out_scratch), afl->fsrv.map_size);
memcpy(save, afl->taint_fsrv.trace_bits, afl->fsrv.map_size);
afl->taint_fsrv.map_size = plen; // speed :)
write_to_testcase(afl, mem, len);
if (afl_fsrv_run_target(&afl->taint_fsrv, afl->fsrv.exec_tmout * 4,
&afl->stop_soon) == 0) {
bytes = q->taint_bytes_all =
count_bytes_len(afl, afl->taint_fsrv.trace_bits, plen);
if (afl->debug)
fprintf(stderr, "Debug: tainted %u out of %u bytes\n", bytes, len);
/* DEBUG FIXME TODO XXX */
u32 i;
for (i = 0; i < len; i++) {
if (afl->taint_fsrv.trace_bits[i] &&
afl->taint_fsrv.trace_bits[i] != '!')
FATAL("invalid taint map value %02x at pos %d",
afl->taint_fsrv.trace_bits[i], i);
}
if (len < plen)
for (i = len; i < plen; i++) {
if (afl->taint_fsrv.trace_bits[i])
FATAL("invalid taint map value %02x in padding at pos %d",
afl->taint_fsrv.trace_bits[i], i);
}
}
// if all is tainted we do not need to write taint data away
if (bytes && bytes < len) {
// save the bytes away
int w = open(q->fname_taint, O_CREAT | O_WRONLY, 0644);
if (w >= 0) {
ck_write(w, afl->taint_fsrv.trace_bits, len, q->fname_taint);
close(w);
// find the highest tainted offset in the input (for trim opt)
s32 i = len;
while (i > 0 && !afl->taint_fsrv.trace_bits[i - 1])
i--;
q->taint_bytes_highest = i;
afl->taint_count++;
} else {
FATAL("could not create %s", q->fname_taint);
q->taint_bytes_all = bytes = 0;
}
// it is possible that there is no main taint file - if the whole file
// is tainted - but a .new taint file if it had new tainted bytes
// check if there is a previous queue entry and if it had taint
if (bytes && prev && prev->taint_bytes_all &&
prev->taint_bytes_all < prev->len) {
// check if there are new bytes in the taint vs the previous
int r = open(prev->fname_taint, O_RDONLY);
if (r >= 0) {
u8 *bufr = mmap(0, prev->len, PROT_READ, MAP_PRIVATE, r, 0);
if ((ssize_t)bufr != -1) {
u32 i;
u8 *tmp = ck_maybe_grow(BUF_PARAMS(in_scratch), plen);
memset(tmp, 0, plen);
for (i = 0; i < len; i++)
if (afl->taint_fsrv.trace_bits[i] && (i >= prev->len || !bufr[i]))
tmp[i] = '!';
q->taint_bytes_new = count_bytes_len(afl, tmp, plen);
if (afl->debug)
fprintf(stderr, "Debug: %u new taint out of %u bytes\n", bytes,
len);
if (q->taint_bytes_new) {
u8 *fnw = alloc_printf("%s.new", q->fname_taint);
if (fnw) {
int w = open(fnw, O_CREAT | O_WRONLY, 0644);
if (w >= 0) {
ck_write(w, tmp, plen, fnw);
close(w);
} else {
FATAL("count not create '%s'", fnw);
q->taint_bytes_new = 0;
}
ck_free(fnw);
} else {
q->taint_bytes_new = 0;
}
}
munmap(bufr, prev->len);
}
close(r);
}
}
}
memcpy(afl->taint_fsrv.trace_bits, save, afl->fsrv.map_size);
}
if (!bytes) {
q->taint_bytes_highest = q->taint_bytes_all = q->taint_bytes_new = 0;
if (q->fname_taint) {
ck_free(q->fname_taint);
q->fname_taint = NULL;
}
}
}
/* check if ascii or UTF-8 */
static u8 check_if_text(struct queue_entry *q) {
@ -375,12 +212,10 @@ static u8 check_if_text(struct queue_entry *q) {
/* Append new test case to the queue. */
void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len,
struct queue_entry *prev_q, u8 passed_det) {
void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
struct queue_entry *q = ck_alloc(sizeof(struct queue_entry));
q->prev = prev_q;
q->fname = fname;
q->len = len;
q->depth = afl->cur_depth + 1;
@ -419,13 +254,6 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len,
afl->last_path_time = get_cur_time();
/* trigger the tain gathering if this is not a dry run */
if (afl->taint_mode && mem) { perform_taint_run(afl, q, fname, mem, len); }
/* only redqueen currently uses is_ascii */
if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q);
/* run custom mutators afl_custom_queue_new_entry() */
if (afl->custom_mutators_count) {
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
@ -445,6 +273,9 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u8 *mem, u32 len,
}
/* only redqueen currently uses is_ascii */
if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(q);
}
/* Destroy the entire queue. */

View File

@ -350,9 +350,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
if (unlikely(afl->taint_mode))
q->exec_cksum = 0;
else if (q->exec_cksum) {
if (q->exec_cksum) {
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
hnb = has_new_bits(afl, afl->virgin_bits);
@ -755,10 +753,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
while (remove_pos < q->len) {
u32 trim_avail = MIN(remove_len, q->len - remove_pos);
if (likely((!q->taint_bytes_highest) ||
(q->len - trim_avail > q->taint_bytes_highest))) {
u64 cksum;
write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail);
@ -805,15 +799,10 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
/* Since this can be slow, update the screen every now and then. */
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
++afl->stage_cur;
} else {
remove_pos += remove_len;
}
}
remove_len >>= 1;
@ -866,8 +855,6 @@ abort_trimming:
}
#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
/* Write a modified test case, run program, process results. Handle
error conditions, returning 1 if it's time to bail out. This is
a helper function for fuzz_one(). */
@ -877,32 +864,6 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
u8 fault;
if (unlikely(afl->taint_needs_splode)) {
s32 new_len = afl->queue_cur->len + len - afl->taint_len;
if (new_len < 4)
new_len = 4;
else if (new_len > MAX_FILE)
new_len = MAX_FILE;
u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), new_len);
u32 i, taint = 0;
for (i = 0; i < (u32)new_len; i++) {
if (i >= afl->taint_len || i >= afl->queue_cur->len || afl->taint_map[i])
new_buf[i] = out_buf[taint++];
else
new_buf[i] = afl->taint_src[i];
}
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
out_buf = new_buf;
len = new_len;
}
write_to_testcase(afl, out_buf, len);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
@ -950,5 +911,3 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
}
#undef BUF_PARAMS

View File

@ -75,7 +75,7 @@ static list_t afl_states = {.element_prealloc_count = 0};
/* Initializes an afl_state_t. */
void afl_state_init_1(afl_state_t *afl, uint32_t map_size) {
void afl_state_init(afl_state_t *afl, uint32_t map_size) {
/* thanks to this memset, growing vars like out_buf
and out_size are NULL/0 by default. */
@ -100,6 +100,16 @@ void afl_state_init_1(afl_state_t *afl, uint32_t map_size) {
afl->cpu_aff = -1; /* Selected CPU core */
#endif /* HAVE_AFFINITY */
afl->virgin_bits = ck_alloc(map_size);
afl->virgin_tmout = ck_alloc(map_size);
afl->virgin_crash = ck_alloc(map_size);
afl->var_bytes = ck_alloc(map_size);
afl->top_rated = ck_alloc(map_size * sizeof(void *));
afl->clean_trace = ck_alloc(map_size);
afl->clean_trace_custom = ck_alloc(map_size);
afl->first_trace = ck_alloc(map_size);
afl->map_tmp_buf = ck_alloc(map_size);
afl->fsrv.use_stdin = 1;
afl->fsrv.map_size = map_size;
// afl_state_t is not available in forkserver.c
@ -151,24 +161,6 @@ void afl_state_init_1(afl_state_t *afl, uint32_t map_size) {
}
void afl_state_init_2(afl_state_t *afl, uint32_t map_size) {
afl->shm.map_size = map_size ? map_size : MAP_SIZE;
afl->virgin_bits = ck_alloc(map_size);
afl->virgin_tmout = ck_alloc(map_size);
afl->virgin_crash = ck_alloc(map_size);
afl->var_bytes = ck_alloc(map_size);
afl->top_rated = ck_alloc(map_size * sizeof(void *));
afl->clean_trace = ck_alloc(map_size);
afl->clean_trace_custom = ck_alloc(map_size);
afl->first_trace = ck_alloc(map_size);
afl->map_tmp_buf = ck_alloc(map_size);
afl->fsrv.map_size = map_size;
}
/*This sets up the environment variables for afl-fuzz into the afl_state
* struct*/

View File

@ -116,7 +116,6 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
"edges_found : %u\n"
"var_byte_count : %u\n"
"havoc_expansion : %u\n"
"tainted_inputs : %u\n"
"afl_banner : %s\n"
"afl_version : " VERSION
"\n"
@ -150,8 +149,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
#else
-1,
#endif
t_bytes, afl->var_byte_count, afl->expand_havoc, afl->taint_count,
afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
t_bytes, afl->var_byte_count, afl->expand_havoc, afl->use_banner,
afl->unicorn_mode ? "unicorn" : "",
afl->fsrv.qemu_mode ? "qemu " : "",
afl->non_instrumented_mode ? " non_instrumented " : "",
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",

View File

@ -53,9 +53,6 @@ static void at_exit() {
ptr = getenv("__AFL_TARGET_PID2");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
ptr = getenv("__AFL_TARGET_PID3");
if (ptr && *ptr && (i = atoi(ptr)) > 0) kill(i, SIGKILL);
i = 0;
while (list[i] != NULL) {
@ -92,8 +89,6 @@ static void usage(u8 *argv0, int more_help) {
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
" -A - use first level taint analysis (see "
"qemu_taint/README.md)\n"
" -p schedule - power schedules compute a seed's performance score. "
"<explore\n"
" (default), fast, coe, lin, quad, exploit, mmopt, "
@ -246,8 +241,7 @@ int main(int argc, char **argv_orig, char **envp) {
s32 opt;
u64 prev_queued = 0;
u32 sync_interval_cnt = 0, seek_to, show_help = 0, map_size = MAP_SIZE,
real_map_size = 0;
u32 sync_interval_cnt = 0, seek_to, show_help = 0, map_size = MAP_SIZE;
u8 * extras_dir = 0;
u8 mem_limit_given = 0, exit_1 = 0, debug = 0;
char **use_argv;
@ -263,7 +257,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (get_afl_env("AFL_DEBUG")) { debug = afl->debug = 1; }
map_size = get_map_size();
afl_state_init_1(afl, map_size);
afl_state_init(afl, map_size);
afl->debug = debug;
afl_fsrv_init(&afl->fsrv);
@ -283,15 +277,10 @@ int main(int argc, char **argv_orig, char **envp) {
while ((opt = getopt(
argc, argv,
"+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QANUWe:p:s:V:E:L:hRP:")) > 0) {
"+b:c:i:I:o:f:F:m:t:T:dDnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > 0) {
switch (opt) {
case 'A':
afl->taint_mode = 1;
if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; }
break;
case 'I':
afl->infoexec = optarg;
break;
@ -499,7 +488,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!optarg) { FATAL("Wrong usage of -m"); }
if (!strcmp(optarg, "none") || !strcmp(optarg, "0")) {
if (!strcmp(optarg, "none")) {
afl->fsrv.mem_limit = 0;
break;
@ -829,15 +818,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (afl->taint_mode && afl->fsrv.map_size < MAX_FILE) {
real_map_size = map_size;
map_size = MAX_FILE;
}
afl_state_init_2(afl, map_size);
if (!mem_limit_given && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
@ -845,7 +825,8 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("afl++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus");
OKF("Power schedules from github.com/mboehme/aflfast");
OKF("Python Mutator from github.com/choller/afl");
OKF("Python Mutator and llvm_mode instrument file list from "
"github.com/choller/afl");
OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL");
if (afl->sync_id && afl->is_main_node &&
@ -891,19 +872,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); }
if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
if (afl->taint_mode) { FATAL("-A and -n are mutually exclusive"); }
}
if (afl->limit_time_sig != 0 && afl->taint_mode) {
FATAL("-A and -L are mutually exclusive");
}
if (afl->unicorn_mode != 0 && afl->taint_mode) {
FATAL("-A and -U are mutually exclusive");
}
@ -1004,7 +972,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->afl_env.afl_preload) {
if (afl->fsrv.qemu_mode || afl->taint_mode) {
if (afl->fsrv.qemu_mode) {
u8 *qemu_preload = getenv("QEMU_SET_ENV");
u8 *afl_preload = getenv("AFL_PRELOAD");
@ -1100,13 +1068,6 @@ int main(int argc, char **argv_orig, char **envp) {
afl->fsrv.trace_bits =
afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
if (real_map_size && map_size != real_map_size) {
afl->fsrv.map_size = real_map_size;
if (afl->cmplog_binary) afl->cmplog_fsrv.map_size = real_map_size;
}
if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); }
memset(afl->virgin_tmout, 255, afl->fsrv.map_size);
memset(afl->virgin_crash, 255, afl->fsrv.map_size);
@ -1262,6 +1223,7 @@ int main(int argc, char **argv_orig, char **envp) {
ACTF("Spawning cmplog forkserver");
afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
// TODO: this is semi-nice
afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
@ -1272,70 +1234,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (afl->taint_mode) {
ACTF("Spawning qemu_taint forkserver");
u8 *disable = getenv("AFL_DISABLE_LLVM_INSTRUMENTATION");
setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0);
afl_fsrv_init_dup(&afl->taint_fsrv, &afl->fsrv);
afl->taint_fsrv.taint_mode = 1;
afl->taint_fsrv.trace_bits = afl->fsrv.trace_bits;
ck_free(afl->taint_fsrv.target_path);
afl->argv_taint = ck_alloc(sizeof(char *) * (argc + 4 - optind));
afl->taint_fsrv.target_path = find_afl_binary("afl-qemu-taint", argv[0]);
afl->argv_taint[0] = find_afl_binary("afl-qemu-taint", argv[0]);
if (!afl->argv_taint[0])
FATAL(
"Cannot find 'afl-qemu-taint', read qemu_taint/README.md on how to "
"build it.");
u32 idx = optind - 1, offset = 0;
do {
idx++;
offset++;
afl->argv_taint[offset] = argv[idx];
} while (argv[idx] != NULL);
if (afl->fsrv.use_stdin)
unsetenv("AFL_TAINT_INPUT");
else
setenv("AFL_TAINT_INPUT", afl->fsrv.out_file, 1);
afl_fsrv_start(&afl->taint_fsrv, afl->argv_taint, &afl->stop_soon,
afl->afl_env.afl_debug_child_output);
afl->taint_input_file = alloc_printf("%s/taint/.input", afl->out_dir);
int fd = open(afl->taint_input_file, O_CREAT | O_TRUNC | O_RDWR, 0644);
if (fd < 0)
FATAL("Cannot create taint inpu file '%s'", afl->taint_input_file);
lseek(fd, MAX_FILE, SEEK_SET);
ck_write(fd, "\0", 1, afl->taint_input_file);
if (!disable) unsetenv("AFL_DISABLE_LLVM_INSTRUMENTATION");
OKF("Taint forkserver successfully started");
const rlim_t kStackSize = 128L * 1024L * 1024L; // min stack size = 128 Mb
struct rlimit rl;
rl.rlim_cur = kStackSize;
if (getrlimit(RLIMIT_STACK, &rl) != 0)
WARNF("Setting a higher stack size failed!");
#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
u8 *tmp1 = ck_maybe_grow(BUF_PARAMS(eff), MAX_FILE + 4096);
u8 *tmp2 = ck_maybe_grow(BUF_PARAMS(ex), MAX_FILE + 4096);
u8 *tmp3 = ck_maybe_grow(BUF_PARAMS(in_scratch), MAX_FILE + 4096);
u8 *tmp4 = ck_maybe_grow(BUF_PARAMS(out), MAX_FILE + 4096);
u8 *tmp5 = ck_maybe_grow(BUF_PARAMS(out_scratch), MAX_FILE + 4096);
#undef BUF_PARAMS
if (!tmp1 || !tmp2 || !tmp3 || !tmp4 || !tmp5)
FATAL("memory issues. me hungry, feed me!");
}
perform_dry_run(afl);
cull_queue(afl);
@ -1410,7 +1308,7 @@ int main(int argc, char **argv_orig, char **envp) {
break;
case 1:
if (afl->limit_time_sig == 0 && !afl->custom_only &&
!afl->python_only && !afl->taint_mode) {
!afl->python_only) {
afl->limit_time_sig = -1;
afl->limit_time_puppet = 0;
@ -1598,11 +1496,8 @@ stop_fuzzing:
}
if (afl->cmplog_binary) afl_fsrv_deinit(&afl->cmplog_fsrv);
if (afl->taint_mode) afl_fsrv_deinit(&afl->taint_fsrv);
afl_fsrv_deinit(&afl->fsrv);
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
if (afl->argv_taint) { ck_free(afl->argv_taint); }
ck_free(afl->fsrv.target_path);
ck_free(afl->fsrv.out_file);
ck_free(afl->sync_id);