6

First of all, I don't want to inject a dll. I want to inject code using WriteProcessMemory() (if this is even possible). I already used ReadProcessMemory() so I think writing is not a big deal.
Well, lets say there is a function at TargetProgram.exe+D78C612
and let's say it could be called like this:

push eax
push [esp+08]
push edx
push 00
push TargetProgram.exe+AF76235
push 04
call TargetProgram.exe+D78C612

How exactly would I accomplish this with WriteProcessMemory()?
I mean where do I find a section in which I can inject my code without overwriting important stuff. And most importantly, how would I call the function?
Just put a jump to my code in the active routine, jump back and delete it afterwards? But how would I find the routine?
So many questions and I have no idea how to start... I hope you can help me. :)
And if you have the time I would really like to see an example code of a function-call-injection.

Forivin
  • 14,780
  • 27
  • 106
  • 199

2 Answers2

4

You can use VirtualAllocEx to allocate memory in the remote process and then copy your procedure into this memory.

Here are the steps to do the injection:

SuspendThread(hThread); // Suspend the remote thread
remote_address = VirtualAllocEx(hProcess, ...) // allocate memory for your code
WriteProcessMemory(hProcess, remote_address, local_address, length, NULL)  // copy your code to remote process
WriteProcessMemory(hProcess, remote_fixup, ...) // insert a jump to your code 
ResumeThread(hThread); // Resume the remote thread
Max
  • 19,654
  • 13
  • 84
  • 122
  • I have a similar problem as OP but I dont get your 1st WriteProcessMemory call. As a local_address I can pass address of my function but I cant pass its length in a next argument. Simply because I have no idea how big it is (since compiler hasnt compiled it yet). So is WriteProcessMemory suitable for writing a function/code from my process to another? Edit: or is the only key writing function in assembler (I can count it then) instead of C++? – Kra Nov 23 '13 at 19:01
  • 2
    @Kra In most cases you cannot just copy your C function to another process, because jump addresses will be broken. You have to either fix relocs or write a code which is relocatable. In both cases you have to use assembly language. To answer your question about function code length, I think you can try disabling optimizations and write two functions f1() and f2(), where f2 follows f1 in code. Then you can subtract address of f1 from the address of f2 and [hopefully] get the length of f1. But function size is the least of your problems here. – Max Nov 23 '13 at 19:12
1

As mentioned by Max's answer, VirtualAllocEx is one way to allocate memory pages in a remote process, assuming you have the PROCESS_VM_OPERATION access right for the process in question. You will also want to make sure the new pages are marked PAGE_EXECUTE_READWRITE for their protection level during the writing and then change it later to PAGE_EXECUTE_READ using VirtualProtectEx.

Note that branching and some call instructions in x86 are IP-relative. This means their encodings are dependent upon where they are located in memory, as they use a signed relative displacement from the end of the instruction. So if you plan on calling an existing function from your new code, make sure you take this into account when using a relative call instruction or use an indirect/immediate form instead.

However, without knowing exactly what you're trying to accomplish here, it's difficult to recommend a technique for executing your new target code. With the new code in place, you could just inject a remote thread using CreateRemoteThread to execute it without having to disrupt any existing threads. This would be the simplest solution to execute the new code, but requires that the code you're calling is thread-safe. Picking an already running thread, suspending it, modifying EIP or introducing a detour, and resuming it without side effects (properly saving context across the injected call) is very tricky to say the least.

Personal note: as the author of the code coverage tool in Visual Studio 2012 that uses a bunch of tricks to rewrite third-party x86/x86-64 code on the fly to collect coverage data, this stuff is oh-so-much fun to hack and think on :)

Peter Huene
  • 5,758
  • 2
  • 34
  • 35