mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 06:42:42 +00:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
9b701605a7 | |||
a6d3b33902 | |||
1ef94511eb | |||
757beb547e | |||
e935c40e1e | |||
c8b066b168 | |||
2d279f05dd | |||
befd6b2be4 | |||
982f15d939 | |||
e2a3c560dc | |||
a8346a2412 | |||
0dc2af0ecb | |||
eb85fe7b08 | |||
bf4d01e549 | |||
fa0ce5f51f | |||
4c0212a054 | |||
f375b69e26 | |||
17aa6b942a | |||
5f47ef406a | |||
10ccd9a97b |
12
README.md
12
README.md
@ -1,7 +1,5 @@
|
||||
# qemu_taint variant.
|
||||
|
||||
UPDATE: **WORKS NOW** **PLEASE TEST** **:-)**
|
||||
|
||||
## HOWTO
|
||||
|
||||
cd qemu_taint && ./build_qemu_taint.sh
|
||||
@ -10,13 +8,15 @@ afl-fuzz -A ...
|
||||
|
||||
## CAVEATS
|
||||
|
||||
* llvm shmem persistent mode does not and can not not work
|
||||
** Tests have shown that taint is rarely helping, in approx 20-30% of cases
|
||||
and there only slightly, hence this is not further followed-up **
|
||||
|
||||
**There is still a bug somewhere which can crash afl-fuzz :-(**
|
||||
|
||||
* llvm shmem persistent mode does not and cannot 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
|
||||
|
||||
|
@ -106,7 +106,7 @@ 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 = 0;
|
||||
|
||||
// libFuzzer interface is thin, so we don't include any libFuzzer headers.
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
|
||||
@ -283,11 +283,7 @@ 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_manual_init();
|
||||
|
||||
}
|
||||
if (!getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) { __afl_manual_init(); }
|
||||
|
||||
return ExecuteFilesOnyByOne(argc, argv);
|
||||
|
||||
|
@ -515,7 +515,7 @@ typedef struct afl_state {
|
||||
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;
|
||||
taint_len, taint_count, taint_runs;
|
||||
|
||||
u64 total_crashes, /* Total number of crashes */
|
||||
unique_crashes, /* Crashes with unique signatures */
|
||||
|
@ -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): */
|
||||
|
@ -282,13 +282,14 @@
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define ck_read(fd, buf, len, fn) \
|
||||
do { \
|
||||
\
|
||||
s32 _len = (s32)(len); \
|
||||
s32 _res = read(fd, buf, _len); \
|
||||
if (_res != _len) RPFATAL(_res, "Short read from %s", fn); \
|
||||
\
|
||||
#define ck_read(fd, buf, len, fn) \
|
||||
do { \
|
||||
\
|
||||
s32 _len = (s32)(len); \
|
||||
s32 _res = read(fd, buf, _len); \
|
||||
if (_res != _len) \
|
||||
RPFATAL(_res, "Short read from %s, %d < %d", fn, _res, (s32)_len); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif /* ! _HAVE_DEBUG_H */
|
||||
|
@ -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) {
|
||||
|
||||
fprintf(stderr,
|
||||
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
|
||||
"be able to run this instrumented program!\n",
|
||||
__afl_final_loc);
|
||||
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",
|
||||
__afl_final_loc);
|
||||
|
||||
if (id_str) {
|
||||
|
||||
send_forkserver_error(FS_ERROR_MAP_SIZE);
|
||||
@ -225,10 +222,11 @@ static void __afl_map_shm(void) {
|
||||
|
||||
} else {
|
||||
|
||||
fprintf(stderr,
|
||||
"Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
|
||||
"be able to run this instrumented program!\n",
|
||||
__afl_final_loc);
|
||||
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",
|
||||
__afl_final_loc);
|
||||
|
||||
}
|
||||
|
||||
@ -251,6 +249,13 @@ static void __afl_map_shm(void) {
|
||||
|
||||
if (id_str) {
|
||||
|
||||
if (__afl_area_ptr && __afl_area_ptr != __afl_area_initial) {
|
||||
|
||||
free(__afl_area_ptr);
|
||||
__afl_area_ptr = __afl_area_initial;
|
||||
|
||||
}
|
||||
|
||||
#ifdef USEMMAP
|
||||
const char * shm_file_path = id_str;
|
||||
int shm_fd = -1;
|
||||
@ -332,6 +337,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);
|
||||
@ -902,15 +915,10 @@ __attribute__((constructor(0))) void __afl_auto_first(void) {
|
||||
|
||||
if (getenv("AFL_DISABLE_LLVM_INSTRUMENTATION")) return;
|
||||
u8 *ptr;
|
||||
u32 get_size = __afl_final_loc ? __afl_final_loc : 1024000;
|
||||
|
||||
if (__afl_final_loc > MAP_INITIAL_SIZE) {
|
||||
|
||||
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; }
|
||||
|
||||
}
|
||||
ptr = (u8 *)malloc(get_size);
|
||||
if (ptr && (ssize_t)ptr != -1) { __afl_area_ptr = ptr; }
|
||||
|
||||
}
|
||||
|
||||
@ -978,6 +986,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",
|
||||
|
@ -458,145 +458,182 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
u32 tmp_val = 0;
|
||||
u32 tmp_val = 0, taint_finds, taint_execs;
|
||||
|
||||
if (unlikely(afl->taint_mode)) {
|
||||
|
||||
tmp_val = afl->queue_cycle % 2; // starts with 1
|
||||
ret_val = 0;
|
||||
afl->taint_needs_splode = 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;
|
||||
if (!tmp_val) { // sole fuzz tainted new bytes
|
||||
|
||||
ret_val = 1;
|
||||
ret_val = 0;
|
||||
if (likely(!afl->queue_cur->taint_bytes_new ||
|
||||
afl->queue_cur->taint_bytes_new == afl->queue_cur->len))
|
||||
goto abandon_entry;
|
||||
if (unlikely(afl->queue_cur->cal_failed)) goto abandon_entry;
|
||||
if (unlikely(!afl->skip_deterministic && !afl->queue_cur->passed_det))
|
||||
goto abandon_entry;
|
||||
|
||||
s32 dst = 0, i;
|
||||
ret_val = 1;
|
||||
afl->taint_needs_splode = 1;
|
||||
taint_finds = afl->queued_paths + afl->unique_crashes;
|
||||
taint_execs = afl->fsrv.total_execs;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->taint_needs_splode)) {
|
||||
|
||||
// s32 dst = 0, i;
|
||||
temp_len = len = afl->queue_cur->len;
|
||||
s32 j = 0; // tmp
|
||||
// s32 j = 0; // tmp
|
||||
|
||||
// if (afl->queue_cur->len < 4) len = 4;
|
||||
// else len = afl->queue_cur->len;
|
||||
|
||||
fd = open(afl->queue_cur->fname, O_RDONLY);
|
||||
afl->taint_src = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
afl->taint_src =
|
||||
mmap(0, len < 4 ? 4 : 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) {
|
||||
/*
|
||||
afl->taint_needs_splode = 1;
|
||||
|
||||
case 1: // fuzz only tainted bytes
|
||||
switch (tmp_val) {
|
||||
|
||||
// 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) {
|
||||
case 1: // fuzz only tainted bytes
|
||||
|
||||
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) {
|
||||
|
||||
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);
|
||||
afl->queue_cur->taint_bytes_all = 0;
|
||||
goto abandon_entry;
|
||||
|
||||
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];
|
||||
if ((ssize_t)afl->taint_map == -1)
|
||||
FATAL("unable to mmap '%s'", afl->queue_cur->fname_taint);
|
||||
close(fd);
|
||||
|
||||
// FIXME DEBUG TODO XXX
|
||||
for (i = 0; i < (s32)afl->queue_cur->len; i++) {
|
||||
for (i = 0; i < (s32)afl->queue_cur->len && dst < len; i++)
|
||||
if (afl->taint_map[i]) in_buf[dst++] = afl->taint_src[i];
|
||||
|
||||
switch (afl->taint_map[i]) {
|
||||
// FIXME DEBUG TODO XXX
|
||||
/ *
|
||||
for (i = 0; i < (s32)afl->queue_cur->len; 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);
|
||||
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;
|
||||
if (j != len)
|
||||
FATAL("different taint values in map vs in queue (%d !=
|
||||
%d)", j, len);
|
||||
* /
|
||||
break;
|
||||
|
||||
case 0: // fuzz only newly tainted bytes
|
||||
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) {
|
||||
|
||||
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;
|
||||
ck_free(fn);
|
||||
afl->queue_cur->taint_bytes_new = 0;
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
|
||||
if ((ssize_t)afl->taint_map == -1) FATAL("unable to mmap '%s'", fn);
|
||||
close(fd);
|
||||
|
||||
u8 *fndata = alloc_printf("%s.data", fn);
|
||||
fd = open(fndata, O_RDONLY);
|
||||
/*
|
||||
if (fd < 0) {
|
||||
|
||||
ck_free(fn);
|
||||
afl->queue_cur->taint_bytes_new = 0;
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
temp_len = len = afl->taint_len = afl->queue_cur->taint_bytes_new;
|
||||
orig_in = in_buf =
|
||||
mmap(0, len + 4, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
if (fd < 0 || (ssize_t)in_buf == -1)
|
||||
FATAL("unable to open '%s' for %u bytes", fndata, len);
|
||||
close(fd);
|
||||
|
||||
ck_free(fndata);
|
||||
ck_free(fn);
|
||||
afl->taint_runs++;
|
||||
|
||||
// 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. */
|
||||
@ -611,7 +648,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
len = afl->queue_cur->len;
|
||||
|
||||
orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
// if (afl->queue_cur->len < 4) len = 4;
|
||||
// else len = afl->queue_cur->len;
|
||||
|
||||
orig_in = in_buf =
|
||||
mmap(0, len < 4 ? 4 : len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (unlikely(orig_in == MAP_FAILED)) {
|
||||
|
||||
@ -637,7 +678,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
* CALIBRATION (only if failed earlier on) *
|
||||
*******************************************/
|
||||
|
||||
if (unlikely(afl->queue_cur->cal_failed)) {
|
||||
if (unlikely(afl->queue_cur->cal_failed && !afl->taint_needs_splode)) {
|
||||
|
||||
u8 res = FSRV_RUN_TMOUT;
|
||||
|
||||
@ -699,6 +740,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
//fprintf(stderr, "%p[%u] %p[%u] %u (%p %p)\n", out_buf, afl->out_size, in_buf, afl->in_size, len, afl->out_buf, afl->in_buf);
|
||||
memcpy(out_buf, in_buf, len);
|
||||
|
||||
/*********************
|
||||
@ -709,9 +751,10 @@ 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 && !afl->taint_needs_splode)) {
|
||||
|
||||
int res;
|
||||
/*
|
||||
if (unlikely(afl->taint_needs_splode)) {
|
||||
|
||||
len = afl->queue_cur->len;
|
||||
@ -723,12 +766,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
res = 1;
|
||||
|
||||
} else {
|
||||
|
||||
*/
|
||||
res = input_to_state_stage(afl, in_buf, out_buf, len,
|
||||
afl->queue_cur->exec_cksum);
|
||||
|
||||
/*
|
||||
}
|
||||
|
||||
*/
|
||||
if (unlikely(res)) { goto abandon_entry; }
|
||||
|
||||
}
|
||||
@ -738,11 +781,13 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
if it has gone through deterministic testing in earlier, resumed runs
|
||||
(passed_det). */
|
||||
|
||||
if (likely(afl->queue_cur->passed_det) || likely(afl->skip_deterministic) ||
|
||||
likely(perf_score <
|
||||
(afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100
|
||||
? afl->queue_cur->depth * 30
|
||||
: afl->havoc_max_mult * 100))) {
|
||||
if (likely(afl->queue_cur->passed_det) ||
|
||||
likely(!afl->taint_needs_splode && afl->skip_deterministic) ||
|
||||
likely(!afl->taint_needs_splode &&
|
||||
perf_score <
|
||||
(afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100
|
||||
? afl->queue_cur->depth * 30
|
||||
: afl->havoc_max_mult * 100))) {
|
||||
|
||||
goto custom_mutator_stage;
|
||||
|
||||
@ -2256,7 +2301,7 @@ havoc_stage:
|
||||
out_buf[rand_below(afl, temp_len)] ^= 1 + rand_below(afl, 255);
|
||||
break;
|
||||
|
||||
case 11 ... 12: {
|
||||
case 11: {
|
||||
|
||||
/* Delete bytes. We're making this a bit more likely
|
||||
than insertion (the next option) in hopes of keeping
|
||||
@ -2281,7 +2326,7 @@ havoc_stage:
|
||||
|
||||
}
|
||||
|
||||
case 13:
|
||||
case 12 ... 13:
|
||||
|
||||
if (temp_len + HAVOC_BLK_XL < MAX_FILE) {
|
||||
|
||||
@ -2343,7 +2388,7 @@ havoc_stage:
|
||||
|
||||
/* Tail */
|
||||
memmove(new_buf + clone_to + clone_len, out_buf + clone_to,
|
||||
temp_len - clone_to);
|
||||
temp_len - clone_to);
|
||||
|
||||
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
|
||||
out_buf = new_buf;
|
||||
@ -2392,7 +2437,7 @@ havoc_stage:
|
||||
|
||||
u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
|
||||
copy_to + copy_len);
|
||||
memcpy(new_buf, in_buf, copy_to);
|
||||
memcpy(new_buf, out_buf, copy_to);
|
||||
memcpy(new_buf + copy_to, afl->taint_src + copy_from,
|
||||
copy_len);
|
||||
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
|
||||
@ -2600,8 +2645,12 @@ havoc_stage:
|
||||
memcpy(temp_buf + clone_to, new_buf + clone_from, clone_len);
|
||||
|
||||
/* Tail */
|
||||
memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
|
||||
temp_len - clone_to);
|
||||
if (unlikely(afl->taint_needs_splode))
|
||||
memmove(temp_buf + clone_to + clone_len, out_buf + clone_to,
|
||||
temp_len - clone_to);
|
||||
else
|
||||
memcpy(temp_buf + clone_to + clone_len, out_buf + clone_to,
|
||||
temp_len - clone_to);
|
||||
|
||||
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
|
||||
out_buf = temp_buf;
|
||||
@ -2772,6 +2821,15 @@ abandon_entry:
|
||||
|
||||
afl->splicing_with = -1;
|
||||
|
||||
if (afl->taint_needs_splode) {
|
||||
|
||||
afl->stage_finds[STAGE_PYTHON] +=
|
||||
(afl->queued_paths + afl->unique_crashes - taint_finds);
|
||||
afl->stage_cycles[STAGE_PYTHON] += (afl->fsrv.total_execs - taint_execs);
|
||||
afl->stage_finds[STAGE_CUSTOM_MUTATOR]++;
|
||||
|
||||
}
|
||||
|
||||
/* Update afl->pending_not_fuzzed count if we made it through the calibration
|
||||
cycle and have not seen this entry before. */
|
||||
|
||||
|
@ -106,6 +106,8 @@ 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) {
|
||||
|
||||
if (q->len < 16) return;
|
||||
|
||||
u8 * ptr, *fn = fname;
|
||||
u32 bytes = 0, plen = len;
|
||||
struct queue_entry *prev = q->prev;
|
||||
@ -131,29 +133,34 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
|
||||
fprintf(stderr, "Debug: tainted %u out of %u bytes\n", bytes, len);
|
||||
|
||||
/* DEBUG FIXME TODO XXX */
|
||||
u32 i;
|
||||
for (i = 0; i < len; i++) {
|
||||
/*
|
||||
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 (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 (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 (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 (((bytes * 100) / len) > 85) bytes = len;
|
||||
|
||||
// if all is tainted we do not need to write taint data away
|
||||
if (bytes && bytes < len) {
|
||||
if (bytes) {
|
||||
|
||||
// save the bytes away
|
||||
int w = open(q->fname_taint, O_CREAT | O_WRONLY, 0644);
|
||||
@ -168,7 +175,7 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
|
||||
i--;
|
||||
q->taint_bytes_highest = i;
|
||||
|
||||
afl->taint_count++;
|
||||
// afl->taint_count++;
|
||||
|
||||
} else {
|
||||
|
||||
@ -207,6 +214,29 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
|
||||
fprintf(stderr, "Debug: %u new taint out of %u bytes\n", bytes,
|
||||
len);
|
||||
|
||||
switch (q->taint_bytes_new) {
|
||||
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (len <= 64) q->taint_bytes_new = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (len <= 32) q->taint_bytes_new = 0;
|
||||
break;
|
||||
case 3:
|
||||
if (len <= 16) q->taint_bytes_new = 0;
|
||||
break;
|
||||
case 4:
|
||||
if (len <= 8) q->taint_bytes_new = 0;
|
||||
break;
|
||||
default:
|
||||
if (((q->taint_bytes_new * 100) / len) >= 50)
|
||||
q->taint_bytes_new = 0;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (q->taint_bytes_new) {
|
||||
|
||||
u8 *fnw = alloc_printf("%s.new", q->fname_taint);
|
||||
@ -217,6 +247,8 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
|
||||
|
||||
ck_write(w, tmp, plen, fnw);
|
||||
close(w);
|
||||
afl->taint_count++;
|
||||
afl->stage_cycles[STAGE_CUSTOM_MUTATOR]++;
|
||||
|
||||
} else {
|
||||
|
||||
@ -225,6 +257,38 @@ void perform_taint_run(afl_state_t *afl, struct queue_entry *q, u8 *fname,
|
||||
|
||||
}
|
||||
|
||||
u8 *fnwdata = alloc_printf("%s.data", fnw);
|
||||
if (fnwdata) {
|
||||
|
||||
u8 *data = ck_maybe_grow(BUF_PARAMS(out_scratch), plen);
|
||||
if ((ssize_t)data == -1) FATAL("maybegrow failed");
|
||||
|
||||
u32 j = 0;
|
||||
for (i = 0; i < len && j < q->taint_bytes_new; i++)
|
||||
if (tmp[i] == '!') data[j++] = mem[i];
|
||||
memset(data + q->taint_bytes_new, 0, 4);
|
||||
|
||||
int w = open(fnwdata, O_CREAT | O_WRONLY, 0644);
|
||||
if (w >= 0) {
|
||||
|
||||
ck_write(w, data, q->taint_bytes_new + 4, fnw);
|
||||
close(w);
|
||||
|
||||
} else {
|
||||
|
||||
FATAL("count not create '%s'", fnwdata);
|
||||
q->taint_bytes_new = 0;
|
||||
|
||||
}
|
||||
|
||||
ck_free(fnwdata);
|
||||
|
||||
} else {
|
||||
|
||||
q->taint_bytes_new = 0;
|
||||
|
||||
}
|
||||
|
||||
ck_free(fnw);
|
||||
|
||||
} else {
|
||||
@ -272,12 +336,18 @@ static u8 check_if_text(struct queue_entry *q) {
|
||||
|
||||
if (q->len < AFL_TXT_MIN_LEN) return 0;
|
||||
|
||||
u8 buf[MAX_FILE];
|
||||
s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp;
|
||||
|
||||
if (len >= MAX_FILE) len = MAX_FILE - 1;
|
||||
if ((fd = open(q->fname, O_RDONLY)) < 0) return 0;
|
||||
if ((comp = read(fd, buf, len)) != len) return 0;
|
||||
u8 *buf = ck_alloc(q->len + 32);
|
||||
if ((comp = read(fd, buf, len)) != len) {
|
||||
|
||||
ck_free(buf);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
buf[len] = 0;
|
||||
close(fd);
|
||||
|
||||
@ -363,6 +433,8 @@ static u8 check_if_text(struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
u32 percent_utf8 = (utf8 * 100) / comp;
|
||||
u32 percent_ascii = (ascii * 100) / len;
|
||||
|
||||
|
@ -862,6 +862,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
abort_trimming:
|
||||
|
||||
afl->bytes_trim_out += q->len;
|
||||
if (unlikely(afl->taint_mode)) {
|
||||
if (q->taint_bytes_all > q->len) q->taint_bytes_all = q->len;
|
||||
if (q->taint_bytes_new > q->len) afl->taint_len = q->taint_bytes_new = q->len;
|
||||
if (q->taint_bytes_highest > q->len) q->taint_bytes_highest = q->len;
|
||||
afl->taint_len = q->len;
|
||||
}
|
||||
return fault;
|
||||
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
"var_byte_count : %u\n"
|
||||
"havoc_expansion : %u\n"
|
||||
"tainted_inputs : %u\n"
|
||||
"tainted_runs : %u\n"
|
||||
"afl_banner : %s\n"
|
||||
"afl_version : " VERSION
|
||||
"\n"
|
||||
@ -151,7 +152,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
-1,
|
||||
#endif
|
||||
t_bytes, afl->var_byte_count, afl->expand_havoc, afl->taint_count,
|
||||
afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
|
||||
afl->taint_runs, 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 " : "",
|
||||
|
@ -1318,7 +1318,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
OKF("Taint forkserver successfully started");
|
||||
|
||||
const rlim_t kStackSize = 128L * 1024L * 1024L; // min stack size = 128 Mb
|
||||
const rlim_t kStackSize = 16L * 1024L * 1024L; // min stack size = 16 Mb
|
||||
struct rlimit rl;
|
||||
rl.rlim_cur = kStackSize;
|
||||
if (getrlimit(RLIMIT_STACK, &rl) != 0)
|
||||
|
Reference in New Issue
Block a user