Ejemplo n.º 1
0
bool Inject(DWORD pid)
{
	LPTHREAD_START_ROUTINE start_routine = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
	EnableDebugPrivilege(TRUE);
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	if (hProcess)
	{
		auto dll_name_length = strlen("hook.dll") + 1;
		LPVOID Param = VirtualAllocEx(hProcess, 0, dll_name_length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if (WriteProcessMemory(hProcess, Param, "hook.dll", dll_name_length, NULL))
		{
			HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, start_routine, Param, 0, NULL);
			if (hThread)
			{
				WaitForSingleObject(hThread, INFINITE);
				//一段shellcode,功能是调用Hook.dll中的Hook方法
				FILE* in_file = fopen("shellcode.bin", "r");
				char shell_code[1024];
				auto shell_code_length=fread(shell_code, 1, 1024, in_file);
				fclose(in_file);
				auto hook_method_routine= (LPTHREAD_START_ROUTINE)VirtualAllocEx(hProcess, 0, shell_code_length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
				if (WriteProcessMemory(hProcess, hook_method_routine, shell_code, shell_code_length, NULL))
				{
					HANDLE hThread2 = CreateRemoteThread(hProcess, NULL, NULL, hook_method_routine, NULL, 0, NULL);
					if (hThread2) //success
					{
						WaitForSingleObject(hThread2, INFINITE);
						return true;
					}
				}
			}
		}
	}
	return false;
}
Ejemplo n.º 2
0
HANDLE StartPatcherThread( unsigned PID, DWORD *pPatcherThreadID = NULL)
{
	EnableDebugPrivilege();
	if (GetRemoteModuleHandle64Aware(PID, _T("VBoxDD.dll")))
	{
		//We are inside VirtualBox

#ifdef _WIN64
		if (GetRemoteModuleHandle64Aware(PID, _T("kdclient64.dll")))
#else
		if (GetRemoteModuleHandle64Aware(PID, _T("kdclient.dll")))
#endif
			return 0;


		if (!s_bUserWarnedAboutVBox)
		{
			s_bUserWarnedAboutVBox = true;
			MessageBox(0, _T("VirtualKD cannot patch VirtualBox on-the-fly.\r\nPlease register the VirtualKD device for VirtualBox by running \"regsvr32 VBoxKD64.dll\". If this does not help, close all instances of VirtualBox and terminate VBoxSVC.exe and try again."),
				_T("VirtualKD"),
				MB_ICONWARNING | MB_TASKMODAL);
		}
		return INVALID_HANDLE_VALUE;
	}
	RemoteDllLoader ldr(g_hThisDll, false);
	if (ldr.FindLibraryInProcess(PID))
		return NULL;
	return ldr.InitiateDLLLoading(PID, pPatcherThreadID);
}
Ejemplo n.º 3
0
//Does EAT hooking
BOOL placeEATHooking(PVOID hookProc, LPTSTR functionName, PVOID imgBase) {
	PVOID exports, names, exportAddr;
	int i;
	DWORD relJump;
	PIMAGE_NT_HEADERS headers = imgBase + INTO (imgBase + 0x3c); // Get PE header
    PIMAGE_EXPORT_DIRECTORY desc = imgBase + 
		headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
	EnableDebugPrivilege();
	exports = imgBase + desc->AddressOfFunctions;
	names = imgBase + desc->AddressOfNames;
	for(i=0; i < desc->NumberOfNames; i++) {
		if(strcmp((char*)(imgBase + INTO((int)names + 4*i)), functionName) == 0) {
			exportAddr = exports + 4*i;
			DWORD oldProtect;
            if(!VirtualProtect(exportAddr, 4, PAGE_EXECUTE_READWRITE, &oldProtect))
			{
				return FALSE;
			}
			relJump = hookProc - imgBase;
            CopyMemory(exportAddr, &relJump, 4);
			if(!VirtualProtect(exportAddr, 4, oldProtect, &oldProtect))
			{
				return FALSE;
			}
		}
		
	}
	DisableDebugPrivilege();
	return TRUE;
}
BOOL CCodeInjectAssiantApp::InitInstance()
{
	INITCOMMONCONTROLSEX InitCtrls;
	InitCtrls.dwSize = sizeof(InitCtrls);
	InitCtrls.dwICC = ICC_WIN95_CLASSES;
	InitCommonControlsEx(&InitCtrls);

	CWinAppEx::InitInstance();

	AfxEnableControlContainer();

	EnableDebugPrivilege(TRUE);

	CCodeInjectAssiantDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		
	}
	else if (nResponse == IDCANCEL)
	{
		
	}
	return FALSE;
}
Ejemplo n.º 5
0
int WINAPI _tWinMain( HINSTANCE hInst, HINSTANCE, LPTSTR, int )
{
	_tsetlocale( LC_ALL, _T(".OCP") );

	ATLVERIFY( SUCCEEDED( _Module.Init( NULL, hInst ) ) );
	if( !EnableDebugPrivilege() )
	{
		MessageBoxV( NULL, IDS_NO_DEBUG_PRIVILEGE, MB_OK | MB_ICONHAND );
		return 0;
	}

	InitializeCriticalSection( &g_cs );
	LoadInternalExceptionList();
	LoadSettings();
	DumpInit();

	if( !ProcessCommandLine() )
	{
		AtlInitCommonControls( ICC_BAR_CLASSES );
		LoadLibrary( CRichEditCtrl::GetLibraryName() );

		CMainDlg dlgMain;
		g_pMainWnd = &dlgMain;
		int nRet = dlgMain.DoModal();
		g_pMainWnd = NULL;
	}

	DumpUninit();
	SaveSettings();
	DeleteCriticalSection( &g_cs );

	_Module.Term();
	return 0;
}
Ejemplo n.º 6
0
HANDLE StartUnpatcherThread( unsigned PID, DWORD *pPatcherThreadID = NULL)
{
	if (GetRemoteModuleHandle64Aware(PID, _T("VBoxDD0.dll")))
		return INVALID_HANDLE_VALUE;
	EnableDebugPrivilege();
	RemoteDllLoader ldr(g_hThisDll, false);
	if (!ldr.FindLibraryInProcess(PID))
		return NULL;
	return ldr.InitiateDLLUnloading(PID, true, pPatcherThreadID);
}
Ejemplo n.º 7
0
/*
调用参数:  -pid 1234 -dll C:\\test.dll
*/
int main(int argc, _TCHAR* argv[])
{
	EnableDebugPrivilege();
	
	CString strPid;
	CString strDllPath;

	ParseCommandLine(GetCommandLineW(),strPid,strDllPath);
	DWORD dwTargetPid = _ttoi(strPid);

	return InjectDll_RemoteThread(dwTargetPid,strDllPath,4000);
}
Ejemplo n.º 8
0
unsigned GetVMSessionNameW(unsigned PID, wchar_t *pName, size_t MaxNameLength)
{
#ifndef _WIN64
	if (IsRundll64Required(PID))
	{
		return (unsigned)Call64BitKDCLIENT(kGetVMSessionName, PID, pName, MaxNameLength);
	}
#endif
	extern HMODULE g_hThisDll;
	EnableDebugPrivilege();
	if (!PID || !pName)
		return 0;
	return SessionNameFromVMCmdLineW(GetRemoteProcessInfo(PID), pName, MaxNameLength);
}
Ejemplo n.º 9
0
HANDLE StartPatcherThread( unsigned PID, DWORD *pPatcherThreadID = NULL)
{
	EnableDebugPrivilege();
	if (GetRemoteModuleHandle64Aware(PID, _T("VBoxDD0.dll")))
		return 0;
	if (GetRemoteModuleHandle64Aware(PID, _T("VBoxDD.dll")))
	{
		if (!s_bUserWarnedAboutVBox)
		{
			s_bUserWarnedAboutVBox = true;
			MessageBox(0, _T("VirtualKD cannot patch VirtualBox on-the-fly.\r\nPlease, shut down all your VMs, rename VBoxDD.dll\t\nto VBoxDD0.dll and copy VBoxDD.dll from VirtualKD\t\npackage to VirtualBox directory."),
				_T("VirtualKD"),
				MB_ICONWARNING | MB_TASKMODAL);
		}
		return INVALID_HANDLE_VALUE;
	}
	RemoteDllLoader ldr(g_hThisDll, false);
	if (ldr.FindLibraryInProcess(PID))
		return NULL;
	return ldr.InitiateDLLLoading(PID, pPatcherThreadID);
}
Ejemplo n.º 10
0
// [2015/12/15 wupeng]
// if failed return 0, success return the Process ID
DWORD GetSpecificProcIDByName(LPWSTR lpName)
{
    DWORD resProcessID = 0;
    if (ISNULL(lpName))
    {
        DOLOG("Process Name can't be null");
        return 0;
    }

    if (ISFALSE(EnableDebugPrivilege(TRUE)))
    {
        DOLOG("EnableDebugPrivilege Failed !");
        return 0;
    }

    PROCESSENTRY32W pe32;
    ZeroMemory(&pe32, sizeof(pe32));

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
        DOLOG(" CreateToolhelp32Snapshot Failed ! \n" + GetLastError());
        return 0;
    }

    BOOL bMore = Process32FirstW(hProcessSnap, &pe32);
    while (bMore)
    {
        DOLOGW(L" >>" + pe32.szExeFile + L" : " + pe32.th32ProcessID);
        if (lstrcmpW(pe32.szExeFile, lpName) == 0)
        {
            resProcessID = pe32.th32ProcessID;
        }
        bMore = Process32NextW(hProcessSnap, &pe32);
    }

    // 不要忘记清除掉snapshot对象
    CloseHandle(hProcessSnap);
    return resProcessID;
}
Ejemplo n.º 11
0
HTHREAD StartVMSessionUnpatching(unsigned PID)
{
#ifndef _WIN64
	if (IsRundll64Required(PID))
	{
		DWORD dwID = (DWORD)Call64BitKDCLIENT(kStartVMSessionUnpatching, PID);
		EnableDebugPrivilege();
		if(!dwID)
			return 0;
		else if (dwID == -1)
			return INVALID_HANDLE_VALUE;
		else
		{
			HANDLE h = OpenThread(THREAD_ALL_ACCESS, FALSE, dwID);
			if (!h || (h == INVALID_HANDLE_VALUE))	//Thread already finished
				return 0;
			return h;
		}
	}
#endif
	return StartUnpatcherThread(PID);
}
Ejemplo n.º 12
0
int _tmain(int argc, _TCHAR* argv[])
{
  if (3 == argc)
  {
    _tprintf(_T("%s %s\n"), argv[1], argv[2]);
    EnableDebugPrivilege();
    if (InjectProcess(argv[1], _wtoi(argv[2])))
    {
      _tprintf(_T("inject sucessed!\n"));
      NotifyGdiChecker();
      return 1;
    }
    else
    {
      DWORD dwError = GetLastError();
      _tprintf(_T("inject failed %d!"), dwError);
    }
  }
  else
  {
    printf("command line error,please input like this:\n\"dll path\" pid\n");
  }
	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
    bool parentprocess = false;
    DWORD createflags = 0;
    WCHAR* cmdline = nullptr;
    int pid = 0;
    int illevel = -1;

    if (!ParseArgs(argc, argv, &pid, &parentprocess, &createflags, &cmdline, &illevel))
    {
        printf("NewProcessFromToken: [options] pid cmdline\n");
        printf("Options:\n");
        printf("-p : Use parent process technique to create the new process\n");
        printf("-j : Try and break away from the current process job\n");
        printf("-c : Create a new console for the process\n");
        printf("-il level: Set the process IL level\n");
        printf("* level:\n");
        printf("  u - Untrusted\n");
        printf("  l - Low\n");
        printf("  m - Medium\n");
        printf("  h - High\n");
        printf("  s - System\n");
        printf("  0xXXXX - Arbitrary IL\n");
    }
    else
    {
        if (pid == 0)
        {
            pid = GetCurrentProcessId();
        }

        EnableDebugPrivilege();
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,
                                      FALSE, pid);
        if (hProcess)
        {
            if (!parentprocess)
            {
                HANDLE hToken;

                if (OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
                {
                    HANDLE hDupToken;

                    if (DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, nullptr, SecurityImpersonation, TokenPrimary, &hDupToken))
                    {
                        if (illevel >= 0)
                        {
                            SetTokenIL(hDupToken, illevel);
                        }

                        STARTUPINFO startInfo = { 0 };
                        PROCESS_INFORMATION procInfo = { 0 };

                        startInfo.cb = sizeof(startInfo);

                        if (CreateProcessAsUserW(hDupToken, nullptr, cmdline, nullptr, nullptr, FALSE, createflags, nullptr, nullptr, &startInfo, &procInfo))
                        {
                            printf("Created process %d\n", procInfo.dwProcessId);
                        }
                        else
                        {
                            printf("Error CreateProcessAsUser: %ls\n", GetErrorMessage().c_str());
                            if (CreateProcessWithTokenW(hDupToken, 0, nullptr, cmdline, createflags, nullptr, nullptr, &startInfo, &procInfo))
                            {
                                printf("Created process %d\n", procInfo.dwProcessId);
                            }
                            else
                            {
                                printf("Error CreateProcessWithToken: %ls\n", GetErrorMessage().c_str());
                            }
                        }
                    }
                    else
                    {
                        printf("Error Duplicating Token: %ls\n", GetErrorMessage().c_str());
                    }
                }
                else
                {
                    printf("Error OpenProcessToken: %ls\n", GetErrorMessage().c_str());
                }
            }
            else
            {
                SIZE_T size = 0;

                InitializeProcThreadAttributeList(nullptr, 1, 0, &size);

                std::vector<BYTE> attrlist(size);
                LPPROC_THREAD_ATTRIBUTE_LIST pattrlist = (LPPROC_THREAD_ATTRIBUTE_LIST)&attrlist[0];

                InitializeProcThreadAttributeList(pattrlist, 1, 0, &size);

                if (UpdateProcThreadAttribute(pattrlist, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hProcess, sizeof(hProcess), nullptr, nullptr))
                {
                    STARTUPINFOEX startInfo = { 0 };
                    PROCESS_INFORMATION procInfo = { 0 };

                    startInfo.StartupInfo.cb = sizeof(startInfo);
                    startInfo.lpAttributeList = pattrlist;

                    if (CreateProcess(nullptr, cmdline, nullptr, nullptr, FALSE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT | createflags,
                                      nullptr, nullptr, &startInfo.StartupInfo, &procInfo))
                    {
                        printf("Created process %d\n", procInfo.dwProcessId);
                        if (illevel >= 0)
                        {
                            HANDLE hToken;

                            if (OpenProcessToken(procInfo.hProcess, TOKEN_ALL_ACCESS, &hToken))
                            {
                                SetTokenIL(hToken, illevel);
                            }
                        }

                        ResumeThread(procInfo.hThread);
                    }
                    else
                    {
                        printf("Error: CreateProcess %ls\n", GetErrorMessage().c_str());
                    }
                }

                DeleteProcThreadAttributeList(pattrlist);
            }

        }
        else
        {
            printf("Error OpenProcess: %ls\n", GetErrorMessage().c_str());
        }
    }

    return 0;
}
Ejemplo n.º 14
0
// [2015/12/15 wupeng]
// if failed return 0, success return the Process ID
DWORD GetSpecificProcIDByNameEx(LPSTR lpName)
{
    if (ISNULL(lpName))
    {
        DOLOG("Process Name can't be null");
        return 0;
    }

    if (ISFALSE(EnableDebugPrivilege(TRUE)))
    {
        DOLOG("EnableDebugPrivilege Failed !");
        return 0;
    }

    DWORD allProcessIDs[2048] = { 0 };
    DWORD cbNeed = 0;

    if (ISZERO(EnumProcesses(allProcessIDs, sizeof(allProcessIDs), &cbNeed)))
    {
        DOLOG("EnumProcess Failed ! " + GetLastError());
        return 0;
    }

    HANDLE hProcess = NULL;
    CHAR szProcessName[MAX_PATH] = { 0 };
    for (DWORD i = 0; i < cbNeed; i++)
    {
        if (ISZERO(allProcessIDs[i]))
        {
            continue;
        }

        ZeroMemory(szProcessName, sizeof(szProcessName));
        hProcess = OpenProcess(
                       PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE,
                       allProcessIDs[i]);
        if (ISNOTNULL(hProcess))
        {
            DWORD dwNameSize = sizeof(szProcessName);
            if (QueryFullProcessImageNameA(hProcess, 0, szProcessName, &dwNameSize))
                //if (ISNOZERO(GetModuleBaseNameA(hProcess, NULL, szProcessName,
                //	sizeof(szProcessName))))
            {
                DOLOG(" >>" + szProcessName + " : " + allProcessIDs[i]);

                string strPath = szProcessName;
                TrimFilePathA(strPath);
                if (ISZERO(_stricmp(strPath.c_str(), lpName)))
                {
                    DOLOG("Found the Process " + lpName);
                    CloseHandle(hProcess);
                    return allProcessIDs[i];
                }
            }
            else
            {
                DOLOG("GetmoudleBaseName Failed ! " + GetLastError());
            }
            CloseHandle(hProcess);
        }
        else
        {
            DOLOG("OpenProcess Failed ! " + allProcessIDs[i] + " LastError:" + GetLastError());
        }
    }

    DOLOG("can't found the specify name process Failed ! ");
    return 0;
}
Ejemplo n.º 15
0
CApiHookEngine::CApiHookEngine(){
	DWORD dwCurrentPid;
	EnableDebugPrivilege();
	dwCurrentPid = ::GetCurrentProcessId();
	m_hProc = ::OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwCurrentPid);
}
Ejemplo n.º 16
0
int _tmain(int argc, _TCHAR* argv[])
{
	EnableDebugPrivilege(TRUE);
	hDriverFile = CreateFile(
			TEXT("\\\\.\\DriverExample"),
			GENERIC_READ | GENERIC_WRITE, 
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			0,                     // Default security
			OPEN_EXISTING,
			0,                     // Perform synchronous I/O
			0);                    // No template

	hEvent = OpenEvent(SYNCHRONIZE, FALSE, TEXT("ProcessEvent") );
	if (hEvent == INVALID_HANDLE_VALUE)
	{
		std::cout << "Error open event";
		return 0;
	}

	OVERLAPPED  ov          = { 0 };
	DWORD       dwBytesReturned;
	PROCESS_CALLBACK_INFO  callbackInfo;
	TCHAR szFileName[MAX_PATH];
	while (true)
	{
		SwitchToThread(); //Переключитесь На Нить
		WaitForSingleObject (hEvent,INFINITE);
		DeviceIoControl(//Функция DeviceIoControl отправляет управляющий код непосредственно указанному драйверу устройства, заставляя соответствующее устройство выполнить соответствующую операцию.
			hDriverFile,
			IOCTL_PROCOBSRV_GET_PROCINFO,
			0, 
			0,
			&callbackInfo, sizeof(callbackInfo),
			&dwBytesReturned,
			&ov
			);

		
		GetOverlappedResult( //будет дожидаться завершения выполнения операции 
			hDriverFile, 
			&ov,
			&dwBytesReturned, 
			TRUE
			);

		HANDLE Handle = OpenProcess(
				PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
				FALSE,
				callbackInfo.hProcessId 
			);
		Sleep(1000);
		GetModuleFileNameEx(Handle, 0, szFileName, MAX_PATH);
			

		if (!wcscmp(szFileName,TEXT("C:\\WINDOWS\\system32\\notepad.exe")))   
		{
			if (callbackInfo.bCreate == TRUE)
			{
				STARTUPINFO startupInfo;
				PROCESS_INFORMATION piProcess;
				ZeroMemory( &startupInfo, sizeof(startupInfo) );
				startupInfo.cb = sizeof(startupInfo);
				ZeroMemory( &piProcess, sizeof(piProcess) );
				SECURITY_ATTRIBUTES saProcess, saThread;
				saProcess.nLength = sizeof(saProcess);
				saProcess.lpSecurityDescriptor = NULL;
				saProcess.bInheritHandle = TRUE;
				saThread.nLength = sizeof(saThread);
				saThread.lpSecurityDescriptor = NULL;
				saThread.bInheritHandle = FALSE;
	
				TCHAR commandLine[] = L"";
				TCHAR applicationPath[] = L"C:\\Windows\\system32\\calc.exe";

				CreateProcess(applicationPath, commandLine, 
					&saProcess, &saThread, FALSE, 0, NULL, NULL, &startupInfo, &piProcess);
				openedProcesses.insert ( std::pair<DWORD,HANDLE>(callbackInfo.hProcessId ,piProcess.hProcess) );
				
			}
			else
			{

				std::map<DWORD,HANDLE>::iterator iter = openedProcesses.find(callbackInfo.hProcessId);
				if(iter != openedProcesses.end())
				{
					TerminateProcess(iter->second,0);
					openedProcesses.erase(iter);
				}
			}
		}
        CloseHandle(Handle);

		
	}
	return 0;
}
Ejemplo n.º 17
0
STDAPI AttachProfiler(int pid, LPCWSTR wszTargetVersion, LPCWSTR wszProfilerPath, ProfConfig * pProfConfig, BOOL fConsoleMode)
{
    HMODULE hModule = NULL;
    LPVOID pvClientData = NULL;
    DWORD cbClientData = 0;
    HRESULT hr;

    ICLRMetaHost * pMetaHost = NULL;
    IEnumUnknown * pEnum = NULL;
    IUnknown * pUnk = NULL;
    ICLRRuntimeInfo * pRuntime = NULL;
    ICLRProfiling * pProfiling = NULL;

    g_fConsoleMode = fConsoleMode;

    DWORD dwProfileeProcessID = (DWORD) pid;

    CLSID clsidProfiler;
    CLSIDFromString(PROFILER_GUID_WCHAR, &clsidProfiler);
    
    DWORD dwMillisecondsMax = pProfConfig->dwDefaultTimeoutMs;

    bool fCLRFound = false;

    //---------------------------------------------------------------------------------------
    // GET AND CALL API
    //---------------------------------------------------------------------------------------

    hModule = LoadLibrary(L"mscoree.dll");
    if (hModule == NULL)
    {
        Log(L"LoadLibrary mscoree.dll failed.  hr=0x%x.\n", hr = HRESULT_FROM_WIN32(GetLastError()));
        goto Cleanup;
    }

    // Note: This is the ONLY C export we need out of mscoree.dll.  This enables us to
    // get started with the metahost interfaces, and it's all COM from that point
    // forward.
    CLRCreateInstanceFnPtr pfnCreateInstance = 
        (CLRCreateInstanceFnPtr)GetProcAddress(hModule, "CLRCreateInstance");
    if (pfnCreateInstance == NULL)
    {
        Log(L"GetProcAddress on 'CLRCreateInstance' failed.  hr=0x%x.\n", hr = HRESULT_FROM_WIN32(GetLastError()));
        goto Cleanup;
    }

    hr = (*pfnCreateInstance)(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID *)&pMetaHost);
    if (FAILED(hr))
    {
        Log(L"CLRCreateInstance IID_ICLRMetaHost' failed.  hr=0x%x.\n", hr);
        goto Cleanup;
    }

    // Cross-user attach requires the SE_DEBUG_NAME privilege, so attempt to enable it
    // now.  Even if the privilege is not found, the CLRProfiler still continues to attach the target process.
    // We'll just fail later on if we do try to attach to a different-user target process.
    HRESULT hrEnableDebugPrivilege = EnableDebugPrivilege();
    
    HANDLE hndProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProfileeProcessID);
    if (hndProcess == NULL)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        //If EnableDebugPrivilege is not successful, let the customer know running CLRProfiler as administrator may solve the problem.
        if (hrEnableDebugPrivilege == E_FAIL) 
        {
            Log(L"CLRProfiler can not open the target process %d (error: 0x%x), probably because CLRProfiler could not enable the debug privilege (error: 0x%x).  \n"
                L"Please run the CLRProfiler as administrator and try again.", dwProfileeProcessID, hr, hrEnableDebugPrivilege);
        }
        else
        {
            Log(L"OpenProcess failed.  hr=0x%x.\n", hr);
        }
        goto Cleanup;
    }

    // One process may have multiple versions of the CLR loaded.  Grab an enumerator to
    // get back all the versions currently loaded.
    hr = pMetaHost->EnumerateLoadedRuntimes(hndProcess, &pEnum);
    if (FAILED(hr))
    {
        Log(L"EnumerateLoadedRuntimes' failed.  hr=0x%x.\n", hr);
        goto Cleanup;
    }

    while (pEnum->Next(1, &pUnk, NULL) == S_OK)
    {
        hr = pUnk->QueryInterface(IID_ICLRRuntimeInfo, (LPVOID *) &pRuntime);
        if (FAILED(hr))
            goto LoopCleanup;
       
        WCHAR wszVersion[30];
        DWORD cchVersion = ARRAY_LEN(wszVersion);
        hr = pRuntime->GetVersionString(wszVersion, &cchVersion);
        if (SUCCEEDED(hr) && _wcsnicmp(wszVersion, wszTargetVersion, min(cchVersion, wcslen(wszTargetVersion))) == 0)
        {
            fCLRFound = true;
            hr = pRuntime->GetInterface(CLSID_CLRProfiling, IID_ICLRProfiling, (LPVOID *)&pProfiling);
            if (FAILED(hr))
            {
                Log(L"Can not get the ICLRProfiling interface. Error: 0x%x.", hr);
                break;
            }
            // Here it is!  Attach the profiler!
            // The profilee may not have access to the profler dll 
            // Give it a try.
            hr = pProfiling->AttachProfiler(dwProfileeProcessID,
                                            dwMillisecondsMax,
                                            &clsidProfiler,
                                            wszProfilerPath,
                                            (LPVOID)pProfConfig,
                                            sizeof(*pProfConfig));


            if(FAILED(hr))
            {
                if (hr == ERROR_TIMEOUT)//ERROR_TIMEOUT 
                {
                    Log(L"CLRProfiler timed out to attach to the process.\nPlease check the event log to find out whether the attach succeeded or failed.");
                }
                else if (hr == COR_E_UNAUTHORIZEDACCESS)//0x80070005
                {
                    Log(L"CLRProfiler failed to attach to the process with error code 0x80070005(COR_E_UNAUTHORIZEDACCESS).\n"
                        L"This may occur if the target process(%d) does not have access to ProfilerOBJ.dll or the directory in which ProfilerOBJ.dll is located.\n"
                        L"Please check event log for more details.", pid);
                }
                else if (hr == CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE)
                {
                    Log(L"Profiler initialization failed because the target process is running with concurrent GC enabled. Either\n"
                        L"  1) turn off concurrent GC in the application's configuration file before launching the application, or\n" 
                        L"  2) simply start the application from CLRProfiler rather than trying to attach CLRProfiler after the application has already started.");
                }
                else
                {
                    Log(L"Attach Profiler Failed 0x%x, please check the event log for more details.", hr);
                }
                    
            }

            pProfiling->Release();
            pProfiling = NULL;
            break;
        }

LoopCleanup:
        if (pRuntime != NULL)
        {
            pRuntime->Release();
            pRuntime = NULL;
        }

        if (pUnk != NULL)
        {
            pUnk->Release();
            pUnk = NULL;
        }
    }

    if (fCLRFound == false)
    {
        Log(L"No CLR Version %s is loaded into the target process.", wszTargetVersion);
        hr = E_FAIL;
    }



Cleanup:

    if (pRuntime != NULL)
    {
        pRuntime->Release();
        pRuntime = NULL;
    }

    if (pUnk != NULL)
    {
        pUnk->Release();
        pUnk = NULL;
    }

    if (pEnum != NULL)
    {
        pEnum->Release();
        pEnum = NULL;
    }

    if (pMetaHost != NULL)
    {
        pMetaHost->Release();
        pMetaHost = NULL;
    }

    if (hModule != NULL)
    {
        FreeLibrary(hModule);
        hModule = NULL;
    }

    return hr;
}