CreateRemoteThreadEx 函数 (processthreadsapi.h)

创建一个线程,该线程在另一个进程的虚拟地址空间中运行,并选择性地指定扩展属性,例如处理器组相关性。

语法

HANDLE CreateRemoteThreadEx(
  [in]            HANDLE                       hProcess,
  [in, optional]  LPSECURITY_ATTRIBUTES        lpThreadAttributes,
  [in]            SIZE_T                       dwStackSize,
  [in]            LPTHREAD_START_ROUTINE       lpStartAddress,
  [in, optional]  LPVOID                       lpParameter,
  [in]            DWORD                        dwCreationFlags,
  [in, optional]  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
  [out, optional] LPDWORD                      lpThreadId
);

参数

[in] hProcess

要在其中创建线程的进程句柄。 句柄必须具有PROCESS_CREATE_THREAD、PROCESS_QUERY_INFORMATION、PROCESS_VM_OPERATION、PROCESS_VM_WRITE和PROCESS_VM_READ访问权限。 在 Windows 10版本 1607 中,代码必须获取新句柄的这些访问权限。 但是,从 Windows 10 版本 1703 开始,如果新句柄有权获得这些访问权限,系统会为你获取这些访问权限。 有关详细信息,请参阅 进程安全和访问权限

[in, optional] lpThreadAttributes

指向 SECURITY_ATTRIBUTES 结构的指针,该结构指定新线程的安全描述符,并确定子进程是否可以继承返回的句柄。 如果 lpThreadAttributes 为 NULL,则线程将获取默认安全描述符,并且无法继承句柄。 访问控制在来自创建者主令牌的线程的默认安全描述符中列出 (ACL) 。

[in] dwStackSize

堆栈的初始大小(以字节为单位)。 系统将此值舍入到最近的页。 如果此参数为 0 (零) ,则新线程将使用可执行文件的默认大小。 有关详细信息,请参阅 线程堆栈大小

[in] lpStartAddress

指向 LPTHREAD_START_ROUTINE要由 线程执行的应用程序定义函数的指针,表示远程进程中线程的起始地址。 函数必须存在于远程进程中。 有关详细信息,请参阅 ThreadProc

[in, optional] lpParameter

指向要传递给 lpStartAddress 指向的线程函数的变量的指针。 此参数可以为 NULL。

[in] dwCreationFlags

控制线程创建的标志。

含义
0
线程在创建后立即运行。
CREATE_SUSPENDED
0x00000004
线程以挂起状态创建,在调用 ResumeThread 函数之前不会运行。
STACK_SIZE_PARAM_IS_A_RESERVATION
0x00010000
dwStackSize 参数指定堆栈的初始保留大小。 如果未指定此标志, dwStackSize 将指定提交大小。

[in, optional] lpAttributeList

包含新线程的其他参数的属性列表。 此列表由 InitializeProcThreadAttributeList 函数创建。

[out, optional] lpThreadId

指向接收线程标识符的变量的指针。

如果此参数为 NULL,则不返回线程标识符。

返回值

如果函数成功,则返回值是新线程的句柄。

如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

注解

CreateRemoteThreadEx 函数会导致新的执行线程在指定进程的地址空间中开始。 线程有权访问进程打开的所有对象。 lpAttribute 参数可用于指定扩展属性,例如新线程的处理器组相关性。 如果 lpAttribute 为 NULL,则函数的行为与 CreateRemoteThread 相同。

在Windows 8之前,终端服务根据设计隔离每个终端会话。 因此,如果目标进程与调用进程位于不同的会话中, CreateRemoteThread 将失败。

创建新线程句柄时具有对新线程的完全访问权限。 如果未提供安全描述符,则句柄可用于任何需要线程对象句柄的函数中。 提供安全描述符时,在授予访问权限之前,对句柄的所有后续使用执行访问检查。 如果访问检查拒绝访问,则请求进程无法使用句柄获取对线程的访问权限。

如果线程是在可运行状态下创建的, (也就是说,如果未) 使用CREATE_SUSPENDED标志,则线程可以在 CreateThread 返回之前开始运行,尤其是在调用方收到所创建线程的句柄和标识符之前。

线程的创建优先级为 THREAD_PRIORITY_NORMAL。 若要获取和设置线程的优先级值,请使用 GetThreadPrioritySetThreadPriority 函数。

当线程终止时,线程对象会获得一个信号状态,该状态满足正在等待该对象的线程。

线程对象将保留在系统中,直到线程终止,并且通过调用 CloseHandle 关闭其所有句柄。

ExitProcessExitThreadCreateThreadCreateRemoteThread 函数以及由于 CreateProcess 调用 () 而启动的进程在进程中相互序列化。 一次只有其中一个事件在地址空间中发生。 这意味着存在以下限制:

  • 在进程启动和 DLL 初始化例程期间,可以创建新线程,但在为进程完成 DLL 初始化之前,这些线程不会开始执行。
  • 一个进程中一个线程一次只能位于 DLL 初始化或分离例程中。
  • ExitProcess 在所有线程完成其 DLL 初始化或分离例程后返回。
此函数的常见用途是将线程注入正在调试以发出中断的进程。 但是,不建议使用此用法,因为额外的线程会让调试应用程序的人员感到困惑,并且使用此技术有几个副作用:
  • 它将单线程应用程序转换为多线程应用程序。
  • 它会更改进程的计时和内存布局。
  • 它会导致调用进程中每个 DLL 的入口点。
此函数的另一个常见用途是将线程注入进程以查询堆或其他进程信息。 这可能会导致上一段落中提到的相同副作用。 此外,如果线程尝试获取另一个线程正在使用的锁的所有权,应用程序可能会死锁。

要求

要求
最低受支持的客户端 Windows 7 [仅限桌面应用]
最低受支持的服务器 Windows Server 2008 R2 [仅限桌面应用]
目标平台 Windows
标头 processthreadsapi.h (包括 Windows Server 2008 Windows Server 2008 R2 上的 Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

另请参阅

CreateRemoteThread