#include "instrument.h"
#include "prefetch.h"
#include "stalker.h"
#include "stats.h"
#include "util.h"
guint stalker_ic_entries = 0;
gboolean backpatch_enable = TRUE;
guint stalker_adjacent_blocks = 0;
static GumStalker *stalker = NULL;
struct _GumAflStalkerObserver {
GObject parent;
};
#define GUM_TYPE_AFL_STALKER_OBSERVER (gum_afl_stalker_observer_get_type())
G_DECLARE_FINAL_TYPE(GumAflStalkerObserver, gum_afl_stalker_observer, GUM,
AFL_STALKER_OBSERVER, GObject)
static void gum_afl_stalker_observer_iface_init(gpointer g_iface,
gpointer iface_data);
static void gum_afl_stalker_observer_class_init(
GumAflStalkerObserverClass *klass);
static void gum_afl_stalker_observer_init(GumAflStalkerObserver *self);
G_DEFINE_TYPE_EXTENDED(
GumAflStalkerObserver, gum_afl_stalker_observer, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE(GUM_TYPE_STALKER_OBSERVER,
gum_afl_stalker_observer_iface_init))
static GumAflStalkerObserver *observer = NULL;
static void gum_afl_stalker_observer_iface_init(gpointer g_iface,
gpointer iface_data) {
UNUSED_PARAMETER(g_iface);
UNUSED_PARAMETER(iface_data);
}
static void gum_afl_stalker_observer_class_init(
GumAflStalkerObserverClass *klass) {
UNUSED_PARAMETER(klass);
}
static void gum_afl_stalker_observer_init(GumAflStalkerObserver *self) {
UNUSED_PARAMETER(self);
}
void stalker_config(void) {
if (!gum_stalker_is_supported()) { FFATAL("Failed to initialize embedded"); }
backpatch_enable = (getenv("AFL_FRIDA_INST_NO_BACKPATCH") == NULL);
stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES", 32);
stalker_adjacent_blocks =
util_read_num("AFL_FRIDA_STALKER_ADJACENT_BLOCKS", 32);
observer = g_object_new(GUM_TYPE_AFL_STALKER_OBSERVER, NULL);
}
static gboolean stalker_exclude_self(const GumRangeDetails *details,
gpointer user_data) {
UNUSED_PARAMETER(user_data);
gchar *name;
gboolean found;
GumStalker *stalker;
if (details->file == NULL) { return TRUE; }
name = g_path_get_basename(details->file->path);
found = (g_strcmp0(name, "afl-frida-trace.so") == 0);
g_free(name);
if (!found) { return TRUE; }
stalker = stalker_get();
gum_stalker_exclude(stalker, details->range);
return FALSE;
}
void stalker_init(void) {
FOKF(cBLU "Stalker" cRST " - " cGRN "backpatch:" cYEL " [%c]",
backpatch_enable ? 'X' : ' ');
FOKF(cBLU "Stalker" cRST " - " cGRN "ic_entries:" cYEL " [%u]",
stalker_ic_entries);
FOKF(cBLU "Stalker" cRST " - " cGRN "adjacent_blocks:" cYEL " [%u]",
stalker_adjacent_blocks);
#if !(defined(__x86_64__) || defined(__i386__) || defined(__aarch64__))
if (getenv("AFL_FRIDA_STALKER_IC_ENTRIES") != NULL) {
FFATAL("AFL_FRIDA_STALKER_IC_ENTRIES not supported");
}
if (getenv("AFL_FRIDA_STALKER_ADJACENT_BLOCKS") != NULL) {
FFATAL("AFL_FRIDA_STALKER_ADJACENT_BLOCKS not supported");
}
#endif
if (instrument_coverage_filename != NULL) {
if (getenv("AFL_FRIDA_STALKER_ADJACENT_BLOCKS") != NULL) {
FFATAL(
"AFL_FRIDA_STALKER_ADJACENT_BLOCKS and AFL_FRIDA_INST_COVERAGE_FILE "
"are incompatible");
} else {
stalker_adjacent_blocks = 0;
}
}
gum_stalker_activate_experimental_unwind_support();
#if defined(__x86_64__) || defined(__i386__)
stalker = g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries,
"adjacent-blocks", stalker_adjacent_blocks, NULL);
#elif defined(__aarch64__)
stalker =
g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries, NULL);
#else
stalker = gum_stalker_new();
#endif
if (stalker == NULL) { FFATAL("Failed to initialize stalker"); }
gum_stalker_set_trust_threshold(stalker, -1);
/* *NEVER* stalk the stalker, only bad things will ever come of this! */
gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, stalker_exclude_self, NULL);
}
GumStalker *stalker_get(void) {
if (stalker == NULL) { FFATAL("Stalker uninitialized"); }
return stalker;
}
void stalker_start(void) {
GumStalkerTransformer *transformer = instrument_get_transformer();
gum_stalker_follow_me(stalker, transformer, NULL);
gum_stalker_set_observer(stalker, GUM_STALKER_OBSERVER(observer));
}
void stalker_trust(void) {
if (backpatch_enable) { gum_stalker_set_trust_threshold(stalker, 0); }
}
GumStalkerObserver *stalker_get_observer(void) {
if (observer == NULL) { FFATAL("Stalker not yet initialized"); }
return GUM_STALKER_OBSERVER(observer);
}