about summary refs log tree commit diff
diff options
context:
space:
mode:
authorfuzzah <fuzzah@tuta.io>2021-03-17 01:51:40 +0300
committerfuzzah <fuzzah@tuta.io>2021-03-20 01:32:28 +0300
commitd7e121e2c99c02d4b6984f21ba837d44bce9c77c (patch)
tree2263044f6ce1e845226245b0ba7381ab99490976
parent65b90001f6e731f22178cb592b9812639bff4cb5 (diff)
downloadafl++-d7e121e2c99c02d4b6984f21ba837d44bce9c77c.tar.gz
add AFL_TARGET_ENV to afl-fuzz
-rw-r--r--README.md1
-rw-r--r--docs/Changelog.md3
-rw-r--r--docs/env_variables.md6
-rw-r--r--include/common.h4
-rw-r--r--include/envs.h1
-rw-r--r--src/afl-common.c96
-rw-r--r--src/afl-fuzz.c8
7 files changed, 119 insertions, 0 deletions
diff --git a/README.md b/README.md
index 69e5bb74..700fe818 100644
--- a/README.md
+++ b/README.md
@@ -1178,6 +1178,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 bf04c58e..fdb1cf5c 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -9,6 +9,9 @@ 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 ++3.12a (dev)
+  - afl-fuzz:
+    - added AFL_TARGET_ENV variable to pass extra env vars to the target
+      (for things like LD_LIBRARY_PATH)
   - afl-cc:
     - fix cmplog rtn (rare crash and not being able to gather ptr data)
     - link runtime not to shared libs
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 b7adbaec..06453b8e 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 cfd73b68..fda4ab55 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -130,6 +130,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 27b63434..72a95fbc 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -706,6 +706,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 cfb507a7..9ea1fb34 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]);