سؤال

أنا أقوم بتطوير أ كوم بديل كائن في C ، سيتم استخدامه من قبل تطبيقاتي للاتصال بحوار رفع UAC لبعض الإجراءات التي تتطلب حقوقًا إدارية.

تتمثل الخطة في جعل هذا تصدير وظيفة تأخذ مؤشرًا إلى وظيفة مع عدد متغير من الوسائط وتنفيذها في سياق مختلف. وبهذه الطريقة ، يمكن للتطبيق استخدام هذا الكائن لأداء بعض الإجراءات مع حقوق المسؤول ، كل ما يحتاجون إليه هو استخدام هذا الكائن وتمريره إلى الوظيفة التي يجب تنفيذها مع الحقوق المذكورة.

هذا يعمل جزئيا ، والاتصال cocreateinstance يذهب بشكل جيد ، يتم تمرير مؤشر الوظيفة ويتم تنفيذ وظيفتي. ومع ذلك ، عندما أقوم بإنشاء مثيل لهذا الكائن باستخدام cocreateinstanceasadmin, ، تحدث المشاكل ؛ هنا هو الرمز:


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;
}

الدعوة cocreateinstanceasadmin فشل مع "فئة غير مسجلة".

يتم تسجيل الكائن عن طريق إنشاء مفاتيح التسجيل التالية (إليك مجموعة ملف Reg)


[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]

أفترض أن بعض إدخالات التسجيل مفقودة - هذا هو الاستنتاج الذي أصل إليه عند قراءة رسالة الخطأ. ومع ذلك ، تم تجميع قائمة مفاتيح التسجيل هذه بعد استكشاف الوثائق على MSDN والمواقع الأخرى - لذلك أنا متأكد تمامًا من أنه لم يتم تفويت أي شيء.

من بين الأشياء التي حاولت حلها ذلك لتنفيذها عبر ATL (مثل التسجيل آلي). هذا يعمل ، لكن المشكلة هي أنه لا يمكنني تمرير مؤشر الترون إلى النموذج الأولي للوظيفة التي تم إنشاؤها.

حاولت تمريره باستخدام البديل يكتب:


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

ونتيجة لذلك ، أحصل على "نوع وسيطة غير صالح".

هل يمكن لأحد أن يلقي بعض الضوء على هذا الموضوع؟ ربما ما أحاول تحقيقه غير ممكن حسب التصميم؟

لا يوجد حل صحيح

نصائح أخرى

أعتقد أن المشكلات التي تواجهها هي حسب التصميم وأن نية التحسينات الأمنية للنافذة هي المساعدة في تجنب المخاطر الأمنية المحتملة.

لا تريدك Microsoft حقًا أن ترفع امتيازاتك إذا كان بإمكانك منعك من القيام بذلك. لا ينبغي أن يكون تنفيذ الوظائف التعسفية كمستخدم متميز سهلاً بأي شكل من الأشكال إذا كان Windows نظامًا مضمونًا بشكل لائق. قد تتمكن من محاولة انتحال شخصية مستخدم مختلف باستخدام الرموز المميزة والوصول بشكل أفضل بهذه الطريقة ، ولكن حتى ذلك الحين سيكون امتدادًا. إذا كنت أتذكر صحيحًا ، فلن تضمن انتحالات المستخدمين حتى الحصول على وصول كامل. أفضل حل في هذه الحالة هو فقط استخدام حساب المستخدم Super وطلب الامتيازات الصحيحة بشكل صحيح.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top