CreateProcess из буфера памяти

Я могу использовать CreateProcess для запуска EXE. Я хочу иметь содержимое EXE в буфере памяти и сделать CreateProcess (или эквивалент) на нем без необходимости записывать его в файл. Есть ли способ сделать это?

Предыстория: мы делаем игры. Мы отправляем простой дистрибутив EXE нашим дистрибьюторам, которые затем оборачивают его, используя свои любимые DRM, и продают его своим пользователям. Были случаи, когда пользователи находили сбои. Для устранения большинства сбоев требуется 5 минут, но патч должен пройти через дистрибьютора, и это может занять несколько дней, даже недель. Я не могу просто отправить исправленный EXE-файл игрокам, потому что у него не будет DRM дистрибьютора. Я думаю о том, чтобы распространять настоящий EXE-файл игры в зашифрованном файле данных, чтобы то, что было упаковано (внешний EXE-файл), просто расшифровывало и запускало настоящий EXE-файл. Таким образом, я мог бы безопасно распространить исправление, не отключая DRM.

6 ответов

Это на самом деле довольно легко. Подобная техника была описана в статье, которую я прочитал 3 года назад.

Windows позволяет вам вызывать функцию CreateProcess с флагом CREATE_SUSPENDED, который говорит API о необходимости приостановить процесс до вызова функции ResumeThread.

Это дает нам время для захвата контекста приостановленного потока с помощью функции GetThreadContext, а затем в регистре EBX будет храниться указатель на структуру PBE(блок обработки процесса), которая нам необходима для определения базового адреса.

Из макета структуры PBE мы можем видеть, что ImageBaseAddress хранится в 8-м байте, поэтому [EBX+8] даст нам фактический базовый адрес приостановленного процесса.

Теперь нам нужен EXE-файл в памяти и выполняется соответствующее выравнивание, если выравнивание EXE-файла и памяти отличается.

Если базовый адрес приостановленного процесса и исполняемого файла в памяти совпадает, плюс если imageSize исполняемого файла в памяти меньше или равен приостановленному процессу, мы можем просто использовать WriteProcessMemory для записи исполняемого файла в памяти в пространство памяти приостановленный процесс.

Но если вышеупомянутые условия не были выполнены, нам нужно немного больше магии. Сначала нам нужно отменить отображение исходного изображения с помощью ZwUnmapViewOfSection, а затем выделить достаточно памяти, используя VirtualAllocEx, в пространстве памяти приостановленного процесса. Теперь нам нужно записать исполняемый файл в памяти в пространство приостановленного процесса, используя функцию WriteProcessMemory.

Затем вставьте BaseAddress исполняемого файла в памяти в PEB->ImageBaseAddress приостановленного процесса.

Регистр EAX контекста потока содержит адрес EntryPoint, который нам нужно переписать с адресом EntryPoint исполняемого файла в памяти. Теперь нам нужно сохранить измененный контекст потока, используя функцию SetThreadContext.

Вуаля! Мы готовы вызвать функцию ResumeThread в приостановленном процессе, чтобы выполнить ее!

Вы можете скомпилировать игру как DLL и поместить DLL в зашифрованный файл данных. DLL может быть загружена из памяти без записи на диск. Пожалуйста, смотрите этот учебник (с примером кода в конце): Загрузка DLL из памяти

Для того, что вы хотите сделать, требуется NtCreateProcess, но он недокументирован и поэтому хрупок. Эта книга, по- видимому, охватывает его использование.

Возможно, вы могли бы создать систему исправлений? Например, при запуске программа проверяет наличие исправления DLL в том же каталоге и загружает его, если он существует.

Зачем вам нужно создавать новый процесс? Я бы подумал, что вы можете запустить в контексте процесса, который выполняет распаковку / дешифрование.

То, что вы хотите, может быть достигнуто с помощью так называемого "упаковщика". На самом деле запуск exe из памяти может быть возможен, но это намного сложнее, чем упаковщик;)

Одним из самых известных упаковщиков является UPX (Google it). Существуют инструменты для его расшифровки, но он должен по крайней мере дать вам отправную точку для работы с ним. Я также уверен, что UPX с открытым исходным кодом.

Посмотрите на BoxedAppSDK

Он поддерживает запуск exe из буфера памяти.

Надеюсь, поможет.

Другие вопросы по тегам