diff options
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | docs/Changelog.md | 2 | ||||
-rw-r--r-- | docs/env_variables.md | 6 | ||||
-rw-r--r-- | include/common.h | 4 | ||||
-rw-r--r-- | include/envs.h | 1 | ||||
-rw-r--r-- | src/afl-common.c | 96 | ||||
-rw-r--r-- | src/afl-fuzz.c | 8 |
7 files changed, 118 insertions, 0 deletions
diff --git a/README.md b/README.md index 2528e1d1..627e1b0f 100644 --- a/README.md +++ b/README.md @@ -1184,6 +1184,7 @@ without feedback, bug reports, or patches from: Josephine Calliotte Konrad Welc Thomas Rooijakkers David Carlier Ruben ten Hove Joey Jiao + fuzzah ``` Thank you! diff --git a/docs/Changelog.md b/docs/Changelog.md index 166393cb..ab0312f8 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. ### Version ++3.12a (dev) - afl-fuzz: + - added AFL_TARGET_ENV variable to pass extra env vars to the target + (for things like LD_LIBRARY_PATH) - better map detection, AFL_MAP_SIZE not needed anymore for most cases - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) diff --git a/docs/env_variables.md b/docs/env_variables.md index c6ad0aa4..96fd520f 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -408,6 +408,12 @@ checks or alter some of the more exotic semantics of the tool: without disrupting the afl-fuzz process itself. This is useful, among other things, for bootstrapping libdislocator.so. + - Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables + for the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz ... ` + This exists mostly for things like `LD_LIBRARY_PATH` but it would theoretically + allow fuzzing of AFL++ itself (with 'target' AFL++ using some AFL_ vars that + would disrupt work of 'fuzzer' AFL++). + - Setting `AFL_NO_UI` inhibits the UI altogether, and just periodically prints some basic stats. This behavior is also automatically triggered when the output from afl-fuzz is redirected to a file or to a pipe. diff --git a/include/common.h b/include/common.h index 46585c88..05137fb6 100644 --- a/include/common.h +++ b/include/common.h @@ -49,6 +49,10 @@ 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 * get_afl_env(char *env); +/* Extract env vars from input string and set them using setenv() + For use with AFL_TARGET_ENV, ... */ +u8 extract_and_set_env(u8 *env_str); + extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ diff --git a/include/envs.h b/include/envs.h index 2ce50be7..d7578045 100644 --- a/include/envs.h +++ b/include/envs.h @@ -131,6 +131,7 @@ static char *afl_environment_variables[] = { "AFL_PATH", "AFL_PERFORMANCE_FILE", "AFL_PRELOAD", + "AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV", diff --git a/src/afl-common.c b/src/afl-common.c index 04736901..6e485117 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -618,6 +618,102 @@ char *get_afl_env(char *env) { } +u8 extract_and_set_env(u8 *env_str) { + + if (!env_str) { return 0; } + + u8 *p = ck_strdup(env_str); + + u8 *end = p + strlen((char *)p); + + u8 ret_val = 0; // return false by default + + u8 *rest = p; + u8 *key = p; + u8 *val = p; + + u8 closing_sym = ' '; + u8 c; + + size_t num_pairs = 0; + + while (rest < end) { + + while (*rest == ' ') { + + rest++; + + } + + if (rest + 1 >= end) break; + + key = rest; + // env variable names may not start with numbers or '=' + if (*key == '=' || (*key >= '0' && *key <= '9')) { goto free_and_return; } + + while (rest < end && *rest != '=' && *rest != ' ') { + + c = *rest; + // lowercase is bad but we may still allow it + if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && + (c < '0' || c > '9') && c != '_') { + + goto free_and_return; + + } + + rest++; + + } + + if (*rest != '=') { goto free_and_return; } + + *rest = '\0'; // done with variable name + + rest += 1; + if (rest >= end || *rest == ' ') { goto free_and_return; } + + val = rest; + if (*val == '\'' || *val == '"') { + + closing_sym = *val; + val += 1; + rest += 1; + if (rest >= end) { goto free_and_return; } + + } else { + + closing_sym = ' '; + + } + + while (rest < end && *rest != closing_sym) { + + rest++; + + } + + if (closing_sym != ' ' && *rest != closing_sym) { goto free_and_return; } + + *rest = '\0'; // done with variable value + + rest += 1; + if (rest < end && *rest != ' ') { goto free_and_return; } + + num_pairs += 1; + + setenv(key, val, 1); + + } + + if (num_pairs > 0) { ret_val = 1; } + +free_and_return: + ck_free(p); + return ret_val; + +} + /* Read mask bitmap from file. This is for the -B option. */ void read_bitmap(u8 *fname, u8 *map, size_t len) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 1518a707..b1d01959 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -223,6 +223,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_PYTHON_MODULE: mutate and trim inputs with the specified Python module\n" "AFL_QUIET: suppress forkserver status messages\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" + "AFL_TARGET_ENV: pass extra environment variables to target\n" "AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n" "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" @@ -1303,6 +1304,13 @@ int main(int argc, char **argv_orig, char **envp) { } + u8 *extra_env = (u8 *)getenv("AFL_TARGET_ENV"); + if (extra_env && !extract_and_set_env(extra_env)) { + + FATAL("Bad value of AFL_TARGET_ENV"); + + } + save_cmdline(afl, argc, argv); fix_up_banner(afl, argv[optind]); |