From a0e884cf8bffe1a0394d106375f6a23edd2b60e6 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 15 Jan 2021 16:56:40 +0100 Subject: merge cmplog --- src/afl-fuzz.c | 60 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 15 deletions(-) (limited to 'src/afl-fuzz.c') diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index bb2674f0..1e914ca6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -77,13 +77,8 @@ static void at_exit() { } int kill_signal = SIGKILL; - /* AFL_KILL_SIGNAL should already be a valid int at this point */ - if (getenv("AFL_KILL_SIGNAL")) { - - kill_signal = atoi(getenv("AFL_KILL_SIGNAL")); - - } + if ((ptr = getenv("AFL_KILL_SIGNAL"))) { kill_signal = atoi(ptr); } if (pid1 > 0) { kill(pid1, kill_signal); } if (pid2 > 0) { kill(pid2, kill_signal); } @@ -103,13 +98,14 @@ static void usage(u8 *argv0, int more_help) { "Execution control settings:\n" " -p schedule - power schedules compute a seed's performance score:\n" - " -- see docs/power_schedules.md\n" + " fast(default), explore, exploit, seek, rare, mmopt, " + "coe, lin\n" + " quad -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" " -t msec - timeout for each run (auto-scaled, 50-%u ms)\n" - " -m megs - memory limit for child process (%u MB, 0 = no limit)\n" + " -m megs - memory limit for child process (%u MB, 0 = no limit " + "[default])\n" " -Q - use binary-only instrumentation (QEMU mode)\n" " -U - use unicorn-based instrumentation (Unicorn mode)\n" " -W - use qemu-based instrumentation with Wine (Wine " @@ -125,7 +121,9 @@ static void usage(u8 *argv0, int more_help) { " See docs/README.MOpt.md\n" " -c program - enable CmpLog by specifying a binary compiled for " "it.\n" - " if using QEMU, just use -c 0.\n\n" + " if using QEMU, just use -c 0.\n" + " -l cmplog_level - set the complexity/intensivity of CmpLog.\n" + " Values: 1 (default), 2 (intensive) and 3 (heavy)\n\n" "Fuzzing behavior settings:\n" " -Z - sequential queue selection instead of weighted " @@ -337,7 +335,6 @@ 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(afl, map_size); afl->debug = debug; afl_fsrv_init(&afl->fsrv); @@ -358,7 +355,8 @@ 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:QNUWe:p:s:V:E:L:hRP:Z")) > 0) { + "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNo:p:P:RQs:S:t:T:UV:Wx:Z")) > + 0) { switch (opt) { @@ -787,6 +785,26 @@ int main(int argc, char **argv_orig, char **envp) { } break; + case 'l': { + + afl->cmplog_lvl = atoi(optarg); + if (afl->cmplog_lvl < 1 || afl->cmplog_lvl > CMPLOG_LVL_MAX) { + + FATAL( + "Bad complog level value, accepted values are 1 (default), 2 and " + "%u.", + CMPLOG_LVL_MAX); + + } + + if (afl->cmplog_lvl == CMPLOG_LVL_MAX) { + + afl->cmplog_max_filesize = MAX_FILE; + + } + + } break; + case 'L': { /* MOpt mode */ if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); } @@ -1635,6 +1653,14 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->use_splicing) { ++afl->cycles_wo_finds; + + if (unlikely(afl->shm.cmplog_mode && + afl->cmplog_max_filesize < MAX_FILE)) { + + afl->cmplog_max_filesize <<= 4; + + } + switch (afl->expand_havoc) { case 0: @@ -1652,6 +1678,7 @@ int main(int argc, char **argv_orig, char **envp) { } afl->expand_havoc = 2; + if (afl->cmplog_lvl < 2) afl->cmplog_lvl = 2; break; case 2: // if (!have_p) afl->schedule = EXPLOIT; @@ -1665,11 +1692,14 @@ int main(int argc, char **argv_orig, char **envp) { afl->expand_havoc = 4; break; case 4: - // if not in sync mode, enable deterministic mode? - // if (!afl->sync_id) afl->skip_deterministic = 0; afl->expand_havoc = 5; + if (afl->cmplog_lvl < 3) afl->cmplog_lvl = 3; break; case 5: + // if not in sync mode, enable deterministic mode? + if (!afl->sync_id) afl->skip_deterministic = 0; + afl->expand_havoc = 6; + case 6: // nothing else currently break; -- cgit 1.4.1 From c71ce79963ffd3e1203d1078b8a60f91c4ecebf1 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 17 Jan 2021 15:18:20 +0100 Subject: fix colorization --- GNUmakefile | 4 +-- include/afl-fuzz.h | 4 +-- instrumentation/afl-compiler-rt.o.c | 3 +- src/afl-fuzz-one.c | 6 ++-- src/afl-fuzz-redqueen.c | 56 ++++++++++++++++++++++--------------- src/afl-fuzz.c | 2 ++ src/afl-showmap.c | 25 ++++++++++++++--- 7 files changed, 65 insertions(+), 35 deletions(-) (limited to 'src/afl-fuzz.c') diff --git a/GNUmakefile b/GNUmakefile index 7b05a1d5..c71a7d47 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -428,8 +428,8 @@ src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm -afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS) +afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 + $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS) afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 8a2122dc..621e8745 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -1136,9 +1136,9 @@ void read_foreign_testcases(afl_state_t *, int); u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len); /* RedQueen */ -u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, - u64 exec_cksum); +u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len); +/* our RNG wrapper */ AFL_RAND_RETURN rand_next(afl_state_t *afl); /* probability between 0.0 and 1.0 */ diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 5d75af78..bbec52f9 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1209,7 +1209,8 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) { void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) { - // fprintf(stderr, "hook1 arg0=%02x arg1=%02x attr=%u\n", arg1, arg2, attr); + // fprintf(stderr, "hook1 arg0=%02x arg1=%02x attr=%u\n", + // (u8) arg1, (u8) arg2, attr); if (unlikely(!__afl_cmp_map)) return; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 596bae22..4ce22c08 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -562,8 +562,7 @@ u8 fuzz_one_original(afl_state_t *afl) { !(afl->fsrv.total_execs % afl->queued_paths) || get_cur_time() - afl->last_path_time > 15000) { - if (input_to_state_stage(afl, in_buf, out_buf, len, - afl->queue_cur->exec_cksum)) { + if (input_to_state_stage(afl, in_buf, out_buf, len)) { goto abandon_entry; @@ -2986,8 +2985,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { !(afl->fsrv.total_execs % afl->queued_paths) || get_cur_time() - afl->last_path_time > 15000) { - if (input_to_state_stage(afl, in_buf, out_buf, len, - afl->queue_cur->exec_cksum)) { + if (input_to_state_stage(afl, in_buf, out_buf, len)) { goto abandon_entry; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 955a9232..052f59f1 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -88,7 +88,7 @@ static struct range *pop_biggest_range(struct range **ranges) { static void dump(char *txt, u8 *buf, u32 len) { u32 i; - fprintf(stderr, "DUMP %s %llx ", txt, hash64(buf, len, 0)); + fprintf(stderr, "DUMP %s %llx ", txt, hash64(buf, len, HASH_CONST)); for (i = 0; i < len; i++) fprintf(stderr, "%02x", buf[i]); fprintf(stderr, "\n"); @@ -117,6 +117,7 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) { if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; } *cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); + return 0; } @@ -200,7 +201,7 @@ static void type_replace(afl_state_t *afl, u8 *buf, u32 len) { } -static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum, +static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, struct tainted **taints) { struct range * ranges = add_range(NULL, 0, len - 1), *rng; @@ -208,18 +209,31 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum, u8 * backup = ck_alloc_nozero(len); u8 * changed = ck_alloc_nozero(len); - u64 orig_hit_cnt, new_hit_cnt; + u64 orig_hit_cnt, new_hit_cnt, exec_cksum; orig_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_name = "colorization"; afl->stage_short = "colorization"; afl->stage_max = (len << 1); - afl->stage_cur = 0; + + // in colorization we do not classify counts, hence we have to calculate + // the original checksum! + if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) { + + goto checksum_fail; + + } + memcpy(backup, buf, len); memcpy(changed, buf, len); type_replace(afl, changed, len); +#ifdef _DEBUG + dump("ORIG", buf, len); + dump("CHAN", changed, len); +#endif + while ((rng = pop_biggest_range(&ranges)) != NULL && afl->stage_cur < afl->stage_max) { @@ -227,7 +241,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u64 exec_cksum, memcpy(buf + rng->start, changed + rng->start, s); - u64 cksum; + u64 cksum = 0; u64 start_us = get_cur_time_us(); if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) { @@ -633,11 +647,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) { // if (its_len >= 4 && (attr <= 1 || attr >= 8)) - // fprintf(stderr, - // "TestU32: %u>=4 %x==%llx" - // " %x==%llx (idx=%u attr=%u) <= %llx<-%llx\n", - // its_len, *buf_32, pattern, *o_buf_32, o_pattern, idx, attr, - // repl, changed_val); + // fprintf(stderr, + // "TestU32: %u>=4 %x==%llx" + // " %x==%llx (idx=%u attr=%u) <= %llx<-%llx\n", + // its_len, *buf_32, pattern, *o_buf_32, o_pattern, idx, attr, + // repl, changed_val); if (its_len >= 4 && ((*buf_32 == (u32)pattern && *o_buf_32 == (u32)o_pattern) || @@ -702,10 +716,10 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (*status != 1) { // u8 // if (its_len >= 1 && (attr <= 1 || attr >= 8)) - // fprintf(stderr, - // "TestU8: %u>=1 %x==%x %x==%x (idx=%u attr=%u) <= %x<-%x\n", - // its_len, *buf_8, pattern, *o_buf_8, o_pattern, idx, attr, - // repl, changed_val); + // fprintf(stderr, + // "TestU8: %u>=1 %x==%x %x==%x (idx=%u attr=%u) <= %x<-%x\n", + // its_len, *buf_8, (u8)pattern, *o_buf_8, (u8)o_pattern, idx, + // attr, (u8)repl, (u8)changed_val); if (its_len >= 1 && ((*buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) || @@ -1659,8 +1673,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, ///// Input to State stage // afl->queue_cur->exec_cksum -u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, - u64 exec_cksum) { +u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { u8 r = 1; if (unlikely(!afl->orig_cmp_map)) { @@ -1686,7 +1699,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) { - if (unlikely(colorization(afl, buf, len, exec_cksum, &taint))) { return 1; } + if (unlikely(colorization(afl, buf, len, &taint))) { return 1; } // no taint? still try, create a dummy to prevent again colorization if (!taint) { @@ -1696,6 +1709,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, } +#ifdef _DEBUG + dump("NEW ", buf, len); +#endif + } else { buf = afl->queue_cur->cmplog_colorinput; @@ -1705,11 +1722,6 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, } -#ifdef _DEBUG - dump("ORIG", orig_buf, len); - dump("NEW ", buf, len); -#endif - struct tainted *t = taint; while (t) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1e914ca6..88c40ee8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1094,6 +1094,8 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->shm.cmplog_mode) { OKF("CmpLog level: %u", afl->cmplog_lvl); } + /* Dynamically allocate memory for AFLFast schedules */ if (afl->schedule >= FAST && afl->schedule <= RARE) { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 5c9d38e0..5d98d646 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -42,6 +42,7 @@ #include "sharedmem.h" #include "forkserver.h" #include "common.h" +#include "hash.h" #include #include @@ -86,7 +87,8 @@ static u8 quiet_mode, /* Hide non-essential messages? */ binary_mode, /* Write output as a binary map */ keep_cores, /* Allow coredumps? */ remove_shm = 1, /* remove shmem? */ - collect_coverage; /* collect coverage */ + collect_coverage, /* collect coverage */ + no_classify; /* do not classify counts */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ @@ -317,7 +319,9 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, } - classify_counts(fsrv); + if (fsrv->trace_bits[0] == 1) { fsrv->trace_bits[0] = 0; } + + if (!no_classify) { classify_counts(fsrv); } if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); } @@ -490,7 +494,9 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { } - classify_counts(fsrv); + if (fsrv->trace_bits[0] == 1) { fsrv->trace_bits[0] = 0; } + + if (!no_classify) { classify_counts(fsrv); } if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); } @@ -680,6 +686,7 @@ static void usage(u8 *argv0) { " -q - sink program's output and don't show messages\n" " -e - show edge coverage only, ignore hit counts\n" " -r - show real tuple values instead of AFL filter values\n" + " -s - do not classify the map\n" " -c - allow core dumps\n\n" "This tool displays raw tuple data captured by AFL instrumentation.\n" @@ -729,10 +736,14 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZQUWbcrsh")) > 0) { switch (opt) { + case 's': + no_classify = 1; + break; + case 'C': collect_coverage = 1; quiet_mode = 1; @@ -1213,6 +1224,12 @@ int main(int argc, char **argv_orig, char **envp) { showmap_run_target(fsrv, use_argv); tcnt = write_results_to_file(fsrv, out_file); + if (!quiet_mode) { + + OKF("Hash of coverage map: %llx", + hash64(fsrv->trace_bits, fsrv->map_size, HASH_CONST)); + + } } -- cgit 1.4.1 From e7b572af3608e2d097aad17408ad4853befdc02c Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 20 Jan 2021 01:49:32 +0100 Subject: bugfix and new transform detection feature --- instrumentation/afl-compiler-rt.o.c | 14 +- src/afl-fuzz-redqueen.c | 430 ++++++++++++++++++++++++++++++++---- src/afl-fuzz.c | 14 ++ 3 files changed, 416 insertions(+), 42 deletions(-) (limited to 'src/afl-fuzz.c') diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index 0ce96673..a290f110 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1545,6 +1545,18 @@ static int area_is_mapped(void *ptr, size_t len) { void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { + /* + u32 i; + if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return; + fprintf(stderr, "rtn arg0="); + for (i = 0; i < 8; i++) + fprintf(stderr, "%02x", ptr1[i]); + fprintf(stderr, " arg1="); + for (i = 0; i < 8; i++) + fprintf(stderr, "%02x", ptr2[i]); + fprintf(stderr, "\n"); + */ + if (unlikely(!__afl_cmp_map)) return; if (!area_is_mapped(ptr1, 32) || !area_is_mapped(ptr2, 32)) return; @@ -1555,7 +1567,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) { u32 hits; - if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) { + if (__afl_cmp_map->headers[k].type != CMP_TYPE_RTN) { __afl_cmp_map->headers[k].type = CMP_TYPE_RTN; hits = 0; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 1c5b95f6..bf41863e 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -30,18 +30,21 @@ //#define _DEBUG #define COMBINE -#define CMPLOG_INTROSPECTION +//#define CMPLOG_INTROSPECTION //#define ARITHMETIC_LESSER_GREATER +//#define TRANSFORM // CMP attribute enum enum { - IS_EQUAL = 1, - IS_GREATER = 2, - IS_LESSER = 4, - IS_FP = 8, - IS_FP_MOD = 16, - IS_INT_MOD = 32 + IS_EQUAL = 1, // arithemtic equal comparison + IS_GREATER = 2, // arithmetic greater comparison + IS_LESSER = 4, // arithmetic lesser comparison + IS_FP = 8, // is a floating point, not an integer + /* --- below are internal settings, not from target cmplog */ + IS_FP_MOD = 16, // arithemtic changed floating point + IS_INT_MOD = 32, // arithmetic changed interger + IS_TRANSFORM = 64 // transformed integer }; @@ -466,6 +469,7 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { } +#ifdef TRANSFORM static int strntoll(const char *str, size_t sz, char **end, int base, long long *out) { @@ -513,6 +517,8 @@ static int strntoull(const char *str, size_t sz, char **end, int base, } +#endif + static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u64 pattern, u64 repl, u64 o_pattern, u64 changed_val, u8 attr, u32 idx, u32 taint_len, @@ -553,14 +559,15 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, u32 its_len = MIN(len - idx, taint_len); - u8 * endptr; - u8 use_num = 0, use_unum = 0; - unsigned long long unum; - long long num; - +#ifdef TRANSFORM // reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3 if (lvl & LVL3) { + u8 * endptr; + u8 use_num = 0, use_unum = 0; + unsigned long long unum; + long long num; + if (afl->queue_cur->is_ascii) { endptr = buf_8; @@ -575,11 +582,11 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } -#ifdef _DEBUG + #ifdef _DEBUG if (idx == 0) fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n", afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern); -#endif + #endif // num is likely not pattern as atoi("AAA") will be zero... if (use_num && ((u64)num == pattern || !num)) { @@ -626,8 +633,201 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, } + // Try to identify transform magic + if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) { + + u64 *ptr = (u64 *)&buf[idx]; + u64 *o_ptr = (u64 *)&orig_buf[idx]; + u64 b_val, o_b_val, mask; + + switch (SHAPE_BYTES(h->shape)) { + + case 0: + case 1: + b_val = (u64)(*ptr % 0x100); + o_b_val = (u64)(*o_ptr % 0x100); + mask = 0xff; + break; + case 2: + case 3: + b_val = (u64)(*ptr % 0x10000); + o_b_val = (u64)(*o_ptr % 0x10000); + mask = 0xffff; + break; + case 4: + case 5: + case 6: + case 7: + b_val = (u64)(*ptr % 0x100000000); + o_b_val = (u64)(*o_ptr % 0x100000000); + mask = 0xffffffff; + break; + default: + b_val = *ptr; + o_b_val = *o_ptr; + mask = 0xffffffffffffffff; + + } + + // test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..." + s64 diff = pattern - b_val; + s64 o_diff = o_pattern - o_b_val; + /* + fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx, + h->shape + 1, o_pattern, o_b_val, o_diff); + fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern, + b_val, diff);*/ + if (diff == o_diff && diff) { + + // this could be an arithmetic transformation + + u64 new_repl = (u64)((s64)repl - diff); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + return 1; + + } + + if (*status == 1) { fprintf(stderr, "FOUND!\n"); } + + } + + // test for XOR, eg. "if ((user_val ^ 0xabcd) == 0x1234) ..." + if (*status != 1) { + + diff = pattern ^ b_val; + s64 o_diff = o_pattern ^ o_b_val; + + /* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n", + idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr, + "DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/ + if (diff == o_diff && diff) { + + // this could be a XOR transformation + + u64 new_repl = (u64)((s64)repl ^ diff); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + return 1; + + } + + if (*status == 1) { fprintf(stderr, "FOUND!\n"); } + + } + + } + + // test for to lowercase, eg. "new_val = (user_val | 0x2020) ..." + if (*status != 1) { + + if ((b_val | (0x2020202020202020 & mask)) == (pattern & mask)) { + + diff = 1; + + } else { + + diff = 0; + + } + + if ((o_b_val | (0x2020202020202020 & mask)) == (o_pattern & mask)) { + + o_diff = 1; + + } else { + + diff = 0; + + } + + /* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n", + idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr, + "DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/ + if (o_diff && diff) { + + // this could be a lower to upper + + u64 new_repl = (repl & (0x5f5f5f5f5f5f5f5f & mask)); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + return 1; + + } + + if (*status == 1) { fprintf(stderr, "FOUND!\n"); } + + } + + } + + // test for to uppercase, eg. "new_val = (user_val | 0x5f5f) ..." + if (*status != 1) { + + if ((b_val & (0x5f5f5f5f5f5f5f5f & mask)) == (pattern & mask)) { + + diff = 1; + + } else { + + diff = 0; + + } + + if ((o_b_val & (0x5f5f5f5f5f5f5f5f & mask)) == (o_pattern & mask)) { + + o_diff = 1; + + } else { + + o_diff = 0; + + } + + /* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n", + idx, h->shape + 1, o_pattern, o_b_val, o_diff); fprintf(stderr, + "DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);*/ + if (o_diff && diff) { + + // this could be a lower to upper + + u64 new_repl = (repl | (0x2020202020202020 & mask)); + // fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl); + + if (unlikely(cmp_extend_encoding( + afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx, + taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) { + + return 1; + + } + + if (*status == 1) { fprintf(stderr, "FOUND!\n"); } + + } + + } + + *status = 0; + + } + } +#endif + // we only allow this for ascii2integer (above) if (unlikely(pattern == o_pattern)) { return 0; } @@ -783,7 +983,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, // in original buffer) #ifdef ARITHMETIC_LESSER_GREATER - if (lvl < LVL3) { return 0; } + if (lvl < LVL3 || attr == IS_TRANSFORM) { return 0; } // lesser/greater FP comparison if ((attr & (IS_LESSER + IS_GREATER)) && @@ -1374,56 +1574,185 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl, - u8 *o_pattern, u32 idx, u32 taint_len, - u8 *orig_buf, u8 *buf, u8 *cbuf, u32 len, - u8 *status) { + u8 *o_pattern, u8 *changed_val, u32 idx, + u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf, + u32 len, u8 lvl, u8 *status) { #ifndef COMBINE (void)(cbuf); #endif - u32 i; + u32 i = 0; u32 its_len = MIN((u32)32, len - idx); its_len = MIN(its_len, taint_len); u8 save[32]; memcpy(save, &buf[idx], its_len); - for (i = 0; i < its_len; ++i) { + if (lvl == LVL1) { - if ((pattern[i] != buf[idx + i] && o_pattern[i] != orig_buf[idx + i]) || - *status == 1) { + for (i = 0; i < its_len; ++i) { - break; + if ((pattern[i] != buf[idx + i] && o_pattern[i] != orig_buf[idx + i]) || + *status == 1) { + + break; + + } + + buf[idx + i] = repl[i]; + + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + +#ifdef COMBINE + if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i); } +#endif } - buf[idx + i] = repl[i]; + } + + if (*status == 1) return 0; + + if (lvl & LVL3) { + + u8 toupper = 0, tolower = 0, xor = 0, arith = 0; + u8 xor_val[32], arith_val[32]; + u32 j; + +#ifdef _DEBUG + fprintf(stderr, "RTN TRANSFORM idx=%u ", idx); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", orig_buf[idx + j]); + fprintf(stderr, " -> "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", o_pattern[j]); + fprintf(stderr, " <= "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", repl[j]); + fprintf(stderr, "\n"); + fprintf(stderr, " "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", buf[idx + j]); + fprintf(stderr, " -> "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", pattern[j]); + fprintf(stderr, " <= "); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", changed_val[j]); + fprintf(stderr, "\n"); +#endif + for (i = 0; i < its_len; ++i) { + + xor_val[i] = pattern[i] ^ buf[idx + i]; + arith_val[i] = pattern[i] - buf[idx + i]; + + if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) { + + ++xor; + + } + + if ((o_pattern[i] - orig_buf[idx + i]) == arith_val[i] && arith_val[i]) { + + ++arith; + + } + + if ((buf[idx + i] | 0x20) == pattern[i] && + (orig_buf[idx + i] | 0x20) == o_pattern[i]) { + + ++tolower; - if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + } + + if ((buf[idx + i] & 0x5a) == pattern[i] && + (orig_buf[idx + i] & 0x5a) == o_pattern[i]) { + + ++toupper; + + } + +#ifdef _DEBUG + fprintf(stderr, "RTN loop=%u %u %u %u %u (%u %u)\n", i, xor, arith, + tolower, toupper, arith_val[i], xor_val[i]); +#endif + + if (xor > i) { + + for (j = 0; j <= i; j++) + buf[idx + j] = repl[j] ^ xor_val[j]; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT xor %u result %u\n", xor, *status); + + } + + if (arith > i && *status != 1) { + + for (j = 0; j <= i; j++) + buf[idx + j] = repl[j] - arith_val[j]; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith, *status); + + } + + if (toupper > i && *status != 1) { + + for (j = 0; j <= i; j++) + buf[idx + j] = repl[j] | 0x20; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT toupper %u result %u\n", toupper, + // *status); + + } + + if (tolower > i && *status != 1) { + + for (j = 0; j <= i; j++) + buf[idx + j] = repl[j] & 0x5f; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } + // fprintf(stderr, "RTN ATTEMPT tolower %u result %u\n", tolower, + // *status); + + } #ifdef COMBINE - if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i); } + if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i); } #endif + if ((i >= xor&&i >= arith &&i >= tolower &&i >= toupper) || + repl[i] != changed_val[i] || *status == 1) { + + break; + + } + + } + } memcpy(&buf[idx], save, i); + return 0; } static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, - u32 len, struct tainted *taint) { + u32 len, u8 lvl, struct tainted *taint) { struct tainted * t; struct cmp_header *h = &afl->shm.cmp_map->headers[key]; - u32 i, j, idx, have_taint = 1, taint_len; + u32 i, j, idx, have_taint = 1, taint_len, loggeds; + u8 status = 0, found_one = 0; - u32 loggeds = h->hits; - if (h->hits > CMP_MAP_RTN_H) { loggeds = CMP_MAP_RTN_H; } + if (h->hits > CMP_MAP_RTN_H) { - u8 status = 0; - u8 found_one = 0; + loggeds = CMP_MAP_RTN_H; + + } else { + + loggeds = h->hits; + + } for (i = 0; i < loggeds; ++i) { @@ -1445,6 +1774,20 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } + /* + struct cmp_header *hh = &afl->orig_cmp_map->headers[key]; + fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id, + h->shape, h->attribute); for (j = 0; j < 8; j++) fprintf(stderr, "%02x", + o->v0[j]); fprintf(stderr, " v1="); for (j = 0; j < 8; j++) fprintf(stderr, + "%02x", o->v1[j]); fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u + o0=", hh->hits, hh->id, hh->shape, hh->attribute); for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", orig_o->v0[j]); + fprintf(stderr, " o1="); + for (j = 0; j < 8; j++) + fprintf(stderr, "%02x", orig_o->v1[j]); + fprintf(stderr, "\n"); + */ + t = taint; while (t->next) { @@ -1476,9 +1819,9 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, status = 0; - if (unlikely(rtn_extend_encoding(afl, o->v0, o->v1, orig_o->v0, idx, - taint_len, orig_buf, buf, cbuf, len, - &status))) { + if (unlikely(rtn_extend_encoding(afl, o->v0, o->v1, orig_o->v0, + orig_o->v1, idx, taint_len, orig_buf, + buf, cbuf, len, lvl, &status))) { return 1; @@ -1493,9 +1836,9 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, status = 0; - if (unlikely(rtn_extend_encoding(afl, o->v1, o->v0, orig_o->v1, idx, - taint_len, orig_buf, buf, cbuf, len, - &status))) { + if (unlikely(rtn_extend_encoding(afl, o->v1, o->v0, orig_o->v1, + orig_o->v0, idx, taint_len, orig_buf, + buf, cbuf, len, lvl, &status))) { return 1; @@ -1511,7 +1854,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf, } // If failed, add to dictionary - if (!found_one) { + if (!found_one && (lvl & LVL1)) { if (unlikely(!afl->pass_stats[key].total)) { @@ -1702,9 +2045,14 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) { } - } else if (lvl & LVL1) { + } else if ((lvl & LVL1) + +#ifdef TRANSFORM + || (lvl & LVL3) +#endif + ) { - if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, taint))) { + if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) { goto exit_its; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 88c40ee8..0f76e8a3 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1515,7 +1515,21 @@ int main(int argc, char **argv_orig, char **envp) { } + u8 *save_env = NULL; + if (afl->cmplog_binary) { + + save_env = ck_strdup(getenv(CMPLOG_SHM_ENV_VAR)); + unsetenv(CMPLOG_SHM_ENV_VAR); // normal forkserver should not have this + + } + perform_dry_run(afl); + if (save_env) { + + setenv(CMPLOG_SHM_ENV_VAR, save_env, 1); // needed for at_exit() + ck_free(save_env); + + } /* if (!user_set_cache && afl->q_testcase_max_cache_size) { -- cgit 1.4.1 From 9dff3495d54c0bd3da59ef43ca25df06c6d9f2c2 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 20 Jan 2021 10:01:34 +0100 Subject: better cmp map fsrv fix --- src/afl-forkserver.c | 4 +++- src/afl-fuzz-cmplog.c | 2 ++ src/afl-fuzz.c | 14 -------------- 3 files changed, 5 insertions(+), 15 deletions(-) (limited to 'src/afl-fuzz.c') diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 39f044f2..c1b3d02f 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -58,7 +58,9 @@ static list_t fsrv_list = {.element_prealloc_count = 0}; static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { - if (fsrv->qemu_mode) setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); + if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } + + unsetenv(CMPLOG_SHM_ENV_VAR); // we do not want that in non-cmplog fsrv execv(fsrv->target_path, argv); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 8ffc6e1b..27c6c413 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -33,6 +33,8 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); + if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } + if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) { argv[0] = fsrv->cmplog_binary; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 0f76e8a3..88c40ee8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1515,21 +1515,7 @@ int main(int argc, char **argv_orig, char **envp) { } - u8 *save_env = NULL; - if (afl->cmplog_binary) { - - save_env = ck_strdup(getenv(CMPLOG_SHM_ENV_VAR)); - unsetenv(CMPLOG_SHM_ENV_VAR); // normal forkserver should not have this - - } - perform_dry_run(afl); - if (save_env) { - - setenv(CMPLOG_SHM_ENV_VAR, save_env, 1); // needed for at_exit() - ck_free(save_env); - - } /* if (!user_set_cache && afl->q_testcase_max_cache_size) { -- cgit 1.4.1