diff options
Diffstat (limited to 'frida_mode/src')
-rw-r--r-- | frida_mode/src/entry.c | 1 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument.c | 11 | ||||
-rw-r--r-- | frida_mode/src/js/api.js | 430 | ||||
-rw-r--r-- | frida_mode/src/js/js.c | 13 | ||||
-rw-r--r-- | frida_mode/src/js/js_api.c | 12 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent.c | 28 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_arm64.c | 399 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_x64.c | 174 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_x86.c | 111 |
9 files changed, 561 insertions, 618 deletions
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index 186d5098..e95b923b 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -13,6 +13,7 @@ guint64 entry_point = 0; static void entry_launch(void) { + OKF("Entry point reached"); __afl_manual_init(); /* Child here */ diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index d6ae505d..2a217d96 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -11,6 +11,7 @@ #include "entry.h" #include "frida_cmplog.h" #include "instrument.h" +#include "js.h" #include "persistent.h" #include "prefetch.h" #include "ranges.h" @@ -165,8 +166,6 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } - begin = FALSE; - } instrument_debug_instruction(instr->address, instr->size); @@ -178,7 +177,13 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } - gum_stalker_iterator_keep(iterator); + if (js_stalker_callback(instr, begin, excluded, output)) { + + gum_stalker_iterator_keep(iterator); + + } + + begin = FALSE; } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 983f1efa..4cb04704 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -1,201 +1,243 @@ -const write = new NativeFunction( - Module.getExportByName(null, 'write'), - 'int', - ['int', 'pointer', 'int'] -); - -const afl_frida_trace = Process.findModuleByName('afl-frida-trace.so'); - -function get_api(name, ret, args) { - const addr = afl_frida_trace.findExportByName(name); - return new NativeFunction(addr, ret, args); -} - -const js_api_done = get_api( - 'js_api_done', - 'void', - []); - -const js_api_error = get_api( - 'js_api_error', - 'void', - ['pointer']); - -const js_api_set_entrypoint = get_api( - 'js_api_set_entrypoint', - 'void', - ['pointer']); - -const js_api_set_persistent_address = get_api( - 'js_api_set_persistent_address', - 'void', - ['pointer']); - -const js_api_set_persistent_return = get_api( - 'js_api_set_persistent_return', - 'void', - ['pointer']); - -const js_api_set_persistent_count = get_api( - 'js_api_set_persistent_count', - 'void', - ['uint64']); - -const js_api_set_persistent_debug = get_api( - 'js_api_set_persistent_debug', - 'void', - []); - -const js_api_set_debug_maps = get_api( - 'js_api_set_debug_maps', - 'void', - []); - -const js_api_add_include_range = get_api( - 'js_api_add_include_range', - 'void', - ['pointer', 'size_t']); - -const js_api_add_exclude_range = get_api( - 'js_api_add_exclude_range', - 'void', - ['pointer', 'size_t']); - -const js_api_set_instrument_libraries = get_api( - 'js_api_set_instrument_libraries', - 'void', - []); - -const js_api_set_instrument_debug_file = get_api( - 'js_api_set_instrument_debug_file', - 'void', - ['pointer']); - -const js_api_set_prefetch_disable = get_api( - 'js_api_set_prefetch_disable', - 'void', - []); - -const js_api_set_instrument_no_optimize = get_api( - 'js_api_set_instrument_no_optimize', - 'void', - []); - -const js_api_set_instrument_trace = get_api( - 'js_api_set_instrument_trace', - 'void', - []); - -const js_api_set_instrument_trace_unique = get_api( - 'js_api_set_instrument_trace_unique', - 'void', - []); - -const js_api_set_stdout = get_api( - 'js_api_set_stdout', - 'void', - ['pointer']); - -const js_api_set_stderr = get_api( - 'js_api_set_stderr', - 'void', - ['pointer']); - -const js_api_set_stats_file = get_api( - 'js_api_set_stats_file', - 'void', - ['pointer']); - -const js_api_set_stats_interval = get_api( - 'js_api_set_stats_interval', - 'void', - ['uint64']); - -const js_api_set_stats_transitions = get_api( - 'js_api_set_stats_transitions', - 'void', - []); - -const afl = { - print: function (msg) { +"use strict"; +class Afl { + /** + * This is equivalent to setting a value in `AFL_FRIDA_EXCLUDE_RANGES`, + * it takes as arguments a `NativePointer` and a `number`. It can be + * called multiple times to exclude several ranges. + */ + static addExcludedRange(addressess, size) { + Afl.jsApiAddExcludeRange(addressess, size); + } + /** + * This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`, + * it takes as arguments a `NativePointer` and a `number`. It can be + * called multiple times to include several ranges. + */ + static addIncludedRange(addressess, size) { + Afl.jsApiAddIncludeRange(addressess, size); + } + /** + * This must always be called at the end of your script. This lets + * FRIDA mode know that your configuration is finished and that + * execution has reached the end of your script. Failure to call + * this will result in a fatal error. + */ + static done() { + Afl.jsApiDone(); + } + /** + * This function can be called within your script to cause FRIDA + * mode to trigger a fatal error. This is useful if for example you + * discover a problem you weren't expecting and want everything to + * stop. The user will need to enable `AFL_DEBUG_CHILD=1` to view + * this error message. + */ + static error(msg) { + const buf = Memory.allocUtf8String(msg); + Afl.jsApiError(buf); + } + /** + * Function used to provide access to `__afl_fuzz_ptr`, which contains the length of + * fuzzing data when using in-memory test case fuzzing. + */ + static getAflFuzzLen() { + return Afl.jsApiGetSymbol("__afl_fuzz_len"); + } + /** + * Function used to provide access to `__afl_fuzz_ptr`, which contains the fuzzing + * data when using in-memory test case fuzzing. + */ + static getAflFuzzPtr() { + return Afl.jsApiGetSymbol("__afl_fuzz_ptr"); + } + /** + * Print a message to the STDOUT. This should be preferred to + * FRIDA's `console.log` since FRIDA will queue it's log messages. + * If `console.log` is used in a callback in particular, then there + * may no longer be a thread running to service this queue. + */ + static print(msg) { const STDOUT_FILENO = 2; const log = `${msg}\n`; const buf = Memory.allocUtf8String(log); - write(STDOUT_FILENO, buf, log.length); - }, - done: function() { - js_api_done(); - }, - error: function(msg) { - const buf = Memory.allocUtf8String(msg); - js_api_error(buf); - }, - setEntryPoint: function(addr) { - js_api_set_entrypoint(addr); - }, - setPersistentAddress: function(addr) { - js_api_set_persistent_address(addr); - }, - setPersistentReturn: function(addr) { - js_api_set_persistent_return(addr); - }, - setPersistentCount: function(addr) { - js_api_set_persistent_count(addr); - }, - setPersistentDebug: function() { - js_api_set_persistent_debug(); - }, - setDebugMaps: function() { - js_api_set_debug_maps(); - }, - addIncludedRange: function(address, size) { - js_api_add_include_range(address, size); - }, - addExcludedRange: function(address, size) { - js_api_add_exclude_range(address, size); - }, - setInstrumentLibraries: function() { - js_api_set_instrument_libraries(); - }, - setInstrumentDebugFile: function(file) { + Afl.jsApiWrite(STDOUT_FILENO, buf, log.length); + } + /** + * See `AFL_FRIDA_DEBUG_MAPS`. + */ + static setDebugMaps() { + Afl.jsApiSetDebugMaps(); + } + /** + * This has the same effect as setting `AFL_ENTRYPOINT`, but has the + * convenience of allowing you to use FRIDAs APIs to determine the + * address you would like to configure, rather than having to grep + * the output of `readelf` or something similarly ugly. This + * function should be called with a `NativePointer` as its + * argument. + */ + static setEntryPoint(address) { + Afl.jsApiSetEntryPoint(address); + } + /** + * Function used to enable in-memory test cases for fuzzing. + */ + static setInMemoryFuzzing() { + Afl.jsApiAflSharedMemFuzzing.writeInt(1); + } + /** + * See `AFL_FRIDA_INST_DEBUG_FILE`. This function takes a single `string` as + * an argument. + */ + static setInstrumentDebugFile(file) { const buf = Memory.allocUtf8String(file); - js_api_set_instrument_debug_file(buf) - }, - setPrefetchDisable: function() { - js_api_set_prefetch_disable(); - }, - setInstrumentNoOptimize: function() { - js_api_set_instrument_no_optimize(); - }, - setInstrumentEnableTracing: function() { - js_api_set_instrument_trace(); - }, - setInstrumentTracingUnique: function() { - js_api_set_instrument_trace_unique(); - }, - setStdOut: function(file) { + Afl.jsApiSetInstrumentDebugFile(buf); + } + /** + * See `AFL_FRIDA_INST_TRACE`. + */ + static setInstrumentEnableTracing() { + Afl.jsApiSetInstrumentTrace(); + } + /** + * See `AFL_INST_LIBS`. + */ + static setInstrumentLibraries() { + Afl.jsApiSetInstrumentLibraries(); + } + /** + * See `AFL_FRIDA_INST_NO_OPTIMIZE` + */ + static setInstrumentNoOptimize() { + Afl.jsApiSetInstrumentNoOptimize(); + } + /** + * See `AFL_FRIDA_INST_TRACE_UNIQUE`. + */ + static setInstrumentTracingUnique() { + Afl.jsApiSetInstrumentTraceUnique(); + } + /** + * This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a + * `NativePointer` should be provided as it's argument. + */ + static setPersistentAddress(address) { + Afl.jsApiSetPersistentAddress(address); + } + /** + * This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a + * `number` should be provided as it's argument. + */ + static setPersistentCount(count) { + Afl.jsApiSetPersistentCount(count); + } + /** + * See `AFL_FRIDA_PERSISTENT_DEBUG`. + */ + static setPersistentDebug() { + Afl.jsApiSetPersistentDebug(); + } + /** + * See `AFL_FRIDA_PERSISTENT_ADDR`. This function takes a NativePointer as an + * argument. See above for examples of use. + */ + static setPersistentHook(address) { + Afl.jsApiSetPersistentHook(address); + } + /** + * This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a + * `NativePointer` should be provided as it's argument. + */ + static setPersistentReturn(address) { + Afl.jsApiSetPersistentReturn(address); + } + /** + * See `AFL_FRIDA_INST_NO_PREFETCH`. + */ + static setPrefetchDisable() { + Afl.jsApiSetPrefetchDisable(); + } + /* + * Set a function to be called for each instruction which is instrumented + * by AFL FRIDA mode. + */ + static setStalkerCallback(callback) { + Afl.jsApiSetStalkerCallback(callback); + } + /** + * See `AFL_FRIDA_STATS_FILE`. This function takes a single `string` as + * an argument. + */ + static setStatsFile(file) { const buf = Memory.allocUtf8String(file); - js_api_set_stdout(buf) - }, - setStdErr: function(file) { + Afl.jsApiSetStatsFile(buf); + } + /** + * See `AFL_FRIDA_STATS_INTERVAL`. This function takes a `number` as an + * argument + */ + static setStatsInterval(interval) { + Afl.jsApiSetStatsInterval(interval); + } + /** + * See `AFL_FRIDA_STATS_TRANSITIONS` + */ + static setStatsTransitions() { + Afl.jsApiSetStatsTransitions(); + } + /** + * See `AFL_FRIDA_OUTPUT_STDERR`. This function takes a single `string` as + * an argument. + */ + static setStdErr(file) { const buf = Memory.allocUtf8String(file); - js_api_set_stderr(buf) - }, - setStatsFile: function(file) { + Afl.jsApiSetStdErr(buf); + } + /** + * See `AFL_FRIDA_OUTPUT_STDOUT`. This function takes a single `string` as + * an argument. + */ + static setStdOut(file) { const buf = Memory.allocUtf8String(file); - js_api_set_stats_file(buf) - }, - setStatsInterval: function(interval) { - js_api_set_stats_interval(interval); - }, - setStatsTransitions: function() { - js_api_set_stats_transitions(); - } - -}; - -Object.defineProperty(global, 'Afl', {value: afl, writeable: false}); - -//////////////////////////////////////////////////////////////////////////////// -// END OF API // -//////////////////////////////////////////////////////////////////////////////// + Afl.jsApiSetStdOut(buf); + } + static jsApiGetFunction(name, retType, argTypes) { + const addr = Afl.module.getExportByName(name); + return new NativeFunction(addr, retType, argTypes); + } + static jsApiGetSymbol(name) { + return Afl.module.getExportByName(name); + } +} +/** + * Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode + * implementation). + */ +Afl.module = Process.getModuleByName("afl-frida-trace.so"); +Afl.jsApiAddExcludeRange = Afl.jsApiGetFunction("js_api_add_exclude_range", "void", ["pointer", "size_t"]); +Afl.jsApiAddIncludeRange = Afl.jsApiGetFunction("js_api_add_include_range", "void", ["pointer", "size_t"]); +Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing"); +Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []); +Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]); +Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []); +Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]); +Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]); +Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); +Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); +Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []); +Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []); +Afl.jsApiSetPersistentAddress = Afl.jsApiGetFunction("js_api_set_persistent_address", "void", ["pointer"]); +Afl.jsApiSetPersistentCount = Afl.jsApiGetFunction("js_api_set_persistent_count", "void", ["uint64"]); +Afl.jsApiSetPersistentDebug = Afl.jsApiGetFunction("js_api_set_persistent_debug", "void", []); +Afl.jsApiSetPersistentHook = Afl.jsApiGetFunction("js_api_set_persistent_hook", "void", ["pointer"]); +Afl.jsApiSetPersistentReturn = Afl.jsApiGetFunction("js_api_set_persistent_return", "void", ["pointer"]); +Afl.jsApiSetPrefetchDisable = Afl.jsApiGetFunction("js_api_set_prefetch_disable", "void", []); +Afl.jsApiSetStalkerCallback = Afl.jsApiGetFunction("js_api_set_stalker_callback", "void", ["pointer"]); +Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", ["pointer"]); +Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]); +Afl.jsApiSetStatsTransitions = Afl.jsApiGetFunction("js_api_set_stats_transitions", "void", []); +Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]); +Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]); +Afl.jsApiWrite = new NativeFunction( +/* tslint:disable-next-line:no-null-keyword */ +Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]); diff --git a/frida_mode/src/js/js.c b/frida_mode/src/js/js.c index 79e716ad..ed378d2c 100644 --- a/frida_mode/src/js/js.c +++ b/frida_mode/src/js/js.c @@ -5,8 +5,9 @@ #include "js.h" #include "util.h" -static char *js_script = NULL; -gboolean js_done = FALSE; +static char * js_script = NULL; +gboolean js_done = FALSE; +js_api_stalker_callback_t js_user_callback = NULL; static gchar * filename = "afl.js"; static gchar * contents; @@ -111,3 +112,11 @@ void js_start(void) { } +gboolean js_stalker_callback(const cs_insn *insn, gboolean begin, + gboolean excluded, GumStalkerOutput *output) { + + if (js_user_callback == NULL) { return TRUE; } + return js_user_callback(insn, begin, excluded, output); + +} + diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 018c0b9a..91dccab2 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -138,5 +138,15 @@ void js_api_set_stats_transitions() { } -// "AFL_FRIDA_PERSISTENT_HOOK", +void js_api_set_persistent_hook(void *address) { + + persistent_hook = address; + +} + +void js_api_set_stalker_callback(const js_api_stalker_callback_t callback) { + + js_user_callback = callback; + +} diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c index e3e0b0ca..bcc59ea7 100644 --- a/frida_mode/src/persistent/persistent.c +++ b/frida_mode/src/persistent/persistent.c @@ -47,19 +47,6 @@ void persistent_config(void) { } -} - -void persistent_init(void) { - - OKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)", - persistent_start == 0 ? ' ' : 'X', persistent_start); - OKF("Instrumentation - persistent count [%c] (%" G_GINT64_MODIFIER "d)", - persistent_start == 0 ? ' ' : 'X', persistent_count); - OKF("Instrumentation - hook [%s]", hook_name); - - OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)", - persistent_ret == 0 ? ' ' : 'X', persistent_ret); - if (hook_name == NULL) { return; } void *hook_obj = dlopen(hook_name, RTLD_NOW); @@ -79,7 +66,20 @@ void persistent_init(void) { if (persistent_hook == NULL) FATAL("Failed to find afl_persistent_hook in %s", hook_name); - __afl_sharedmem_fuzzing = 1; +} + +void persistent_init(void) { + + OKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)", + persistent_start == 0 ? ' ' : 'X', persistent_start); + OKF("Instrumentation - persistent count [%c] (%" G_GINT64_MODIFIER "d)", + persistent_start == 0 ? ' ' : 'X', persistent_count); + OKF("Instrumentation - hook [%s]", hook_name); + + OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)", + persistent_ret == 0 ? ' ' : 'X', persistent_ret); + + if (persistent_hook != NULL) { __afl_sharedmem_fuzzing = 1; } } diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c index e618fbac..003f058a 100644 --- a/frida_mode/src/persistent/persistent_arm64.c +++ b/frida_mode/src/persistent/persistent_arm64.c @@ -9,99 +9,15 @@ #include "util.h" #if defined(__aarch64__) +typedef struct { -struct arm64_regs { + GumCpuContext ctx; + uint64_t rflags; - uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10; +} persistent_ctx_t; - union { - - uint64_t x11; - uint32_t fp_32; - - }; - - union { - - uint64_t x12; - uint32_t ip_32; - - }; - - union { - - uint64_t x13; - uint32_t sp_32; - - }; - - union { - - uint64_t x14; - uint32_t lr_32; - - }; - - union { - - uint64_t x15; - uint32_t pc_32; - - }; - - union { - - uint64_t x16; - uint64_t ip0; - - }; - - union { - - uint64_t x17; - uint64_t ip1; - - }; - - uint64_t x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28; - - union { - - uint64_t x29; - uint64_t fp; - - }; - - union { - - uint64_t x30; - uint64_t lr; - - }; - - union { - - uint64_t x31; - uint64_t sp; - - }; - - // the zero register is not saved here ofc - - uint64_t pc; - - uint32_t cpsr; - - uint8_t vfp_zregs[32][16 * 16]; - uint8_t vfp_pregs[17][32]; - uint32_t vfp_xregs[16]; - -}; - -typedef struct arm64_regs arch_api_regs; - -static arch_api_regs saved_regs = {0}; -static gpointer saved_lr = NULL; +static persistent_ctx_t saved_regs = {0}; +static gpointer saved_lr = NULL; gboolean persistent_is_supported(void) { @@ -109,8 +25,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumArm64Writer * cw, - struct arm64_regs *regs) { +static void instrument_persitent_save_regs(GumArm64Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); const guint32 mrs_x1_nzcv = 0xd53b4201; @@ -129,83 +45,87 @@ static void instrument_persitent_save_regs(GumArm64Writer * cw, /* Skip x0 & x1 we'll do that later */ - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, - ARM64_REG_X0, (16 * 1), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X4, ARM64_REG_X5, - ARM64_REG_X0, (16 * 2), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X6, ARM64_REG_X7, - ARM64_REG_X0, (16 * 3), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X8, ARM64_REG_X9, - ARM64_REG_X0, (16 * 4), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X10, ARM64_REG_X11, - ARM64_REG_X0, (16 * 5), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X12, ARM64_REG_X13, - ARM64_REG_X0, (16 * 6), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X14, ARM64_REG_X15, - ARM64_REG_X0, (16 * 7), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X16, ARM64_REG_X17, - ARM64_REG_X0, (16 * 8), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X18, ARM64_REG_X19, - ARM64_REG_X0, (16 * 9), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X20, ARM64_REG_X21, - ARM64_REG_X0, (16 * 10), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X22, ARM64_REG_X23, - ARM64_REG_X0, (16 * 11), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X24, ARM64_REG_X25, - ARM64_REG_X0, (16 * 12), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X26, ARM64_REG_X27, - ARM64_REG_X0, (16 * 13), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X28, ARM64_REG_X29, - ARM64_REG_X0, (16 * 14), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, + offsetof(GumCpuContext, x[2]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X0, + offsetof(GumCpuContext, x[4]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X6, ARM64_REG_X7, ARM64_REG_X0, + offsetof(GumCpuContext, x[6]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X0, + offsetof(GumCpuContext, x[8]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X0, + offsetof(GumCpuContext, x[10]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X0, + offsetof(GumCpuContext, x[12]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X14, ARM64_REG_X15, ARM64_REG_X0, + offsetof(GumCpuContext, x[14]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X0, + offsetof(GumCpuContext, x[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X0, + offsetof(GumCpuContext, x[18]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X0, + offsetof(GumCpuContext, x[20]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X22, ARM64_REG_X23, ARM64_REG_X0, + offsetof(GumCpuContext, x[22]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X0, + offsetof(GumCpuContext, x[24]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X0, + offsetof(GumCpuContext, x[26]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X28, ARM64_REG_X29, ARM64_REG_X0, + offsetof(GumCpuContext, x[28]), GUM_INDEX_SIGNED_OFFSET); - /* LR & Adjusted SP */ - gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_X2, ARM64_REG_SP, - (GUM_RED_ZONE_SIZE + 32)); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X2, - ARM64_REG_X0, (16 * 15), - GUM_INDEX_SIGNED_OFFSET); + /* LR (x30) */ + gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, + offsetof(GumCpuContext, x[30])); - /* PC & CPSR */ + /* PC & Adjusted SP (31) */ gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, GUM_ADDRESS(persistent_start)); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X1, - ARM64_REG_X0, (16 * 16), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_X3, ARM64_REG_SP, + (GUM_RED_ZONE_SIZE + 32)); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, offsetof(GumCpuContext, pc), + GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_Q0, ARM64_REG_Q1, - ARM64_REG_X0, (16 * 17), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_Q2, ARM64_REG_Q3, - ARM64_REG_X0, (16 * 18), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_Q4, ARM64_REG_Q5, - ARM64_REG_X0, (16 * 19), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_Q6, ARM64_REG_Q7, - ARM64_REG_X0, (16 * 20), - GUM_INDEX_SIGNED_OFFSET); + /* CPSR */ + gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, + offsetof(persistent_ctx_t, rflags)); + + /* Q */ + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0, + offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0, + offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0, + offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0, + offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET); /* x0 & x1 */ gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_SP, 16, GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, - ARM64_REG_X0, (16 * 0), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_stp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, + offsetof(GumCpuContext, x[0]), GUM_INDEX_SIGNED_OFFSET); /* Pop the saved values */ gum_arm64_writer_put_ldp_reg_reg_reg_offset( @@ -217,8 +137,8 @@ static void instrument_persitent_save_regs(GumArm64Writer * cw, } -static void instrument_persitent_restore_regs(GumArm64Writer * cw, - struct arm64_regs *regs) { +static void instrument_persitent_restore_regs(GumArm64Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); const guint32 msr_nzcv_x1 = 0xd51b4201; @@ -228,82 +148,81 @@ static void instrument_persitent_restore_regs(GumArm64Writer * cw, /* Skip x0 - x3 we'll do that last */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X4, ARM64_REG_X5, - ARM64_REG_X0, (16 * 2), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X6, ARM64_REG_X7, - ARM64_REG_X0, (16 * 3), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X8, ARM64_REG_X9, - ARM64_REG_X0, (16 * 4), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X10, ARM64_REG_X11, - ARM64_REG_X0, (16 * 5), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X12, ARM64_REG_X13, - ARM64_REG_X0, (16 * 6), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X14, ARM64_REG_X15, - ARM64_REG_X0, (16 * 7), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X16, ARM64_REG_X17, - ARM64_REG_X0, (16 * 8), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X18, ARM64_REG_X19, - ARM64_REG_X0, (16 * 9), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X20, ARM64_REG_X21, - ARM64_REG_X0, (16 * 10), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X22, ARM64_REG_X23, - ARM64_REG_X0, (16 * 11), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X24, ARM64_REG_X25, - ARM64_REG_X0, (16 * 12), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X26, ARM64_REG_X27, - ARM64_REG_X0, (16 * 13), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X28, ARM64_REG_X29, - ARM64_REG_X0, (16 * 14), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X0, + offsetof(GumCpuContext, x[4]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X6, ARM64_REG_X7, ARM64_REG_X0, + offsetof(GumCpuContext, x[6]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X0, + offsetof(GumCpuContext, x[8]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X0, + offsetof(GumCpuContext, x[10]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X0, + offsetof(GumCpuContext, x[12]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X14, ARM64_REG_X15, ARM64_REG_X0, + offsetof(GumCpuContext, x[14]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X0, + offsetof(GumCpuContext, x[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X0, + offsetof(GumCpuContext, x[18]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X0, + offsetof(GumCpuContext, x[20]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X22, ARM64_REG_X23, ARM64_REG_X0, + offsetof(GumCpuContext, x[22]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X0, + offsetof(GumCpuContext, x[24]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X0, + offsetof(GumCpuContext, x[26]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X28, ARM64_REG_X29, ARM64_REG_X0, + offsetof(GumCpuContext, x[28]), GUM_INDEX_SIGNED_OFFSET); - /* LR & Adjusted SP (use x1 as clobber) */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X1, - ARM64_REG_X0, (16 * 15), - GUM_INDEX_SIGNED_OFFSET); + /* LR (x30) */ + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, + offsetof(GumCpuContext, x[30])); + /* Adjusted SP (31) (use x1 as clobber)*/ + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, + offsetof(GumCpuContext, sp)); gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_SP, ARM64_REG_X1); - /* Don't restore RIP use x1-x3 as clobber */ - - /* PC (x2) & CPSR (x1) */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X1, - ARM64_REG_X0, (16 * 16), - GUM_INDEX_SIGNED_OFFSET); + /* CPSR */ + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, + offsetof(persistent_ctx_t, rflags)); gum_arm64_writer_put_instruction(cw, msr_nzcv_x1); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_Q0, ARM64_REG_Q1, - ARM64_REG_X0, (16 * 17), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_Q2, ARM64_REG_Q3, - ARM64_REG_X0, (16 * 18), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_Q4, ARM64_REG_Q5, - ARM64_REG_X0, (16 * 19), - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_Q6, ARM64_REG_Q7, - ARM64_REG_X0, (16 * 20), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0, + offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0, + offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0, + offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0, + offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET); /* x2 & x3 */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, - ARM64_REG_X0, (16 * 1), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, + offsetof(GumCpuContext, x[2]), GUM_INDEX_SIGNED_OFFSET); /* x0 & x1 */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X1, - ARM64_REG_X0, (16 * 0), - GUM_INDEX_SIGNED_OFFSET); + gum_arm64_writer_put_ldp_reg_reg_reg_offset( + cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_X0, + offsetof(GumCpuContext, x[0]), GUM_INDEX_SIGNED_OFFSET); } @@ -334,29 +253,29 @@ static void instrument_afl_persistent_loop(GumArm64Writer *cw) { } -static void persistent_prologue_hook(GumArm64Writer * cw, - struct arm64_regs *regs) { +static void persistent_prologue_hook(GumArm64Writer * cw, + persistent_ctx_t *regs) { if (persistent_hook == NULL) return; gum_arm64_writer_put_sub_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, GUM_RED_ZONE_SIZE); - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X3, + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, GUM_ADDRESS(&__afl_fuzz_len)); - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X3, ARM64_REG_X3, 0); - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X3, ARM64_REG_X3, 0); + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); - gum_arm64_writer_put_and_reg_reg_imm(cw, ARM64_REG_X3, ARM64_REG_X3, + gum_arm64_writer_put_and_reg_reg_imm(cw, ARM64_REG_X2, ARM64_REG_X2, G_MAXULONG); - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, + gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X1, GUM_ADDRESS(&__afl_fuzz_ptr)); - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); + gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X1, 0); gum_arm64_writer_put_call_address_with_arguments( - cw, GUM_ADDRESS(persistent_hook), 4, GUM_ARG_ADDRESS, GUM_ADDRESS(regs), - GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER, ARM64_REG_X2, - GUM_ARG_REGISTER, ARM64_REG_X3); + cw, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, + GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, ARM64_REG_X1, GUM_ARG_REGISTER, + ARM64_REG_X2); gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, GUM_RED_ZONE_SIZE); @@ -406,6 +325,8 @@ void persistent_prologue(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; + OKF("Persistent loop reached"); + instrument_persitent_save_regs(cw, &saved_regs); /* loop: */ diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index a91abc1c..b2186db1 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -10,40 +10,15 @@ #if defined(__x86_64__) -struct x86_64_regs { +typedef struct { - uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, - r15; + GumCpuContext ctx; + uint64_t rflags; - union { +} persistent_ctx_t; - uint64_t rip; - uint64_t pc; - - }; - - union { - - uint64_t rsp; - uint64_t sp; - - }; - - union { - - uint64_t rflags; - uint64_t flags; - - }; - - uint8_t zmm_regs[32][64]; - -}; - -typedef struct x86_64_regs arch_api_regs; - -static arch_api_regs saved_regs = {0}; -static gpointer saved_ret = NULL; +static persistent_ctx_t saved_regs = {0}; +static gpointer saved_ret = NULL; gboolean persistent_is_supported(void) { @@ -51,8 +26,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumX86Writer * cw, - struct x86_64_regs *regs) { +static void instrument_persitent_save_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, @@ -64,41 +39,41 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 1), - GUM_REG_RBX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 2), - GUM_REG_RCX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 3), - GUM_REG_RDX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 4), - GUM_REG_RDI); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 5), - GUM_REG_RSI); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 6), - GUM_REG_RBP); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 7), - GUM_REG_R8); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 8), - GUM_REG_R9); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 9), - GUM_REG_R10); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 10), - GUM_REG_R11); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 11), - GUM_REG_R12); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 12), - GUM_REG_R13); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 13), - GUM_REG_R14); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 14), - GUM_REG_R15); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rbx), GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rcx), GUM_REG_RCX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rdx), GUM_REG_RDX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rdi), GUM_REG_RDI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rsi), GUM_REG_RSI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rbp), GUM_REG_RBP); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r8), GUM_REG_R8); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r9), GUM_REG_R9); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r10), GUM_REG_R10); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r11), GUM_REG_R11); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r12), GUM_REG_R12); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r13), GUM_REG_R13); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r14), GUM_REG_R14); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, r15), GUM_REG_R15); /* Store RIP */ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RBX, GUM_ADDRESS(persistent_start)); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 15), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rip), GUM_REG_RBX); /* Store adjusted RSP */ gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_RBX, GUM_REG_RSP); @@ -106,18 +81,18 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, /* RED_ZONE + Saved flags, RAX, alignment */ gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX, GUM_RED_ZONE_SIZE + (0x8 * 2)); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 16), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rsp), GUM_REG_RBX); /* Save the flags */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x8); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 17), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(persistent_ctx_t, rflags), GUM_REG_RBX); /* Save the RAX */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x0); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 0), - GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_RAX, offsetof(GumCpuContext, rax), GUM_REG_RBX); /* Pop the saved values */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 0x10); @@ -127,56 +102,56 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, } -static void instrument_persitent_restore_regs(GumX86Writer * cw, - struct x86_64_regs *regs) { +static void instrument_persitent_restore_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RAX, - (0x8 * 2)); + offsetof(GumCpuContext, rcx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RAX, - (0x8 * 3)); + offsetof(GumCpuContext, rdx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDI, GUM_REG_RAX, - (0x8 * 4)); + offsetof(GumCpuContext, rdi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RAX, - (0x8 * 5)); + offsetof(GumCpuContext, rsi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBP, GUM_REG_RAX, - (0x8 * 6)); + offsetof(GumCpuContext, rbp)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R8, GUM_REG_RAX, - (0x8 * 7)); + offsetof(GumCpuContext, r8)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R9, GUM_REG_RAX, - (0x8 * 8)); + offsetof(GumCpuContext, r9)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R10, GUM_REG_RAX, - (0x8 * 9)); + offsetof(GumCpuContext, r10)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R11, GUM_REG_RAX, - (0x8 * 10)); + offsetof(GumCpuContext, r11)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R12, GUM_REG_RAX, - (0x8 * 11)); + offsetof(GumCpuContext, r12)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R13, GUM_REG_RAX, - (0x8 * 12)); + offsetof(GumCpuContext, r13)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R14, GUM_REG_RAX, - (0x8 * 13)); + offsetof(GumCpuContext, r14)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX, - (0x8 * 14)); + offsetof(GumCpuContext, r15)); /* Don't restore RIP */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSP, GUM_REG_RAX, - (0x8 * 16)); + offsetof(GumCpuContext, rsp)); /* Restore RBX, RAX & Flags */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -(GUM_RED_ZONE_SIZE)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, - (0x8 * 1)); + offsetof(GumCpuContext, rbx)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, - (0x8 * 0)); + offsetof(GumCpuContext, rax)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, - (0x8 * 17)); + offsetof(persistent_ctx_t, rflags)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_popfx(cw); @@ -217,28 +192,27 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { } -static void persistent_prologue_hook(GumX86Writer * cw, - struct x86_64_regs *regs) { +static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { if (persistent_hook == NULL) return; gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -(GUM_RED_ZONE_SIZE)); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RCX, + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX, GUM_ADDRESS(&__afl_fuzz_len)); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_RDI, 0xffffffff); - gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RCX, GUM_REG_RDI); + gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RDX, GUM_REG_RDI); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX, + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RSI, GUM_ADDRESS(&__afl_fuzz_ptr)); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RSI, 0); gum_x86_writer_put_call_address_with_arguments( - cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 4, GUM_ARG_ADDRESS, - GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER, - GUM_REG_RDX, GUM_ARG_REGISTER, GUM_REG_RCX); + cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, + GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, GUM_REG_RSI, GUM_ARG_REGISTER, + GUM_REG_RDX); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (GUM_RED_ZONE_SIZE)); @@ -296,6 +270,8 @@ void persistent_prologue(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; + OKF("Persistent loop reached"); + /* Pop the return value */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8); diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index 1d01d8e4..f50bccb0 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -1,45 +1,23 @@ #include "frida-gumjs.h" #include "config.h" +#include "debug.h" #include "instrument.h" #include "persistent.h" #if defined(__i386__) -struct x86_regs { +typedef struct { - uint32_t eax, ebx, ecx, edx, edi, esi, ebp; + GumCpuContext ctx; + uint32_t eflags; - union { +} persistent_ctx_t; - uint32_t eip; - uint32_t pc; +static persistent_ctx_t saved_regs = {0}; - }; - - union { - - uint32_t esp; - uint32_t sp; - - }; - - union { - - uint32_t eflags; - uint32_t flags; - - }; - - uint8_t xmm_regs[8][16]; - -}; - -typedef struct x86_regs arch_api_regs; - -static arch_api_regs saved_regs = {0}; -static gpointer saved_ret = NULL; +static gpointer saved_ret = NULL; gboolean persistent_is_supported(void) { @@ -47,8 +25,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumX86Writer * cw, - struct x86_regs *regs) { +static void instrument_persitent_save_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); @@ -58,80 +36,80 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 1), - GUM_REG_EBX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 2), - GUM_REG_ECX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 3), - GUM_REG_EDX); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 4), - GUM_REG_EDI); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 5), - GUM_REG_ESI); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 6), - GUM_REG_EBP); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, ebx), GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, ecx), GUM_REG_ECX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, edx), GUM_REG_EDX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, edi), GUM_REG_EDI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, esi), GUM_REG_ESI); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, ebp), GUM_REG_EBP); /* Store RIP */ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EBX, GUM_ADDRESS(persistent_start)); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 7), - GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, eip), GUM_REG_EBX); /* Store adjusted RSP */ gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_EBX, GUM_REG_ESP); /* RED_ZONE + Saved flags, RAX */ gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EBX, (0x4 * 2)); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 8), - GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, esp), GUM_REG_EBX); /* Save the flags */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x4); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 9), - GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(persistent_ctx_t, eflags), GUM_REG_EBX); /* Save the RAX */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x0); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 0), - GUM_REG_EBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_EAX, offsetof(GumCpuContext, eax), GUM_REG_EBX); /* Pop the saved values */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 0x8); } -static void instrument_persitent_restore_regs(GumX86Writer * cw, - struct x86_regs *regs) { +static void instrument_persitent_restore_regs(GumX86Writer * cw, + persistent_ctx_t *regs) { GumAddress regs_address = GUM_ADDRESS(regs); gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_EAX, - (0x4 * 2)); + offsetof(GumCpuContext, ecx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX, - (0x4 * 3)); + offsetof(GumCpuContext, edx)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX, - (0x4 * 4)); + offsetof(GumCpuContext, edi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX, - (0x4 * 5)); + offsetof(GumCpuContext, esi)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX, - (0x4 * 6)); + offsetof(GumCpuContext, ebp)); /* Don't restore RIP */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESP, GUM_REG_EAX, - (0x4 * 8)); + offsetof(GumCpuContext, esp)); /* Restore RBX, RAX & Flags */ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, - (0x4 * 1)); + offsetof(GumCpuContext, ebx)); gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, - (0x4 * 0)); + offsetof(GumCpuContext, eax)); gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX, - (0x4 * 9)); + offsetof(persistent_ctx_t, eflags)); gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); gum_x86_writer_put_popfx(cw); @@ -165,7 +143,7 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { } -static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) { +static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { if (persistent_hook == NULL) return; @@ -180,9 +158,8 @@ static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) { /* Base address is 64-bits (hence two zero arguments) */ gum_x86_writer_put_call_address_with_arguments( - cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 5, GUM_ARG_ADDRESS, - GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_ADDRESS, - GUM_ADDRESS(0), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER, + cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, + GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER, GUM_REG_ECX); } @@ -233,6 +210,8 @@ void persistent_prologue(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; + OKF("Persistent loop reached"); + /* Pop the return value */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4); |