Example #1
0
	void Bootstrap::StartTheDotNetRuntime()
	{		 
		ofstream myfile;
		myfile.open(L"C:\\Temp\\cppLog.txt");
		myfile << "Entered Injection function";
		myfile.close();

		ICLRMetaHost *pMetaHost = NULL;
		CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost);

		ICLRRuntimeInfo *pRuntimeInfo = NULL;
		pMetaHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (LPVOID*)&pRuntimeInfo);

		ICLRRuntimeHost *pClrRuntimeHost = NULL;
		pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&pClrRuntimeHost);		

		//Run the CLR so run a >NET runtime
		pClrRuntimeHost->Start();		

		HRESULT hr = LoadManagedLibrary(pClrRuntimeHost);
		
		myfile.open(L"C:\\Temp\\cppLog.txt");
		myfile << "After to loading .NET dll";
		myfile.close();		

		// free resources
		pMetaHost->Release();
		pRuntimeInfo->Release();
		pClrRuntimeHost->Release();
	}	
Example #2
0
extern "C" __declspec(dllexport) HRESULT Inject(_In_ LPCSTR param)
{
    DWORD pReturnValue;
    ICLRMetaHost*    pMetaHost       = NULL;
    ICLRRuntimeInfo* pRuntimeInfo    = NULL;
    ICLRRuntimeHost* pClrRuntimeHost = NULL;

    if (CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)) != S_OK)
    {
        return -1;
    }
    if (pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo)) != S_OK)
    {
        return -1;
    }
    if (pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost)) != S_OK)
    {
        return -1;
    }

    if (pClrRuntimeHost->Start() != S_OK)
    {
        return -1;
    }

    WCHAR wsz[MAX_PATH];
    MultiByteToWideChar(CP_ACP, 0, param, -1, wsz, MAX_PATH);

    HRESULT hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(
        wsz,
        L"FakePacketSender.InjectedEntry",
        L"Run",
        wsz,
        &pReturnValue);

    if (hr = pClrRuntimeHost->Stop() != S_OK)
    {
        _com_error err(hr);
        MessageBox(0, err.ErrorMessage(), L"Error", 0);
        return -1;
    }

    if (hr != S_OK)
    {
        _com_error err(hr);
        MessageBox(0, err.ErrorMessage(), L"Error", 0);
        return -1;
    }

    pMetaHost->Release();
    pRuntimeInfo->Release();
    pClrRuntimeHost->Release();

    return hr;
}
HRESULT clrWrapper(LPCWSTR runtimeVersion, std::function<HRESULT(ICLRRuntimeHost* pClrRuntimeHost)> callback)
{
    HRESULT hr = E_FAIL;
    ICLRMetaHost* pMetaHost = nullptr;
    ICLRRuntimeInfo* pRuntimeInfo = nullptr;
    ICLRRuntimeHost* pClrRuntimeHost = nullptr;

    do {
        hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
        if (FAILED(hr)) {
            break;
        }

        hr = pMetaHost->GetRuntime(runtimeVersion, IID_PPV_ARGS(&pRuntimeInfo));
        if (FAILED(hr)) {
            break;
        }

        hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost));
        if (FAILED(hr)) {
            break;
        }

        hr = pClrRuntimeHost->Start();
        if (FAILED(hr)) {
            break;
        }

        if (callback) {
            hr = callback(pClrRuntimeHost);
            if (FAILED(hr)) {
                break;
            }
        }
    } while (false);

    if (pClrRuntimeHost) {
        pClrRuntimeHost->Release();
        pClrRuntimeHost = nullptr;
    }

    if (pRuntimeInfo) {
        pRuntimeInfo->Release();
        pRuntimeInfo = nullptr;
    }

    if (pMetaHost) {
        pMetaHost->Release();
        pMetaHost = nullptr;
    }

    return hr;
}
DWORD initialize_dotnet_host()
{
	HRESULT hr = S_OK;
	ICLRMetaHost* clrMetaHost = NULL;
	ICLRRuntimeInfo* clrRuntimeInfo = NULL;
	ICorRuntimeHost* clrCorRuntimeHost = NULL;
	IUnknownPtr clrAppDomain = NULL;
	_AppDomainPtr clrAppDomainInterface = NULL;
	_AssemblyPtr clrPowershellAssembly = NULL;
	_TypePtr clrPowershellType = NULL;
	SAFEARRAY* clrByteArray = NULL;
	HMODULE hMsCoree = NULL;

	do
	{
		dprintf("[PSH] Locating CLR instance ...");
		hMsCoree = LoadLibraryA("mscoree.dll");
		if (hMsCoree == NULL)
		{
			hr = (HRESULT)GetLastError();
			dprintf("[PSH] Failed to load mscoree, .NET probably isn't installed. 0x%x", hr);
			break;
		}

		pClrCreateInstance clrCreateInstance = (pClrCreateInstance)GetProcAddress(hMsCoree, "CLRCreateInstance");
		if (clrCreateInstance != NULL)
		{
			dprintf("[PSH] .NET 4 method in use");

			if (FAILED(hr = clrCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&clrMetaHost))))
			{
				dprintf("[PSH] Failed to create instace of the CLR metahost 0x%x", hr);
				break;
			}

			dprintf("[PSH] Getting a reference to the .NET runtime");
			if (FAILED(hr = clrMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&clrRuntimeInfo))))
			{
				dprintf("[PSH] Failed to get runtime v2.0.50727 instance 0x%x", hr);
				if (FAILED(hr = clrMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&clrRuntimeInfo))))
				{
					dprintf("[PSH] Failed to get runtime v4.0.30319 instance 0x%x", hr);
					break;
				}
			}

			dprintf("[PSH] Determining loadablility");
			BOOL loadable = FALSE;
			if (FAILED(hr = clrRuntimeInfo->IsLoadable(&loadable)))
			{
				dprintf("[PSH] Unable to determine of runtime is loadable 0x%x", hr);
				break;
			}

			if (!loadable)
			{
				dprintf("[PSH] Chosen runtime isn't loadable, exiting.");
				break;
			}

			dprintf("[PSH] Instantiating the COR runtime host");
			hr = clrRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost));
			if (FAILED(hr))
			{
				dprintf("[PSH] Unable to get a reference to the COR runtime host 0x%x", hr);
				break;
			}
		}
		else
		{
			dprintf("[PSH] .NET 4 method is missing, attempting to locate .NEt 2 method");
			pCorBindToRuntime corBindToRuntime = (pCorBindToRuntime)GetProcAddress(hMsCoree, "CorBindToRuntime");
			if (corBindToRuntime == NULL)
			{
				dprintf("[PSH] Unable to find .NET clr instance loader");
				hr = E_NOTIMPL;
				break;
			}

			if (FAILED(hr = corBindToRuntime(L"v2.0.50727", L"wks", CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost))))
			{
				dprintf("[PSH] Unable to bind to .NET 2 runtime host: 0x%x", hr);
				break;
			}
		}

		dprintf("[PSH] Starting the COR runtime host");
		if (FAILED(hr = clrCorRuntimeHost->Start()))
		{
			dprintf("[PSH] Unable to start the COR runtime host 0x%x", hr);
			break;
		}

		dprintf("[PSH] Getting a ref to the app domain");
		if (FAILED(hr = clrCorRuntimeHost->GetDefaultDomain(&clrAppDomain)))
		{
			dprintf("[PSH] Unable to get the app domain 0x%x", hr);
			break;
		}

		dprintf("[PSH] Getting a ref to the app domain interface");
		if (FAILED(hr = clrAppDomain->QueryInterface(IID_PPV_ARGS(&clrAppDomainInterface))))
		{
			dprintf("[PSH] Unable to get the app domain interface 0x%x", hr);
			break;
		}

		dprintf("[PSH] CLR app domain ready to run, now loading the powershell runner");
		SAFEARRAYBOUND bounds[1];
		bounds[0].cElements = PSHRUNNER_DLL_LEN;
		bounds[0].lLbound = 0;

		clrByteArray = SafeArrayCreate(VT_UI1, 1, bounds);
		if (clrByteArray == NULL)
		{
			dprintf("[PSH] Failed to create a usable safe array");
			hr = ERROR_OUTOFMEMORY;
			break;
		}

		if (FAILED(hr = SafeArrayLock(clrByteArray)))
		{
			dprintf("[PSH] Safe array lock failed 0x%x", hr);
			break;
		}
		memcpy(clrByteArray->pvData, PowerShellRunnerDll, PSHRUNNER_DLL_LEN);
		SafeArrayUnlock(clrByteArray);

		if (FAILED(hr = clrAppDomainInterface->Load_3(clrByteArray, &clrPowershellAssembly)))
		{
			dprintf("[PSH] Failed to load the powershell runner assembly 0x%x", hr);
			break;
		}

		dprintf("[PSH] Loading the type from memory");
		_bstr_t pshClassName("MSF.Powershell.Runner");
		if (FAILED(hr = clrPowershellAssembly->GetType_2(pshClassName, &clrPowershellType)))
		{
			dprintf("[PSH] Unable to locate the powershell class type 0x%x", hr);
			break;
		}

		dprintf("[PSH] Runtime has been initialized successfully");

	} while(0);

	if (clrByteArray != NULL)
	{
		SafeArrayDestroy(clrByteArray);
	}

	if (FAILED(hr))
	{
		SAFE_RELEASE(clrPowershellAssembly);
		SAFE_RELEASE(clrAppDomainInterface);
		SAFE_RELEASE(clrCorRuntimeHost);
		SAFE_RELEASE(clrRuntimeInfo);
		SAFE_RELEASE(clrMetaHost);
		return (DWORD)hr;
	}

	gClrMetaHost = clrMetaHost;
	gClrRuntimeInfo = clrRuntimeInfo;
	gClrCorRuntimeHost = clrCorRuntimeHost;
	gClrAppDomainInterface = clrAppDomainInterface;
	gClrAppDomain = clrAppDomain;
	gClrPowershellAssembly = clrPowershellAssembly;
	gClrPowershellType = clrPowershellType;
	return ERROR_SUCCESS;
}
Example #5
0
EASYHOOK_NT_INTERNAL CompleteManagedInjection(LPREMOTE_INFO InInfo)
{
/*
Description:

    Loads the NET runtime into the calling process and invokes the
    managed injection entry point (EasyHook.InjectionLoader.Main).
*/
    ICLRMetaHost*           MetaClrHost = NULL;
    ICLRRuntimeInfo*        RuntimeInfo = NULL;
    ICLRRuntimeHost*        RuntimeClrHost = NULL;

	DWORD					ErrorCode = 0;
    WCHAR                   ParamString[MAX_PATH];
    REMOTE_ENTRY_INFO       EntryInfo;
    HMODULE                 hMsCorEE = LoadLibraryA("mscoree.dll");
    PROC_CorBindToRuntime*  CorBindToRuntime = (PROC_CorBindToRuntime*)GetProcAddress(hMsCorEE, "CorBindToRuntime"); // .NET 2.0/3.5 framework creation method
    PROC_CLRCreateInstance* CLRCreateInstance = (PROC_CLRCreateInstance*)GetProcAddress(hMsCorEE, "CLRCreateInstance"); // .NET 4.0+ framework creation method
    DWORD                   RetVal;
    bool                    UseCorBindToRuntime = false;

    if(CorBindToRuntime == NULL && CLRCreateInstance == NULL)
        UNMANAGED_ERROR(10); // mscoree.dll does not exist or does not expose either of the framework creation methods

    UseCorBindToRuntime = CLRCreateInstance == NULL;

    // invoke user defined entry point
    EntryInfo.HostPID = InInfo->HostProcess;
    EntryInfo.UserData = InInfo->UserData;
    EntryInfo.UserDataSize = InInfo->UserDataSize;

    if (!UseCorBindToRuntime)
    {
        // Attempt to use .NET 3.5/4 runtime object creation method rather than deprecated .NET 2.0 CorBindToRuntime
        if (FAILED(CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&MetaClrHost)))
        {
            // Failed to get a MetaHost instance
            DEBUGOUT("Failed to retrieve CLRMetaHost instance");
            UseCorBindToRuntime = true;
        }
        else
        {
            /*
                It is possible to create a ICLRRuntimeInfo object based on the runtime required by InInfo->UserLibrary
                however this requires that the assembly containing the "EasyHook.InjectionLoader" (usually EasyHook.dll)
                must be targetting the same framework version as the assembly(ies) to be injected. This is because the
                first CLR assembly injected into the target process in this case is usually the EasyHook.dll assembly.

                So instead we are providing a specific .NET version (for now v4.0.30319), this will need to be
                passed as a parameter in the future.
            */
            // TODO: add documentation about what happens when injecting into a managed process where the .NET framework is already loaded
            LPCWSTR frameworkVersion = L"v4.0.30319"; // TODO: .NET version string to be passed in "InInfo"
            if (FAILED(MetaClrHost->GetRuntime(
                frameworkVersion, 
                IID_ICLRRuntimeInfo,
                (LPVOID*)&RuntimeInfo)))
            {
                // .NET version requested is not available
                DEBUGOUT("Failed to retrieve runtime info for framework version: %s", frameworkVersion);
                UseCorBindToRuntime = true;
            }
            else
            {
                if (FAILED(RuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&RuntimeClrHost)))
                {
                    // Failed to create the requested CLR host version
                    // TODO: add documentation about why this might happen - e.g. does this happen if an older framework version is already loaded by the target?
                    DEBUGOUT("Failed to create CLR host for framework version: %s", frameworkVersion);
                    UseCorBindToRuntime = true;
                }
                else
                {
                    RuntimeClrHost->Start();

                    // Enable support for running older .NET v2 assemblies within .NET v4 (e.g. EasyHook.dll is .NET 2.0)
	                if (FAILED(RuntimeInfo->BindAsLegacyV2Runtime()))
                        DEBUGOUT("Unable to BindAsLegacyV2Runtime");
                }
            }
        }
    }

    if (UseCorBindToRuntime)
    {
        // load NET-Runtime and execute user defined method
        if(!RTL_SUCCESS(CorBindToRuntime(NULL, NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (void**)&RuntimeClrHost)))
        {
            DEBUGOUT("CorBindToRuntime failed");
            UNMANAGED_ERROR(11);
        }
        
        RuntimeClrHost->Start();
    }

    /*
        Test library code.
        This is because if once we have set the remote signal, there is no way to
        notify the host about errors. If the following call succeeds, then it will
        also do so some lines later... If not, then we are still able to report an error.

        The EasyHook managed injection loader will establish a connection to the
        host, so that further error reporting is still possible after we set the event!
    */
    RtlLongLongToUnicodeHex((LONGLONG)&EntryInfo, ParamString);

    if(!RTL_SUCCESS(RuntimeClrHost->ExecuteInDefaultAppDomain(
            InInfo->UserLibrary,
            L"EasyHook.InjectionLoader",
            L"Main",
            ParamString,
            &RetVal)))
    {
        if (UseCorBindToRuntime)
            UNMANAGED_ERROR(12); // We already tried the CorBindToRuntime method and it has failed

        // Running the assembly in the .NET 4.0 Runtime did not work;
        // Stop and attempt to run it in the .NET 2.0/3.5 Runtime
        if(RuntimeClrHost != NULL)
            RuntimeClrHost->Release();
        
        if(!RTL_SUCCESS(CorBindToRuntime(NULL, NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (void**)&RuntimeClrHost)))
            UNMANAGED_ERROR(11);
        
        RuntimeClrHost->Start();
        
        RtlLongLongToUnicodeHex((LONGLONG)&EntryInfo, ParamString);
        if(!RTL_SUCCESS(RuntimeClrHost->ExecuteInDefaultAppDomain(InInfo->UserLibrary, L"EasyHook.InjectionLoader", L"Main", ParamString, &RetVal)))
            UNMANAGED_ERROR(14); // Execution under both .NET 4 and .NET 2/3.5 failed (new ErrorCode: 14, for EasyHook 2.7)
    }

    if(!RetVal)
        UNMANAGED_ERROR(13);

    // set and close event
    if(!SetEvent(InInfo->hRemoteSignal))
        UNMANAGED_ERROR(22);

    CloseHandle(InInfo->hRemoteSignal);

    InInfo->hRemoteSignal = NULL;

    // execute library code (no way for error reporting, so we dont need to check)
    RuntimeClrHost->ExecuteInDefaultAppDomain(
        InInfo->UserLibrary,
        L"EasyHook.InjectionLoader",
        L"Main",
        ParamString,
        &RetVal);

ABORT_ERROR:

    // release resources
    if(MetaClrHost != NULL)
        MetaClrHost->Release();
    if(RuntimeInfo  != NULL)
        RuntimeInfo->Release();
    if(RuntimeClrHost != NULL)
        RuntimeClrHost->Release();

    if(hMsCorEE != NULL)
        FreeLibrary(hMsCorEE);

    return ErrorCode;
}
Example #6
0
ICLRRuntimeHost* StartCLR(LPCWSTR dotNetVersion)
{
	HRESULT hr;

	ICLRMetaHost* pClrMetaHost = NULL;
	ICLRRuntimeInfo* pClrRuntimeInfo = NULL;
	ICLRRuntimeHost* pClrRuntimeHost = NULL;

	// Get the CLRMetaHost that tells us about .NET on this machine
	hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pClrMetaHost);

	if (hr == S_OK)
	{
		OutputDebugStringW(L"[Bootstrap] Created CLR instance\n");
		// Get the runtime information for the particular version of .NET
		hr = pClrMetaHost->GetRuntime(dotNetVersion, IID_PPV_ARGS(&pClrRuntimeInfo));
		if (hr == S_OK)
		{
			OutputDebugStringW(L"[Bootstrap] Got CLR runtime\n");
			// Check if the specified runtime can be loaded into the process. This
			// method will take into account other runtimes that may already be
			// loaded into the process and set pbLoadable to TRUE if this runtime can
			// be loaded in an in-process side-by-side fashion.
			BOOL fLoadable;
			hr = pClrRuntimeInfo->IsLoadable(&fLoadable);
			if ((hr == S_OK) && fLoadable)
			{
				OutputDebugStringW(L"[Bootstrap] Runtime is loadable!\n");
				// Load the CLR into the current process and return a runtime interface
				// pointer.
				hr = pClrRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost,
					IID_PPV_ARGS(&pClrRuntimeHost));
				if (hr == S_OK)
				{
					OutputDebugStringW(L"[Bootstrap] Got interface.\n");
					// Start it. This is okay to call even if the CLR is already running
					hr = pClrRuntimeHost->Start();
					//       if (hr == S_OK)
					//     {
					OutputDebugStringW(L"[Bootstrap] Started the runtime!\n");
					// Success!
					return pClrRuntimeHost;
					//   }
				}
			}
		}
	}
	// Cleanup if failed
	if (pClrRuntimeHost)
	{
		pClrRuntimeHost->Release();
		pClrRuntimeHost = NULL;
	}
	if (pClrRuntimeInfo)
	{
		pClrRuntimeInfo->Release();
		pClrRuntimeInfo = NULL;
	}
	if (pClrMetaHost)
	{
		pClrMetaHost->Release();
		pClrMetaHost = NULL;
	}

	return NULL;
}
/// <summary>
/// Starts the dot net runtime.
/// </summary>
/// <remarks>http://www.codingthewheel.com/archives/how-to-inject-a-managed-assembly-dll/</remarks>
HRESULT StartTheDotNetRuntime(_In_ LPCTSTR lpCommand)
{
	FILE *file;
	fopen_s(&file, logPath, "a+");

	fprintf(file, "binding runtime.\r\n");
	fflush(file);

    fprintf(file, "Loading the .NET runtime host.\n");
	fflush(file);
      
	ICLRMetaHost *pMetaHost = NULL;
	auto result = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
	if (FAILED(result))
	{
		fprintf(file, "Error: failed to create CLR instance.\n");
		fflush(file);
		
		return result;
	}
 
	fprintf(file, "Loading the .NET runtime.\n");
	fflush(file);

	ICLRRuntimeInfo *pRuntimeInfo = NULL;
	result = pMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&pRuntimeInfo));
	if (FAILED(result))
	{
		fprintf(file, "Error: failed to create CLR instance.\n");
		fflush(file);

		pMetaHost->Release();
		return result;
	}
 
	fprintf(file, "Acquiring the .NET runtime.\n");
	fflush(file);

	ICLRRuntimeHost *pClrRuntimeHost = NULL;
	result = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pClrRuntimeHost));
	if (FAILED(result))
	{
		fprintf(file, "Error: failed to acquire CLR runtime.\n");
		fflush(file);

		pMetaHost->Release();
		return result;
	}

	fprintf(file, "Starting the .NET runtime.\n");
	fflush(file);

	result = pClrRuntimeHost->Start();
	if (FAILED(result))
	{
		fprintf(file, "Error: failed to start CLR runtime.\n");
		fflush(file);

		pClrRuntimeHost->Release();
		pMetaHost->Release();
		return result;
	}

	fprintf(file, "Executing payload assembly.\n");
	fflush(file);
    DWORD dwRet = 0;
    result = pClrRuntimeHost->ExecuteInDefaultAppDomain(
            assemblyPath,
            classFqn, methodName, parameter, &dwRet);
	if (FAILED(result))
	{
		fprintf(file, "Error: unable to execute example code.\n");
		fflush(file);

		pClrRuntimeHost->Stop();
		pClrRuntimeHost->Release();
		pMetaHost->Release();
		return result;
	}

	fprintf(file, "Stopping the .NET runtime.\n");
	fflush(file);

	pClrRuntimeHost->Stop();

	fprintf(file, "Releasing the .NET runtime.\n");
	fflush(file);

	pClrRuntimeHost->Release();
	pMetaHost->Release();

	fclose(file);

	return ERROR_SUCCESS;
}
Example #8
0
BOOL CPipeServer::OpenOrAttachToProcess(void)
{
	ICLRMetaHost *pMetaHost;
	IEnumUnknown *RuntimeEnum;
	HANDLE ths;
	MODULEENTRY32 m;
	HRESULT r;
	BOOL result=FALSE;
	
	

	CLR_DEBUGGING_VERSION v;
	v.wStructVersion=0;
	v.wMajor=4;
	v.wMinor=0;
	v.wRevision=30319;
	v.wBuild=65535;


	CLRDebugging=NULL;
	CorDebugProcess=NULL;
	CorDebugProcess5=NULL;

	libprovider=NULL;
	datacallback=NULL;



	HMODULE hMscoree = LoadLibraryA("mscoree.dll");
	CLRCreateInstanceFnPtr CLRCreateInstance;

	if (hMscoree==NULL)
		return FALSE;

	CLRCreateInstance=(CLRCreateInstanceFnPtr)GetProcAddress(hMscoree, "CLRCreateInstance");
	if (CLRCreateInstance==NULL)
		return FALSE; //only 4.0 is supported for now

	processhandle=OpenProcess(PROCESS_ALL_ACCESS , FALSE, processid);
	if (processhandle==0)
		return FALSE;
	
	if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost)!=S_OK)
		return FALSE;
		
	
	if (pMetaHost->EnumerateLoadedRuntimes(processhandle, &RuntimeEnum)==S_OK)
	{
		ICLRRuntimeInfo *info;
		ULONG count=0;

		RuntimeEnum->Next(1, (IUnknown **)&info, &count);
		if (count)
		{
			result=TRUE;
			libprovider=new CMyICLRDebuggingLibraryProvider(info);  //todo: scan for 4.0			
		}

		RuntimeEnum->Release();
	}
	pMetaHost->Release();

	if (!result)
		return FALSE; //no runtimes

	
	if (CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (void **)&CLRDebugging)!=S_OK)
		return FALSE;

	

	
	ths=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processid);
	if (ths==INVALID_HANDLE_VALUE)
		return FALSE;

	

	ZeroMemory(&m, sizeof(m));
	m.dwSize=sizeof(m);
	if (Module32First(ths, &m))
	{
		datacallback=new CMyIcorDebugDataTarget(processhandle);

		do
		{
			CLR_DEBUGGING_PROCESS_FLAGS flags;

			r=CLRDebugging->OpenVirtualProcess((ULONG64)m.hModule, datacallback,  libprovider, &v, IID_ICorDebugProcess, (IUnknown **)&CorDebugProcess, &v, &flags);
			
			if (r==S_OK)
			{					
				CorDebugProcess->QueryInterface(IID_ICorDebugProcess5, (void **)&CorDebugProcess5);
				break;
			}

		}
		

		while (Module32Next(ths, &m));
	}


	CloseHandle(ths);


	if (r!=S_OK)
	{
#ifdef _DEBUG
		/*
		//todo for older (<4.0) c# versions:
		WCHAR Version[255];
		DWORD vlength;

		ICorDebug *CorDebug;
		processhandle=OpenProcess(PROCESS_ALL_ACCESS, FALSE, processid);

		r=GetVersionFromProcess(processhandle, Version, 255, &vlength);	

		r=CreateDebuggingInterfaceFromVersion(CorDebugVersion_2_0,  Version, (IUnknown **)&CorDebug);

		CorDebug->Initialize();
		//Cor

		CMyICorDebugManagedCallback *MyICorDebugManagedCallback;

		MyICorDebugManagedCallback=new CMyICorDebugManagedCallback();
		
		r=CorDebug->SetManagedHandler((ICorDebugManagedCallback *)MyICorDebugManagedCallback);

		
		r=CorDebug->DebugActiveProcess(processid, false, &CorDebugProcess);

		CorDebugProcess->QueryInterface(IID_ICorDebugProcess5, (void **)&CorDebugProcess5);

		CorDebug->Initialize();

		while (MyICorDebugManagedCallback->attached==FALSE) Sleep(100);

		//r=CorDebug->GetProcess(processid, &CorDebugProcess);

	
		CorDebugProcess->Stop(FALSE);
		CorDebugProcess->Detach();
		CorDebug->Release();
		*/

#endif
		if (r!=S_OK)
			return FALSE;
	}


	

	//still here
	return TRUE;
}
Example #9
0
BOOL CPipeServer::OpenOrAttachToProcess(void)
{
	ICLRMetaHost *pMetaHost;
	IEnumUnknown *RuntimeEnum;
	HANDLE ths;
	MODULEENTRY32 m;
	HRESULT r;
	BOOL result=FALSE;
	
	

	CLR_DEBUGGING_VERSION v;
	v.wStructVersion=0;
	v.wMajor=4;
	v.wMinor=0;
	v.wRevision=30319;
	v.wBuild=65535;


	CLRDebugging=NULL;
	CorDebugProcess=NULL;
	CorDebugProcess5=NULL;

	libprovider=NULL;
	datacallback=NULL;



	HMODULE hMscoree = LoadLibraryA("mscoree.dll");
	CLRCreateInstanceFnPtr CLRCreateInstance;

	if (hMscoree==NULL)
		return FALSE;

	CLRCreateInstance=(CLRCreateInstanceFnPtr)GetProcAddress(hMscoree, "CLRCreateInstance");
	if (CLRCreateInstance==NULL)
		return FALSE; //only 4.0 is supported for now

	processhandle=OpenProcess(PROCESS_ALL_ACCESS , FALSE, processid);
	if (processhandle==0)
		return FALSE;
	
	if (CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&pMetaHost)!=S_OK)
		return FALSE;
		
	
	if (pMetaHost->EnumerateLoadedRuntimes(processhandle, &RuntimeEnum)==S_OK)
	{
		ICLRRuntimeInfo *info;
		ULONG count=0;

		RuntimeEnum->Next(1, (IUnknown **)&info, &count);
		if (count)
		{
			result=TRUE;
			libprovider=new CMyICLRDebuggingLibraryProvider(info);  //todo: scan for 4.0			
		}

		RuntimeEnum->Release();
	}
	pMetaHost->Release();

	if (!result)
		return FALSE; //no runtimes

	
	if (CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, (void **)&CLRDebugging)!=S_OK)
		return FALSE;

	

	
	ths=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processid);
	if (ths==INVALID_HANDLE_VALUE)
		return FALSE;

	

	ZeroMemory(&m, sizeof(m));
	m.dwSize=sizeof(m);
	if (Module32First(ths, &m))
	{
		datacallback=new CMyIcorDebugDataTarget(processhandle);

		do
		{
			CLR_DEBUGGING_PROCESS_FLAGS flags;
			r=CLRDebugging->OpenVirtualProcess((ULONG64)m.hModule, datacallback,  libprovider, &v, IID_ICorDebugProcess, (IUnknown **)&CorDebugProcess, &v, &flags);
				
			if (r==S_OK)
			{					
				CorDebugProcess->QueryInterface(IID_ICorDebugProcess5, (void **)&CorDebugProcess5);
				break;
			}
		}
		while (Module32Next(ths, &m));
	}


	CloseHandle(ths);

	if (r!=S_OK)
		return FALSE;

	

	//still here
	return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
	HRESULT hr;

	ICLRMetaHost *pMetaHost = NULL;
	ICLRRuntimeInfo *pRuntimeInfo = NULL;
	ICorRuntimeHost *pCorRuntimeHost = NULL;

	IUnknownPtr spAppDomainThunk = NULL;
	_AppDomainPtr spDefaultAppDomain = NULL;

	// The .NET assembly to load.
	bstr_t bstrAssemblyName("PowerShellRunner");
	_AssemblyPtr spAssembly = NULL;

	// The .NET class to instantiate.
	bstr_t bstrClassName("PowerShellRunner.PowerShellRunner");
	_TypePtr spType = NULL;


	// Start the runtime
	hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
	if (FAILED(hr))
	{
		wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	hr = pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo));
	if (FAILED(hr))
	{
		wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	// Check if the specified runtime can be loaded into the process.
	BOOL fLoadable;
	hr = pRuntimeInfo->IsLoadable(&fLoadable);
	if (FAILED(hr))
	{
		wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	if (!fLoadable)
	{
		wprintf(L".NET runtime v2.0.50727 cannot be loaded\n");
		goto Cleanup;
	}

	// Load the CLR into the current process and return a runtime interface
	hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost,
		IID_PPV_ARGS(&pCorRuntimeHost));
	if (FAILED(hr))
	{
		wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	// Start the CLR.
	hr = pCorRuntimeHost->Start();
	if (FAILED(hr))
	{
		wprintf(L"CLR failed to start w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}


	// Get a pointer to the default AppDomain in the CLR.
	hr = pCorRuntimeHost->GetDefaultDomain(&spAppDomainThunk);
	if (FAILED(hr))
	{
		wprintf(L"ICorRuntimeHost::GetDefaultDomain failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	hr = spAppDomainThunk->QueryInterface(IID_PPV_ARGS(&spDefaultAppDomain));
	if (FAILED(hr))
	{
		wprintf(L"Failed to get default AppDomain w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	// Load the .NET assembly.
	// (Option 1) Load it from disk - usefully when debugging the PowerShellRunner app (you'll have to copy the DLL into the same directory as the exe)
	//hr = spDefaultAppDomain->Load_2(bstrAssemblyName, &spAssembly);
	
	// (Option 2) Load the assembly from memory
	SAFEARRAYBOUND bounds[1];
	bounds[0].cElements = PowerShellRunner_dll_len;
	bounds[0].lLbound = 0;

	SAFEARRAY* arr = SafeArrayCreate(VT_UI1, 1, bounds);
	SafeArrayLock(arr);
	memcpy(arr->pvData, PowerShellRunner_dll, PowerShellRunner_dll_len);
	SafeArrayUnlock(arr);

	hr = spDefaultAppDomain->Load_3(arr, &spAssembly);

	if (FAILED(hr))
	{
		wprintf(L"Failed to load the assembly w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	// Get the Type of PowerShellRunner.
	hr = spAssembly->GetType_2(bstrClassName, &spType);
	if (FAILED(hr))
	{
		wprintf(L"Failed to get the Type interface w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	// Call the static method of the class
	wchar_t* argument = L"Get-Process\n\
						 #This is a PowerShell Comment\n\
						 Write-Host \"`n`n*******  The next command is going to throw an exception.  This is planned *********`n`n\"\n\
						 Read-Host\n";
	
	InvokeMethod(spType, L"InvokePS", argument);

Cleanup:

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

	return 0;
}
bool createDotNetFourHost(HMODULE* hMscoree, const wchar_t* version, ICorRuntimeHost** ppCorRuntimeHost)
{
	HRESULT hr = NULL;
	funcCLRCreateInstance pCLRCreateInstance = NULL;
	ICLRMetaHost *pMetaHost = NULL;
	ICLRRuntimeInfo *pRuntimeInfo = NULL;
	bool hostCreated = false;

	pCLRCreateInstance = (funcCLRCreateInstance)GetProcAddress(*hMscoree, "CLRCreateInstance");
	if (pCLRCreateInstance == NULL)
	{
		wprintf(L"Could not find .NET 4.0 API CLRCreateInstance");
		goto Cleanup;
	}

	hr = pCLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost));
	if (FAILED(hr))
	{
		// Potentially fails on .NET 2.0/3.5 machines with E_NOTIMPL
		wprintf(L"CLRCreateInstance failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	hr = pMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&pRuntimeInfo));
	if (FAILED(hr))
	{
		wprintf(L"ICLRMetaHost::GetRuntime failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	// Check if the specified runtime can be loaded into the process.
	BOOL loadable;
	hr = pRuntimeInfo->IsLoadable(&loadable);
	if (FAILED(hr))
	{
		wprintf(L"ICLRRuntimeInfo::IsLoadable failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	if (!loadable)
	{
		wprintf(L".NET runtime v2.0.50727 cannot be loaded\n");
		goto Cleanup;
	}

	// Load the CLR into the current process and return a runtime interface
	hr = pRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(ppCorRuntimeHost));
	if (FAILED(hr))
	{
		wprintf(L"ICLRRuntimeInfo::GetInterface failed w/hr 0x%08lx\n", hr);
		goto Cleanup;
	}

	hostCreated = true;

Cleanup:

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

	return hostCreated;
}
Example #12
0
EASYHOOK_NT_INTERNAL CompleteManagedInjection(LPREMOTE_INFO InInfo)
{
    /// Region: Temporary workaround for InInfo->Assemblies not being received correctly
    InInfo->AssembliesCount = 3;
    InInfo->Assemblies = new RhAssemblyInfo[InInfo->AssembliesCount];
    InInfo->Assemblies[0].FullName = L"ProcMonInject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d34a061f079be347, ProcessorArchitecture=MSIL";
    InInfo->Assemblies[0].AssemblyLoadPath = L"D:/Documenten/Documenten/Projects/EasyHook/EasyHook - CLRHostingAPI - vs2008/Debug/x64/ProcMonInject.dll";
    InInfo->Assemblies[0].AssemblyDebugInfoPath = NULL;
    InInfo->Assemblies[1].FullName = L"ProcessMonitor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d34a061f079be347, ProcessorArchitecture=MSIL";
    InInfo->Assemblies[1].AssemblyLoadPath = L"D:/Documenten/Documenten/Projects/EasyHook/EasyHook - CLRHostingAPI - vs2008/Debug/x64/ProcessMonitor.exe";
    InInfo->Assemblies[1].AssemblyDebugInfoPath = NULL;
    InInfo->Assemblies[2].FullName = L"EasyHook, Version=2.5.0.0, Culture=neutral, PublicKeyToken=4b580fca19d0b0c5, ProcessorArchitecture=MSIL";
    InInfo->Assemblies[2].AssemblyLoadPath = L"D:/Documenten/Documenten/Projects/EasyHook/EasyHook - CLRHostingAPI - vs2008/Debug/x64/EasyHook.dll";
    InInfo->Assemblies[2].AssemblyDebugInfoPath = NULL;
    /// Endregion

/*
Description:

    Loads the NET runtime into the calling process and invokes the
    managed injection entry point.
*/

#ifdef _NET4
    ICLRMetaHost*	        pMetaClrHost = NULL;
    ICLRRuntimeInfo*        pRuntimeInfo = NULL;
#endif
    REMOTE_ENTRY_INFO       EntryInfo;
	ICLRRuntimeHost*	    pClr = NULL;
    WCHAR                   ParamString[MAX_PATH];
    DWORD                   ErrorCode = 0;
    HMODULE                 hMsCorEE = LoadLibraryA("mscoree.dll");
    PROC_CorBindToRuntime*  CorBindToRuntime = (PROC_CorBindToRuntime*)GetProcAddress(hMsCorEE, "CorBindToRuntime");

    if(CorBindToRuntime == NULL)
        UNMANAGED_ERROR(10);

    // Invoke user defined entry point
    EntryInfo.HostPID = InInfo->HostProcess;
    EntryInfo.UserData = InInfo->UserData;
    EntryInfo.UserDataSize = InInfo->UserDataSize;

    RtlLongLongToUnicodeHex((LONGLONG)&EntryInfo, ParamString);

    // Load the Common Language Runtime
    if(!RTL_SUCCESS(CorBindToRuntime(NULL, NULL, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (void**)&pClr)))
        UNMANAGED_ERROR(11);
    if (!RTL_SUCCESS(AssociateCustomCLRHost(pClr, InInfo->Assemblies, InInfo->AssembliesCount)))
        UNMANAGED_ERROR(14);
	pClr->Start();

    /*
		Test library code.
		This is because if once we have set the remote signal, there is no way to
		notify the host about errors. If the following call succeeds, then it will
		also do so some lines later... If not, then we are still able to report an error.

        The EasyHook managed injection loader will establish a connection to the
        host, so that further error reporting is still possible after we set the event!
	*/
    RtlLongLongToUnicodeHex((LONGLONG)&EntryInfo, ParamString);

    HRESULT result = pClr->ExecuteInDefaultAppDomain(
                            InInfo->UserLibrary, 
                            L"EasyHook.InjectionLoader", L"Main", 
                            ParamString, &ErrorCode);
	if(!RTL_SUCCESS(result))
	{
        // Test failed!
#ifdef _NET4
        // Target CLR might be .NET 4.0, try to load this CLR instead.
		if(NULL != pClr)
	        pClr->Release();
		if(FAILED(CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (void**)&pMetaClrHost)))
			UNMANAGED_ERROR(11);
		if(FAILED(pMetaClrHost->GetRuntime(L"v4.0.30319", IID_ICLRRuntimeInfo, (void**)&pRuntimeInfo)))
			UNMANAGED_ERROR(11);
		if(FAILED(pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (void**) &pClr)))
			UNMANAGED_ERROR(11);
        AssociateCustomCLRHost(pClr);
		pClr->Start();
		RtlLongLongToUnicodeHex((LONGLONG)&EntryInfo, ParamString);
		if(!RTL_SUCCESS(RuntimeClrHost->ExecuteInDefaultAppDomain(InInfo->UserLibrary, L"EasyHook.InjectionLoader", L"Main", ParamString, &RetVal)))
#endif
			UNMANAGED_ERROR(12);
	}

	if(!ErrorCode)
        UNMANAGED_ERROR(13);

	// set and close event
	if(!SetEvent(InInfo->hRemoteSignal))
		UNMANAGED_ERROR(22);
	CloseHandle(InInfo->hRemoteSignal);

	InInfo->hRemoteSignal = NULL;

	// Execute library code (no way for error reporting, so we dont need to check)
	pClr->ExecuteInDefaultAppDomain(
        InInfo->UserLibrary, 
        L"EasyHook.InjectionLoader", 
        L"Main", 
        ParamString, 
        &ErrorCode);

ABORT_ERROR:

	// Release Resources
	if(NULL != pClr)
		pClr->Release();

#ifdef _NET4
    if (NULL != pMetaClrHost)
        pMetaClrHost->Release();
    if (NULL != pRuntimeInfo)
        pRuntimeInfo->Release();
#endif

	return ErrorCode;
}
Example #13
0
VOID StartAssembly(vector<wstring> const& params) 
{
	ICLRMetaHost *pMetaHost = NULL;
    HRESULT hr;
    hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost,
        (LPVOID*)&pMetaHost);

    if (SUCCEEDED(hr))
    {
        IEnumUnknown *peunkRuntimes;
        hr = pMetaHost->EnumerateInstalledRuntimes(&peunkRuntimes);
        if (SUCCEEDED(hr))
        {
            // *** FINDING LATEST RUNTIME ***
            IUnknown *punkRuntime;
            ICLRRuntimeInfo *prtiLatest = NULL;
            WCHAR szLatestRuntimeVersion[MAX_PATH];
            while (peunkRuntimes->Next(1, &punkRuntime, NULL) == S_OK)
            {
                ICLRRuntimeInfo *prtiCurrent;
                hr = punkRuntime->QueryInterface(IID_PPV_ARGS(&prtiCurrent));
                if (SUCCEEDED(hr))
                {
                    if (!prtiLatest)
                    {
                        hr = prtiCurrent->QueryInterface(IID_PPV_ARGS(&prtiLatest));
                        if (SUCCEEDED(hr))
                        {
                            DWORD cch = ARRAYSIZE(szLatestRuntimeVersion);
                            hr = prtiLatest->GetVersionString(szLatestRuntimeVersion, &cch);
                        }
                    }
                    else
                    {
                        WCHAR szCurrentRuntimeVersion[MAX_PATH];
                        DWORD cch = ARRAYSIZE(szCurrentRuntimeVersion);
                        hr = prtiCurrent->GetVersionString(szCurrentRuntimeVersion, &cch);
                        if (SUCCEEDED(hr))
                        {
                            if (wcsncmp(szLatestRuntimeVersion, szCurrentRuntimeVersion, cch) < 0)
                            {
                                hr = prtiCurrent->GetVersionString(szLatestRuntimeVersion, &cch);
                                if (SUCCEEDED(hr))
                                {
                                    prtiLatest->Release();
                                    hr = prtiCurrent->QueryInterface(IID_PPV_ARGS(&prtiLatest));
                                }
                            }
                        }
                    }
                    prtiCurrent->Release();
                }
                punkRuntime->Release();
            }
            peunkRuntimes->Release();

            // *** STARTING CLR ***
            if (SUCCEEDED(hr))
            {
                ICLRRuntimeHost *prth;
                hr = prtiLatest->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID*)&prth);
                if (SUCCEEDED(hr))
                {
					hr = prth->Start();
					if (SUCCEEDED(hr))
					{
						DWORD dwRet = 0;
						hr = prth->ExecuteInDefaultAppDomain(params.at(0).c_str(), params.at(1).c_str(), 
							params.at(2).c_str(), params.at(3).c_str(), &dwRet);
						// hr = 0x80131513 (System.MissingMethodException)

						if (SUCCEEDED(hr))
						{
							// *** Success ***
							MessageBox(GetDesktopWindow(), L"Successfully called managed function.", L"Success", MB_OK);
						}
						hr = prth->Stop();
					}
					prth->Release();
                }
            } 
        }
        pMetaHost->Release();
    }
}
Example #14
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;
}