問題描述
我可以使用 CreateProcess 來啟動一個 EXE.我想將 EXE 的內容保存在內存緩沖區中,并在其上執行 CreateProcess(或等效程序),而不必將其寫入文件.有沒有辦法做到這一點?
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?
背景故事:我們制作游戲.我們將一個普通的 EXE 發送給我們的經銷商,然后他們使用他們最喜歡的 DRM 將其打包并出售給他們的用戶.曾有用戶發現崩潰的情況.大多數崩潰需要 5 分鐘才能修復,但補丁必須通過分銷商,可能需要幾天甚至幾周的時間.我不能只將修補后的 EXE 發送給玩家,因為它沒有經銷商的 DRM.我正在考慮將真正的游戲 EXE 分發到一個加密的數據文件中,這樣被包裝的內容(外部 EXE)就可以解密并啟動真正的 EXE.這樣我就可以在不禁用 DRM 的情況下安全地分發修復程序.
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.
推薦答案
其實很簡單.類似的技術在我 3 年前讀過的一篇論文中有所描述.
It's actually quite easy. Similar technique has been described in a paper I read like 3 years ago.
Windows 允許您使用 調用 CreateProcess 函數CREATE_SUSPENDED 標志,它告訴 API 保持進程掛起,直到 ResumeThread 函數被調用.
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.
這讓我們有時間使用 獲取掛起線程的上下文GetThreadContext 函數,那么 EBX 寄存器將持有一個指向 PBE(Process Enviroment Block)結構,我們需要用它來確定基地址.
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.
從PBE結構的布局可以看出ImageBaseAddress存儲在第8個字節,因此[EBX+8]會給出被掛起進程的實際基地址.
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.
現在我們需要內存中的EXE,如果內存和內存中EXE的對齊方式不同,則進行適當的對齊.
Now we need the in-memory EXE and do appropiate alignment if the alignment of memory and in-memory EXE differs.
如果掛起進程和內存中exe的基地址匹配,并且內存中exe的imageSize小于或等于掛起進程'我們可以簡單地使用WriteProcessMemory 將內存中的 exe 寫入掛起進程的內存空間.
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.
但如果上述條件不滿足,我們需要更多的魔法.首先,我們需要使用 ZwUnmapViewOfSection 取消映射原始圖像,然后分配在掛起進程的內存空間內使用 VirtualAllocEx 獲得足夠的內存.現在我們需要使用 WriteProcessMemory 函數.
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.
接下來,將內存中exe的BaseAddress補丁到掛起進程的PEB->ImageBaseAddress中.
Next, patch the BaseAddress of the in-memory exe into the PEB->ImageBaseAddress of the suspended process.
線程上下文的EAX寄存器保存著EntryPoint地址,我們需要用內存中exe的EntryPoint地址重寫它.現在我們需要使用 SetThreadContext 函數保存更改的線程上下文.
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.
瞧!我們已準備好調用 ResumeThread 函數掛起的進程來執行它!
Voila! We're ready to call the ResumeThread function on the suspended process to execute it!
這篇關于從內存緩沖區創建進程的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!