|  | 
	
		|  | 
	
		| Remote Thread Execution in System Process using NtCreateThreadEx 
		for Vista & Windows7 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
	
		
	
		 |  | 
		
	
		|  | 
	
		|  | 
	
		|  | 
	
	
		|  | 
	
	
		
	
		 |  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
		 |  | 
	
		| Windows provides API function 
			called, CreateRemoteThread [Reference 2 ] 
			which allows any process to execute thread in the context of remote 
			process. This method has been mainly used to inject DLL into remote 
			process, the technique popularly known as 'DLL Injection'. 
			Especially malware programs exploited this mechanism to evade 
			their detection by injecting their DLL into legitimate process's 
			such as Explorer.exe, Winlogon.exe etc. | 
	
		|  | 
	
		|  | 
 |  | 
	
		
	
	 |  | 
	
		| This DLL Injection technique using 
			CreateRemoteThread technique has worked flawlessly till Vista 
			without any limitations. However since Vista onwards things have changed with the introduction 
			of 'Session Separation' [ Reference 3  
			]. This was one of so many defenses introduced in Vista towards 
			securing the system. 'Session Separation' ensured that core system processes 
			including services always run in session 0 while all user process's 
			run in 
			different sessions. As a result any 
			process running in user session failed to inject DLL into system 
			process as CreateRemoteThread did not work across session 
			boundaries...
			 
			This is clearly evident from the MSDN documentation of 
			CreateRemoteThread [Reference 2 ] function...
			 | 
			
	
		|  | 
			
	
		| "Terminal Services isolates each terminal session by design. Therefore, 
		CreateRemoteThread fails if the target process is in a different session 
		than the calling process." | 
			
	 |  | 
	 |  | 
	
		|  | 
	
		
	
	 |  | 
	
		| With the failure of CreateRemoteThread, there was need for universal 
		solution for remote thread execution on Vista and Windows 7 platform. 
		Then comes the function, NtCreateThreadEx [Reference 
		1], the undocumented function 
		which provides complete solution for executing remote thread across 
		session boundaries. It allows any process to inject DLL into any other 
		process irrespective of session in which it is running as long as it has 
		sufficient privileges. 
 | 
	
		|  | 
	
		| Here is the prototype of NtCreateThreadEx 
		function [undocumented] | 
	
		|  | 
	
		| typedef NTSTATUS (WINAPI *LPFUN_NtCreateThreadEx) (
 OUT PHANDLE hThread,
 IN ACCESS_MASK DesiredAccess,
 IN LPVOID ObjectAttributes,
 IN HANDLE ProcessHandle,
 IN LPTHREAD_START_ROUTINE lpStartAddress,
 IN LPVOID lpParameter,
 IN BOOL CreateSuspended,
 IN ULONG StackZeroBits,
 IN ULONG SizeOfStackCommit,
 IN ULONG SizeOfStackReserve,
 OUT LPVOID lpBytesBuffer
 );
 | 
	
		|  | 
	
		| This function is almost similar to 
		CreateRemoteThread function except the last parameter which takes 
		unknown buffer structure. Here is the definition of that buffer 
		structure parameter... | 
	
		|  | 
	
		| //Buffer argument passed to NtCreateThreadEx function 
 struct NtCreateThreadExBuffer
 {
 ULONG Size;
 ULONG Unknown1;
 ULONG Unknown2;
 PULONG Unknown3;
 ULONG Unknown4;
 ULONG Unknown5;
 ULONG Unknown6;
 PULONG Unknown7;
 ULONG Unknown8;
 };
 | 
	
		|  | 
	
		| This information is derived based on 
		reverse engineering work. Hence meanings and importance of internal fields of this 
		buffer structure is not clear. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
	 |  | 
	
		| The steps involved in the execution of 
		the remote thread using NtCreateThreadEx is almost similar to that of 
		CreateRemoteThread function. Hence the traditional steps such as 
		allocating memory, copying the thread code into remote process are not 
		repeated here. For detailed steps you can refer to article, "Three Ways to Inject Your Code 
		into Another Process" [Reference 4]. 
 Before we begin, we need to load NtCreateThreadEx function from 
		Ntdll.dll as shown below.
 
 
 | 
	
		| HMODULE modNtDll = 
		GetModuleHandle("ntdll.dll"); 
 if( !modNtDll )
 {
 printf("\n failed to get module handle for ntdll.dll, Error=0x%.8x", 
		GetLastError());
 return;
 }
 
 LPFUN_NtCreateThreadEx funNtCreateThreadEx =
 (LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, 
		"NtCreateThreadEx");
 
 if( !funNtCreateThreadEx )
 {
 printf("\n failed to get funtion address from ntdll.dll, Error=0x%.8x", 
		GetLastError());
 return;
 }
 
 | 
	
		|  | 
	
		| Now setup the buffer structure which is 
		passed as last parameter to NtCreateThreadEx function. 
 | 
	
		|  | 
	
		| //setup and initialize the buffer NtCreateThreadExBuffer ntbuffer;
 
 memset (&ntbuffer,0,sizeof(NtCreateThreadExBuffer));
 DWORD temp1 = 0;
 DWORD temp2 = 0;
 
 ntbuffer.Size = sizeof(NtCreateThreadExBuffer);
 ntbuffer.Unknown1 = 0x10003;
 ntbuffer.Unknown2 = 0x8;
 ntbuffer.Unknown3 = &temp2;
 ntbuffer.Unknown4 = 0;
 ntbuffer.Unknown5 = 0x10004;
 ntbuffer.Unknown6 = 4;
 ntbuffer.Unknown7 = &temp1;
 ntbuffer.Unknown8 = 0;
 | 
	
		|  | 
	
		| Finally execute remote thread 'pRemoteFunction' into remote process 
		using NtCreateThreadEx function. Here one can use 'LoadLibrary' function 
		address instead of 'pRemoteFunction' thread to implement 'DLL Injection' 
		technique. | 
	
		|  | 
	
		| NTSTATUS status = 
		funNtCreateThreadEx( &hThread,
 0x1FFFFF,
 NULL,
 hProcess,
 (LPTHREAD_START_ROUTINE) pRemoteFunction,
 pRemoteParameter,
 FALSE, //start instantly
 NULL,
 NULL,
 NULL,
 &ntbuffer
 );
 | 
	
		|  | 
	
		| Now check for the result of NtCreateThreadEx function and then wait 
		for it to execute completely. | 
	
		|  | 
	
		| if (hThread == NULL) {
 printf("\n NtCreateThreadEx failed, Error=0x%.8x", GetLastError());
 return;
 }
 
 //Wait for thread to complete....
 WaitForSingleObject(hThread, INFINITE);
 | 
	
		|  | 
	
		| Finally retrieve the return value from the remote thread function, 
		'pRemoteFunction' to verify the result of function execution. | 
	
		|  | 
	
		| //Check the return 
		code from remote thread function int dwExitCode;
 if( GetExitCodeThread(hThread, (DWORD*) &dwExitCode) )
 {
 printf("\n Remote thread returned with status = %d", dwExitCode);
 }
 
 CloseHandle(hThread);
 | 
	
		|  | 
	
		| The steps illustrated above are almost similar except that here 
		NtCreateThreadEx is used instead of CreateRemoteThread for creating 
		thread in the context of remote process. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
	 |  | 
	
		| Though NtCreateThreadEx provides 
		universal solution on Vista/Win 7 platform for remote thread execution, 
		it is risky to use in the production code as it is undocumented 
		function. As things may change with new version and suppor packs, enough testing is necessary before putting it into production 
		especially when injecting code into system critical process such as 
		LSASS.EXE, CSRSS.EXE. 
 Another limitation is that it cannot be used in earlier platforms before 
		Vista, such as Windows XP because NtCreateThreadEx function is available 
		only Vista onwards. However developers can easily tune their code 
		to dynamically use CreateRemoteThread function on XP and NtCreateThreadEx for 
		Vista/Windows 7.
 
 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
	 |  | 
	
		| Another way to inject DLL into system 
		process is to write the service process (which will run in session 0) 
		and then issue the command from user process to that service to inject DLL into any 
		system process using the CreateRemoteThread function. 
 This technique will work for any system process running in session 0. 
		But it will fail to execute thread into any other process running in 
		session other than 0.
 
 Though it is a clumsy way of doing the work, it still holds good solution to 
		inject thread into system process only.
 | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
 |  | 
	
		| This article provides practical 
		implementation of using NtCreateThreadEx function to execute remote 
		thread into any process on Vista/Windows 7 platform. Though it is 
		undocumented function, it provides universal solution for executing code 
		in any process across session boundaries imposed by Vista. | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		
	
 |  | 
	
		| 
			
			
			NtCreateThreadEx Function
			MSDN 
			Documentation of CreateRemoteThread Function
			Impact 
			of Session 0 Isolation on Services
			Three 
			ways to inject code into remote processDLL Injection & Windows 8 | 
	
		|  | 
	
	
		|  | 
	
		
	
		 |  | 
		
	
		|  | 
		
	
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  | 
	
		|  |