-
-
Notifications
You must be signed in to change notification settings - Fork 251
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
stalker: Add run_on_thread() and run_on_thread_sync()
Co-authored-by: Ole André Vadla Ravnås <[email protected]>
- Loading branch information
1 parent
1f64c08
commit 283a391
Showing
10 changed files
with
917 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2009-2023 Ole André Vadla Ravnås <[email protected]> | ||
* Copyright (C) 2009-2024 Ole André Vadla Ravnås <[email protected]> | ||
* Copyright (C) 2023 Håvard Sørbø <[email protected]> | ||
* | ||
* Licence: wxWindows Library Licence, Version 3.1 | ||
|
@@ -16,6 +16,7 @@ | |
#include "gummemory.h" | ||
#include "gummetalhash.h" | ||
#include "gumspinlock.h" | ||
#include "gumstalker-priv.h" | ||
#include "gumthumbreader.h" | ||
#include "gumthumbrelocator.h" | ||
#include "gumthumbwriter.h" | ||
|
@@ -1588,6 +1589,64 @@ gum_call_probe_unref (GumCallProbe * probe) | |
} | ||
} | ||
|
||
void | ||
_gum_stalker_modify_to_run_on_thread (GumStalker * self, | ||
GumThreadId thread_id, | ||
GumCpuContext * cpu_context, | ||
GumStalkerRunOnThreadFunc func, | ||
gpointer data) | ||
{ | ||
GumExecCtx * ctx; | ||
guint32 pc; | ||
GumArmWriter * cw; | ||
GumAddress cpu_context_copy, infect_body; | ||
|
||
ctx = gum_stalker_create_exec_ctx (self, thread_id, NULL, NULL); | ||
|
||
if ((cpu_context->cpsr & GUM_PSR_T_BIT) == 0) | ||
pc = cpu_context->pc; | ||
else | ||
pc = cpu_context->pc + 1; | ||
|
||
gum_spinlock_acquire (&ctx->code_lock); | ||
|
||
gum_stalker_thaw (self, ctx->thunks, self->thunks_size); | ||
cw = &ctx->arm_writer; | ||
gum_arm_writer_reset (cw, ctx->infect_thunk); | ||
|
||
cpu_context_copy = GUM_ADDRESS (gum_arm_writer_cur (cw)); | ||
gum_arm_writer_put_bytes (cw, (guint8 *) cpu_context, sizeof (GumCpuContext)); | ||
|
||
infect_body = GUM_ADDRESS (gum_arm_writer_cur (cw)); | ||
|
||
gum_exec_ctx_write_arm_prolog (ctx, cw); | ||
|
||
gum_arm_writer_put_call_address_with_arguments (cw, | ||
GUM_ADDRESS (func), 2, | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (cpu_context_copy), | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (data)); | ||
|
||
gum_arm_writer_put_call_address_with_arguments (cw, | ||
GUM_ADDRESS (gum_exec_ctx_unfollow), 2, | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (ctx), | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (pc)); | ||
|
||
gum_exec_ctx_write_arm_epilog (ctx, cw); | ||
|
||
gum_arm_writer_put_push_regs (cw, 2, ARM_REG_R0, ARM_REG_PC); | ||
gum_arm_writer_put_ldr_reg_address (cw, ARM_REG_R0, pc); | ||
gum_arm_writer_put_str_reg_reg_offset (cw, ARM_REG_R0, ARM_REG_SP, 4); | ||
gum_arm_writer_put_pop_regs (cw, 2, ARM_REG_R0, ARM_REG_PC); | ||
|
||
gum_arm_writer_flush (cw); | ||
gum_stalker_freeze (self, cw->base, gum_arm_writer_offset (cw)); | ||
|
||
gum_spinlock_release (&ctx->code_lock); | ||
|
||
cpu_context->cpsr &= ~GUM_PSR_T_BIT; | ||
cpu_context->pc = infect_body; | ||
} | ||
|
||
static GumExecCtx * | ||
gum_stalker_create_exec_ctx (GumStalker * self, | ||
GumThreadId thread_id, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
/* | ||
* Copyright (C) 2009-2023 Ole André Vadla Ravnås <[email protected]> | ||
* Copyright (C) 2009-2024 Ole André Vadla Ravnås <[email protected]> | ||
* | ||
* Licence: wxWindows Library Licence, Version 3.1 | ||
*/ | ||
|
||
#include "gumstalker.h" | ||
|
||
#include "gumstalker-priv.h" | ||
|
||
struct _GumStalker | ||
{ | ||
GObject parent; | ||
|
@@ -183,6 +185,15 @@ gum_stalker_remove_call_probe (GumStalker * self, | |
{ | ||
} | ||
|
||
void | ||
_gum_stalker_modify_to_run_on_thread (GumStalker * self, | ||
GumThreadId thread_id, | ||
GumCpuContext * cpu_context, | ||
GumStalkerRunOnThreadFunc func, | ||
gpointer data) | ||
{ | ||
} | ||
|
||
gboolean | ||
gum_stalker_iterator_next (GumStalkerIterator * self, | ||
const cs_insn ** insn) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2009-2023 Ole André Vadla Ravnås <[email protected]> | ||
* Copyright (C) 2009-2024 Ole André Vadla Ravnås <[email protected]> | ||
* Copyright (C) 2010-2013 Karl Trygve Kalleberg <[email protected]> | ||
* Copyright (C) 2020 Duy Phan Thanh <[email protected]> | ||
* | ||
|
@@ -16,6 +16,7 @@ | |
#include "gummemory.h" | ||
#include "gumx86relocator.h" | ||
#include "gumspinlock.h" | ||
#include "gumstalker-priv.h" | ||
#ifdef HAVE_WINDOWS | ||
# include "gumexceptor.h" | ||
#endif | ||
|
@@ -2172,6 +2173,82 @@ gum_call_probe_unref (GumCallProbe * probe) | |
} | ||
} | ||
|
||
void | ||
_gum_stalker_modify_to_run_on_thread (GumStalker * self, | ||
GumThreadId thread_id, | ||
GumCpuContext * cpu_context, | ||
GumStalkerRunOnThreadFunc func, | ||
gpointer data) | ||
{ | ||
GumExecCtx * ctx; | ||
guint8 * pc; | ||
GumX86Writer * cw; | ||
GumAddress cpu_context_copy; | ||
|
||
ctx = gum_stalker_create_exec_ctx (self, thread_id, NULL, NULL); | ||
|
||
pc = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XIP (cpu_context)); | ||
|
||
gum_spinlock_acquire (&ctx->code_lock); | ||
|
||
gum_stalker_thaw (self, ctx->thunks, self->thunks_size); | ||
cw = &ctx->code_writer; | ||
gum_x86_writer_reset (cw, ctx->infect_thunk); | ||
|
||
cpu_context_copy = GUM_ADDRESS (gum_x86_writer_cur (cw)); | ||
gum_x86_writer_put_bytes (cw, (guint8 *) cpu_context, sizeof (GumCpuContext)); | ||
|
||
#ifdef HAVE_LINUX | ||
/* | ||
* In case the thread is in a Linux system call we prefix with a couple of | ||
* NOPs so that when we restart, we don't re-attempt the syscall. We will | ||
* drop ourselves back to the syscall once we are done. | ||
*/ | ||
gum_x86_writer_put_nop_padding (cw, MAX (sizeof (gum_int80_code), | ||
sizeof (gum_syscall_code))); | ||
#endif | ||
|
||
ctx->infect_body = GUM_ADDRESS (gum_x86_writer_cur (cw)); | ||
gum_exec_ctx_write_prolog (ctx, GUM_PROLOG_MINIMAL, cw); | ||
gum_x86_writer_put_call_address_with_aligned_arguments (cw, GUM_CALL_CAPI, | ||
GUM_ADDRESS (func), 2, | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (cpu_context_copy), | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (data)); | ||
gum_x86_writer_put_call_address_with_aligned_arguments (cw, GUM_CALL_CAPI, | ||
GUM_ADDRESS (gum_exec_ctx_unfollow), 2, | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (ctx), | ||
GUM_ARG_ADDRESS, GUM_ADDRESS (pc)); | ||
gum_exec_ctx_write_epilog (ctx, GUM_PROLOG_MINIMAL, cw); | ||
|
||
#ifdef HAVE_LINUX | ||
if (memcmp (&pc[-sizeof (gum_int80_code)], gum_int80_code, | ||
sizeof (gum_int80_code)) == 0) | ||
{ | ||
gum_x86_writer_put_jmp_address (cw, | ||
GUM_ADDRESS (&pc[-sizeof (gum_int80_code)])); | ||
} | ||
else if (memcmp (&pc[-sizeof (gum_syscall_code)], gum_syscall_code, | ||
sizeof (gum_syscall_code)) == 0) | ||
{ | ||
gum_x86_writer_put_jmp_address (cw, | ||
GUM_ADDRESS (&pc[-sizeof (gum_syscall_code)])); | ||
} | ||
else | ||
{ | ||
gum_x86_writer_put_jmp_address (cw, GUM_ADDRESS (pc)); | ||
} | ||
#else | ||
gum_x86_writer_put_jmp_address (cw, GUM_ADDRESS (pc)); | ||
#endif | ||
|
||
gum_x86_writer_flush (cw); | ||
gum_stalker_freeze (self, cw->base, gum_x86_writer_offset (cw)); | ||
|
||
gum_spinlock_release (&ctx->code_lock); | ||
|
||
GUM_CPU_CONTEXT_XIP (cpu_context) = ctx->infect_body; | ||
} | ||
|
||
static GumExecCtx * | ||
gum_stalker_create_exec_ctx (GumStalker * self, | ||
GumThreadId thread_id, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright (C) 2024 Ole André Vadla Ravnås <[email protected]> | ||
* | ||
* Licence: wxWindows Library Licence, Version 3.1 | ||
*/ | ||
|
||
#ifndef __GUM_STALKER_PRIV_H__ | ||
#define __GUM_STALKER_PRIV_H__ | ||
|
||
#include "gumstalker.h" | ||
|
||
G_BEGIN_DECLS | ||
|
||
G_GNUC_INTERNAL void _gum_stalker_modify_to_run_on_thread (GumStalker * self, | ||
GumThreadId thread_id, GumCpuContext * cpu_context, | ||
GumStalkerRunOnThreadFunc func, gpointer data); | ||
|
||
G_END_DECLS | ||
|
||
#endif |
Oops, something went wrong.