A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #16112  by utsav.0202
 Thu Oct 18, 2012 5:14 pm
Hi
I am using the following code to inject my dll in every process that is started
Code: Select all
HANDLE NtCreateThreadEx(HANDLE hProcess, LPVOID lpRemoteThreadStart, LPVOID lpRemoteCallback) 
{ 
	typedef struct 
	{ 
		ULONG Length; 
		ULONG Unknown1; 
		ULONG Unknown2; 
		PULONG Unknown3; 
		ULONG Unknown4; 
		ULONG Unknown5; 
		ULONG Unknown6; 
		PULONG Unknown7; 
		ULONG Unknown8; 
	} UNKNOWN; 

	typedef DWORD WINAPI NtCreateThreadEx_PROC
	( 
		PHANDLE ThreadHandle, 
		ACCESS_MASK DesiredAccess, 
		LPVOID ObjectAttributes, 
		HANDLE ProcessHandle, 
		LPTHREAD_START_ROUTINE lpStartAddress, 
		LPVOID lpParameter, 
		BOOL CreateSuspended, 
		DWORD dwStackSize, 
		DWORD Unknown1, 
		DWORD Unknown2, 
		LPVOID Unknown3 
	); 

    UNKNOWN Buffer; 
    DWORD dw0 = 0; 
    DWORD dw1 = 0; 

    memset(&Buffer, 0, sizeof(UNKNOWN)); 

    Buffer.Length = sizeof (UNKNOWN); 
    Buffer.Unknown1 = 0x10003; 
    Buffer.Unknown2 = 0x8; 
    Buffer.Unknown3 = &dw1; 
    Buffer.Unknown4 = 0; 
    Buffer.Unknown5 = 0x10004; 
    Buffer.Unknown6 = 4; 
    Buffer.Unknown7 = &dw0; 

    NtCreateThreadEx_PROC* VistaCreateThread = (NtCreateThreadEx_PROC*) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCreateThreadEx"); 

    if(VistaCreateThread == NULL)
	{
        return (NULL); 
	}

    HANDLE hRemoteThread = NULL; 
    HRESULT hRes = 0; 

	hRes = VistaCreateThread(&hRemoteThread, 
							 0x1FFFFF, // all access 
							 NULL, 
							 hProcess, 
							 (LPTHREAD_START_ROUTINE)lpRemoteThreadStart, 
							 lpRemoteCallback, 
							 FALSE, 
							 NULL, 
							 NULL, 
							 NULL,           
							 &Buffer);

	if(!SUCCEEDED(hRes)) 
    { 
        return (NULL); 
    } 

	return (hRemoteThread); 
} 

HANDLE MyCreateRemoteThread(HANDLE hProcess, LPVOID lpRemoteThreadStart, LPVOID lpRemoteCallback) 
{ 
    if (GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCreateThreadEx")) 
    {
        return NtCreateThreadEx(hProcess, lpRemoteThreadStart, lpRemoteCallback); 
    } 
    else 
    {
        return CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemoteThreadStart, lpRemoteCallback, 0, 0); 
    } 

    return NULL; 
} 

VOID InjectDLLThread(PVOID dummy)
{
	DWORD Pid = (DWORD)dummy;
	HANDLE hProcess = NULL;
	LPVOID Memory = NULL;
	LPVOID LoadLibraryx = NULL;
	CHAR dll[MAX_PATH] = "AppinitHook.dll";

	//Sleep(1000);

	HANDLE ht = NULL;

	hProcess = MyOpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
	if(hProcess == NULL || hProcess == INVALID_HANDLE_VALUE)
	{
		return;
	}

	LoadLibraryx = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
	if (LoadLibraryx == NULL)
	{
		goto CleanUp;
	}

	Memory = (LPVOID)VirtualAllocEx(Process, NULL, strlen(dll) + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
	if (Memory == NULL)
	{
		goto CleanUp;
	}
	
	if (!WriteProcessMemory(Process, (LPVOID)Memory, dll, strlen(dll) + 1, NULL))
	{
		goto CleanUp;
	}

	ht = MyCreateRemoteThread(Process, LoadLibraryx, (LPVOID)Memory);
	if (ht)
	{
		WaitForSingleObject(ht, INFINITE);
	}


CleanUp:

	if(Memory)
	{
		VirtualFreeEx(hProcess, Memory, 0, MEM_RELEASE);
		Memory = NULL;
	}

	if(ht)
	{
		CloseHandle(ht);
		ht = NULL;
	}

	if(hProcess)
	{
		CloseHandle(hProcess);
		hProcess = NULL;
	}
}
I am testing this on Windows 7 32 bit OS
I am creating "InjectDLLThread" thread after I get a callback for a newly created process
The problem I am having is that the "MyCreateRemoteThread" call succeeds for every process but the dll is not injected into all the processes.

Thanks
 #16148  by utsav.0202
 Fri Oct 19, 2012 11:10 am
I tried the method described in the link given by xdeadcode but got no difference in result.
CreateRemoteThread succeeds for all processes but the dll is injected only in some processes.
 #16162  by xdeadcode
 Fri Oct 19, 2012 4:10 pm
Hi utsav.0202,

I've checked this PoC and I my opinion it works as expected.

On which process exactly it does not work?
How are you determining if dll was succesfully injected?
Are you sure you have privileges to open e.g system process (if this is process you want to inject dll of course)?

Best regards,
 #16163  by r2nwcnydc
 Fri Oct 19, 2012 4:41 pm
CreateRemoteThread does not work if the process is running under a different security sessions (csrss for example). You need to use RtlCreateUserThread to inject into processes like those. I don't have any example code on hand, but you could probably find some on google.

Edit:
One thing to keep in mind, is that your thread routine needs to manual call ExitThread for the thread to close properly.
 #16164  by xdeadcode
 Fri Oct 19, 2012 4:57 pm
Hi r2nwcnydc,
CreateRemoteThread does not work if the process is running under a different security sessions (csrss for example)
True.
PoC from link I've put should bypass this windows vista feature.

best regards,
 #25395  by anky9783
 Thu Mar 05, 2015 2:47 pm
can any one tell what is problem in my code it is not working.
Code: Select all
HANDLE NtCreateThreadEx(HANDLE process, LPTHREAD_START_ROUTINE Start, LPVOID lpParameter);
 
using namespace std;
 
DWORD getPid(string procName);
int privileges();
 
int main()
{
   privileges();  //don't mind of the result, because maybe it fails because you already have that privilege
 
   DWORD pid =10864;
   if (pid==0) return 1; //error
 
   HANDLE p;
   p = OpenProcess(PROCESS_ALL_ACCESS,false,pid);
   if (p==NULL) return 1; //error
 
   LPCSTR dll = "C:\\reflective_dll.dll";
 
   //--------now we are ready to inject
 
   LPVOID LoadLib = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
 
   LPVOID DataAddress = VirtualAllocEx(p, NULL, strlen(dll) + 1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
 
   WriteProcessMemory(p, DataAddress, dll, strlen(dll), NULL);
 
 
  // HANDLE thread = CreateRemoteThread(p, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLib, DataAddress, 0, NULL);
  //For Vista/Win7
  HANDLE thread = NtCreateThreadEx(p, (LPTHREAD_START_ROUTINE)LoadLib, DataAddress);
     
   /* if (thread!=0){
               //injection completed
               WaitForSingleObject(thread, INFINITE);   //this waits untill thread thread has finished
               VirtualFree(MyFuncAddress, 0, MEM_RELEASE); //free myFunc memory
               VirtualFree(DataAddress, 0, MEM_RELEASE); //free data memory
            CloseHandle(thread);
               CloseHandle(p);  //don't wait for the thread to finish, just close the handle to the process
               cout<<"Injection completed!"<<endl;
     }else{
               cout<<"Error!"<<endl;
     }
 */
    

    system("PAUSE");
    return EXIT_SUCCESS;
}
 
DWORD getPid(string procName){
   HANDLE hsnap;
   PROCESSENTRY32 pt;
   hsnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
   pt.dwSize = sizeof(PROCESSENTRY32);
   do{
          if(!strcmp(pt.szExeFile, procName.c_str())){
             DWORD pid = pt.th32ProcessID;
             CloseHandle(hsnap);
             return pid;
          }
   } while(Process32Next(hsnap, &pt));
   CloseHandle(hsnap);
   return 0;          
}
 
int privileges(){
  HANDLE Token;
  TOKEN_PRIVILEGES tp;
  if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token))
  {
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        if (AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL)==0){
         return 1; //FAIL
        }else{
         return 0; //SUCCESS
        }
   }      
   return 1;
}
 
 
//for VISTA/WIN7
 
 
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 DWORD StackZeroBits,
  IN DWORD SizeOfStackCommit,
  IN DWORD SizeOfStackReserve,
  OUT LPVOID lpBytesBuffer
);
 
struct NtCreateThreadExBuffer
{
  ULONG Size;
  ULONG Unknown1;
  ULONG Unknown2;
  PULONG Unknown3;
  ULONG Unknown4;
  ULONG Unknown5;
  ULONG Unknown6;
  PULONG Unknown7;
  ULONG Unknown8;
};
 
HANDLE NtCreateThreadEx(HANDLE process, LPTHREAD_START_ROUTINE Start, LPVOID lpParameter){
     
    HMODULE modNtDll = LoadLibrary("ntdll.dll");
 
    if(!modNtDll){
       cout<<"Error loading ntdll.dll"<<endl;
       return 0;
    }
 
    LPFUN_NtCreateThreadEx funNtCreateThreadEx = (LPFUN_NtCreateThreadEx) GetProcAddress(modNtDll, "NtCreateThreadEx");
 
    if(!funNtCreateThreadEx){
       cout<<"Error loading NtCreateThreadEx()"<<endl;
       return 0;
    }
    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;
 
    HANDLE hThread;  
    NTSTATUS status = funNtCreateThreadEx(
                        &hThread,
                        0x1FFFFF,
                        NULL,
                        process,
                        (LPTHREAD_START_ROUTINE) Start,
                        lpParameter,
                        FALSE, //start instantly
                        0, //null
                        0, //null
                        0, //null
                        &ntbuffer
                        );
                         if(!SUCCEEDED(status)) 
    { 
    	printf("not able to succed");
        return (NULL); 
    } 
      if (hThread == NULL)
	{
		printf("\n NtCreateThreadEx failed, Error=0x%.8x", GetLastError());
		
	}
		
	printf("\t[+] Remote Thread created! [%d]\n", GetLastError());
			WaitForSingleObject(hThread, INFINITE);
			
			int dwExitCode;
 		if( GetExitCodeThread(hThread, (DWORD*) &dwExitCode) )
		{
				printf("\n Remote thread returned with status = %d", dwExitCode);
		}
		else
		printf("\n Remote thread returned with status = %d", dwExitCode);
    return hThread;
 
}
 #25396  by EP_X0FF
 Thu Mar 05, 2015 3:35 pm
Basically you copy-pasted your "code" from here -> http://noobys-journey.blogspot.co.il/se ... teThreadEx who copy-pasted it from google. In the beginning it was a ridiculous piece of shit but you managed to get it even worse by blind copy-pasting. And now you ask whats wrong? IDK, maybe problem somewhere in your DNA?

Use RtlCreateUserThread and stop copy-pasting shit.

Necroposting. Closed.