12

Is it possible to execute an exe file that is included in the project as a resource? Can I fetch the file as a byte array and execute it in memory?

I don't want to write the file to a temporary location and execute it there. I'm searching for a solution where I can execute it in memory. (It's not a .NET assembly.)

dtb
  • 213,145
  • 36
  • 401
  • 431
MichaelD
  • 8,377
  • 10
  • 42
  • 47
  • 1
    http://stackoverflow.com/questions/1224149/how-to-run-unmanaged-executable-from-memory-rather-than-disc – Darin Dimitrov Feb 01 '10 at 11:07
  • Why don't you want to create a temp file? – Kramii Feb 01 '10 at 16:29
  • 1
    because i prefer executing clean code without having to create temp files every time. if i run it in memory, i don't have to think about write rights in temp folder. – MichaelD Feb 02 '10 at 10:46
  • 2
    _System.IO.Path.GetTempPath()_ returns the path of the current system's temporary folder. You should not have problems with write rights. – Ricardo Nolde Feb 03 '10 at 18:08
  • @Kramii There's no correct way to delete the temporary file – Ian Boyd Nov 09 '11 at 14:57
  • @Ian Boyd: Can't you just wait for the process to terminate and delete the file by name? Or is there something I've missed? – Kramii Nov 09 '11 at 16:53
  • @Kramii If the user has closed your program while the child is still running, then you can't delete it. You also can't delete it on next startup of your app because it might still be in use. Worse is when you have multiple people logged in over terminal services on the same computer, and it's *another user* who's running that executable - can't delete it then. – Ian Boyd Nov 09 '11 at 18:49
  • @Ian Boyd: These are great points, but I do believe that there are ways of overcoming these problems. – Kramii Nov 09 '11 at 21:43
  • @Kramii i've struggled with it for many years. The best you can do is *try* to delete the file you created when your program shuts down (in .NET people hijack the internal `TempFileCollection` (http://msdn.microsoft.com/en-us/library/system.codedom.compiler.tempfilecollection.aspx ) ). You add all "temporary" files you've created to a list. That list *tries* to delete them on app shutdown. If it can't delete a file: then oh well - it stays around forever. But it still suffers from the problem of another user coming along and overwriting that file with their own. Then you mistakenly delete it. – Ian Boyd Nov 10 '11 at 01:58
  • The OS should have a designated folder for temporary files that is wiped on start up and/or shutdown. That's probably a better alternative to having the entire file system be transactional, simply because it's more efficient to wipe one temp folder than it would be to check the entire file system for unfinished transactions after a crash. I agree that we should be able to run executables directly from a byte array, and the "file on disk" requirement is archaic and is simply the result of lack of support for it in the Windows API. – Triynko Nov 12 '12 at 16:55

3 Answers3

7

It's quite possible - I've done it myself - but it's fiddly and more so from managed code. There's no .NET API for it, nor is there a native API for it which you can PInvoke. So you'll have to fenagle the load by hand, which will require some knowledge of the PE (Portable Executable) file format used for modules such as DLLs and EXEs - http://msdn.microsoft.com/en-us/magazine/cc301805.aspx. There'll be a lot of pointer manipulation (mandating use of unsafe {} blocks) and PInvoke.

First load the PE file into memory (or use MapViewOfFile). A PE file is internally made up of different sections containing code, data or resources. The offsets of each section in the file don't always match intended in-memory offsets, so some minor adjustments are required.

Every PE file assumes it'll be loaded at a certain base address in virtual memory. Unless you can ensure this you'll need to walk the PE file's relocation table to adjust pointers accordingly.

Each PE file also has an import table listing which other DLLs' functions it wants to call. You'll need to walk this table and call LoadLibrary() / GetProcAddress() to fill in each import.

Next, memory protection needs to be set correctly for each section. Each section's header notes the protection it wants, so it's just a matter of calling VirtualProtect() for each section with the correct flags. At a minimum you'll need to VirtualProtect the loaded module with PAGE_EXECUTE_READWRITE or you're unlikely to be able to execute any code.

Lastly for a DLL you need to call its entry point, whose address can be found in the PE header; you can then freely call exported functions.

Since you want to run an EXE, you've got some additional headaches. You can just spin up a new thread and call the EXE's entry point from it, but many EXE's may get upset since the process is set up for you, not the EXE. It also may well kill your process when it tries to exit. You might want to spawn a new process therefore - perhaps another copy of your main EXE with special arguments to tell it it's going to run some different code - in which case you'd have to fenagle the EXE into its memory space. You'd probably want to do most of the above work in the new process, not the old. You could either create a named pipe and send the data across from one EXE to the other, or allocate a named shared memory area with MapViewOfFile. Of course the EXE may still get upset since the process its running in still isn't its own.

All in all its far easier just to write to a temporary file and then use Process.Start().

If you still want to do it the hard way, take a look at this example in unmanaged code: http://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/. This doesn't cover executables, just DLLs, but if the code therein doesn't scare you you'd be fine extending the process to cover executables.

El Zorko
  • 3,349
  • 2
  • 26
  • 34
1

A much better way is to create a temporary DLL file with FILE_FLAG_DELETE_ON_CLOSE attribute. This way the file will be deleted automatically when it is no longer used.

I don't think there is a way to load DLL from a memory (rather than a file).

Vlad Lifliand
  • 470
  • 2
  • 5
  • Problem with that flag is that as soon as you close the file it will be deleted (i.e. as soon as you've written the file to the hard drive it will be deleted). And you *have* to close your handle to the file before you can "run" it, because the file will be locked by your process - and you won't be able to run it. – Ian Boyd Nov 09 '11 at 15:00
0

Its not very easy to create a new process from a memory image, all of the kernel functions are geared towards loading an image from disk. See the process section of the Windows NT/2000 native API reference for more information - page 161 has an example of manually forking a process.

If it is ok to run the code from within your own process then you can create a small DLL that will take a pointer to executable data and run it.

Luke Quinane
  • 16,447
  • 13
  • 69
  • 88
  • Strange. Here's a direct link to p161: http://books.google.com/books?id=Fp1ct-bKYdcC&lpg=PP1&ots=ciLzfYAKbI&dq=%22gary%20nebbett%22%20windows%20api&pg=RA1-PA161#v=onepage&q=&f=false – Luke Quinane Feb 02 '10 at 22:11