Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • D dynamorio
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 1,467
    • Issues 1,467
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 44
    • Merge requests 44
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • DynamoRIO
  • dynamorio
  • Issues
  • #5714
Closed
Open
Issue created Nov 01, 2022 by Administrator@rootContributor

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:

  1. Import the necessary COM libraries to declare a CComBSTR object inside dr tool
  2. Run: ddrun.exe -c drtool.dll -- program
  3. 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");

}

```

Screenshot of output: image

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.

Assignee
Assign to
Time tracking