Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run unmanaged executable from memory rather than disc

I want to embed a command-line utility in my C# application, so that I can grab its bytes as an array and run the executable without ever saving it to disk as a separate file (avoids storing executable as separate file and avoids needing ability to write temporary files anywhere).

I cannot find a method to run an executable from just its byte stream. Does windows require it to be on a disk, or is there a way to run it from memory? If windows requires it to be on disk, is there an easy way in the .NET framework to create a virtual drive/file of some kind and map the file to the executable's memory stream?

like image 935
Triynko Avatar asked Aug 03 '09 19:08

Triynko


1 Answers

You are asking for a very low-level, platform-specific feature to be implemented in a high-level, managed environment. Anything's possible...but nobody said it would be easy...

(BTW, I don't know why you think temp file management is onerous. The BCL does it for you: http://msdn.microsoft.com/en-us/library/system.io.path.gettempfilename.aspx )


  1. Allocate enough memory to hold the executable. It can't reside on the managed heap, of course, so like almost everything in this exercise you'll need to PInvoke. (I recommend C++/CLI, actually, so as not to drive yourself too crazy). Pay special attention to the attribute bits you apply to the allocated memory pages: get them wrong and you'll either open a gaping security hole or have your process be shut down by DEP (i.e., you'll crash). See http://msdn.microsoft.com/en-us/library/aa366553(VS.85).aspx

  2. Locate the executable in your assembly's resource library and acquired a pinned handle to it.

  3. Memcpy() the code from the pinned region of the managed heap to the native block.

  4. Free the GCHandle.

  5. Call VirtualProtect to prevent further writes to the executable memory block.

  6. Calculate the address of the executable's Main function within your process' virtual address space, based on the handle you got from VirtualAlloc and the offset within the file as shown by DUMPBIN or similar tools.

  7. Place the desired command line arguments on the stack. (Windows Stdcall convention). Any pointers must point to native or pinned regions, of course.

  8. Jump to the calculated address. Probably easiest to use _call (inline assembly language).

  9. Pray to God that the executable image doesn't have any absolute jumps in it that would've been fixed up by calling LoadLibrary the normal way. (Unless, of course, you feel like re-implementing the brains of LoadLibrary during step #3).

  10. Retrieve the return value from the @eax register.

  11. Call VirtualFree.

Steps #5 and #11 should be done in a finally block and/or use the IDisposable pattern.


The other main option would be to create a RAMdrive, write the executable there, run it, and cleanup. That might be a little safer since you aren't trying to write self-modifying code (which is tough in any case, but especially so when the code isn't even yours). But I'm fairly certain it will require even more platform API calls than the dynamic code injection option -- all of them requiring C++ or PInvoke, naturally.

like image 111
Richard Berg Avatar answered Sep 19 '22 14:09

Richard Berg