CreateRemoteThread 函数 (processthreadsapi.h)

创建在另一个进程的虚拟地址空间中运行的线程。

使用 CreateRemoteThreadEx 函数创建在另一个进程的虚拟地址空间中运行的线程,并选择性地指定扩展属性。

语法

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

参数

[in] hProcess

要在其中创建线程的进程句柄。 句柄必须具有 PROCESS_CREATE_THREADPROCESS_QUERY_INFORMATIONPROCESS_VM_OPERATIONPROCESS_VM_WRITEPROCESS_VM_READ 访问权限,并且在某些平台上没有这些权限可能会失败。 有关详细信息,请参阅 进程安全性和访问权限

[in] lpThreadAttributes

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

Windows XP:线程的默认安全描述符中的 ACL 来自创建者的主令牌或模拟令牌。 此行为随 SP2 和 Windows Server 2003 的 Windows XP 发生更改。

[in] dwStackSize

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

[in] lpStartAddress

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

[in] lpParameter

指向要传递给线程函数的变量的指针。

[in] dwCreationFlags

控制线程创建的标志。

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

[out] lpThreadId

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

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

返回值

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

如果函数失败,则返回值 NULL。 若要获取扩展的错误信息,请调用 GetLastError

请注意,即使 lpStartAddress 指向数据、代码或无法访问,CreateRemoteThread 也可能成功。 如果线程运行时起始地址无效,则会发生异常,线程将终止。 由于启动地址无效,线程终止作为线程进程的错误退出进行处理。 此行为类似于 CreateProcess的异步性质,即使进程引用无效或缺少动态链接库(DLL),也会创建该进程。

言论

CreateRemoteThread 函数会导致在指定进程的地址空间中开始执行的新线程。 线程有权访问进程打开的所有对象。

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

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

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

该线程是使用线程优先级 THREAD_PRIORITY_NORMAL创建的。 使用 GetThreadPrioritySetThreadPriority 函数获取和设置线程的优先级值。

当线程终止时,线程对象将达到信号状态,该状态满足等待对象的线程。

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

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

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

要求

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

另请参阅

CloseHandle

CreateProcess

CreateRemoteThreadEx

CreateThread

ExitProcess

ExitThread

GetThreadPriority

进程和线程函数

ResumeThread

SECURITY_ATTRIBUTES

SetThreadPriority

ThreadProc

线程