Создаю процесс с помощью CreateProcess()
с помощью CREATE_SUSPENDED
, а затем создайте небольшой фрагмент кода внутри удаленного процесса для загрузки DLL и вызова функции (экспортируемой этой DLL) с использованием VirtualAllocEx()
(с ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE
), WriteProcessMemory()
, затем позвоните FlushInstructionCache()
на этом патче памяти с кодом.Является ли первый поток, который запускает внутри процесса Win32 «основной поток»? Необходимо понять семантику
После этого я вызываю 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, чтобы посмотреть, что происходит, и я мог проверить мои наблюдения раньше. Введенный код не терпит крах или что-то еще, вместо этого я вижу, что если я не буду ждать, пока поток не завершится, я закрою программу, в которую был введен код. Я имею в виду, следует ли отложить или что-то вызов CloseHandle(hRemoteThread)
...
Edit + 1: это не CloseHandle()
. Если я оставлю это только для теста, поведение не изменится при ожидании завершения потока.
, пожалуйста, объясните последний пункт. Я ** знаю **, это вызовет проблемы, предполагающие, что DLL загружается в том же базовом addr. в моем процессе, как в удаленном процессе, поэтому явная старая «LoadLibrary», переданная в «CreateRemoteThread», не будет летать - вот почему так. Кроме того, когда основной поток приостанавливается после создания процесса, библиотеки DLL уже загружены, хотя я не уверен, был ли их DllMain' уже вызван. Но это не имеет значения, если я не буду называть свою «LoadLibrary» после того, как основной поток начнет запускаться и может находиться внутри самого «DllMain». Thx – 0xC0000022L
Windows обычно не увидит вызов «LoadLibrary» до инициализации статических DLL. Это может вызвать проблемы. В качестве альтернативы, если статические DllMains вызываются в вашем потоке, это будет путать библиотеки DLL, которые предполагают, что поток инициализации будет длиться всю жизнь процесса, что обычно верно. Как я уже сказал, я размышляю, но, похоже, есть много возможностей для поломки. – arx
Хм, хорошо. Как я могу проверить, были ли вызваны «DllMain's» из других DLL? Из прошлого опыта я знаю, что я даже не смог бы назвать 'CreateRemoteProcess' успешным, если только' kernel32.dll' не был инициализирован, и установлено соединение с Win32. Однако вызов 'CreateRemoteProcess' ** здесь ** успешно. По-прежнему возможно, что вы правы, но я так не думаю в данный момент. – 0xC0000022L