سؤال

أعرف كيفية تشغيل عملية مع امتيازات المسؤول من عملية باستخدام:

proc.StartInfo.UseShellExecute = true;
proc.StartInfo.Verb = "runas";

حيث proc هو system.diagnostics.process. ولكن كيف يفعل المرء العكس؟

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

لا تتردد في تغيير العنوان إلى شيء أفضل، لم أستطع التوصل إلى وصف جيد.

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

المحلول 2

انتهى بنا المطاف باستخدام العينة من مقالة مشروع الرمز هذا: ارتفاع الارتفاع يمكن أن يكون سيئا لتطبيقك: كيفية بدء عملية غير مرتفعة في نهاية التثبيت

يبدو أنه يعمل حتى الآن، أجمعه عن طريق الحقن في Rundll32.exe، بلدي C ++ / Win32 ضعيف إلى حد ما، لذا لم أنظر الكثير في التنفيذ الفعلي، فقط يستخدم. أكد أنه يعمل في نظام التشغيل Vista و Win7 كل من X86 و X64 (على الأقل بالنسبة لنا، X86 و X64 تتطلب DLL مختلفة يتم التحقق منها في وقت التثبيت والآخر يستخدم).

نصائح أخرى

الحل الخاص بك هو استخدام عملية Explorer.exe.

تتمثل الفكرة في تشغيل العملية في الوضع غير المرتفع، باستخدام عملية مستكشف ملفات Windows explorer.exe (معلومات). دعونا نقول العملية التي نريد إطلاقها $TEMP\MyUnElevatedProcess.exe.

لذلك، للحصول على رمز NSIS، سأكتب فقط: (ولكن يمكن تشغيله بأي لغة)

 Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'

مثال رمز (باستخدام مثبت NSIS)

Exec '"$WINDIR\explorer.exe" "$TEMP\MyUnElevatedProcess.exe"'

*** رمز مأخوذة من http://mdb-blog.blogspot.com/2013/01/nsis-lunch-program-as-user-from-uac.html.

إذا كنت ترغب في بدء عملية غير مرتبطة من مرتفع، فيمكنك نسخ رمز الوصول إلى عملية Shell واستخدامه لبدء عملية جديدة.

public static class UnelevatedProcessStarter
{
    public static void Start(string cmdArgs)
    {
        // 1. Get the shell
        var shell = NativeMethods.GetShellWindow();
        if (shell == IntPtr.Zero)
        {
            throw new Exception("Could not find shell window");
        }

        // 2. Copy the access token of the process
        NativeMethods.GetWindowThreadProcessId(shell, out uint shellProcessId);
        var hShellProcess = NativeMethods.OpenProcess(0x00000400 /* QueryInformation */, false, (int)shellProcessId);
        if (!NativeMethods.OpenProcessToken(hShellProcess, 2 /* TOKEN_DUPLICATE */, out IntPtr hShellToken))
        {
            throw new Win32Exception();
        }

        // 3. Dublicate the acess token
        uint tokenAccess = 8 /*TOKEN_QUERY*/ | 1 /*TOKEN_ASSIGN_PRIMARY*/ | 2 /*TOKEN_DUPLICATE*/ | 0x80 /*TOKEN_ADJUST_DEFAULT*/ | 0x100 /*TOKEN_ADJUST_SESSIONID*/;
        var securityAttributes = new SecurityAttributes();

        NativeMethods.DuplicateTokenEx(
            hShellToken,
            tokenAccess,
            ref securityAttributes,
            2 /* SecurityImpersonation */,
            1 /* TokenPrimary */,
            out IntPtr hToken);

        // 4. Create a new process with the copied token
        var si = new Startupinfo();
        si.cb = Marshal.SizeOf(si);

        if (!NativeMethods.CreateProcessWithTokenW(
            hToken,
            0x00000002 /* LogonNetcredentialsOnly */,
            null,
            cmdArgs,
            0x00000010 /* CreateNewConsole */,
            IntPtr.Zero,
            null,
            ref si,
            out ProcessInformation _))
        {
            throw new Win32Exception();
        }
    }

    public class NativeMethods
    {

        [DllImport("user32.dll")]
        public static extern IntPtr GetShellWindow();
        [DllImport("user32.dll", SetLastError = true)]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr OpenProcess(int processAccess, bool bInheritHandle, int processId);
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool OpenProcessToken(IntPtr processHandle, UInt32 desiredAccess, out IntPtr tokenHandle);
        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool DuplicateTokenEx(IntPtr hExistingToken, uint dwDesiredAccess,
            ref SecurityAttributes lpTokenAttributes,
            int impersonationLevel,
            int tokenType,
            out IntPtr phNewToken);
        [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
        public static extern bool CreateProcessWithTokenW(
            IntPtr hToken, int dwLogonFlags,
            string lpApplicationName, string lpCommandLine,
            int dwCreationFlags, IntPtr lpEnvironment,
            string lpCurrentDirectory, [In] ref Startupinfo lpStartupInfo, out ProcessInformation lpProcessInformation);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct ProcessInformation
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SecurityAttributes
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct Startupinfo
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwYSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
}

يمكنك استخدام processstartinfo.username. و processstartinfo.password. لتحديد الحساب الذي تريد تشغيله لعمليتك.

class Program
{
    static void Main(string[] args)
    {
        var psi = new ProcessStartInfo(@"c:\windows\system32\whoami.exe");
        var password = new SecureString();
        password.AppendChar('s');
        password.AppendChar('e');
        password.AppendChar('c');
        password.AppendChar('r');
        password.AppendChar('e');
        password.AppendChar('t');
        psi.Password = password;
        psi.UserName = "username";
        psi.UseShellExecute = false;
        psi.RedirectStandardOutput = true;

        var p = new Process();
        p.StartInfo = psi;
        p.Start();
        p.WaitForExit();

        Console.WriteLine(p.StandardOutput.ReadToEnd());
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top