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; }
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; }
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; }
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; }