Я создаю процесс, используя CreateProcess()
с CREATE_SUSPENDED
, а затем продолжаю создавать небольшой фрагмент кода внутри удаленного процесса для загрузки DLL и вызова функции (экспортируемой этой DLL), используя VirtualAllocEx()
(с ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE
), WriteProcessMemory()
, затем вызовите FlushInstructionCache()
для этого патча памяти с кодом.
После этого я вызываю CreateRemoteThread()
, чтобы вызвать этот код, создав меня hRemoteThread
. Я проверил, что удаленный код работает как задумано. Примечание: этот код просто возвращает, он не вызывает никаких API, кроме LoadLibrary()
и GetProcAddress()
, с последующим вызовом экспортированной функции-заглушки, которая в настоящее время просто возвращает значение, которое затем будет передано как выход из состояния потока.
Теперь пришло странное наблюдение: помните, что PROCESS_INFORMATION::hThread
все еще приостановлен. Когда я просто игнорирую код выхода hRemoteThread
и также не жду, пока он выйдет, все идет хорошо. Процедура, которая вызывает CreateRemoteThread()
, возвращает значение, PROCESS_INFORMATION::hThread
возобновляется, и (удаленная) программа фактически запускается.
Однако, если я позвоню WaitForSingleObject(hRemoteThread, INFINITE)
или сделаю следующее (что имеет тот же эффект):
DWORD exitCode = STILL_ACTIVE;
while(STILL_ACTIVE == exitCode)
{
Sleep(500);
if(!GetExitCodeThread(hRemoteThread, &exitCode))
break;
}
, за которым следует CloseHandle()
, это приводит к завершению hRemoteThread
до возобновления PROCESS_INFORMATION::hThread
, и процесс просто "исчезает". Достаточно, чтобы hRemoteThread
каким-то образом завершился без PROCESS_INFORMATION::hThread
, чтобы остановить процесс.
Это выглядит подозрительно, как состояние гонки, поскольку при определенных обстоятельствах hRemoteThread
может все же быть быстрее, и процесс, вероятно, все равно "исчезнет", даже если я оставлю код как есть.
Означает ли это, что первый поток, который запускается внутри процесса, автоматически становится основным потоком и что для этого основного потока существуют специальные правила?
У меня всегда было впечатление, что процесс завершается, когда умирает его последний поток, а не когда конкретный поток умирает.
Также обратите внимание: здесь нет никакого вызова ExitProcess()
, участвующего здесь каким-либо образом, потому что hRemoteThread
просто возвращается, а PROCESS_INFORMATION::hThread
все еще приостановлено, когда я жду, пока hRemoteThread
вернется.
Это происходит в Windows XP SP3, 32 бита.
Редактировать: Я только что попробовал Sysinternals Process Monitor, чтобы увидеть, что происходит, и я мог проверить свои наблюдения ранее. Внедренный код не аварийно завершает работу или что-то еще, вместо этого я вижу, что если я не жду потока, он не завершает работу, прежде чем закрыть программу, в которую был введен код. Я думаю, стоит ли отложить вызов CloseHandle(hRemoteThread)
или что-то в этом роде ...
Редактировать + 1: это не CloseHandle()
. Если я оставлю это только для теста, поведение не изменится при ожидании завершения потока.