Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stalker: Implement chaining apis #777

Merged
merged 40 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
108cdcf
stalker-x86: Add tests for transformer being able to replace calls/ta…
s1341 Jan 16, 2024
7571e35
stalker-x86: fix jmp in test
s1341 Jan 16, 2024
a32d261
stalker-x86: Add the new api call
s1341 Jan 17, 2024
a913d31
stalker-x86: attempt to implement the gum_stalker_iterator_put_chaini…
s1341 Jan 18, 2024
44dd7be
stalker-x86: Fix put_chaining_return()
oleavr Jan 19, 2024
4f1b47a
stalker-x86: fix 32bit build
s1341 Feb 12, 2024
1dc877a
Style fixes
s1341 Feb 13, 2024
f45f78e
stalker-arm64: implement call->callout tests
s1341 Feb 13, 2024
479b4c8
stalker-arm64: fix register access
s1341 Feb 13, 2024
f4abe47
Style fixes
s1341 Feb 13, 2024
86ff4b6
stalker-arm: introduce call->callout test
s1341 Feb 13, 2024
df3759a
Style fixes
s1341 Feb 13, 2024
9da6387
stalker-arm: add another test and fix previous one
s1341 Feb 13, 2024
ab67e85
Style fixes
s1341 Feb 13, 2024
349aadc
stalker-arm: fix bugs
s1341 Feb 13, 2024
c7eaa82
stalker-arm64: attempt to implement put_chaining_return
s1341 Feb 13, 2024
20445ca
Style fixes
s1341 Feb 13, 2024
3479852
stalker-arm64: fix missing ret_reg
s1341 Feb 13, 2024
8d2addd
stalker-arm64: get rid of unnecessary and undefined function
s1341 Feb 13, 2024
3645241
stalker-arm64: use X30 instead of LR
s1341 Feb 13, 2024
a73f213
stalker-arm: implement empty put_chaining_return
s1341 Feb 13, 2024
76897ff
stalker-arm: fix broken tests
s1341 Feb 13, 2024
5d60144
stalker-arm: fix broken tests
s1341 Feb 13, 2024
4371e5e
stalker-arm: fix broken tests
s1341 Feb 13, 2024
5ef4a28
ARM implementation of chaining return
mineo333 Feb 25, 2024
83e2107
Formatting
mineo333 Feb 25, 2024
fe3a400
Additional formatting fixes
mineo333 Feb 25, 2024
7514450
add newline to check
mineo333 Feb 25, 2024
7391d7e
stylecheck.py fixes
mineo333 Feb 26, 2024
5c73e79
style: get rid of trailing whitespaces
s1341 Feb 28, 2024
cbcf3b1
stalker-arm: missing bracket
s1341 Feb 28, 2024
2843ec3
style: remove trailing spaces
s1341 Feb 28, 2024
d5b0d8e
gumjs bindings for put_chaining_return
s1341 Feb 29, 2024
61a7dcb
gumstalker.c: add documentation for gum_stalker_iterator_put_chaining…
s1341 Feb 29, 2024
624f2c2
fmt
s1341 Feb 29, 2024
bd11f26
Try to fix gumlinux.h
s1341 Feb 29, 2024
f007490
Wrong function call
s1341 Mar 4, 2024
54b3265
Add MIPS stub
oleavr May 10, 2024
404cc80
Revert "Try to fix gumlinux.h"
oleavr May 10, 2024
627ad98
Fix style issues
oleavr May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions bindings/gumjs/gumquickstalker.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ GUMJS_DECLARE_GETTER (gumjs_default_iterator_get_memory_access)
GUMJS_DECLARE_FUNCTION (gumjs_default_iterator_next)
GUMJS_DECLARE_FUNCTION (gumjs_default_iterator_keep)
GUMJS_DECLARE_FUNCTION (gumjs_default_iterator_put_callout)
GUMJS_DECLARE_FUNCTION (gumjs_default_iterator_put_chaining_return)

static JSValue gum_quick_special_iterator_new (GumQuickStalker * parent,
GumQuickSpecialIterator ** iterator);
Expand All @@ -125,6 +126,7 @@ GUMJS_DECLARE_GETTER (gumjs_special_iterator_get_memory_access)
GUMJS_DECLARE_FUNCTION (gumjs_special_iterator_next)
GUMJS_DECLARE_FUNCTION (gumjs_special_iterator_keep)
GUMJS_DECLARE_FUNCTION (gumjs_special_iterator_put_callout)
GUMJS_DECLARE_FUNCTION (gumjs_special_iterator_put_chaining_return)

static void gum_quick_callout_free (GumQuickCallout * callout);
static void gum_quick_callout_on_invoke (GumCpuContext * cpu_context,
Expand Down Expand Up @@ -200,6 +202,8 @@ static const JSCFunctionListEntry gumjs_default_iterator_entries[] =
JS_CFUNC_DEF ("next", 0, gumjs_default_iterator_next),
JS_CFUNC_DEF ("keep", 0, gumjs_default_iterator_keep),
JS_CFUNC_DEF ("putCallout", 0, gumjs_default_iterator_put_callout),
JS_CFUNC_DEF ("putChainingReturn", 0,
gumjs_default_iterator_put_chaining_return),
};

static const JSClassDef gumjs_special_iterator_def =
Expand All @@ -215,6 +219,8 @@ static const JSCFunctionListEntry gumjs_special_iterator_entries[] =
JS_CFUNC_DEF ("next", 0, gumjs_special_iterator_next),
JS_CFUNC_DEF ("keep", 0, gumjs_special_iterator_keep),
JS_CFUNC_DEF ("putCallout", 0, gumjs_special_iterator_put_callout),
JS_CFUNC_DEF ("putChainingReturn", 0,
gumjs_special_iterator_put_chaining_return),
};

static const JSClassExoticMethods gumjs_probe_args_exotic_methods =
Expand Down Expand Up @@ -1016,6 +1022,15 @@ gum_quick_stalker_iterator_put_callout (GumQuickIterator * self,
return JS_UNDEFINED;
}

static JSValue
gum_quick_stalker_iterator_put_chaining_return (GumQuickIterator * self,
JSContext * ctx)
{
gum_stalker_iterator_put_chaining_return (self->handle);

return JS_UNDEFINED;
}

static JSValue
gum_quick_default_iterator_new (GumQuickStalker * parent,
GumQuickDefaultIterator ** iterator)
Expand Down Expand Up @@ -1135,6 +1150,16 @@ GUMJS_DEFINE_FUNCTION (gumjs_default_iterator_put_callout)
return gum_quick_stalker_iterator_put_callout (&self->iterator, ctx, args);
}

GUMJS_DEFINE_FUNCTION (gumjs_default_iterator_put_chaining_return)
{
GumQuickDefaultIterator * self;

if (!gum_quick_default_iterator_get (ctx, this_val, core, &self))
return JS_EXCEPTION;

return gum_quick_stalker_iterator_put_chaining_return (&self->iterator, ctx);
}

static JSValue
gum_quick_special_iterator_new (GumQuickStalker * parent,
GumQuickSpecialIterator ** iterator)
Expand Down Expand Up @@ -1254,6 +1279,16 @@ GUMJS_DEFINE_FUNCTION (gumjs_special_iterator_put_callout)
return gum_quick_stalker_iterator_put_callout (&self->iterator, ctx, args);
}

GUMJS_DEFINE_FUNCTION (gumjs_special_iterator_put_chaining_return)
{
GumQuickSpecialIterator * self;

if (!gum_quick_special_iterator_get (ctx, this_val, core, &self))
return JS_EXCEPTION;

return gum_quick_stalker_iterator_put_chaining_return (&self->iterator, ctx);
}

static void
gum_quick_callout_free (GumQuickCallout * callout)
{
Expand Down
28 changes: 28 additions & 0 deletions bindings/gumjs/gumv8stalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ GUMJS_DECLARE_GETTER (gumjs_stalker_default_iterator_get_memory_access)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_default_iterator_next)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_default_iterator_keep)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_default_iterator_put_callout)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_default_iterator_put_chaining_return)

static GumV8StalkerSpecialIterator *
gum_v8_stalker_special_iterator_new_persistent (GumV8Stalker * parent);
Expand All @@ -149,6 +150,7 @@ GUMJS_DECLARE_GETTER (gumjs_stalker_special_iterator_get_memory_access)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_special_iterator_next)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_special_iterator_keep)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_special_iterator_put_callout)
GUMJS_DECLARE_FUNCTION (gumjs_stalker_special_iterator_put_chaining_return)

static void gum_v8_callout_free (GumV8Callout * callout);
static void gum_v8_callout_on_invoke (GumCpuContext * cpu_context,
Expand Down Expand Up @@ -227,6 +229,7 @@ static const GumV8Function gumjs_stalker_default_iterator_functions[] =
{ "next", gumjs_stalker_default_iterator_next },
{ "keep", gumjs_stalker_default_iterator_keep },
{ "putCallout", gumjs_stalker_default_iterator_put_callout },
{ "putChainingReturn", gumjs_stalker_default_iterator_put_chaining_return },

{ NULL, NULL }
};
Expand All @@ -243,6 +246,7 @@ static const GumV8Function gumjs_stalker_special_iterator_functions[] =
{ "next", gumjs_stalker_special_iterator_next },
{ "keep", gumjs_stalker_special_iterator_keep },
{ "putCallout", gumjs_stalker_special_iterator_put_callout },
{ "putChainingReturn", gumjs_stalker_special_iterator_put_chaining_return },

{ NULL, NULL }
};
Expand Down Expand Up @@ -1083,6 +1087,16 @@ gum_v8_stalker_iterator_put_callout (GumV8StalkerIterator * self,
}
}

static void
gum_v8_stalker_iterator_put_chaining_return (GumV8StalkerIterator * self,
Isolate * isolate)
{
if (!gum_v8_stalker_iterator_check_valid (self, isolate))
return;

gum_stalker_iterator_put_chaining_return (self->handle);
}

static GumV8StalkerDefaultIterator *
gum_v8_stalker_default_iterator_new_persistent (GumV8Stalker * parent)
{
Expand Down Expand Up @@ -1170,6 +1184,13 @@ GUMJS_DEFINE_DIRECT_SUBCLASS_METHOD (gumjs_stalker_default_iterator_put_callout,
gum_v8_stalker_iterator_put_callout (&self->iterator, args, isolate);
}

GUMJS_DEFINE_DIRECT_SUBCLASS_METHOD (
gumjs_stalker_default_iterator_put_chaining_return,
GumV8StalkerDefaultIterator)
{
gum_v8_stalker_iterator_put_chaining_return (&self->iterator, isolate);
}

static GumV8StalkerSpecialIterator *
gum_v8_stalker_special_iterator_new_persistent (GumV8Stalker * parent)
{
Expand Down Expand Up @@ -1257,6 +1278,13 @@ GUMJS_DEFINE_DIRECT_SUBCLASS_METHOD (gumjs_stalker_special_iterator_put_callout,
gum_v8_stalker_iterator_put_callout (&self->iterator, args, isolate);
}

GUMJS_DEFINE_DIRECT_SUBCLASS_METHOD (
gumjs_stalker_special_iterator_put_chaining_return,
GumV8StalkerSpecialIterator)
{
gum_v8_stalker_iterator_put_chaining_return (&self->iterator, isolate);
}

static void
gum_v8_callout_free (GumV8Callout * callout)
{
Expand Down
60 changes: 50 additions & 10 deletions gum/backend-arm/gumstalker-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2512,7 +2512,7 @@ gum_stalker_iterator_arm_next (GumStalkerIterator * self,
return FALSE;
}

if (gum_arm_relocator_eob (rl))
if (!skip_implicitly_requested && gum_arm_relocator_eob (rl))
return FALSE;
}

Expand Down Expand Up @@ -2571,7 +2571,7 @@ gum_stalker_iterator_thumb_next (GumStalkerIterator * self,
return FALSE;
}

if (gum_thumb_relocator_eob (rl))
if (!skip_implicitly_requested && gum_thumb_relocator_eob (rl))
return FALSE;
}

Expand Down Expand Up @@ -2769,11 +2769,13 @@ gum_stalker_iterator_handle_thumb_branch_insn (GumStalkerIterator * self,
case ARM_INS_MOV:
gum_stalker_get_target_address (insn, TRUE, &target, &mask);
gum_exec_block_virtualize_thumb_ret_insn (block, &target, FALSE, 0, gc);
gum_thumb_relocator_skip_one (gc->thumb_relocator);
break;
case ARM_INS_POP:
case ARM_INS_LDM:
gum_stalker_get_target_address (insn, TRUE, &target, &mask);
gum_exec_block_virtualize_thumb_ret_insn (block, &target, TRUE, mask, gc);
gum_thumb_relocator_skip_one (gc->thumb_relocator);
break;
case ARM_INS_SMC:
case ARM_INS_HVC:
Expand Down Expand Up @@ -2833,14 +2835,6 @@ gum_stalker_iterator_handle_thumb_it_insn (GumStalkerIterator * self)
*/
insn->detail->arm.cc = ARM_CC_AL;
gum_stalker_iterator_handle_thumb_branch_insn (self, insn);

/*
* Put a breakpoint to trap and detect any errant continued execution (the
* branch should handle any possible continuation). Skip the original
* branch instruction.
*/
gum_thumb_writer_put_breakpoint (gc->thumb_writer);
gum_thumb_relocator_skip_one (gc->thumb_relocator);
}
else
{
Expand Down Expand Up @@ -3419,6 +3413,31 @@ gum_stalker_invoke_callout (GumCalloutEntry * entry,
ec->pending_calls--;
}

void
gum_stalker_iterator_put_chaining_return (GumStalkerIterator * self)
{
GumExecBlock * block = self->exec_block;
GumGeneratorContext * gc = self->generator_context;
GumBranchTarget target;
GumBranchDirectRegOffset * value;

target.type = GUM_TARGET_DIRECT_REG_OFFSET;
value = &target.value.direct_reg_offset;
value->reg = ARM_REG_LR;
value->offset = 0;
value->mode = GUM_ARM_MODE_CURRENT;

if (gc->is_thumb)
{
gum_exec_block_virtualize_thumb_ret_insn (block, &target, FALSE, 0, gc);
}
else
{
gum_exec_block_virtualize_arm_ret_insn (block, &target, ARM_CC_AL, FALSE, 0,
gc);
}
}

csh
gum_stalker_iterator_get_capstone (GumStalkerIterator * self)
{
Expand Down Expand Up @@ -4572,6 +4591,14 @@ gum_exec_block_virtualize_thumb_branch_insn (GumExecBlock * block,

gum_exec_block_write_thumb_handle_writeback (block, writeback, gc);
gum_exec_block_write_thumb_exec_generated_code (cw, block->ctx);

/*
* We MUST do this last to account for IT blocks.
* gum_thumb_relocator_skip_one() will complete the IT branch, so if we do
* this early (like on ARM), then the end branch will be relocated into the
* middle of the relocated branch.
*/
gum_thumb_relocator_skip_one (gc->thumb_relocator);
}

static void
Expand Down Expand Up @@ -4629,6 +4656,14 @@ gum_exec_block_virtualize_thumb_call_insn (GumExecBlock * block,
gum_thumb_writer_put_ldr_reg_address (gc->thumb_writer, ARM_REG_LR,
GUM_ADDRESS (ret_real_address));
gum_exec_block_write_thumb_exec_generated_code (gc->thumb_writer, block->ctx);

/*
* We MUST do this last to account for IT blocks.
* gum_thumb_relocator_skip_one() will complete the IT branch, so if we do
* this early (like on ARM), then the end branch will be relocated into the
* middle of the relocated branch.
*/
gum_thumb_relocator_skip_one (gc->thumb_relocator);
}

static void
Expand Down Expand Up @@ -4688,6 +4723,8 @@ gum_exec_block_virtualize_arm_ret_insn (GumExecBlock * block,
}

gum_exec_block_write_arm_exec_generated_code (gc->arm_writer, block->ctx);

gum_arm_relocator_skip_one (gc->arm_relocator);
}

static void
Expand Down Expand Up @@ -5124,7 +5161,10 @@ gum_exec_block_write_arm_handle_excluded (GumExecBlock * block,
if (target->type == GUM_TARGET_DIRECT_ADDRESS)
{
if (!check (block->ctx, target->value.direct_address.address))
{
gum_arm_relocator_skip_one (gc->arm_relocator);
return;
}
}

if (target->type != GUM_TARGET_DIRECT_ADDRESS)
Expand Down
22 changes: 22 additions & 0 deletions gum/backend-arm64/gumstalker-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,8 @@ static void gum_exec_block_write_jmp_transfer_code (GumExecBlock * block,
GumGeneratorContext * gc);
static void gum_exec_block_write_ret_transfer_code (GumExecBlock * block,
GumGeneratorContext * gc, arm64_reg ret_reg);
static void gum_exec_block_write_chaining_return_code (GumExecBlock * block,
GumGeneratorContext * gc, arm64_reg ret_reg);
static void gum_exec_block_write_slab_transfer_code (GumArm64Writer * from,
GumArm64Writer * to);
static void gum_exec_block_backpatch_slab (GumExecBlock * block,
Expand Down Expand Up @@ -3146,6 +3148,18 @@ gum_stalker_invoke_callout (GumCalloutEntry * entry,
ec->pending_calls--;
}

void
gum_stalker_iterator_put_chaining_return (GumStalkerIterator * self)
{
GumExecBlock * block = self->exec_block;
GumGeneratorContext * gc = self->generator_context;

if ((block->ctx->sink_mask & GUM_RET) != 0)
gum_exec_block_write_ret_event_code (block, gc, GUM_CODE_INTERRUPTIBLE);

gum_exec_block_write_chaining_return_code (block, gc, ARM64_REG_X30);
}

csh
gum_stalker_iterator_get_capstone (GumStalkerIterator * self)
{
Expand Down Expand Up @@ -5093,6 +5107,14 @@ static void
gum_exec_block_write_ret_transfer_code (GumExecBlock * block,
GumGeneratorContext * gc,
arm64_reg ret_reg)
{
gum_exec_block_write_chaining_return_code (block, gc, ret_reg);
}

static void
gum_exec_block_write_chaining_return_code (GumExecBlock * block,
GumGeneratorContext * gc,
arm64_reg ret_reg)
{
GumArm64Writer * cw = gc->code_writer;
GumArm64Writer * cws = gc->slow_writer;
Expand Down
5 changes: 5 additions & 0 deletions gum/backend-mips/gumstalker-mips.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,11 @@ gum_stalker_iterator_put_callout (GumStalkerIterator * self,
{
}

void
gum_stalker_iterator_put_chaining_return (GumStalkerIterator * self)
{
}

csh
gum_stalker_iterator_get_capstone (GumStalkerIterator * self)
{
Expand Down
Loading