From 8e7081b5df64e1ffdebdf5bce0159ac7f51b2153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Tue, 7 May 2024 22:38:54 +0200 Subject: [PATCH] darwin: Add more temporary debug --- src/darwin/frida-helper-backend-glue.m | 87 +++++++++++++++-- src/darwin/frida-helper-backend.vala | 128 ++++++++++++++----------- 2 files changed, 152 insertions(+), 63 deletions(-) diff --git a/src/darwin/frida-helper-backend-glue.m b/src/darwin/frida-helper-backend-glue.m index 6473aaab8..d13ed3959 100644 --- a/src/darwin/frida-helper-backend-glue.m +++ b/src/darwin/frida-helper-backend-glue.m @@ -2197,13 +2197,13 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier } void -_frida_darwin_helper_backend_schedule_heartbeat_on_dispatch_queue (FridaDarwinHelperBackend * self) +_frida_darwin_helper_backend_schedule_heartbeat_on_dispatch_queue (FridaDarwinHelperBackend * self, guint identifier) { FridaHelperContext * ctx = self->context; dispatch_async (ctx->dispatch_queue, ^ { - _frida_darwin_helper_backend_on_heartbeat (self); + _frida_darwin_helper_backend_on_heartbeat (self, identifier); }); } @@ -2771,10 +2771,14 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier if (instance->server_recv_source != NULL) { + _frida_darwin_helper_backend_log_event (instance->backend, "\tcancelling source for instance %p (on backend %p)", instance, instance->backend); + g_object_ref (instance->backend); dispatch_source_cancel (instance->server_recv_source); return; } + _frida_darwin_helper_backend_log_event (instance->backend, "\tfreeing instance %p (on backend %p)", instance, instance->backend); + self_task = mach_task_self (); if (instance->do_modinit_strcmp_checks != NULL) @@ -2842,9 +2846,53 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier frida_spawn_instance_on_server_cancel (void * context) { FridaSpawnInstance * self = context; + FridaDarwinHelperBackend * backend = self->backend; dispatch_release (g_steal_pointer (&self->server_recv_source)); frida_spawn_instance_free (self); + g_object_unref (backend); +} + +static void +frida_spawn_instance_log_breakpoint_phase (FridaSpawnInstance * self, const gchar * label) +{ + const gchar * name; + + switch (self->breakpoint_phase) + { + case FRIDA_BREAKPOINT_DETECT_FLAVOR: name = "detect-flavor"; break; + + case FRIDA_BREAKPOINT_SET_LIBDYLD_INITIALIZE_CALLER_BREAKPOINT: name = "set-libdyld-initialize-caller-breakpoint"; break; + case FRIDA_BREAKPOINT_LIBSYSTEM_INITIALIZED: name = "libsystem-initialized"; break; + + case FRIDA_BREAKPOINT_SET_HELPERS: name = "set-helpers"; break; + case FRIDA_BREAKPOINT_DLOPEN_LIBC: name = "dlopen-libc"; break; + case FRIDA_BREAKPOINT_SKIP_CLEAR: name = "skip-clear"; break; + case FRIDA_BREAKPOINT_DLOPEN_BOOTSTRAPPER: name = "dlopen-bootstrapper"; break; + + case FRIDA_BREAKPOINT_CF_INITIALIZE: name = "cf-initialize"; break; + case FRIDA_BREAKPOINT_CLEANUP: name = "cleanup"; break; + case FRIDA_BREAKPOINT_DONE: name = "done"; break; + + default: g_assert_not_reached (); + } + + _frida_darwin_helper_backend_log_event (self->backend, "\t%3s breakpoint_phase=\"%s\"", label, name); +} + +static void +frida_spawn_instance_log_pc (FridaSpawnInstance * self, GumAddress pc) +{ + if (pc >= self->dyld->base_address && pc < self->dyld->base_address + self->dyld_size) + { + _frida_darwin_helper_backend_log_event (self->backend, "\tpc=dyld!0x%" G_GINT64_MODIFIER "x", + pc - self->dyld->base_address); + } + else + { + _frida_darwin_helper_backend_log_event (self->backend, "\tpc=0x%" G_GINT64_MODIFIER "x", + pc); + } } static void @@ -2859,6 +2907,7 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier GumDarwinUnifiedThreadState state; guint i, current_bp_index; FridaBreakpoint * breakpoint = NULL; + GumAddress new_pc; gboolean carry_on, pc_changed; frida_spawn_instance_receive_breakpoint_request (self); @@ -2872,6 +2921,8 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier if ((self->single_stepping >= 0 && !is_step_complete) || (self->single_stepping == -1 && is_step_complete)) { + _frida_darwin_helper_backend_log_event (self->backend, "\tack-step single_stepping=%d is_step_complete=%s", + self->single_stepping, is_step_complete ? "TRUE" : "FALSE"); frida_spawn_instance_send_breakpoint_response (self); return; } @@ -2880,7 +2931,10 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier kr = frida_get_thread_state (self->thread, state_flavor, &state, &state_count); if (kr != KERN_SUCCESS) + { + _frida_darwin_helper_backend_log_event (self->backend, "\tfrida_get_thread_state() failed with kr=%u", kr); return; + } #if __has_feature (ptrauth_calls) { @@ -2907,10 +2961,14 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier pc = state.ts_32.__pc; #endif + frida_spawn_instance_log_pc (self, pc); + if (self->single_stepping >= 0) { FridaBreakpoint * bp = &self->breakpoints[self->single_stepping]; + _frida_darwin_helper_backend_log_event (self->backend, "\thandle-step single_stepping=%d", self->single_stepping); + frida_set_hardware_single_step (&self->breakpoint_debug_state, &state, FALSE, self->cpu_type); if (bp->repeat != FRIDA_BREAKPOINT_REPEAT_ALWAYS) @@ -2942,24 +3000,33 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier } } + _frida_darwin_helper_backend_log_event (self->backend, "\thit breakpoint: %s", (breakpoint != NULL) ? "yes" : "no"); if (breakpoint == NULL) goto unexpected_exception; + frida_spawn_instance_log_breakpoint_phase (self, ">>>"); carry_on = frida_spawn_instance_handle_breakpoint (self, breakpoint, &state); + frida_spawn_instance_log_breakpoint_phase (self, "<<<"); + _frida_darwin_helper_backend_log_event (self->backend, "\thandle_breakpoint => carry_on=%s", carry_on ? "TRUE" : "FALSE"); if (!carry_on) return; #ifdef HAVE_I386 if (self->cpu_type == GUM_CPU_AMD64) - pc_changed = state.uts.ts64.__rip != pc; + new_pc = state.uts.ts64.__rip; else - pc_changed = state.uts.ts32.__eip != pc; + new_pc = state.uts.ts32.__eip; #else if (self->cpu_type == GUM_CPU_ARM64) - pc_changed = __darwin_arm_thread_state64_get_pc (state.ts_64) != pc; + new_pc = __darwin_arm_thread_state64_get_pc (state.ts_64); else - pc_changed = state.ts_32.__pc != pc; + new_pc = state.ts_32.__pc; #endif + pc_changed = new_pc != pc; + + _frida_darwin_helper_backend_log_event (self->backend, "\tpc_changed=%s", pc_changed ? "TRUE" : "FALSE"); + if (pc_changed) + frida_spawn_instance_log_pc (self, new_pc); if (!pc_changed) { @@ -3078,7 +3145,10 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier if (self->dyld_flavor == FRIDA_DYLD_V4_PLUS) { if (pc == self->modern_entry_address) + { self->breakpoint_phase = FRIDA_BREAKPOINT_SET_LIBDYLD_INITIALIZE_CALLER_BREAKPOINT; + frida_spawn_instance_log_breakpoint_phase (self, "A"); + } else return frida_spawn_instance_handle_dyld_restart (self); } @@ -3090,6 +3160,7 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier self->breakpoint_phase = FRIDA_BREAKPOINT_CF_INITIALIZE; else self->breakpoint_phase = FRIDA_BREAKPOINT_SET_HELPERS; + frida_spawn_instance_log_breakpoint_phase (self, "B"); } } @@ -3178,6 +3249,7 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier case FRIDA_BREAKPOINT_LIBSYSTEM_INITIALIZED: memcpy (&self->previous_thread_state, state, sizeof (GumDarwinUnifiedThreadState)); self->breakpoint_phase = FRIDA_BREAKPOINT_CF_INITIALIZE; + frida_spawn_instance_log_breakpoint_phase (self, "C"); goto next_phase; case FRIDA_BREAKPOINT_SET_HELPERS: @@ -3265,7 +3337,10 @@ static void frida_darwin_helper_backend_launch_using_lsaw (NSString * identifier #endif case FRIDA_BREAKPOINT_CF_INITIALIZE: + _frida_darwin_helper_backend_log_event (self->backend, "\tenumerate-start"); gum_darwin_enumerate_modules (self->task, frida_find_cf_initialize, self); + _frida_darwin_helper_backend_log_event (self->backend, "\tenumerate-end cf_initialize_address=0x%" G_GINT64_MODIFIER "x", + self->cf_initialize_address); if (self->cf_initialize_address != 0) { diff --git a/src/darwin/frida-helper-backend.vala b/src/darwin/frida-helper-backend.vala index f811fc487..16be3feba 100644 --- a/src/darwin/frida-helper-backend.vala +++ b/src/darwin/frida-helper-backend.vala @@ -60,13 +60,27 @@ namespace Frida { #else policy_softener = new NullPolicySoftener (); #endif + + _log_event ("DarwinHelperBackend.init() %p", this); } - ~DarwinHelperBackend () { + public override void dispose () { + _log_event ("DarwinHelperBackend.dispose() %p", this); + foreach (var instance in spawn_instances.values) _free_spawn_instance (instance); + spawn_instances.clear (); + foreach (var instance in inject_instances.values) _free_inject_instance (instance); + inject_instances.clear (); + + base.dispose (); + } + + ~DarwinHelperBackend () { + _log_event ("DarwinHelperBackend.finalize() %p", this); + _destroy_context (); } @@ -362,6 +376,38 @@ namespace Frida { } } + private Timer log_timer = new Timer (); + private Gee.Map log_threads = new Gee.HashMap (); + private const uint[] log_palette = { 36, 35, 33, 32, 31, 34 }; + private uint log_palette_offset = 0; + + public void _log_event (string format, ...) { + lock (log_timer) { + var builder = new StringBuilder (); + + var timestamp = (uint) (log_timer.elapsed () * 1000.0); + + var tid = (uint) Gum.Process.get_current_thread_id (); + + var color = log_threads[tid]; + if (color == 0) { + color = log_palette[log_palette_offset]; + log_palette_offset = (log_palette_offset + 1) % log_palette.length; + log_threads[tid] = color; + } + builder.append_printf ("\033[0;%um", color); + + builder.append_printf ("[%05u ms] [thread %04x] %p ", timestamp, tid, this); + + var args = va_list (); + builder.append_vprintf (format, args); + + builder.append ("\033[0m\n"); + + stderr.write (builder.str.data); + } + } + public async void prepare_target (uint pid, Cancellable? cancellable) throws Error, IOError { policy_softener.soften (pid); @@ -377,6 +423,11 @@ namespace Frida { if (not_yet_booted) { try { + printerr ("\n------------------------------------------------------------\n"); + lock (log_timer) + log_timer.reset (); + _log_event ("prepare-start pid=%u instance=%p", pid, spawn_instance); + _prepare_spawn_instance_for_injection (spawn_instance, task); resume_process_fast (task); @@ -400,10 +451,12 @@ namespace Frida { return false; }); timeout_source.attach (MainContext.get_thread_default ()); - var heartbeat_source = new TimeoutSource (100); + var heartbeat_source = new TimeoutSource.seconds (1); + uint next_heartbeat_id = 1; heartbeat_source.set_callback (() => { - _on_heartbeat (); - _schedule_heartbeat_on_dispatch_queue (); + uint id = next_heartbeat_id++; + _on_heartbeat (id); + _schedule_heartbeat_on_dispatch_queue (id); return true; }); heartbeat_source.attach (MainContext.get_thread_default ()); @@ -417,7 +470,13 @@ namespace Frida { if (pending_error != null) throw pending_error; + + printerr ("\n"); + _log_event ("prepare-end pid=%u", pid); + printerr ("------------------------------------------------------------\n\n"); } catch (GLib.Error e) { + _log_event ("prepare-error pid=%u message=\"%s\"", pid, e.message); + if (instance_created_here) { spawn_instances.unset (pid); _free_spawn_instance (spawn_instance); @@ -432,8 +491,10 @@ namespace Frida { } public void _on_breakpoint_request (int kr, int exception, int[] code) { + printerr ("\n"); + var message = new StringBuilder.sized (256); - message.append_printf ("_on_breakpoint_request() kr=%d exception=%d code=[", kr, exception); + message.append_printf ("breakpoint-request kr=%d exception=%d code=[", kr, exception); uint i = 0; foreach (int c in code) { if (i != 0) @@ -443,62 +504,15 @@ namespace Frida { } message.append_c (']'); - log_event ("%s", message.str); + _log_event ("%s", message.str); } public void _on_breakpoint_response (int kr) { - log_event ("_on_breakpoint_response() kr=%d", kr); - } - - public void _on_heartbeat () { - log_event ("heartbeat"); + _log_event ("breakpoint-response kr=%d", kr); } - private static Mutex log_mutex; - private static Timer log_timer = null; - private static Gee.HashMap log_threads = null; - private const uint[] log_palette = { 36, 35, 33, 32, 31, 34 }; - private static uint log_palette_offset = 0; - - private void log_event (string format, ...) { - var builder = new StringBuilder (); - - log_mutex.lock (); - - uint time_delta; - if (log_timer == null) { - log_timer = new Timer (); - log_threads = new Gee.HashMap (); - - time_delta = 0; - } else { - time_delta = (uint) (log_timer.elapsed () * 1000.0); - log_timer.reset (); - } - if (time_delta > 0) { - builder.append_printf ("\n*** +%u ms\n", time_delta); - } - - var tid = (uint) Gum.Process.get_current_thread_id (); - - var color = log_threads[tid]; - if (color == 0) { - color = log_palette[log_palette_offset]; - log_palette_offset = (log_palette_offset + 1) % log_palette.length; - log_threads[tid] = color; - } - builder.append_printf ("\033[0;%um", color); - - builder.append_printf ("[thread %04x] %p ", tid, this); - - var args = va_list (); - builder.append_vprintf (format, args); - - builder.append ("\033[0m\n"); - - stderr.write (builder.str.data); - - log_mutex.unlock (); + public void _on_heartbeat (uint id) { + _log_event ("heartbeat id=%u", id); } private bool is_booting (uint task) throws Error { @@ -721,7 +735,7 @@ namespace Frida { protected extern void _prepare_spawn_instance_for_injection (void * instance, uint task) throws Error; protected extern void _resume_spawn_instance (void * instance); protected extern void _free_spawn_instance (void * instance); - protected extern void _schedule_heartbeat_on_dispatch_queue (); + protected extern void _schedule_heartbeat_on_dispatch_queue (uint id); protected extern uint _inject_into_task (uint pid, uint task, string path_or_name, MappedLibraryBlob? blob, string entrypoint, string data) throws Error; protected extern void _demonitor (void * instance);