2

我使用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(). 如果我只是为了测试而忽略它,那么在等待线程完成时行为不会改变。

4

2 回答 2

1

第一个运行的线程并不特别。

例如,创建一个控制台应用程序,该应用程序创建一个挂起的线程并终止原始线程(通过调用 ExitThread)。此过程永远不会终止(无论如何在 Windows 7 上)。

或者让新线程等待五秒钟然后退出。正如预期的那样,该进程将存活五秒钟并在辅助线程终止时退出。

我不知道你的例子发生了什么。避免竞争的最简单方法是让新线程恢复原来的线程。

现在推测,我确实想知道您正在做的事情是否无论如何都不会引起问题。例如,DllMain对隐式加载的 DLL 的所有调用会发生什么情况?它们是否意外发生在错误的线程上,是否被跳过,或者它们是否被推迟到您的代码运行并且主线程启动之后?

于 2012-03-14T03:56:57.023 回答
0

main具有(或等效)函数调用ExitProcess(显式或在其运行时库中)的线程很有可能。ExitProcess,好吧,退出整个进程,包括杀死所有线程。由于主线程不知道您注入的代码,因此它不会等待它完成。

我不知道有什么好方法可以让主线程等待你的完成......

于 2012-03-14T03:20:35.897 回答