From ce9b4698fec5222e0af1b62d68c4105e6364771e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 21 Jul 2020 20:53:51 +0200 Subject: added andrea's splicing, added cycle_schedules --- include/envs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/envs.h') diff --git a/include/envs.h b/include/envs.h index 86222418..cb3c183e 100644 --- a/include/envs.h +++ b/include/envs.h @@ -34,6 +34,7 @@ static char *afl_environment_variables[] = { "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CXX", + "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD_OUTPUT", "AFL_DEBUG_GDB", -- cgit 1.4.1 From b015e4f07aabb39e1683406704f2aae1f7dcde4a Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 22 Jul 2020 16:15:16 +0200 Subject: epand havoc now env --- include/envs.h | 1 + src/afl-fuzz-one.c | 211 ++++++++++++++++++++++++++++++++++------------------- src/afl-fuzz.c | 1 + 3 files changed, 138 insertions(+), 75 deletions(-) (limited to 'include/envs.h') diff --git a/include/envs.h b/include/envs.h index cb3c183e..c1c7d387 100644 --- a/include/envs.h +++ b/include/envs.h @@ -130,6 +130,7 @@ static char *afl_environment_variables[] = { "AFL_USE_CFISAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT", + "AFL_EXPAND_HAVOC_NOW", NULL }; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 250409da..a0ecb7a9 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -564,238 +564,299 @@ static int text_mutation(afl_state_t *afl, u8 **out_buf, s32 *orig_temp_len) { u32 pos, yes = 0, mutations = rand_below(afl, AFL_TXT_STRING_MAX_MUTATIONS) + 1; u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), - *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS); + *orig_temp_len + AFL_TXT_STRING_MAX_MUTATIONS +1); temp_len = *orig_temp_len; memcpy(new_buf, *out_buf, temp_len); + new_buf[temp_len] = 0; for (u32 i = 0; i < mutations; i++) { if (temp_len < AFL_TXT_MIN_LEN) { return 0; } pos = rand_below(afl, temp_len - 1); - int choice = rand_below(afl, 72); + int choice = rand_below(afl, 80); switch (choice) { case 0: /* Semantic statement deletion */ - yes += string_replace(out_buf, &temp_len, pos, "\n", "#"); + yes += string_replace(&new_buf, &temp_len, pos, "\n", "#"); break; case 1: - yes += string_replace(out_buf, &temp_len, pos, "(", "(!"); + yes += string_replace(&new_buf, &temp_len, pos, "(", "(!"); break; case 2: - yes += string_replace(out_buf, &temp_len, pos, "==", "!="); + yes += string_replace(&new_buf, &temp_len, pos, "==", "!="); break; case 3: - yes += string_replace(out_buf, &temp_len, pos, "!=", "=="); + yes += string_replace(&new_buf, &temp_len, pos, "!=", "=="); break; case 4: - yes += string_replace(out_buf, &temp_len, pos, "==", "<"); + yes += string_replace(&new_buf, &temp_len, pos, "==", "<"); break; case 5: - yes += string_replace(out_buf, &temp_len, pos, "<", "=="); + yes += string_replace(&new_buf, &temp_len, pos, "<", "=="); break; case 6: - yes += string_replace(out_buf, &temp_len, pos, "==", ">"); + yes += string_replace(&new_buf, &temp_len, pos, "==", ">"); break; case 7: - yes += string_replace(out_buf, &temp_len, pos, ">", "=="); + yes += string_replace(&new_buf, &temp_len, pos, ">", "=="); break; case 8: - yes += string_replace(out_buf, &temp_len, pos, "=", "<"); + yes += string_replace(&new_buf, &temp_len, pos, "=", "<"); break; case 9: - yes += string_replace(out_buf, &temp_len, pos, "=", ">"); + yes += string_replace(&new_buf, &temp_len, pos, "=", ">"); break; case 10: - yes += string_replace(out_buf, &temp_len, pos, "<", ">"); + yes += string_replace(&new_buf, &temp_len, pos, "<", ">"); break; case 11: - yes += string_replace(out_buf, &temp_len, pos, ">", "<"); + yes += string_replace(&new_buf, &temp_len, pos, ">", "<"); break; case 12: - yes += string_replace(out_buf, &temp_len, pos, "++", "--"); + yes += string_replace(&new_buf, &temp_len, pos, "++", "--"); break; case 13: - yes += string_replace(out_buf, &temp_len, pos, "--", "++"); + yes += string_replace(&new_buf, &temp_len, pos, "--", "++"); break; case 14: - yes += string_replace(out_buf, &temp_len, pos, "+", "-"); + yes += string_replace(&new_buf, &temp_len, pos, "+", "-"); break; case 15: - yes += string_replace(out_buf, &temp_len, pos, "+", "*"); + yes += string_replace(&new_buf, &temp_len, pos, "+", "*"); break; case 16: - yes += string_replace(out_buf, &temp_len, pos, "+", "/"); + yes += string_replace(&new_buf, &temp_len, pos, "+", "/"); break; case 17: - yes += string_replace(out_buf, &temp_len, pos, "+", "%"); + yes += string_replace(&new_buf, &temp_len, pos, "+", "%"); break; case 18: - yes += string_replace(out_buf, &temp_len, pos, "*", "-"); + yes += string_replace(&new_buf, &temp_len, pos, "*", "-"); break; case 19: - yes += string_replace(out_buf, &temp_len, pos, "*", "+"); + yes += string_replace(&new_buf, &temp_len, pos, "*", "+"); break; case 20: - yes += string_replace(out_buf, &temp_len, pos, "*", "/"); + yes += string_replace(&new_buf, &temp_len, pos, "*", "/"); break; case 21: - yes += string_replace(out_buf, &temp_len, pos, "*", "%"); + yes += string_replace(&new_buf, &temp_len, pos, "*", "%"); break; case 22: - yes += string_replace(out_buf, &temp_len, pos, "-", "+"); + yes += string_replace(&new_buf, &temp_len, pos, "-", "+"); break; case 23: - yes += string_replace(out_buf, &temp_len, pos, "-", "*"); + yes += string_replace(&new_buf, &temp_len, pos, "-", "*"); break; case 24: - yes += string_replace(out_buf, &temp_len, pos, "-", "/"); + yes += string_replace(&new_buf, &temp_len, pos, "-", "/"); break; case 25: - yes += string_replace(out_buf, &temp_len, pos, "-", "%"); + yes += string_replace(&new_buf, &temp_len, pos, "-", "%"); break; case 26: - yes += string_replace(out_buf, &temp_len, pos, "/", "-"); + yes += string_replace(&new_buf, &temp_len, pos, "/", "-"); break; case 27: - yes += string_replace(out_buf, &temp_len, pos, "/", "*"); + yes += string_replace(&new_buf, &temp_len, pos, "/", "*"); break; case 28: - yes += string_replace(out_buf, &temp_len, pos, "/", "+"); + yes += string_replace(&new_buf, &temp_len, pos, "/", "+"); break; case 29: - yes += string_replace(out_buf, &temp_len, pos, "/", "%"); + yes += string_replace(&new_buf, &temp_len, pos, "/", "%"); break; case 30: - yes += string_replace(out_buf, &temp_len, pos, "%", "-"); + yes += string_replace(&new_buf, &temp_len, pos, "%", "-"); break; case 31: - yes += string_replace(out_buf, &temp_len, pos, "%", "*"); + yes += string_replace(&new_buf, &temp_len, pos, "%", "*"); break; case 32: - yes += string_replace(out_buf, &temp_len, pos, "%", "/"); + yes += string_replace(&new_buf, &temp_len, pos, "%", "/"); break; case 33: - yes += string_replace(out_buf, &temp_len, pos, "%", "+"); + yes += string_replace(&new_buf, &temp_len, pos, "%", "+"); break; case 34: - yes += string_replace(out_buf, &temp_len, pos, " ", "|"); + yes += string_replace(&new_buf, &temp_len, pos, " ", "|"); break; case 35: - yes += string_replace(out_buf, &temp_len, pos, " ", "$"); + yes += string_replace(&new_buf, &temp_len, pos, " ", "$"); break; case 36: - yes += string_replace(out_buf, &temp_len, pos, "0", "1"); + yes += string_replace(&new_buf, &temp_len, pos, "0", "1"); break; case 37: - yes += string_replace(out_buf, &temp_len, pos, "1", "0"); + yes += string_replace(&new_buf, &temp_len, pos, "1", "0"); break; case 38: - yes += string_replace(out_buf, &temp_len, pos, " ", "`"); + yes += string_replace(&new_buf, &temp_len, pos, " ", "`"); break; case 39: - yes += string_replace(out_buf, &temp_len, pos, " ", "\""); + yes += string_replace(&new_buf, &temp_len, pos, " ", "\""); break; case 40: - yes += string_replace(out_buf, &temp_len, pos, ";", " "); + yes += string_replace(&new_buf, &temp_len, pos, ";", " "); break; case 41: - yes += string_replace(out_buf, &temp_len, pos, "&&", "||"); + yes += string_replace(&new_buf, &temp_len, pos, "&&", "||"); break; case 42: - yes += string_replace(out_buf, &temp_len, pos, "||", "&&"); + yes += string_replace(&new_buf, &temp_len, pos, "||", "&&"); break; case 43: - yes += string_replace(out_buf, &temp_len, pos, "!", ""); + yes += string_replace(&new_buf, &temp_len, pos, "!", ""); break; case 44: - yes += string_replace(out_buf, &temp_len, pos, "==", "="); + yes += string_replace(&new_buf, &temp_len, pos, "==", "="); break; case 45: - yes += string_replace(out_buf, &temp_len, pos, "--", ""); + yes += string_replace(&new_buf, &temp_len, pos, "--", ""); break; case 46: - yes += string_replace(out_buf, &temp_len, pos, "<<", "<"); + yes += string_replace(&new_buf, &temp_len, pos, "<<", "<"); break; case 47: - yes += string_replace(out_buf, &temp_len, pos, ">>", ">"); + yes += string_replace(&new_buf, &temp_len, pos, ">>", ">"); break; case 48: - yes += string_replace(out_buf, &temp_len, pos, "<", "<<"); + yes += string_replace(&new_buf, &temp_len, pos, "<", "<<"); break; case 49: - yes += string_replace(out_buf, &temp_len, pos, ">", ">>"); + yes += string_replace(&new_buf, &temp_len, pos, ">", ">>"); break; case 50: - yes += string_replace(out_buf, &temp_len, pos, "\"", "'"); + yes += string_replace(&new_buf, &temp_len, pos, "\"", "'"); break; case 51: - yes += string_replace(out_buf, &temp_len, pos, "'", "\""); + yes += string_replace(&new_buf, &temp_len, pos, "'", "\""); break; case 52: - yes += string_replace(out_buf, &temp_len, pos, "(", "\""); + yes += string_replace(&new_buf, &temp_len, pos, "(", "\""); break; case 53: /* Remove a semicolon delimited statement after a semicolon */ - yes += delim_replace(out_buf, &temp_len, pos, ";", ";", ";"); + yes += delim_replace(&new_buf, &temp_len, pos, ";", ";", ";"); break; case 54: /* Remove a semicolon delimited statement after a left curly brace */ - yes += delim_replace(out_buf, &temp_len, pos, "}", ";", "}"); + yes += delim_replace(&new_buf, &temp_len, pos, "}", ";", "}"); break; case 55: /* Remove a curly brace construct */ - yes += delim_replace(out_buf, &temp_len, pos, "{", "}", ""); + yes += delim_replace(&new_buf, &temp_len, pos, "{", "}", ""); break; case 56: /* Replace a curly brace construct with an empty one */ - yes += delim_replace(out_buf, &temp_len, pos, "{", "}", "{}"); + yes += delim_replace(&new_buf, &temp_len, pos, "{", "}", "{}"); break; case 57: - yes += delim_swap(out_buf, &temp_len, pos, ";", ";", ";"); + yes += delim_swap(&new_buf, &temp_len, pos, ";", ";", ";"); break; case 58: - yes += delim_swap(out_buf, &temp_len, pos, "}", ";", ";"); + yes += delim_swap(&new_buf, &temp_len, pos, "}", ";", ";"); break; case 59: /* Swap comma delimited things case 1 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ")"); + yes += delim_swap(&new_buf, &temp_len, pos, "(", ",", ")"); break; case 60: /* Swap comma delimited things case 2 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", ",", ","); + yes += delim_swap(&new_buf, &temp_len, pos, "(", ",", ","); break; case 61: /* Swap comma delimited things case 3 */ - yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ","); + yes += delim_swap(&new_buf, &temp_len, pos, ",", ",", ","); break; case 62: /* Swap comma delimited things case 4 */ - yes += delim_swap(out_buf, &temp_len, pos, ",", ",", ")"); + yes += delim_swap(&new_buf, &temp_len, pos, ",", ",", ")"); break; case 63: /* Just delete a line */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", ""); + yes += delim_replace(&new_buf, &temp_len, pos, "\n", "\n", ""); break; case 64: /* Delete something like "const" case 1 */ - yes += delim_replace(out_buf, &temp_len, pos, " ", " ", ""); + yes += delim_replace(&new_buf, &temp_len, pos, " ", " ", ""); break; case 65: /* Delete something like "const" case 2 */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", " ", ""); + yes += delim_replace(&new_buf, &temp_len, pos, "\n", " ", ""); break; case 66: /* Delete something like "const" case 3 */ - yes += delim_replace(out_buf, &temp_len, pos, "(", " ", ""); + yes += delim_replace(&new_buf, &temp_len, pos, "(", " ", ""); break; case 67: /* Swap space delimited things case 1 */ - yes += delim_swap(out_buf, &temp_len, pos, " ", " ", " "); + yes += delim_swap(&new_buf, &temp_len, pos, " ", " ", " "); break; case 68: /* Swap space delimited things case 2 */ - yes += delim_swap(out_buf, &temp_len, pos, " ", " ", ")"); + yes += delim_swap(&new_buf, &temp_len, pos, " ", " ", ")"); break; case 69: /* Swap space delimited things case 3 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", " ", " "); + yes += delim_swap(&new_buf, &temp_len, pos, "(", " ", " "); break; case 70: /* Swap space delimited things case 4 */ - yes += delim_swap(out_buf, &temp_len, pos, "(", " ", ")"); + yes += delim_swap(&new_buf, &temp_len, pos, "(", " ", ")"); break; case 71: /* Duplicate a single line of code */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", "\n", NULL); + yes += delim_replace(&new_buf, &temp_len, pos, "\n", "\n", NULL); break; case 72: /* Duplicate a construct (most often, a non-nested for loop */ - yes += delim_replace(out_buf, &temp_len, pos, "\n", "}", NULL); + yes += delim_replace(&new_buf, &temp_len, pos, "\n", "}", NULL); break; + default: { + + for (u32 j = pos; j < temp_len; ++j) { + if (isdigit(new_buf[j])) { + + u8* endptr; + unsigned long long num = strtoull(new_buf +j, (char**)&endptr, 0); + + switch (rand_below(afl, 8)) { + case 0: + num = rand_below(afl, INT_MAX); + break; + case 1: + num = rand_next(afl); + break; + case 2: + num += 1 + rand_below(afl, 255); + break; + case 3: + num -= 1 + rand_below(afl, 255); + break; + case 4: + num *= 1 + rand_below(afl, 255); + break; + case 5: + num /= 1 + rand_below(afl, 255); + break; + case 6: + num /= 1 + rand_below(afl, 255); + break; + case 7: + num = ~num; + break; + } + + const char* fmt = "%llu"; + if (rand_below(afl, 5) == 0) // add - sign with 1/5 probability + fmt = "-%llu"; + + size_t num_len = snprintf(NULL, 0, fmt, num); + size_t old_len = endptr - (new_buf +j); + if (num_len < old_len) { + memmove(new_buf +j +num_len, endptr, temp_len - (endptr - new_buf)); + snprintf(new_buf +j, num_len, fmt, num); + temp_len -= old_len - num_len; + } else if (num_len == old_len) { + snprintf(new_buf +j, num_len, fmt, num); + } else { + new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + (num_len - old_len)); + memmove(new_buf +j +num_len, endptr, temp_len - (endptr - new_buf)); + snprintf(new_buf +j, num_len, fmt, num); + temp_len += num_len - old_len; + } + + yes += 1; + + } + } + + } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 88f8e902..8220b41b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -900,6 +900,7 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } if (get_afl_env("AFL_FAST_CAL")) { afl->fast_cal = 1; } + if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; } if (afl->afl_env.afl_autoresume) { -- cgit 1.4.1 From 185f4436598aacb3f25736ce6eb53309d1d9472f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 31 Jul 2020 17:53:01 +0200 Subject: add LTO AFL_LLVM_DOCUMENT_IDS feature --- docs/Changelog.md | 2 ++ docs/FAQ.md | 12 +++++----- docs/env_variables.md | 35 ++++++++++++++++------------ include/envs.h | 1 + llvm_mode/README.lto.md | 6 +++++ llvm_mode/afl-clang-fast.c | 2 ++ llvm_mode/afl-llvm-lto-instrumentation.so.cc | 18 ++++++++++++++ 7 files changed, 55 insertions(+), 21 deletions(-) (limited to 'include/envs.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index dcaf64a7..14d00a43 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,6 +26,8 @@ sending a mail to . - LTO: autodictionary mode is a default - 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 + was given to which function during compilation - setting AFL_LLVM_LAF_SPLIT_FLOATS now activates AFL_LLVM_LAF_SPLIT_COMPARES - added honggfuzz mangle as a custom mutator in custom_mutators/honggfuzz diff --git a/docs/FAQ.md b/docs/FAQ.md index e09385a8..b09a16ae 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -95,12 +95,13 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation! 2. Second step: Find the responsible function. - a) For LTO instrumented binaries just disassemble or decompile the target - and look which edge is writing to that edge ID. Ghidra is a good tool - for this: [https://ghidra-sre.org/](https://ghidra-sre.org/) + 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. - b) For PCGUARD instrumented binaries it is more difficult. Here you can - either modify the __sanitizer_cov_trace_pc_guard function in + b) For PCGUARD instrumented binaries it is much more difficult. Here you + can either modify the __sanitizer_cov_trace_pc_guard function in llvm_mode/afl-llvm-rt.o.c to write a backtrace to a file if the ID in __afl_area_ptr[*guard] is one of the unstable edge IDs. Then recompile and reinstall llvm_mode and rebuild your target. Run the recompiled @@ -121,4 +122,3 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation! 4. Fourth step: recompile the target Recompile, fuzz it, be happy :) - diff --git a/docs/env_variables.md b/docs/env_variables.md index 87344331..4c0d2db7 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -121,18 +121,16 @@ Then there are a few specific features that are only available in llvm_mode: built if LLVM 11 or newer is used. - AFL_LLVM_INSTRUMENT=CFG will use Control Flow Graph instrumentation. - (recommended) - - - AFL_LLVM_LTO_AUTODICTIONARY will generate a dictionary in the target - binary based on string compare and memory compare functions. - afl-fuzz will automatically get these transmitted when starting to - fuzz. + (not recommended!) None of the following options are necessary to be used and are rather for manual use (which only ever the author of this LTO implementation will use). These are used if several seperated instrumentation are performed which are then later combined. + - AFL_LLVM_DOCUMENT_IDS=file will document to a file which edge ID was given + to which function. This helps to identify functions with variable bytes + or which functions were touched by an input. - AFL_LLVM_MAP_ADDR sets the fixed map address to a different address than the default 0x10000. A value of 0 or empty sets the map address to be dynamic (the original afl way, which is slower) @@ -254,15 +252,6 @@ checks or alter some of the more exotic semantics of the tool: useful if you can't change the defaults (e.g., no root access to the system) and are OK with some performance loss. - - Setting AFL_NO_FORKSRV disables the forkserver optimization, reverting to - fork + execve() call for every tested input. This is useful mostly when - working with unruly libraries that create threads or do other crazy - things when initializing (before the instrumentation has a chance to run). - - Note that this setting inhibits some of the user-friendly diagnostics - normally done when starting up the forkserver and causes a pretty - significant performance drop. - - AFL_EXIT_WHEN_DONE causes afl-fuzz to terminate when all existing paths have been fuzzed and there were no new finds for a while. This would be normally indicated by the cycle counter in the UI turning green. May be @@ -338,6 +327,13 @@ checks or alter some of the more exotic semantics of the tool: - In QEMU mode (-Q), AFL_PATH will be searched for afl-qemu-trace. + - Setting AFL_CYCLE_SCHEDULES will switch to a different schedule everytime + a cycle is finished. + + - Setting AFL_EXPAND_HAVOC_NOW will start in the extended havoc mode that + includes costly mutations. afl-fuzz automatically enables this mode when + deemed useful otherwise. + - Setting AFL_PRELOAD causes AFL to set LD_PRELOAD for the target binary without disrupting the afl-fuzz process itself. This is useful, among other things, for bootstrapping libdislocator.so. @@ -365,6 +361,15 @@ checks or alter some of the more exotic semantics of the tool: for an existing out folder, even if a different `-i` was provided. Without this setting, afl-fuzz will refuse execution for a long-fuzzed out dir. + - Setting AFL_NO_FORKSRV disables the forkserver optimization, reverting to + fork + execve() call for every tested input. This is useful mostly when + working with unruly libraries that create threads or do other crazy + things when initializing (before the instrumentation has a chance to run). + + Note that this setting inhibits some of the user-friendly diagnostics + normally done when starting up the forkserver and causes a pretty + significant performance drop. + - Outdated environment variables that are that not supported anymore: AFL_DEFER_FORKSRV AFL_PERSISTENT diff --git a/include/envs.h b/include/envs.h index c1c7d387..7153ed47 100644 --- a/include/envs.h +++ b/include/envs.h @@ -65,6 +65,7 @@ static char *afl_environment_variables[] = { "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CTX", + "AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_LTO_AUTODICTIONARY", diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index a4c969b9..e521ac82 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -140,6 +140,12 @@ to be dynamic - the original afl way, which is slower). AFL_LLVM_MAP_DYNAMIC can be set so the shared memory address is dynamic (which is safer but also slower). +## Document edge IDs + +Setting `export AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge +ID was given to which function. This helps to identify functions with variable +bytes or which functions were touched by an input. + ## Solving difficult targets Some targets are difficult because the configure script does unusual stuff that diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index dca11bf3..a2550d2c 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -890,6 +890,8 @@ int main(int argc, char **argv, char **envp) { "AFL_NO_BUILTIN: compile for use with libtokencap.so\n" "AFL_PATH: path to instrumenting pass and runtime " "(afl-llvm-rt.*o)\n" + "AFL_LLVM_DOCUMENT_IDS: document edge IDs given to which function (LTO " + "only)\n" "AFL_QUIET: suppress verbose output\n" "AFL_USE_ASAN: activate address sanitizer\n" "AFL_USE_CFISAN: activate control flow sanitizer\n" diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 3c1d3565..46a97e54 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -103,6 +103,7 @@ bool AFLLTOPass::runOnModule(Module &M) { std::vector calls; DenseMap valueMap; char * ptr; + FILE * documentFile = NULL; IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int32Ty = IntegerType::getInt32Ty(C); @@ -120,6 +121,13 @@ bool AFLLTOPass::runOnModule(Module &M) { be_quiet = 1; + if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) { + + if ((documentFile = fopen(ptr, "a")) == NULL) + WARNF("Cannot access document file %s", ptr); + + } + if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0; if (getenv("AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK") || @@ -579,6 +587,14 @@ bool AFLLTOPass::runOnModule(Module &M) { } + if (documentFile) { + + fprintf(documentFile, "%s %u\n", + origBB->getParent()->getName().str().c_str(), + afl_global_id); + + } + BasicBlock::iterator IP = newBB->getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); @@ -632,6 +648,8 @@ bool AFLLTOPass::runOnModule(Module &M) { } + if (documentFile) fclose(documentFile); + } // save highest location ID to global variable -- cgit 1.4.1