win32 visual studio programming program gui for first example app c++ winapi visual-c++

c++ - visual - CreateProcess desde el búfer de memoria



winapi lpcstr (6)

Puedo usar CreateProcess para iniciar un EXE. Quiero tener el contenido de un EXE en un búfer de memoria y hacer CreateProcess (o un equivalente) en él sin tener que escribirlo en un archivo. ¿Hay alguna forma de hacer eso?

La historia de fondo: hacemos juegos. Enviamos un EXE simple a nuestros distribuidores, que luego lo envuelven con su DRM favorito y se lo venden a sus usuarios. Ha habido casos en que los usuarios encuentran bloqueos. La mayoría de los fallos demoran 5 minutos en solucionarse, pero el parche debe pasar por el distribuidor y puede llevar varios días, incluso semanas. No puedo simplemente enviar el EXE parcheado a los jugadores porque no tendría el DRM del distribuidor. Estoy pensando en distribuir el juego real EXE dentro de un archivo de datos encriptado, así que lo que se envuelve (el EXE externo) simplemente descifra y ejecuta el EXE real. De esta forma podría distribuir de manera segura una solución sin deshabilitar el DRM.


¿Por qué necesitas crear un nuevo proceso? Pensé que podrías ejecutar en el contexto del proceso que realiza el desempaquetado / descifrado.


En realidad es bastante fácil. Se ha descrito una técnica similar en un documento que leí hace 3 años.

Windows le permite llamar a la función CreateProcess con el indicador CREATE_SUSPENDED , que le dice a la API que mantenga el proceso suspendido hasta que se ResumeThread función ResumeThread .

Esto nos da tiempo para captar el contexto del hilo suspendido utilizando la función GetThreadContext , luego el registro EBX mantendrá un puntero a la estructura PBE (Process Enviroment Block) , que necesitamos para determinar la dirección base.

Desde el diseño de la estructura PBE, podemos ver que ImageBaseAddress se almacena en el octavo byte, por lo tanto, [EBX + 8] nos dará la dirección base real del proceso que se suspende.

Ahora necesitamos el EXE en memoria y alinearnos apropiadamente si la alineación de la memoria y el EXE en la memoria difieren.

Si la dirección base del proceso suspendido y el exe en memoria coinciden, más si el tamaño de la imagen del exe en la memoria es menor o igual que el proceso suspendido, simplemente podemos usar WriteProcessMemory para escribir el exe en memoria en el espacio de la memoria del proceso suspendido

Pero si las condiciones antes mencionadas no se cumplieron, necesitamos un poco más de magia. Primero, debemos desasignar la imagen original usando ZwUnmapViewOfSection , y luego asignar suficiente memoria usando VirtualAllocEx dentro del espacio de memoria del proceso suspendido. Ahora necesitamos escribir el exe en memoria en el espacio de memoria del proceso suspendido usando la función WriteProcessMemory .

A continuación, aplique un parche a la BaseAddress del exe en la memoria en el PEB-> ImageBaseAddress del proceso suspendido.

El registro EAX del contexto del hilo contiene la dirección de EntryPoint, que necesitamos reescribir con la dirección de EntryPoint del exe en la memoria. Ahora tenemos que guardar el contexto de subproceso alterado utilizando la función SetThreadContext .

Voila! ¡Estamos listos para ResumeThread función ResumeThread en el proceso suspendido para ejecutarlo!


Lo que quiere hacer requiere NtCreateProcess, pero no está documentado y, por lo tanto, es frágil. Este libro aparentemente cubre su uso.

Tal vez podrías construir un sistema de parches? Por ejemplo, en el lanzamiento, el programa comprueba si hay DLL parche en el mismo directorio y lo carga si existe.


Lo que quiere se puede lograr con algo llamado "Packer". En realidad, es posible lanzar un exe desde la memoria, pero es mucho más difícil que un empacador;)

Uno de los empacadores más conocidos es UPX (google it). Hay herramientas para descifrarlo, pero al menos debería darle un punto de partida para trabajar. También estoy bastante seguro de que UPX es de código abierto.


Mira BoxedAppSDK

Es compatible con el lanzamiento de exe desde un búfer de memoria.

Espero eso ayude.


Puede compilar el juego como un archivo DLL y colocar el archivo DLL en el archivo de datos cifrados. Se puede cargar una DLL desde la memoria sin escribirla en el disco. Consulte este tutorial (con un código de muestra al final): cargando un archivo DLL desde la memoria