Question

I am developing a COM surrogate object in C, it will be used by my applications to call the UAC elevation dialog for certain actions that require administrative rights.

The plan is to make this it export a function that takes a pointer to a function with a variable number of arguments and executes it in a different context. This way, an application can use this object to perform some actions with admin rights, all they need to do is use that object and pass it a pointer to the function that has to be executed with said rights.

This works partially, calling CoCreateInstance goes fine, the function pointer is passed and my function is executed. However, when I create an instance of this object using CoCreateInstanceAsAdmin, problems occur; here is the code:


HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
 // Manual implementation of CreateInstanceAsAdmin
 CComPtr BindCtx;
 HRESULT hr = CreateBindCtx(0,&BindCtx);
 BIND_OPTS3 bo;
 memset(&bo, 0, sizeof(bo));
 bo.cbStruct = sizeof(bo);
 bo.grfMode = STGM_READWRITE;
 bo.hwnd = hwnd;
 bo.dwClassContext = CLSCTX_LOCAL_SERVER;
 hr = BindCtx->SetBindOptions(&bo);
 if (SUCCEEDED(hr))
 {
  // Use the passed in CLSID to help create the COM elevation moniker string
  CComPtr Moniker;
  WCHAR wszCLSID[50];
  WCHAR wszMonikerName[300];
  StringFromGUID2(rclsid,wszCLSID,sizeof(wszCLSID) / sizeof(wszCLSID[0]));
  //Elevation:Administrator!new
  hr = StringCchPrintfW(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);
  if (SUCCEEDED(hr))
  {
   // Create the COM elevation moniker
   ULONG ulEaten = 0;
   ULONG ulLen = (ULONG)wcslen(wszMonikerName);
   LPBC pBindCtx = BindCtx.p;
   hr = MkParseDisplayName(pBindCtx,wszMonikerName,&ulEaten,&Moniker);
   if (SUCCEEDED(hr) && ulEaten == ulLen)
   {
    // Use passed in reference to IID to bind to the object
    IDispatch * pv = NULL;
    hr = Moniker->BindToObject(pBindCtx,NULL,riid,ppv);
   }
  }
 }
 return hr;
}

Calling CoCreateInstanceAsAdmin fails with "Class not registered".

The object is registered by creating the following registry keys (here's the body of the REG file)


[HKEY_CLASSES_ROOT\COMsurrogate]
@="COMsurrogate Class"

[HKEY_CLASSES_ROOT\COMsurrogate\CurVer]
@="COMsurrogate.1"

[HKEY_CLASSES_ROOT\COMsurrogate\CLSID]
@="{686B6F70-06AE-4dfd-8C26-4564684D9F9F}"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}]
@="COMsurrogate Class"
"LocalizedString"="@C:\\Windows\\system32\\COMsurrogate.dll,-101"
"DllSurrogate"=""

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\ProgID]
@="COMsurrogate.1"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\VersionIndependentProgID]
@="COMsurrogate"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\InprocServer32]
@="@C:\\windows\system32\COMsurrogate.dll"
"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\NotInsertable]

[HKEY_CLASSES_ROOT\CLSID\{686B6F70-06AE-4dfd-8C26-4564684D9F9F}\Programmable]

I suppose that some registry entries are missing - that's the conclusion I reach when reading the error message. However, this list of registry keys was compiled after exploring the documentation on MSDN and other sites - so I am pretty certain that nothing was missed.

Among the things I've tried to solve this is to implement it via ATL (such that registration is automated). That works, but the problem is that I can't pass a funtion pointer to the MIDL generated function prototype.

I tried to pass it using the VARIANT type:


 v.vt = VT_PTR;
 void (*myptr)(void);
 myptr = &DoTheStuff;
 v.byref = myptr;
 hr = theElevated->CoTaskExecuter(0, v);

as result I get "Invalid argument type".

Could someone shed some light on the subject? Perhaps what I am trying to achieve is not possible by design?

No correct solution

OTHER TIPS

I believe the issues you are having is by design and that the intent of window's security improvements were to help avoid potential security risks.

Microsoft doesn't really want you to elevate your privileges if it can stop you from doing so. Executing arbitrary functions as a privileged user shouldn't be easy in any way if Windows is even a decently secured system. You might could try impersonating a different user using tokens and getting better access that way, but even then it would be a stretch. If I remember right, user impersonations won't even guarantee that you'll get full access. The best solution in this case is just to use the super user account and properly request the correct privileges.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top