Frage

This is my first time around, and I really hope you guys can help me, as I have ran out of ideas by now.

I have searched for an answer for a couple of hours now, and could not find an answer that would actually work.

I would like to directly inject code into a running process. Yes, you have read it right. I am trying to inject code into another application, and - believe it or not - this is only to extend the functionality of it.

I am using Visual Studio 2012 Express Edition on Windows.

I have the following code:

__declspec(naked) void Foo()
{
    __asm
    {
        // Inline assembly code here
    }
}
__declspec(naked) void FooEnd() {}

int main()
{
    cout << HEX(Foo) << endl;
    cout << HEX(FooEnd) <<  endl;
    cout << (int)FooEnd - (int)Foo << endl;

    // Inject code here using WriteProcessMemory

    return 0;
}

Most of the code has been removed in order to maintain readability, though I can post other portions of it on request.

Output is the following:

0x010B1000
0x010B1010
16

The resulting size is actually incorrect. The functions are compiled in the right order (made sure using /ORDER), but the compiler adds a bunch of 0xCC (int 3) bytes after each method which extends it's size, and so I can't get the real (useful) number of bytes that contains actual executable code.

In another stackoverflow question, it has been said that disabling "Edit and Continue" would make these extra bytes go away, but no matter what, that didn't work for me.

I also tried using Release setup instead of Debug, changed a bunch of optimization settings, but none of these had any effect. What do you think could be the solution? I may be missing something obvious.

Anyway, is this (in your opinion) the best way to acquire a function's length (readability, reliability, ease of use)?

I hope I explained everything I had to in order for you to be able to help. If you have further questions, please feel free to leave a comment.

Thanks for your time and efforts.

War es hilfreich?

Lösung 2

You don't need the extra padding when you're injecting the code, so it's fine to discard them. It should also be fine to copy them over, it will just result in a few extra bytes of copying. Chances are the memory you're injecting to will by a page-aligned block anyway, so you're not really gaining anything by stripping it out.

But if you really want to strip it out, a simple solution to your problem would be to just iterate backwards from the last byte before the next function, until there are no more 0xcc bytes.

i.e.:

__declspec(naked) void Foo()
{
   __asm
   {
      _emit 0x4A
      _emit 0x4B
   }
}
__declspec(naked) void FooEnd() {}


int main(int argc, char** argv)
{
   //start at the last byte of the memory-aligned code instead of the first byte of FooEnd
   unsigned char* fooLast = (unsigned char*)FooEnd-1;

   //keep going backwards until we don't have a 0xcc
   while(*fooLast == 0xCC)
      fooLast--;

   //fooLast will now point at the last byte of your function, so you need to add 1
   int length = ((int)fooLast - (int)Foo) + 1;

   //should output 2 for the length of Foo
   std::cout << length;
}

Andere Tipps

As Devolus points out, the compiler is inserting these extra bytes after your code in order to align the next function on a reasonable (usually divisible by 16) starting address.

The compiler is actually trying to help you since 0xCC is the breakpoint instruction, the code will break into the debugger (if attached) should the instruction pointer accidentally point outside a function at any point during execution.

None of this should worry you for your purposes. You can consider the 0xCC padding as part of the function.

The extra bytes are inserted by the compiler to create a memory alignment, so you can't discard it, since you are using the next function as a marker.

On the other hand, since you are writing the injected code in assembly anyway, you can just as well write the code, compile it, and then put the binary form in a byte array. That's how I would do this, because then you have the exact length.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top