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.
