我可以使用CreateProcess来启动EXE.我希望在内存缓冲区中包含EXE的内容,并在其上执行CreateProcess(或等效),而不必将其写入文件.有没有办法做到这一点?
背景故事:我们制作游戏.我们向经销商发送一个简单的EXE,然后使用他们喜欢的DRM将其包装并出售给他们的用户.曾经有过用户发现崩溃的情况.大多数崩溃需要5分钟才能解决,但补丁必须经过分销商,可能需要几天甚至几周.我不能将修补后的EXE发送给玩家,因为它没有经销商的DRM.我正在考虑将实际游戏EXE分发到加密数据文件中,这样包装(外部EXE)就会解密并启动真正的EXE.这样我就可以在不禁用DRM的情况下安全地分发修复程序.
这实际上非常简单.我在3年前读过的一篇论文中描述了类似的技术.
Windows允许您使用CREATE_SUSPENDED标志调用CreateProcess函数,该标志告诉API在调用ResumeThread函数之前保持进程暂停.
这使我们有时间使用GetThreadContext函数获取挂起线程的上下文,然后EBX寄存器将保存指向PBE(进程环境块)结构的指针,我们需要确定基址.
从PBE结构的布局我们可以看到ImageBaseAddress存储在第8个字节,因此[EBX + 8]将给出我们暂停的进程的实际基地址.
现在我们需要内存中的EXE并且如果内存和内存中EXE的对齐不同,则进行适当的对齐.
如果挂起的进程和内存中的exe的基地址匹配,加上如果内存中的exe的imageSize小于或等于挂起的进程,我们可以简单地使用WriteProcessMemory将内存中的exe写入到内存空间中.暂停过程.
但如果不满足上述条件,我们需要更多的魔力.首先,我们需要使用ZwUnmapViewOfSection取消原始图像的映射,然后使用VirtualAllocEx在挂起的进程的内存空间中分配足够的内存.现在我们需要使用WriteProcessMemory函数将内存中的exe写入挂起进程的内存空间.
接下来,将内存中exe的BaseAddress修补到挂起进程的PEB-> ImageBaseAddress中.
线程上下文的EAX寄存器保存EntryPoint地址,我们需要使用内存中exe的EntryPoint地址重写.现在我们需要使用SetThreadContext函数保存更改的线程上下文.
瞧!我们准备在挂起的进程上调用ResumeThread函数来执行它!
您可以将游戏编译为DLL并将DLL放入加密数据文件中.可以从内存加载DLL而无需将其写入磁盘.请参阅本教程(最后带有示例代码):从内存加载DLL