Support for setting a fixed seed for the hash function (#1026)

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
WorksButNotTested
2021-07-15 19:32:44 +01:00
committed by GitHub
parent 6f03749c73
commit 9e8afcc615
9 changed files with 67 additions and 17 deletions

View File

@ -162,6 +162,9 @@ instrumentation (the default where available). Required to use
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default the child will * `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default the child will
report instrumented blocks back to the parent so that it can also instrument report instrumented blocks back to the parent so that it can also instrument
them and they be inherited by the next child on fork. them and they be inherited by the next child on fork.
* `AFL_FRIDA_INST_SEED` - Sets the initial seed for the hash function used to
generate block (and hence edge) IDs. Setting this to a constant value may be
useful for debugging purposes, e.g. investigating unstable edges.
* `AFL_FRIDA_INST_TRACE` - Log to stdout the address of executed blocks, * `AFL_FRIDA_INST_TRACE` - Log to stdout the address of executed blocks,
implies `AFL_FRIDA_INST_NO_OPTIMIZE`. implies `AFL_FRIDA_INST_NO_OPTIMIZE`.
* `AFL_FRIDA_INST_TRACE_UNIQUE` - As per `AFL_FRIDA_INST_TRACE`, but each edge * `AFL_FRIDA_INST_TRACE_UNIQUE` - As per `AFL_FRIDA_INST_TRACE`, but each edge

View File

@ -14,6 +14,7 @@
js_api_set_instrument_jit; js_api_set_instrument_jit;
js_api_set_instrument_libraries; js_api_set_instrument_libraries;
js_api_set_instrument_no_optimize; js_api_set_instrument_no_optimize;
js_api_set_instrument_seed;
js_api_set_instrument_trace; js_api_set_instrument_trace;
js_api_set_instrument_trace_unique; js_api_set_instrument_trace_unique;
js_api_set_persistent_address; js_api_set_persistent_address;

View File

@ -12,6 +12,9 @@ extern gboolean instrument_unique;
extern __thread guint64 instrument_previous_pc; extern __thread guint64 instrument_previous_pc;
extern guint64 instrument_hash_zero; extern guint64 instrument_hash_zero;
extern gboolean instrument_use_fixed_seed;
extern guint64 instrument_fixed_seed;
extern uint8_t *__afl_area_ptr; extern uint8_t *__afl_area_ptr;
extern uint32_t __afl_map_size; extern uint32_t __afl_map_size;

View File

@ -27,6 +27,9 @@ gboolean instrument_unique = false;
guint64 instrument_hash_zero = 0; guint64 instrument_hash_zero = 0;
guint64 instrument_hash_seed = 0; guint64 instrument_hash_seed = 0;
gboolean instrument_use_fixed_seed = FALSE;
guint64 instrument_fixed_seed = 0;
static GumStalkerTransformer *transformer = NULL; static GumStalkerTransformer *transformer = NULL;
__thread guint64 instrument_previous_pc = 0; __thread guint64 instrument_previous_pc = 0;
@ -221,6 +224,8 @@ void instrument_config(void) {
instrument_optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL); instrument_optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
instrument_tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL); instrument_tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
instrument_unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL); instrument_unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
instrument_use_fixed_seed = (getenv("AFL_FRIDA_INST_SEED") != NULL);
instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED");
instrument_debug_config(); instrument_debug_config();
asan_config(); asan_config();
@ -235,6 +240,8 @@ void instrument_init(void) {
OKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' '); OKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' ');
OKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' '); OKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' ');
OKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' '); OKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' ');
OKF("Instrumentation - fixed seed [%c] [0x%016" G_GINT64_MODIFIER "x]",
instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed);
if (instrument_tracing && instrument_optimize) { if (instrument_tracing && instrument_optimize) {
@ -270,7 +277,8 @@ void instrument_init(void) {
g_assert(edges_notified != MAP_FAILED); g_assert(edges_notified != MAP_FAILED);
/* /*
* Configure the shared memory region to be removed once the process dies. * Configure the shared memory region to be removed once the process
* dies.
*/ */
if (shmctl(shm_id, IPC_RMID, NULL) < 0) { if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
@ -283,14 +291,26 @@ void instrument_init(void) {
} }
/* if (instrument_use_fixed_seed) {
* By using a different seed value for the hash, we can make different
* instances have edge collisions in different places when carrying out /*
* parallel fuzzing. The seed itself, doesn't have to be random, it just * This configuration option may be useful for diagnostics or
* needs to be different for each instance. * debugging.
*/ */
instrument_hash_seed = instrument_hash_seed = instrument_fixed_seed;
g_get_monotonic_time() ^ (((guint64)getpid()) << 32) ^ syscall(SYS_gettid);
} else {
/*
* By using a different seed value for the hash, we can make different
* instances have edge collisions in different places when carrying out
* parallel fuzzing. The seed itself, doesn't have to be random, it
* just needs to be different for each instance.
*/
instrument_hash_seed = g_get_monotonic_time() ^
(((guint64)getpid()) << 32) ^ syscall(SYS_gettid);
}
OKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]", OKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]",
instrument_hash_seed); instrument_hash_seed);

View File

@ -117,6 +117,12 @@ class Afl {
static setInstrumentNoOptimize() { static setInstrumentNoOptimize() {
Afl.jsApiSetInstrumentNoOptimize(); Afl.jsApiSetInstrumentNoOptimize();
} }
/*
* See `AFL_FRIDA_INST_SEED`
*/
static setInstrumentSeed(seed) {
Afl.jsApiSetInstrumentSeed(seed);
}
/** /**
* See `AFL_FRIDA_INST_TRACE_UNIQUE`. * See `AFL_FRIDA_INST_TRACE_UNIQUE`.
*/ */
@ -231,6 +237,7 @@ Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_de
Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []); Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []);
Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []);
Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]);
Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []); Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []);
Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []); Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []);
Afl.jsApiSetPersistentAddress = Afl.jsApiGetFunction("js_api_set_persistent_address", "void", ["pointer"]); Afl.jsApiSetPersistentAddress = Afl.jsApiGetFunction("js_api_set_persistent_address", "void", ["pointer"]);

View File

@ -89,10 +89,7 @@ static void load_cb(GObject *source_object, GAsyncResult *result,
UNUSED_PARAMETER(source_object); UNUSED_PARAMETER(source_object);
UNUSED_PARAMETER(user_data); UNUSED_PARAMETER(user_data);
gum_script_load_finish(script, result); gum_script_load_finish(script, result);
if (error != NULL) if (error != NULL) { FATAL("Failed to load script - %s", error->message); }
{
FATAL("Failed to load script - %s", error->message);
}
} }
@ -102,10 +99,7 @@ static void create_cb(GObject *source_object, GAsyncResult *result,
UNUSED_PARAMETER(source_object); UNUSED_PARAMETER(source_object);
UNUSED_PARAMETER(user_data); UNUSED_PARAMETER(user_data);
script = gum_script_backend_create_finish(backend, result, &error); script = gum_script_backend_create_finish(backend, result, &error);
if (error != NULL) if (error != NULL) { FATAL("Failed to create script: %s", error->message); }
{
FATAL("Failed to create script: %s", error->message);
}
gum_script_set_message_handler(script, js_msg, NULL, NULL); gum_script_set_message_handler(script, js_msg, NULL, NULL);
@ -145,3 +139,4 @@ gboolean js_stalker_callback(const cs_insn *insn, gboolean begin,
return js_user_callback(insn, begin, excluded, output); return js_user_callback(insn, begin, excluded, output);
} }

View File

@ -127,6 +127,14 @@ __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
} }
__attribute__((visibility("default"))) void js_api_set_instrument_seed(
guint64 seed) {
instrument_use_fixed_seed = TRUE;
instrument_fixed_seed = seed;
}
__attribute__((visibility("default"))) void js_api_set_instrument_trace(void) { __attribute__((visibility("default"))) void js_api_set_instrument_trace(void) {
instrument_tracing = TRUE; instrument_tracing = TRUE;

View File

@ -140,6 +140,13 @@ class Afl {
Afl.jsApiSetInstrumentNoOptimize(); Afl.jsApiSetInstrumentNoOptimize();
} }
/*
* See `AFL_FRIDA_INST_SEED`
*/
public static setInstrumentSeed(seed: NativePointer): void {
Afl.jsApiSetInstrumentSeed(seed);
}
/** /**
* See `AFL_FRIDA_INST_TRACE_UNIQUE`. * See `AFL_FRIDA_INST_TRACE_UNIQUE`.
*/ */
@ -295,6 +302,11 @@ class Afl {
"void", "void",
[]); []);
private static readonly jsApiSetInstrumentSeed = Afl.jsApiGetFunction(
"js_api_set_instrument_seed",
"void",
["uint64"]);
private static readonly jsApiSetInstrumentTrace = Afl.jsApiGetFunction( private static readonly jsApiSetInstrumentTrace = Afl.jsApiGetFunction(
"js_api_set_instrument_trace", "js_api_set_instrument_trace",
"void", "void",

View File

@ -60,6 +60,7 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_OPTIMIZE",
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH",
"AFL_FRIDA_INST_RANGES", "AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_SEED",
"AFL_FRIDA_INST_TRACE", "AFL_FRIDA_INST_TRACE",
"AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_TRACE_UNIQUE",
"AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_JS_SCRIPT",