بدء عملية مرتفعة UAC من خدمة غير تفاعلية (WIN32 / .NET / POWERSHELL)

StackOverflow https://stackoverflow.com/questions/2426594

سؤال

أنا أستخدم خدمة Windows Thrid Windows التي تعالج بعض مهام التشغيل الآلي عن طريق تشغيل البرامج النصية والتنفيذ باستخدام CreateProcessasuser (). أنا في مشاكل في Windows Server 2008 بسبب UAC والطريقة التي يتم التعامل بها ارتفاع LUA من خلال واجهات برمجة التطبيقات.

تعمل الخدمة كوسوع Localsystem ولا تحتوي على تمكين "التفاعل مع سطح المكتب". يتم تشغيل العمليات كمستخدمين في مجموعة المسؤولين، ولكن ليس حساب المسؤول (الذي يعفى من العديد من قيود UAC). جميع الإعدادات الافتراضية UAC في المكان.

يمكنني اجتياز أوامر تعسفية أو كود PowerShell إلى الخدمة، لكنني لا أستطيع أن يبدو أنني "الخروج" من العملية غير المرتفعة وغير التفاعلية التي يتم طرده من الخدمة.

يبدو أن جوهر المشكلة هو أن خيار API الوحيد (العام) لبدء عملية مرتفعة هو shellexecute () الفعل "Runas"، ولكن بقدر ما أستطيع أن أخبر أنه لا يمكن استدعاؤه من غير تفاعلي الخدمة أو تحصل على أخطاء مثل "هذه العملية تتطلب محطة نافذة تفاعلية".

الحل الوحيد الذي وجدته هو مذكور هنا:http://www.eggheadcafe.com/software/aspnet/29620442/how-to-proper-use-sendinp.aspx.

في نظام التشغيل Vista، فإن الطريقة الموثقة الرسمية لرفع العملية تستخدم سوى استخدام SHELT API Shellexecute (EX) (وليس CreateProcess أو CreateProcessasSer). لذلك يجب طلب طلبك استدعاء shelllexecute (ex) لإطلاق مساعد مرتفعة للاتصال SendInput. علاوة على ذلك، نظرا للدورة 0 العزلة، لا يمكن لخدمة استخدام CreateProcessasSuser أو createProcessWithlogonw (لا يمكن استخدام shelllexecute (ex)) لتحديد سطح المكتب التفاعلي.

.. أعتقد أنه لا توجد طريقة مباشرة لتفرخ عملية مرتفعة من خدمة Windows. لا يمكننا إلا أولا استخدام CreateProcessasSuser أو CreateProcessWithlogonw لتفرخ عملية غير مرتفعة في جلسة المستخدم (سطح المكتب التفاعلي). ثم في العملية غير المرتفعة، قد يستخدم SHELLEXECUTE (EX) لتفرخ عملية مرتفعة للمهمة الحقيقية.

للقيام بذلك من .NET / PowerShell Code، يبدو الأمر كما لو أنني يجب أن أقوم ببعض الأشياء المفصلة P / Invoke للاتصال CreateProcessasuser أو CreateProcessWithlogonw منذ أن كان System.Diagnostics.ProcessStartinfo لا يحتوي على ما يعادل LPDesktop الذي يمكنني اضبط على "Winsta0 Default". وأنا لست واضحا إذا كان لدى Localsystem حتى الحق في الاتصال CreateProcessasser أو CreateProcessWithlogonw.

نظرت أيضاhttp:/blogs.msdn.com/alejacma/archive/2007/12/20/how-call-call-createprocesswithlogonw-createprocessasuser-in-aspx.وprocess.start مع أوراق اعتماد مختلفة مع UAC على

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

وإذا كان أي شخص من الأشخاص الذين ينتهي بهم الأمر فوق قراءة هذا، فقد لاحظت أن طريقة التعامل مع Hellexecute تتعامل مع الارتفاع داخليا عن طريق الاتصال بخدمة معلومات التطبيق (AIS). لماذا لا تتوفر نفس الدعوة إلى AIS من خلال بعض Win32 أو api؟http://msdn.microsoft.com/en-us/library/bb756945.aspx.

آسف أن ركض طويل قليلا. شكرا لأي أفكار.

هل كانت مفيدة؟

المحلول

تتمثل طريقة "الرسمية" لكسر جلسة العزلة الصفرية في استخدام مزيج من API للخدمات الطرفية و CreateProcessAsUser() لإطلاق عملية ضمن جلسة مستخدم. في وظيفتي القديمة، فعلنا ذلك تماما، كما كنا بحاجة لعرض مربع حوار للمستخدم من خدمة قبل تثبيت التحديث الذي تم تنزيله، وأنا أعلم أنه يعمل، على WinXP، WIN2K3، VISTA، و WIN7 على الأقل، لكنني على الأقل، لكني لا تتوقع أن الفوز 2k8 سيكون مختلفا جدا. في الأساس، تسير العملية على النحو التالي:

  1. يتصل WTSGetActiveConsoleSessionId() للحصول على معرف جلسة وحدة التحكم النشطة (مهم جدا، لأن الجلسة التفاعلية هي ليس دائما جلسة 1، حتى على أنظمة العملاء). هذا API سيعود أيضا -1 إذا لم يكن هناك مستخدم نشط تسجيل الدخول إلى الجلسة التفاعلية (أي، قام بتسجيل الدخول محليا إلى الجهاز الفعلي، بدلا من استخدام RDP).
  2. اجتياز معرف الجلسة من API السابقة WTSQueryUserToken() للحصول على رمز مميز مفتوح تمبر المستخدم على تسجيل الدخول إلى وحدة التحكم.
  3. يتصل DuplicateTokenEx() لتحويل رمز الانتحال (من WTSQueryUserToken) في رمز أساسي.
  4. يتصل CreateEnvironmentBlock() لإنشاء بيئة جديدة للعملية (اختياري، ولكن إذا لم تكن، فلن تتمتع العملية واحدة).
  5. اجتياز الرمز المميز الأساسي من الخطوة رقم 3 إلى مكالمة CreateProccessAsUser(), ، جنبا إلى جنب مع سطر الأوامر للتنفيذ. إذا قمت بإنشاء كتلة بيئة من الخطوة رقم 4، فيجب عليك اجتياز CREATE_UNICODE_ENVIRONMENT العلم كذلك (دائما). قد يبدو هذا سخيفا، لكن API يفشل بشكل فظيع إذا لم تفعل (مع ERROR_INVALID_PARAMTER).
  6. إذا قمت بإنشاء كتلة بيئة، فأنت بحاجة إلى الاتصال DestroyEnvironmentBlock, وإلا فسوف تولد تسرب الذاكرة. يتم إعطاء العملية نسخة منفصلة من كتلة البيئة عند إطلاقها، لذلك تقوم بتدمير البيانات المحلية فقط.

وفويلا! يقوم Windows ببعض السحر الداخلي، وترى إطلاق التطبيق. ومع ذلك، على الرغم من أن هذا سوف يطلق وعملية تفاعلية من خدمة، إلا أنني لست متأكدا مما إذا كان سيتم تجاوز UAC (ولكن لا اقتبسني بذلك). بمعنى آخر، قد لا يتم تشغيلها كعملية مرتفعة ما لم تقول التسجيل أو البيان الداخلي للقيام بذلك، وحتى عندئذ، ستظل قد تظل مطالبة UAC. إذا كان الرمز المميز الذي تحصل عليه من Step # 3 هو رمز مقيد، فقد تتمكن من استخدامه AdjustTokenPrivileges() لاستعادة الرمز المرتفع (الكامل)، لكن لا اقتبسني بذلك. ومع ذلك، كما هو مذكور في مستندات MSDN، يرجى ملاحظة أنه من الممكن "إضافة" امتيازات "على رمز مميز لم يكن لديها بالفعل (على سبيل المثال لا يمكنك تحويل رمز مستخدم مقيد إلى مسؤول باستخدام AdjustTokenPrivileges; ؛ يجب أن يكون المستخدم الأساسي هو المسؤول عن البدء به).

من الممكن تقنيا أن تفعل كل هذا من WIN2K إلى الأمام. ومع ذلك، فإنه حقا ممكن فقط بدءا من ويندوز إكس بي، كما يفتقر WIN2K إلى WTSGetActiveConsoleSessionId() و WTSQueryUserToken() API (جنبا إلى جنب مع WTSEnumerateProcesses() ل win2k الموالية). يمكنك الكود الصعب 0 كمعرف الجلسة (نظرا لأن هذا هو الحال دائما في WIN2K)، وأفترض أنك قد تتمكن من الحصول على رمز المستخدم من خلال تعداد العمليات الجارية وتكرار واحدة من رموز الرموز الخاصة بهم (يجب أن تكون واحدة لديها الحاضر SID التفاعلي). بغض النظر، CreateProcessAsUser() سوف تتصرف بنفس الطريقة عندما مرت رمز مستخدم تفاعلي، حتى إذا لم تختف "تفاعل مع سطح المكتب" من إعدادات الخدمة. إنه أيضا أكثر أمانا من إطلاقه مباشرة من الخدمة على أي حال، لأن العملية لن ترث إله LocalSystem رمز وصول.

الآن، لا أعرف إذا كان تطبيق طرفك الثالث يقوم بأي من هذا عندما يقوم بتشغيل البرنامج النصي / العملية، ولكن إذا كنت ترغب في القيام بذلك من خدمة، فهذا هو كيف (ومع نظام التشغيل Vista أو Win7، إنها الطريقة الوحيدة ل التغلب على الجلسة 0 العزلة).

نصائح أخرى

اعتمادا على حالة استخدامك، يمكنك أن تفعل ما أقوم به. أطارد عملية Winlogon للجلسة النشطة وسرقة رمزية لها. إذا لم تكن هناك جلسة نشطة (تم إرجاع API -1)، فاستخدم 1 إذا winver> = 6 خلاف ذلك 0. هذا النتائج في النظام في الجلسة النشطة.

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