views:

29

answers:

1

Hello everyone.
I have a question about remote threads.I've read Mike Stall's article present here: http://blogs.msdn.com/b/jmstall/archive/2006/09/28/managed-create-remote-thread.aspx
I would like to create a remote thread that executes a delegate in another process, just like Mike Stall does. However, he declares the delegate in the target process, obtaining a memory address for it and then he creates the remote thread from another process using that address. The code of the target process CANNOT be modified. So, I cannot use his example, unless I can allocate memory in the target process and then WriteProcessMemory() using my delegate. I have tried using VirtualAllocEx() to allocate space in the target process but it always returns 0. This is how it looks so far.

Console.WriteLine("Pid {0}:Started Child process", pid);
uint pidTarget= uint.Parse(args[0]);
IntPtr targetPid= new IntPtr(pidTarget);

// Create delegate I would like to call.
ThreadProc proc = new ThreadProc(MyThreadProc);
Console.WriteLine("Delegate created");
IntPtr fproc = Marshal.GetFunctionPointerForDelegate(proc);
Console.WriteLine("Fproc:"+fproc);
uint allocSize = 512;
Console.WriteLine("AllocSize:" + allocSize.ToString());
IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pidParent);
Console.WriteLine("Process Opened: " + hProcess.ToString());
IntPtr allocatedPtr = VirtualAllocEx(targetPid, IntPtr.Zero, allocSize, AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
Console.WriteLine("AllocatedPtr: " + allocatedPtr.ToString());

Now my questions are:

  1. In the code above, why does VirtualAllocEx() not work? It has been imported using DLLImport from Kernel32. The allocatedPtr is always 0.

  2. How can I calculate alloc size? Is there a way I can see how much space the delegate might need or should I just leave it as a large constant?

  3. How do I call WriteMemory() after all of this to get my delegate in the other process?

Thank you in advance.

A: 

That blog post is of very questionable value. It is impossible to make this work in the general case. It only works because:

  • the CLR is known to be available
  • the address of the method to execute is known
  • it doesn't require injecting a DLL in the target process
  • Windows security is unlikely to stop this particular approach

Which it achieves by handing the client process everything it needs get that thread started. The far more typical usage of CreateRemoteThread is to do so when the target process does not cooperate. In other words, you don't have the CLR, you have to inject a DLL with the code, that code can't be managed, you have to deal with the DLL getting relocated and Windows will balk at all this.

Anyhoo, addressing your question: you don't check for any errors so you don't know what is going wrong. Make sure your [DllImport] declarations have SetLastError=true, check the return value for failure (IntPtr.Zero here) and use Marshal.GetLastWin32Error() to retrieve the error code.

Hans Passant
I agree with you about the article. I figured out that the VirtualAllocEx wasn't working because I need to pass the IntPtr hProcess from OpenProcess(). I've injected data objects using WriteMemoryProcess() since they can be serialized to byte[], but injecting the delegate seems impossible since I cannot serialize it. So, it is not possible to inject just a single function into a process and execute it remotely? Do you have any good links on how to Inject DLLs using remote threads? I would like to avoid using hooks.
prettyCode
No, you cannot inject functions. Injecting an unmanaged DLL is required. Codeproject.com has plenty of articles on it.
Hans Passant
Thank you for your help. I will look into it.
prettyCode