我使用CreateProcess()with创建了一个进程CREATE_SUSPENDED,然后继续在远程进程中创建一小块代码来加载一个 DLL 并调用一个函数(由该 DLL 导出),使用VirtualAllocEx()(with ..., MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE), WriteProcessMemory(),然后调用FlushInstructionCache()该内存块与代码。
之后我调用CreateRemoteThread()调用该代码,为我创建一个hRemoteThread. 我已验证远程代码按预期工作。注意:此代码仅返回,它不调用除LoadLibrary()and之外的任何 API 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返回时仍然暂停。
这发生在 32 位 Windows XP SP3 上。
编辑:我刚刚尝试了 Sysinternals Process Monitor 来查看发生了什么,我可以验证我之前的观察结果。注入的代码不会崩溃或任何事情,相反,我会看到,如果我不等待线程,它不会在我关闭注入代码的程序之前退出。我在考虑是否CloseHandle(hRemoteThread)应该推迟致电或其他什么...
编辑+1:不是CloseHandle(). 如果我只是为了测试而忽略它,那么在等待线程完成时行为不会改变。