Dynamorio NOTICE: Unable to load OLEAUT32.dll: lib initiliazer failed
Created by: Caflo
Describe the bug When I run with my dr tool on a specific function that does WMI logic, Dynamorio fires a notice saying that cannot load OLEAUT32 module.
To Reproduce Steps to reproduce the behavior:
- Import the necessary COM libraries to declare a CComBSTR object inside dr tool
- Run: ddrun.exe -c drtool.dll -- program
- Exact output or incorrect behavior: Application C:\Users\student\Documents\DBITOOL\tests\wmiexample\Debug\wmiexample.exe (5464). Unable to load client library: OLEAUT32.dll: library initializer failed..
Please also answer these questions:
- What happens when you run without any client? No error.
- What happens when you run with debug build ("-debug" flag to drrun/drconfig/drinject)? Ouput is printed on console instead of Notice window: Application C:\Users\student\Documents\DBITOOL\tests\wmiexample\Debug\wmiexample.exe (5464). Unable to load client library: OLEAUT32.dll: library initializer failed..
Expected behavior I expect the program to continue the execution.
Screenshots or Pasted Text This is the source code for the program to be instrumented:
``` #define _WIN32_DCOM #include #include #include #include #pragma comment(lib, "wbemuuid.lib") using namespace std; BOOL InitWMI(IWbemServices** pSvc, IWbemLocator** pLoc, const TCHAR* szNetworkResource) { // Initialize COM. HRESULT hres; hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { return 0; } // Set general COM security levels hres = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL); if (FAILED(hres)) { CoUninitialize(); return 0; } // Obtain the initial locator to WMI hres = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(pLoc)); if (FAILED(hres)) { CoUninitialize(); return 0; } BSTR strNetworkResource = SysAllocString(szNetworkResource); if (strNetworkResource) { // Connect to the root\cimv2 namespace // 'ConnectServer' function makes dr throw strange exceptions, and this happen only in al-khaser (wmiexample is good) // I tried disabling everything in my DBI tool, but can't solve the problem hres = (*pLoc)->ConnectServer(strNetworkResource, NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, 0, 0, pSvc); if (FAILED(hres)) { SysFreeString(strNetworkResource); (*pLoc)->Release(); CoUninitialize(); return 0; } SysFreeString(strNetworkResource); } // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket(*pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); if (FAILED(hres)) { (*pSvc)->Release(); (*pLoc)->Release(); CoUninitialize(); return 0; } return 1; } BOOL ExecWMIQuery(IWbemServices** pSvc, IWbemLocator** pLoc, IEnumWbemClassObject** pEnumerator, const TCHAR* szQuery) { // Execute WMI query BSTR strQueryLanguage = SysAllocString(OLESTR("WQL")); BSTR strQuery = SysAllocString(szQuery); BOOL bQueryResult = TRUE; if (strQueryLanguage && strQuery) { HRESULT hres = (*pSvc)->ExecQuery(strQueryLanguage, strQuery, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, pEnumerator); if (FAILED(hres)) { bQueryResult = FALSE; (*pSvc)->Release(); (*pLoc)->Release(); CoUninitialize(); } } if (strQueryLanguage) SysFreeString(strQueryLanguage); if (strQuery) SysFreeString(strQuery); return bQueryResult; } BOOL disk_size_wmi() { IWbemServices* pSvc = NULL; IWbemLocator* pLoc = NULL; IEnumWbemClassObject* pEnumerator = NULL; BOOL bStatus = FALSE; HRESULT hRes; BOOL bFound = FALSE; UINT64 minHardDiskSize = (80ULL * (1024ULL * (1024ULL * (1024ULL)))); UINT minHardDiskSize32 = (80ULL * (1024ULL * (1024ULL * (1024ULL)))); // Init WMI bStatus = InitWMI(&pSvc, &pLoc, _T("ROOT\\CIMV2")); if (bStatus) { // If success, execute the desired query bStatus = ExecWMIQuery(&pSvc, &pLoc, &pEnumerator, _T("SELECT * FROM Win32_LogicalDisk")); if (bStatus) { // Get the data from the query IWbemClassObject* pclsObj = NULL; ULONG uReturn = 0; VARIANT vtProp; // Iterate over our enumator while (pEnumerator) { hRes = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) break; // Get the value of the Name property const wchar_t* str = _T("Size"); hRes = pclsObj->Get(str, 0, &vtProp, NULL, 0); printf("Addr of str: 0x%x\n", str); printf("Addr of vProp: 0x%x\n", &vtProp); if (SUCCEEDED(hRes)) { if (V_VT(&vtProp) != VT_NULL) { // convert disk size string to bytes errno = 0; unsigned long long diskSizeBytes = _tcstoui64_l(vtProp.bstrVal, NULL, 10, _get_current_locale()); printf("diskSizeBytes: %llu\n", diskSizeBytes); printf("minHardDiskSize32: %llu\n", minHardDiskSize32); printf("minHardDiskSize: %llu\n", minHardDiskSize); // do the check only if we successfuly got the disk size if (errno == 0) { // Do our comparison if (diskSizeBytes < minHardDiskSize) { // Less than 80GB bFound = TRUE; } } //wchar_t wc[] = L"85793435648"; //vtProp.bstrVal = MySysAllocString(wc); BSTR wc = SysAllocString(L"85793435648"); vtProp.bstrVal = wc; // release the current result object HRESULT hres = VariantClear(&vtProp); //SysFreeString(vtProp.bstrVal); } } // release class object pclsObj->Release(); // break from while if (bFound) break; } // Cleanup pEnumerator->Release(); pSvc->Release(); pLoc->Release(); CoUninitialize(); } } return bFound; } void wmi_get_cpu_fan() { HRESULT hres; // Initialize COM. hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. " << "Error code = 0x" << hex << hres << endl; exit(-1); // Program has failed. } // Initialize hres = CoInitializeSecurity( NULL, -1, // COM negotiates service NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { cout << "Failed to initialize security. " << "Error code = 0x" << hex << hres << endl; CoUninitialize(); exit(-1); // Program has failed. } // Obtain the initial locator to Windows Management // on a particular host computer. IWbemLocator* pLoc = 0; hres = CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLoc); if (FAILED(hres)) { cout << "Failed to create IWbemLocator object. " << "Error code = 0x" << hex << hres << endl; CoUninitialize(); exit(-1); // Program has failed. } IWbemServices* pSvc = 0; // Connect to the root\cimv2 namespace with the // current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), // WMI namespace NULL, // User name NULL, // User password 0, // Locale NULL, // Security flags 0, // Authority 0, // Context object &pSvc // IWbemServices proxy ); if (FAILED(hres)) { cout << "Could not connect. Error code = 0x" << hex << hres << endl; pLoc->Release(); CoUninitialize(); exit(-1); // Program has failed. } cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl; // Set the IWbemServices proxy so that impersonation // of the user (client) occurs. hres = CoSetProxyBlanket( pSvc, // the proxy to set RPC_C_AUTHN_WINNT, // authentication service RPC_C_AUTHZ_NONE, // authorization service NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // authentication level RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hres)) { cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); exit(-1); // Program has failed. } // Use the IWbemServices pointer to make requests of WMI. // Make requests here: // For example, query for all the running processes IEnumWbemClassObject* pEnumerator = NULL; printf("Executing ::ExecQuery ...\n"); hres = pSvc->ExecQuery( bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Fan"), // prepend 'My' if you are executing it without DBI WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { cout << "Query for processes failed. " << "Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); exit(-1); // Program has failed. } else { //pEnumerator = (IEnumWbemClassObject *)malloc(sizeof(IEnumWbemClassObject)); IWbemClassObject* pclsObj; ULONG uReturn = 0; while (pEnumerator) { printf("Executing ::Next ...\n"); hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (0 == uReturn) { break; } VARIANT vtProp; // Get the value of the Name property printf("Executing ::Get ...\n"); hres = pclsObj->Get(L"Description", 0, &vtProp, 0, 0); if (FAILED(hres)) { cout << "Query for processes failed. " << "Error code = 0x" << hex << hres << endl; pSvc->Release(); pLoc->Release(); CoUninitialize(); exit(-1); // Program has failed. } else { wcout << "Result : " << vtProp.bstrVal << endl; VariantClear(&vtProp); pclsObj->Release(); pclsObj = NULL; } } } // Cleanup // ======== pSvc->Release(); pLoc->Release(); pEnumerator->Release(); CoUninitialize(); return; // Program successfully completed. } int main(int argc, char** argv) { //wmi_get_cpu_fan(); // THIS DOES NOT THROW ERROR disk_size_wmi(); // THIS THROWS ERROR printf("\nEnd of tests.\n"); } ```
Versions
- What version of DynamoRIO are you using? drrun version 9.0.19213 -- build 0
- Does the latest build from https://github.com/DynamoRIO/dynamorio/releases solve the problem? No
- What operating system version are you running on? ("Windows 10" is not sufficient: give the release number.) Microsoft Windows [Version 10.0.17134.165]
- Is your application 32-bit or 64-bit? 32bit
Additional context Add any other context about the problem here.