Это на самом деле довольно легко. Подобная техника была описана в статье, которую я прочитал 3 года назад.
Windows позволяет вам вызывать функцию CreateProcess с флагом CREATE_SUSPENDED , который сообщает API о необходимости приостановить процесс до вызова функции ResumeThread .
Это дает нам время для захвата контекста приостановленного потока с помощью функции GetThreadContext , тогда в регистре EBX будет храниться указатель на PBE (Block Enviroment Block) структуру, которая нам нужна определить базовый адрес.
Из структуры структуры PBE мы можем видеть, что ImageBaseAddress хранится в 8-м байте, поэтому [EBX + 8] даст нам фактический базовый адрес приостановленного процесса.
Теперь нам нужен EXE-файл в памяти и выполняется выравнивание, если выравнивание EXE-файла и памяти отличается.
Если базовый адрес приостановленного процесса и исполняемого файла в памяти совпадает, плюс если размер изображения исполняемого файла в памяти меньше или равен приостановленному процессу, мы можем просто использовать WriteProcessMemory для записи в -памяти памяти в пространство приостановленного процесса.
Но если вышеупомянутые условия не были выполнены, нам нужно немного больше магии.
Сначала нам нужно удалить исходное изображение, используя ZwUnmapViewOfSection , а затем выделить достаточно памяти, используя VirtualAllocEx в пространстве памяти приостановленного процесса. Теперь нам нужно записать исполняемый файл в памяти в пространство приостановленного процесса, используя функцию WriteProcessMemory .
Затем установите исправление BaseAddress исполняемого файла в памяти в PEB-> ImageBaseAddress приостановленного процесса.
Регистр EAX контекста потока содержит адрес EntryPoint, который нам нужно переписать с адресом EntryPoint исполняемого файла в памяти. Теперь нам нужно сохранить измененный контекст потока, используя функцию SetThreadContext .
Вуаля! Мы готовы вызвать функцию ResumeThread в приостановленном процессе, чтобы выполнить ее!