views:

2368

answers:

8

I can use CreateProcess to launch an EXE. I want to have the contents of an EXE in a memory buffer and do CreateProcess (or an equivalent) on it without having to write it to a file. Is there any way to do that?

The backstory : we make games. We send a plain EXE to our distributors, which then wrap it using their favorite DRM and sell it to their users. There have been instances where users find crashes. Most of the crashes take 5 minutes to fix, but the patch must go through the distributor and it may take several days, even weeks. I can't just send the patched EXE to the players because it wouldn't have the distributor's DRM. I'm thinking of distributing the real game EXE inside an encrypted datafile so what gets wrapped (the external EXE) just decrypts and launches the real EXE. This way I could safely distribute a fix without disabling the DRM.

+1  A: 

Why do you need to create a new process? I would have thought you could run in the context of process which does the unpacking/decryption.

Will Dean
I can definitely do that. I mentioned CreateProcess because it's my best alternative, but what you say would work.
ggambett
A: 

What you want can be achieved with something called a "Packer". Actually launching an exe from memory might be possible, but it's a lot harder than a packer ;)

One of the best known packers is UPX (google it). There are tools to decrypt it, but it should at least give you a starting point to work froim. I'm also fairly certain UPX is open-source.

Frans-Willem
I had used UPX before but I didn't think of it this time. May be worth exploring. Thanks!
ggambett
+1  A: 

What you want to do requires NtCreateProcess, but it's undocumented and therefore brittle. This book apparently covers its use.

Perhaps you could build a patch system? E.g. on launch, program checks for patch DLL in same directory, and loads it if it exists.

Mark
+6  A: 

You can compile the game as a DLL and put the DLL in the encrypted data file. A DLL can be loaded from memory without writing it to disk. Please see this tutorial (with sample code at the end): Loading a DLL From Memory

smt
See also http://stackoverflow.com/questions/638277/loading-dll-from-a-location-in-memory
Suma
+8  A: 

It's actually quite easy. Similar technique has been described in a paper I read like 3 years ago.

Windows allow you to call the CreateProcess function with CREATE_SUSPENDED flag, that tells the API to keep the process suspended until the ResumeThread function is called.

This gives us time to grab the suspended thread's context using GetThreadContext function, then the EBX register will hold a pointer to the PBE(Process Enviroment Block) structure, which we need to determine the base address.

From the layout of the PBE structure we can see that the ImageBaseAddress is stored at the 8th byte, therefore [EBX+8] will give us actual base address of the process being suspended.

Now we need the in-memory EXE and do appropiate alignment if the alignment of memory and in-memory EXE differs.

If the base address of suspended process and in-memory exe matches, plus if the imageSize of the in-memory exe is lesser or equal to the suspended process' we can simply use WriteProcessMemory to write in-memory exe into the memory space of the suspended process.

But if the aforementioned conditions weren't met, we need a little more magic. First, we need to unmap the original image using ZwUnmapViewOfSection, and then allocate enough memory using VirtualAllocEx within the memory space of the suspended process. Now we need to write the in-memory exe into the memory space of the suspended process using the WriteProcessMemory function.

Next, patch the BaseAddress of the in-memory exe into the PEB->ImageBaseAddress of the suspended process.

EAX register of the thread context holds EntryPoint address, which we need to rewrite with the EntryPoint address of the in-memory exe. Now we need to save the altered thread context using the SetThreadContext function.

Voila! We're ready to call the ResumeThread function on the suspended process to execute it!

arul
A: 

It's a Win32 FAQ for more than 13 years (since Win 9x) See comp.os.ms-windows.programmer.win32 where code (in C) has been posted several times.

A: 

Look at BoxedAppSDK

It supports launching exe from a memory buffer.

hope it helps.

Art
A: 

Here is a document explaining how to do that: Launching an executable from a memory buffer.

Szere Dyeri