C++ – CreateProcess from memory buffer

cvisual c++winapi

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.

Best Answer

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!