Pregunta

Yo sé cómo poner en marcha un proceso con privilegios de administrador de un proceso que utiliza:

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

donde proc es un System.Diagnostics.Process. Pero ¿cómo se hace todo lo contrario?

Si el proceso que está en que ya es elevado, ¿cómo se inicia el nuevo proceso sin privilegios de administrador? Más exactamente, es necesario poner en marcha el nuevo proceso con el mismo nivel de permisos como el Explorador de Windows, por lo que no hay cambio si UAC está desactivado, pero si UAC está habilitado, pero nuestro proceso se está ejecutando elevada, es necesario realizar una determinada operación de la ONU-elevado porque estamos creando una unidad virtual y si es creada con permisos elevados y Windows explorer se ejecuta unelevated no se mostrará.

No dude en cambiar el título a algo mejor, no podía llegar a una buena descripción.

¿Fue útil?

Solución 2

Terminamos con la muestra de este artículo Proyecto de Código: alta elevación puede ser malo para su aplicación: ¿Cómo iniciar un proceso no elevada al final de la instalación

Parece que funciona hasta ahora, supongo que inyecta en RUNDLL32.EXE, mi C ++ / Win32 es bastante débil por lo que no se veía demasiado en la implementación real, simplemente su uso. Confirmó que funciona en Vista y Win7 tanto x86 y x64 (al menos para nosotros, x86 y x64 requieren diferente de DLL que se comprueba durante la instalación y se utiliza el apropiado).

Otros consejos

La solución para usted es utilizar el proceso explorer.exe.

La idea es ejecutar el proceso en modo elevado por la ONU, usando explorer.exe proceso de explorador de archivos de Windows ( información de ). Digamos que el proceso que queremos poner en marcha está en $TEMP\MyUnElevatedProcess.exe.

Por lo tanto, para el código NSIS, voy a escribir: (pero se puede ejecutar en cualquier idioma)

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

Ejemplo de código ( usando el instalador NSIS )

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

*** código tomado de http://mdb-blog.blogspot.com/2013/01/nsis-lunch-program-as-user-from-uac.html

Si desea iniciar un proceso de una unelevated una elevada podría copiar el token de acceso del proceso de concha y utilizarlo para iniciar un nuevo proceso.

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

Puede utilizar ProcessStartInfo.UserName y ProcessStartInfo.Password para especificar el cuenta a la que desea que su proceso se ejecute bajo.

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());
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top