Scanning COM dll registry without admin privileges

0

I'm trying to create a program that scans a COM dll and creates a reg file of the necessary registry keys, without having to call regsvr32 and without having to have administrative permissions.

To do that, I'm using RegOverridePredefKey to remap the windows registry hives inside a subkey of HKEY_CURRENT_USER.

https://msdn.microsoft.com/pt-br/library/windows/desktop/ms724901(v=vs.85).aspx

The remapping is working. I know because I can, for instance, call a windows api function to create a bogus registry key under HKEY_LOCAL_MACHINE and it actually appears under my HKEY_CURRENT_USER subkey. No admin privileges required.

Here is the remaping code:

if (reg::remapRegistry(HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, basekey + "hkcr"))
    {
        if (reg::remapRegistry(HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER, basekey + "hklm"))
        {
            if (reg::remapRegistry(HKEY_USERS, HKEY_CURRENT_USER, basekey + "hku"))
            {
                if (reg::remapRegistry(HKEY_CURRENT_USER, HKEY_CURRENT_USER, basekey + "hkcu"))
                {
                    reg::createKey(HKEY_LOCAL_MACHINE, "Software\\Classes");
                    reg::createKey(HKEY_CURRENT_USER, "Software\\Classes");
                    ret = scan(args);
                    reg::cancelRemapedRegistry(HKEY_CURRENT_USER);
                }
                reg::cancelRemapedRegistry(HKEY_USERS);
            }
            reg::cancelRemapedRegistry(HKEY_LOCAL_MACHINE);
        }
        reg::cancelRemapedRegistry(HKEY_CLASSES_ROOT);
    }

The args parameter to my scan function is just a structure with the path to my dll. The reg:: functions are just wrappers around windows api.

Here is my scan function:

int scan(const Args &args)
{
typedef HRESULT (__stdcall *pDllRegisterServer) (void);
try
{
    HMODULE hDLL = LoadLibrary(args.dll.c_str());
    if (hDLL == NULL)
    {
        LOGERROR("Cannot load dll");
        return 1;
    }

    pDllRegisterServer DllRegisterServer = (pDllRegisterServer) GetProcAddress(hDLL, "DllRegisterServer");
    if (DllRegisterServer == NULL)
    {
        LOGERROR("Cannot find function DllRegisterServer in dll");
        FreeLibrary(hDLL);
        return 2;
    }

    HRESULT res = DllRegisterServer();
    DWORD err = GetLastError();

    switch (res)
    {
    case S_OK:
        LOGINFO("successfully called DllRegisterServer");
        return 0;
    case SELFREG_E_TYPELIB:
        LOGERROR("DllRegisterServer error SELFREG_E_TYPELIB");
        return 3;
    case SELFREG_E_CLASS:
        LOGERROR("DllRegisterServer error SELFREG_E_CLASS");
        return 4;
    case E_OUTOFMEMORY:
        LOGERROR("DllRegisterServer error E_OUTOFMEMORY");
        return 5;
    case E_UNEXPECTED:
        LOGERROR("DllRegisterServer error E_UNEXPECTED");
        return 6;
    default:
        LOGERROR("DllRegisterServer really unexpected error");
    }

    return 7;
}
catch (...)
{
    LOGERROR("unknown error loading dll or function");
    return -1;
}
}

DllRegisterServer is returning S_OK but only half the registry keys are being created. My remapped HKEY_CLASSES_ROOT under HKEY_CURRENT_USER\tempkey\hkcr contains all the expected keys. But HKEY_CURRENT_USER\tempkey\hklm (remapped HKEY_LOCAL_MACHINE) contains only the empty keys "Software\Classes" that I have created myself. It is missing the "TypeLib" and "Interface" keys that DllRegisterServer was supposed to create.

It is not a remapping or permission problem because I can create the empty "Software\Classes" under HKEY_LOCAL_MACHINE without admin rights.

Strangely, testing on another machine DllRegisterServer failed with SELFREG_E_TYPELIB.

I also tried calling LoadTypeLib() and RegisterTypeLib() for which I get the error code "0x8002801c Error accessing the OLE registry."

If I then restart visual studio as administrator and run the program again, I get all expected registry key, including the ones under HKLM.

Any ideas on why is it failing and how to get this thing working?

I know it is possible to get all registry keys without being an administrator, because wix's harvest tool heat.exe does that successfully. I already inspected their source code and I believe I'm already doing all that they are doing. And I don't want to have the wix toolset as a requirement to my build environment just to do that, also because I would need to parse their file format into a *.reg file.

wix
registry
regsvr32
heat
asked on Stack Overflow Jun 5, 2017 by Alex

1 Answer

0

I found out the solution: we must call the function OaEnablePerUserTLibRegistration() before doing the remap.

https://msdn.microsoft.com/en-us/library/windows/desktop/cc713570(v=vs.85).aspx

After calling that function, the callback DllRegisterServer() from the COM dll will try to create the typelib keys under HKCR instead of HKLM.

answered on Stack Overflow Jun 7, 2017 by Alex

User contributions licensed under CC BY-SA 3.0