CreateRemoteThread function

Expand
9 out of 13 rated this helpful - Rate this topic

CreateRemoteThread function

Applies to: desktop apps only

Creates a thread that runs in the virtual address space of another process.

Use the CreateRemoteThreadEx function to create a thread that runs in the virtual address space of another processor and optionally specify extended attributes.

Syntax

HANDLE WINAPI 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
);

Parameters

hProcess [in]

A handle to the process in which the thread is to be created. The handle must have the PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ access rights, and may fail without these rights on certain platforms. For more information, see Process Security and Access Rights.

lpThreadAttributes [in]

A pointer to a SECURITY_ATTRIBUTES structure that specifies a security descriptor for the new thread and determines whether child processes can inherit the returned handle. If lpThreadAttributes is NULL, the thread gets a default security descriptor and the handle cannot be inherited. The access control lists (ACL) in the default security descriptor for a thread come from the primary token of the creator.

Windows XP:  The ACLs in the default security descriptor for a thread come from the primary or impersonation token of the creator. This behavior changed with Windows XP with SP2 and Windows Server 2003.
dwStackSize [in]

The initial size of the stack, in bytes. The system rounds this value to the nearest page. If this parameter is 0 (zero), the new thread uses the default size for the executable. For more information, see Thread Stack Size.

lpStartAddress [in]

A pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. For more information, see ThreadProc.

lpParameter [in]

A pointer to a variable to be passed to the thread function.

dwCreationFlags [in]

The flags that control the creation of the thread.

ValueMeaning
0

The thread runs immediately after creation.

CREATE_SUSPENDED
0x00000004

The thread is created in a suspended state, and does not run until the ResumeThread function is called.

STACK_SIZE_PARAM_IS_A_RESERVATION
0x00010000

The dwStackSize parameter specifies the initial reserve size of the stack. If this flag is not specified, dwStackSize specifies the commit size.

 

lpThreadId [out]

A pointer to a variable that receives the thread identifier.

If this parameter is NULL, the thread identifier is not returned.

Return value

If the function succeeds, the return value is a handle to the new thread.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Note that CreateRemoteThread may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLL).

Remarks

The CreateRemoteThread function causes a new thread of execution to begin in the address space of the specified process. The thread has access to all objects that the process opens.

Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process.

The new thread handle is created with full access to the new thread. If a security descriptor is not provided, the handle may be used in any function that requires a thread object handle. When a security descriptor is provided, an access check is performed on all subsequent uses of the handle before access is granted. If the access check denies access, the requesting process cannot use the handle to gain access to the thread.

If the thread is created in a runnable state (that is, if the CREATE_SUSPENDED flag is not used), the thread can start running before CreateThread returns and, in particular, before the caller receives the handle and identifier of the created thread.

The thread is created with a thread priority of THREAD_PRIORITY_NORMAL. Use the GetThreadPriority and SetThreadPriority functions to get and set the priority value of a thread.

When a thread terminates, the thread object attains a signaled state, which satisfies the threads that are waiting for the object.

The thread object remains in the system until the thread has terminated and all handles to it are closed through a call to CloseHandle.

The ExitProcess, ExitThread, CreateThread, CreateRemoteThread functions, and a process that is starting (as the result of a CreateProcess call) are serialized between each other within a process. Only one of these events occurs in an address space at a time. This means the following restrictions hold:

  • During process startup and DLL initialization routines, new threads can be created, but they do not begin execution until DLL initialization is done for the process.
  • Only one thread in a process can be in a DLL initialization or detach routine at a time.
  • ExitProcess returns after all threads have completed their DLL initialization or detach routines.

A common use of this function is to inject a thread into a process that is being debugged to issue a break. However, this use is not recommended, because the extra thread is confusing to the person debugging the application and there are several side effects to using this technique:

  • It converts single-threaded applications into multithreaded applications.
  • It changes the timing and memory layout of the process.
  • It results in a call to the entry point of each DLL in the process.

Another common use of this function is to inject a thread into a process to query heap or other process information. This can cause the same side effects mentioned in the previous paragraph. Also, the application can deadlock if the thread attempts to obtain ownership of locks that another thread is using.

Requirements

Minimum supported client

Windows XP

Minimum supported server

Windows Server 2003

Header

WinBase.h (include Windows.h)

Library

Kernel32.lib

DLL

Kernel32.dll

See also

CloseHandle
CreateProcess
CreateRemoteThreadEx
CreateThread
ExitProcess
ExitThread
GetThreadPriority
Process and Thread Functions
ResumeThread
SECURITY_ATTRIBUTES
SetThreadPriority
ThreadProc
Threads

 

 

Send comments about this topic to Microsoft

Build date: 5/5/2012

Did you find this helpful?
(1500 characters remaining)
Community Additions ADD
Terminal session separation breaks existing code

The description:

Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process.

from the remarks section seems to apply mainly from Vista onwards. While privileged processes (such as services) could create remote threads in other processes in Windows 2000, XP, 2003 without problems. In Windows Vista and later the function fails, returning NULL and the last error is being set to ERROR_NOT_ENOUGH_MEMORY.

The behavior may exist pre-Vista if you try to create a remote thread within a different terminal session, but services are not yet separated in the same way they're now on Vista on these previous OS versions.

Workarounds (with similar functionality) would be to:

  • Create a process by duplicating the token of the remote process and then creating a new process that inherits the properties from that duplicated token using CreateProcessAsUser().
  • Debug the remote process.
  • Write relocatable code that you can inject into a running thread in the target application by suspending the target thread, modifying the thread context to point to your code and make sure the context will be the same after returning from your code and then resuming the remote thread at your code.
  • Use undocumented native APIs (not recommended). However, this approach is limited, because the Win32 subsystem does not get informed of the thread creation if you use one of the functions from NTDLL.
6/16/2008