免责声明:这些 API 的实现可能会在 Windows 版本之间发生变化。我将在我的回答中引用 32 位 Windows XP SP3。您的结果可能会有所不同。
创建线程的工作原理
在调用之前必须初始化三个结构NtCreateThread:
INITIAL_TEB: 包含指向堆栈区域的指针
CONTEXT: 包含寄存器状态
OBJECT_ATTRIBUTES: 包含线程的安全属性
:我在执行,有处理这些任务的专用功能BaseCreateStack,BaseInitializeContext和BaseFormatObjectAttributes分别。
BaseInitializeContext但是,该函数是您感兴趣的函数,因为新线程将从CONTEXT.Eip.
有趣的是,BaseInitializeContext将线程的起始地址(即新进程的入口点)放入CONTEXT.Eax. 并CONTEXT.Eip设置为 的地址BaseProcessStartThunk。(由于kernel32在每个进程中都映射到相同的地址,我们知道这也将BaseProcessStartThunk是其他进程中的地址)
因此,当我们打电话NtCreateThread,我们在开始在其他进程中一个新的线程BaseProcessStartThunk与eax相同的入口点。
BaseProcessStartThunk从 register 保存起始地址eax。它通过NtSetInformationThread使用ThreadInformationClassof调用在内部设置起始地址ThreadQuerySetWin32StartAddress(请参阅 参考资料ntddk.h)。然后调用起始地址。最后,当线程返回时,它调用ExitThread.
可执行映像如何映射到新进程中
如果您想知道流程是首先创建的,我们必须返回几个步骤。
首先,新进程可执行文件的句柄通过NtOpenFile.
文件句柄用于创建一个部分经由对象NtCreateSection。
调用NtQuerySectionwithInformationClass设置为SectionImageInformation。这将解析 section 对象并填充一个SECTION_IMAGE_INFORMATION结构,其中最显着的是包含字段的EntryPoint字段。这就是新进程的入口点是如何确定的。
最终,NtCreateProcessEx被调用,给定节句柄 fromNtCreateSection作为参数。这就是实际创建新进程并将可执行映像映射到新进程的地址空间等的内容。 NtCreateProcessEx还提供了我们传递NtCreateThread给创建新线程的进程句柄。