frida / frida-gum

Cross-platform instrumentation and introspection library written in C
https://frida.re
Other
753 stars 245 forks source link

Callout on CALL instruction are not emitted #806

Closed hillelpinto closed 4 months ago

hillelpinto commented 4 months ago

@oleavr

When stalking a thread, i want to emit a callout on every call using cmodule but the callout is never called In the following picture we can see that we entered the if condition in the transform callback but the callout is never called...

image


To reproduce the issue, use the following code:

var module = Process.enumerateModules()[0] var mem = Memory.alloc(16); var appStart = parseInt(module.base, 16); var ptrToAppStart = mem.writeU64(appStart); var mem2 = Memory.alloc(16); var appEnd = appStart + parseInt(module.size,10); var ptrToAppEnd = mem2.writeU64(appEnd);

const cm = new CModule(`

include <gum/gumstalker.h>

include <gum/gummemory.h>

include

extern void logging (gchar message); extern guint64 ptrToAppStart ; extern guint64 ptrToAppEnd ; static void log (const gchar format,...) { gchar * message; va_list args;

va_start (args, format);
message = g_strdup_vprintf (format, args);
va_end (args);

logging(message);

g_free (message);

}

static void on_cmp_wrapper(GumCpuContext cpu_context, gpointer user_data) { cs_insn insn = (cs_insn *)user_data; log("Got as instruction ID: %d", insn->id); }

void transform (GumStalkerIterator iterator, GumStalkerOutput output, gpointer user_data) {

cs_insn * insn;

while (gum_stalker_iterator_next (iterator, &insn)) {

  gum_stalker_iterator_keep (iterator);
 if (insn->id == X86_INS_CALL && (gpointer)insn->address > ptrToAppStart && (gpointer)insn->address < ptrToAppEnd)
 {
    log("Entered to emit the callout for CALL instructions");
      gum_stalker_iterator_put_callout (iterator,
       on_cmp_wrapper, insn, NULL);

 }

} }

`, { ptrToAppStart, ptrToAppEnd, logging: new NativeCallback((msg) => { console.log(msg.readCString()); }, 'void', ['pointer'])

} );

Stalker.follow( Process.enumerateThreads()[0].id, { transform: cm.transform } );

The helloworld.exe targeted can be found here: helloworld.zip

Same issue if we set the if condition to match each RET instructions

oleavr commented 4 months ago

Move the keep() call after the callout. Code emitted after a branch isn't reached, as execution is transferred to the next block.

hillelpinto commented 4 months ago

@oleavr As you said, I've changed the code like this and this causes the target process to crash and nothing is printed is frida CLI: image

I also tried to keep the first keep() and just add a second keep() after the callout and still the callout is not called but some log are printed in frida cli but it also trigger the target process to crash image

oleavr commented 4 months ago

I didn't mean to move it inside the if-block. That crashes because you're telling Stalker to skip all instructions except CALL instructions.

Code you emit before keep() is inserted before the instruction being kept, code you emit after gets inserted after the instruction being kept.

hillelpinto commented 4 months ago

right, i fixed it like this

image

thx a lot !

the issue https://github.com/frida/frida-gum/issues/805 still remains though