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 * `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 code. Code is considered to be JIT if the executable segment is not backed by
a file. 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 * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
instrumentation (the default where available). Required to use instrumentation (the default where available). Required to use
`AFL_FRIDA_INST_TRACE`. `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 * `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 code. Code is considered to be JIT if the executable segment is not backed by
a file. 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 * `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
instrumentation (the default where available). Required to use 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 * `AFL_FRIDA_INST_REGS_FILE` - File to write raw register contents at the start
of each block. of each block.
`AFL_FRIDA_INST_TRACE`.
* `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to * `AFL_FRIDA_INST_NO_CACHE` - Don't use a look-up table to cache real to
instrumented address block translations. instrumented address block translations.
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will * `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will

View File

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

View File

@ -19,6 +19,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_instructions; js_api_set_instrument_instructions;
js_api_set_instrument_no_dynamic_load;
js_api_set_instrument_no_optimize; js_api_set_instrument_no_optimize;
js_api_set_instrument_regs_file; js_api_set_instrument_regs_file;
js_api_set_instrument_seed; js_api_set_instrument_seed;

View File

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

View File

@ -150,6 +150,12 @@ class Afl {
static setInstrumentLibraries() { static setInstrumentLibraries() {
Afl.jsApiSetInstrumentLibraries(); Afl.jsApiSetInstrumentLibraries();
} }
/**
* See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD`
*/
static setInstrumentNoDynamicLoad() {
Afl.jsApiSetInstrumentNoDynamicLoad();
}
/** /**
* See `AFL_FRIDA_INST_NO_OPTIMIZE` * 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.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []);
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.jsApiSetInstrumentNoDynamicLoad = Afl.jsApiGetFunction("js_api_set_instrument_no_dynamic_load", "void", []);
Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "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.jsApiSetInstrumentRegsFile = Afl.jsApiGetFunction("js_api_set_instrument_regs_file", "void", ["pointer"]);
Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]); 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( __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
void) { void) {

View File

@ -18,6 +18,7 @@ typedef struct {
gboolean ranges_debug_maps = FALSE; gboolean ranges_debug_maps = FALSE;
gboolean ranges_inst_libs = FALSE; gboolean ranges_inst_libs = FALSE;
gboolean ranges_inst_jit = FALSE; gboolean ranges_inst_jit = FALSE;
gboolean ranges_inst_dynamic_load = TRUE;
static GArray *module_ranges = NULL; static GArray *module_ranges = NULL;
static GArray *libs_ranges = NULL; static GArray *libs_ranges = NULL;
@ -25,6 +26,7 @@ static GArray *jit_ranges = NULL;
static GArray *include_ranges = NULL; static GArray *include_ranges = NULL;
static GArray *exclude_ranges = NULL; static GArray *exclude_ranges = NULL;
static GArray *ranges = NULL; static GArray *ranges = NULL;
static GArray *whole_memory_ranges = NULL;
static void convert_address_token(gchar *token, GumMemoryRange *range) { 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, static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra,
GumMemoryRange *rb) { GumMemoryRange *rb) {
@ -574,11 +591,17 @@ void ranges_config(void) {
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; } if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = 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_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(); } if (ranges_debug_maps) { ranges_print_debug_maps(); }
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_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); print_ranges("step4", step4);
/* /*
* After step4, we have the total ranges to be instrumented, we now subtract * After step 4 we have the total ranges to be instrumented, we now subtract
* that from the original ranges of the modules to configure stalker. * 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); print_ranges("step5", step5);
ranges = merge_ranges(step5); ranges = merge_ranges(step5);

View File

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

View File

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