frida mode: add dynamic loaded code exclusion

Add the AFL_FRIDA_INST_NO_DYNAMIC_LOAD environment variable and its
associated JS function setInstrumentNoDynamicLoad to prevent the
instrumentation of late dynamic loaded code.

Resolve #1708
This commit is contained in:
eleguevel
2023-04-21 12:00:56 +02:00
parent 4e5f42cab6
commit 30495e6bfe
10 changed files with 76 additions and 4 deletions

View File

@ -677,6 +677,8 @@ support.
* `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled
code. Code is considered to be JIT if the executable segment is not backed by
a file.
* `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` - Don't instrument the code loaded late at
runtime. Strictly limits instrumentation to what has been included.
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
instrumentation (the default where available). Required to use
`AFL_FRIDA_INST_TRACE`.

View File

@ -178,11 +178,13 @@ Default is 256Mb.
* `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled
code. Code is considered to be JIT if the executable segment is not backed by
a file.
* `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` - Don't instrument the code loaded late at
runtime. Strictly limits instrumentation to what has been included.
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
instrumentation (the default where available). Required to use
`AFL_FRIDA_INST_TRACE`.
* `AFL_FRIDA_INST_REGS_FILE` - File to write raw register contents at the start
of each block.
`AFL_FRIDA_INST_TRACE`.
* `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to
instrumented address block translations.
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will

View File

@ -844,6 +844,12 @@ class Afl {
static setInstrumentLibraries() {
Afl.jsApiSetInstrumentLibraries();
}
/**
* See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD`
*/
static setInstrumentNoDynamicLoad() {
Afl.jsApiSetInstrumentNoDynamicLoad();
}
/**
* See `AFL_FRIDA_INST_NO_OPTIMIZE`
*/

View File

@ -19,6 +19,7 @@
js_api_set_instrument_jit;
js_api_set_instrument_libraries;
js_api_set_instrument_instructions;
js_api_set_instrument_no_dynamic_load;
js_api_set_instrument_no_optimize;
js_api_set_instrument_regs_file;
js_api_set_instrument_seed;

View File

@ -6,6 +6,7 @@
extern gboolean ranges_debug_maps;
extern gboolean ranges_inst_libs;
extern gboolean ranges_inst_jit;
extern gboolean ranges_inst_dynamic_load;
void ranges_config(void);
void ranges_init(void);

View File

@ -150,6 +150,12 @@ class Afl {
static setInstrumentLibraries() {
Afl.jsApiSetInstrumentLibraries();
}
/**
* See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD`
*/
static setInstrumentNoDynamicLoad() {
Afl.jsApiSetInstrumentNoDynamicLoad();
}
/**
* See `AFL_FRIDA_INST_NO_OPTIMIZE`
*/
@ -342,6 +348,7 @@ Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_de
Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []);
Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []);
Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
Afl.jsApiSetInstrumentNoDynamicLoad = Afl.jsApiGetFunction("js_api_set_instrument_no_dynamic_load", "void", []);
Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []);
Afl.jsApiSetInstrumentRegsFile = Afl.jsApiGetFunction("js_api_set_instrument_regs_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]);

View File

@ -156,6 +156,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_instructions(
}
__attribute__((visibility("default"))) void js_api_set_instrument_no_dynamic_load(
void) {
ranges_inst_dynamic_load = FALSE;
}
__attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
void) {

View File

@ -18,6 +18,7 @@ typedef struct {
gboolean ranges_debug_maps = FALSE;
gboolean ranges_inst_libs = FALSE;
gboolean ranges_inst_jit = FALSE;
gboolean ranges_inst_dynamic_load = TRUE;
static GArray *module_ranges = NULL;
static GArray *libs_ranges = NULL;
@ -25,6 +26,7 @@ static GArray *jit_ranges = NULL;
static GArray *include_ranges = NULL;
static GArray *exclude_ranges = NULL;
static GArray *ranges = NULL;
static GArray *whole_memory_ranges = NULL;
static void convert_address_token(gchar *token, GumMemoryRange *range) {
@ -387,6 +389,21 @@ static GArray *collect_jit_ranges(void) {
}
static GArray *collect_whole_mem_ranges(void) {
GArray *result;
GumMemoryRange range;
result = g_array_new(false, false, sizeof(GumMemoryRange));
range.base_address = 0;
range.size = G_MAXULONG;
g_array_append_val(result, range);
return result;
}
static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra,
GumMemoryRange *rb) {
@ -574,11 +591,17 @@ void ranges_config(void) {
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; }
if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; }
if (getenv("AFL_FRIDA_INST_NO_DYNAMIC_LOAD") != NULL) {
ranges_inst_dynamic_load = FALSE;
}
if (ranges_debug_maps) { ranges_print_debug_maps(); }
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");
whole_memory_ranges = collect_whole_mem_ranges();
}
@ -628,10 +651,20 @@ void ranges_init(void) {
print_ranges("step4", step4);
/*
* After step4, we have the total ranges to be instrumented, we now subtract
* that from the original ranges of the modules to configure stalker.
* After step 4 we have the total ranges to be instrumented, we now subtract
* that either from the original ranges of the modules or from the whole
* memory if AFL_INST_NO_DYNAMIC_LOAD to configure the stalker.
*/
step5 = subtract_ranges(module_ranges, step4);
if (ranges_inst_dynamic_load) {
step5 = subtract_ranges(module_ranges, step4);
} else {
step5 = subtract_ranges(whole_memory_ranges, step4);
}
print_ranges("step5", step5);
ranges = merge_ranges(step5);

View File

@ -178,6 +178,13 @@ class Afl {
Afl.jsApiSetInstrumentLibraries();
}
/**
* See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD`
*/
public static setInstrumentNoDynamicLoad(): void {
Afl.jsApiSetInstrumentNoDynamicLoad();
}
/**
* See `AFL_FRIDA_INST_NO_OPTIMIZE`
*/
@ -443,6 +450,11 @@ class Afl {
"void",
[]);
private static readonly jsApiSetInstrumentNoDynamicLoad = Afl.jsApiGetFunction(
"js_api_set_instrument_no_dynamic_load",
"void",
[]);
private static readonly jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction(
"js_api_set_instrument_no_optimize",
"void",

View File

@ -65,6 +65,7 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_INST_INSN",
"AFL_FRIDA_INST_JIT",
"AFL_FRIDA_INST_NO_CACHE",
"AFL_FRIDA_INST_NO_DYNAMIC_LOAD",
"AFL_FRIDA_INST_NO_OPTIMIZE",
"AFL_FRIDA_INST_NO_PREFETCH",
"AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",