1
votes

I'm working on a plugin for somthing (which I don't have access to the source of) and have run into an issue. The following assembly extract is from the main program and is the start of the procedure that is responsible for calling into my code (the entire code for this is very very long since it is very generall being able to call any function with upto 16 arguments plus relevant memory management for strings, and supporting either __stdcall or __cdecl). Unfortunatly one very important value is not passed through this function into my code, the "this" pointer held in the edx register.

So I need to inject some sort of code into the start of this function (The provided API's allow me to get the address of it, in this case 0x00613ED4) that will store the value in the edx register for me to retrieve later.

Ive done some x86 assembly before, however I never needed to inject new code into an existing module at runtime before and I couldnt find any information on how to go about doing such things :( If such things can actually be done from within C/C++ without me having to write all the stuff in assembly that would be even better.

00613ED4 push       ebp
00613ED5 mov        ebp,esp
00613ED7 add        esp, 0FFFFFE64h
00613EDD push       ebx
00613EDE push       esi
00613EDF push       edi
00613EE0 mov        dword ptr [ebp-19Ch],ecx
00613EE6 mov        ecx,11h
00613EEB lea        eax, [ebp-198h]
...
3

3 Answers

2
votes

You can't really insert code between two assembly instructions. You have to shift up all the code to make some room, and this is likely to break all of the hard coded offsets (such as jump targets or offsets in data segments).

What you could do is set up a code breakpoint at the relevant area and have that iret into the new code, and then have the new code ret into the original code.

If performance is a requirement, then be aware that this will hurt performance.


Another similar option is to use the INT3 debug breakpoint. It is actually meant exactly for this purpose. The way it is used, the debugger replaces the opcode it wants to break on with an INT3 opcode, which (conveniently) is a single byte opcode, ensuring that it can be inserted anywhere. This will cause a jump to the exception handler like you suggested in the comment. By examining the EIP that was pushed onto the stack you'll be able to tell where you came from and act accordingly.

This will have the same performance penalty as the other option.


Two points to consider:

  • I know of no way to do this in C/C++, but then again I'm no expert.
  • Fiddling with exception handlers is likely to require work at CPL0. You should make sure your code can do that.
2
votes

If you work on Linux, you can have a look at kernel probes (KProbes), a handy in-kernel facility. They are designed to allow executing almost arbitrary code at almost arbitrary place in the kernel. It is like an advanced version of INT 3/Breakpoint.

You can determine the address of the functions you are interested in, place KProbes at their first bytes, and the handlers you provide will execute when these functions run. The handlers are written in C. They receive information about the contents of the registers too and may allow changing it (not sure about the latter though).

Internally, KProbes use INT 3 or jumps and detour buffers, depending on the situation.

0
votes

Was just thinking that if I can turn somthing into a jmp somehow then I can put my code somewhere else, do whatever I overwrote and jump back to the next instruction after?

...this is a good approach for patching code at run-time, yes. But there may be fiddly details to consider depending on exactly what the instructions that are overwritten do. And code injection may be harder than you expect anyway: for example, the code may well be mapped read-only.

the entire code for this is very very long since it is very generall being able to call any function with upto 16 arguments plus relevant memory management for strings, and supporting either __stdcall or __cdecl)

So: this code calls back into your code, and can pass arguments? Can you register at least one pointer-sized argument along with the function that will be called back?

If so, you can pass the this pointer yourself, with a bit of fiddling. You will need to register a function that does not require a this pointer (such as a static member function) as the callback, along with the this pointer as an argument for the callback; that callback can then unwrap the argument in order to call the member function that you really want to call.

Something like this (with apologies if it's obvious that I spend most of my life writing C rather than C++):

#include <iostream>

// Simple C callback interface

extern "C" {

  typedef void (*tCallbackFn)(void *);

  static struct {
    tCallbackFn fn;
    void *context;
  } callback;

  static void set_callback(tCallbackFn fn, void *context)
  {
    callback.fn = fn;
    callback.context = context;
  }

  static void call_callback(void)
  {
    (callback.fn)(callback.context);
  }

}

// Simple test class

class MyClass
{
public:
  // We'll use this for test purposes
  int id;

  // This is the actual member function we want to invoke
  void DoIt(void)
  {
    std::cout << "Callback - id = " << id << std::endl;
  }

  // Static wrapper which we can pass as the function in the callback interface
  static void CallbackWrapper(void *context)
  {
    static_cast<MyClass *>(context)->DoIt();
  }

  // Register wrapper as callback function, with "this" pointer as context
  void Test(void)
  {
    set_callback(CallbackWrapper, static_cast<void *>(this));
    call_callback();
  }
};

// Test it

int main(void)
{
  MyClass m1, m2;

  m1.id = 1;
  m2.id = 2;
  m1.Test();
  m2.Test();

  return 0;
}