Как вы понижаете привилегии для дочернего процесса

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

  •  19-09-2019
  •  | 
  •  

Вопрос

Я знаю, как запустить процесс с правами администратора из процесса, использующего:

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

где proc - это система.Диагностика.Процесс.Но как можно сделать обратное?

Если у процесса, в котором вы участвуете, уже повышены права доступа, как вы запускаете новый процесс без прав администратора?Точнее, нам нужно запустить новый процесс с тем же уровнем разрешений, что и проводник Windows, поэтому никаких изменений, если UAC отключен, не произойдет, но если UAC включен, но наш процесс запущен с повышенными правами доступа, нам нужно выполнить определенную операцию без повышенных прав доступа, потому что мы создаем виртуальный диск, и если он создан с повышенными правами доступа, а проводник Windows запущен без повышенных прав доступа, он не будет отображаться.

Не стесняйтесь изменить название на что-нибудь получше, я не смог придумать хорошего описания.

Это было полезно?

Решение 2

В итоге мы использовали пример из этой статьи Code Project: Большая высота может быть вредна для вашего приложения:Как запустить процесс без повышенных прав в конце установки

Кажется, пока это работает, я полагаю, это внедряется в RunDll32.exe мой C ++ / Win32 довольно слаб, поэтому я не слишком разбирался в реальной реализации, просто использовал ее.Подтверждено, что это работает в Vista и Win7 как для x86, так и для x64 (по крайней мере, для нас для x86 и x64 требуются разные библиотеки dll, которые проверяются во время установки и используется правильная).

Другие советы

Решение для вас - использовать EXPLORER.exe process.

Идея состоит в том, чтобы запустить процесс в режиме без прав доступа, используя процесс проводника 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

Если вы хотите запустить процесс без повышения уровня с процесса с повышенным уровнем, вы могли бы скопировать токен доступа процесса оболочки и использовать его для запуска нового процесса.

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.Имя пользователя и ProcessStartInfo.Пароль указать учетную запись, под которой вы хотите, чтобы ваш процесс выполнялся.

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