Generare un processo eseguito nel contesto dell'utente rappresentato in Microsoft ASP.NET

Questo articolo descrive come generare un processo eseguito nel contesto dell'utente rappresentato.

Versione originale del prodotto: ASP.NET
Numero KB originale: 889251

Introduzione

Questo articolo dettagliato descrive come generare un processo eseguito nel contesto dell'utente rappresentato nelle pagine ASP.NET. Per generare un processo eseguito nel contesto dell'utente rappresentato, non è possibile utilizzare il System.Diagnostics.Process.Start metodo . Ciò avviene perché in ASP.NET la rappresentazione viene eseguita a livello di thread e non a livello di processo. Pertanto, qualsiasi processo generato da ASP.NET verrà eseguito nel contesto del processo di lavoro ASP.NET e non nel contesto rappresentato.

Descrizione della tecnica

Per risolvere questo problema, è necessario effettuare chiamate platform invoke (P/Invoke) alle API Win32 seguenti:

  • La CreateProcessAsUser funzione crea un processo sotto l'identità del token di sicurezza specificato in uno dei parametri. Tuttavia, la chiamata alla CreateProcessAsUser funzione richiede un token primario. Pertanto, è necessario convertire il token rappresentato in un token primario.

  • La DuplicateTokenEx funzione converte un token rappresentato in un token primario. La chiamata alla CreateProcessAsUser funzione usa questo token primario.

Nota

Per il corretto funzionamento della CreateProcessAsUser chiamata alla funzione, è necessario assegnare all'utente rappresentato i diritti utente di sicurezza seguenti:

  • In un computer che esegue Windows assegnare il diritto utente Sostituisci un token a livello di processo e il diritto utente Aumenta quote all'utente rappresentato.
  • In un computer che esegue Windows Server o Windows XP assegnare il diritto utente Sostituisci un token a livello di processo all'utente rappresentato.

Passaggi per generare un processo

Microsoft fornisce esempi di programmazione a scopo puramente illustrativo, senza alcuna garanzia di qualsiasi tipo, sia espressa che implicita, ivi incluse, senza limitazioni, le garanzie implicite di commerciabilità o idoneità per uno scopo particolare. In questo articolo si presuppone che l'utente conosca il linguaggio di programmazione in questione e gli strumenti utilizzati per creare ed eseguire il debug delle procedure. Gli esperti Microsoft sono autorizzati a fornire spiegazioni in merito alla funzionalità di una particolare routine, ma in nessun caso a modificare questi esempi per fornire funzionalità aggiuntive o a creare routine atte a soddisfare specifiche esigenze. Per generare un processo eseguito nel contesto dell'utente rappresentato, seguire questa procedura:

  1. In Visual Studio .NET creare una nuova applicazione Web Visual C# ASP.NET e quindi denominare l'applicazione Q889251.

  2. Aprire il file WebForm1.aspx nella visualizzazione codice.

  3. Nel file WebForm1.aspx aggiungere le istruzioni seguenti al blocco using di codice.

    using System.Runtime.InteropServices;
    using System.Security.Principal;
    
  4. Individuare la riga di codice simile alla riga di codice seguente.

    public class WebForm1 : System.Web.UI.Page
    
  5. Dopo la riga di codice identificata nel passaggio 4, aggiungere il codice seguente.

    [StructLayout(LayoutKind.Sequential)]
    public struct STARTUPINFO
    {
        public int cb;
        public String lpReserved;
        public String lpDesktop;
        public String lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public uint dwProcessId;
        public uint dwThreadId;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int Length;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }
    [DllImport("kernel32.dll", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    public extern static bool CloseHandle(IntPtr handle);
    [DllImport("advapi32.dll", EntryPoint="CreateProcessAsUser", SetLastError=true, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.StdCall)]
    public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment, String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
    [DllImport("advapi32.dll", EntryPoint="DuplicateTokenEx")]
    public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess, ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);
    
  6. In Esplora soluzioni fare clic con il pulsante destro del mouse su WebForm1.aspx e quindi scegliere Apri. Il modulo Web viene aperto in visualizzazione progettazione.

  7. Scegliere Origine HTML dal menu Visualizza.

  8. Sostituire tutto il codice esistente nella finestra Origine HTML con il codice seguente.

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="Q889251.WebForm1" %>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
    <HTML>
       <HEAD>
          <title>WebForm1</title>
          <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">
          <meta name="CODE_LANGUAGE" Content="C#">
          <meta name="vs_defaultClientScript" content="JavaScript">
          <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
       </HEAD>
       <body>
          <form id="Form1" method="post" runat="server">
             <P>&nbsp;</P>
             <P>
                Enter Path of process to be run (with relevant parameters)
                <asp:TextBox id="TextBox1" runat="server"></asp:TextBox>
             </P>
             <P>
                <asp:Button id="Button1" runat="server" Text="CreateProcess"></asp:Button>
             </P>
             <P>
                <asp:Label id="Label1" runat="server">Status:</asp:Label>
             </P>
             <P>
                <asp:Label id="Label2" runat="server">Impersonated Identity:</asp:Label>
             </P>
          </form>
       </body>
    </HTML>
    
  9. Scegliere Progettazione dal menu Visualizza.

  10. Fare doppio clic su CreateProcess. Il Button1_Click metodo viene inserito nel codice e il codice viene visualizzato nel riquadro del contenuto.

  11. Sostituire il metodo esistente Button1_Click con il codice seguente.

    private void Button1_Click(object sender, System.EventArgs e)
    {
        IntPtr Token = new IntPtr(0);
        IntPtr DupedToken = new IntPtr(0);
        bool ret;
        Label2.Text+=WindowsIdentity.GetCurrent().Name.ToString();
        SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
        sa.bInheritHandle = false;
        sa.Length = Marshal.SizeOf(sa);
        sa.lpSecurityDescriptor = (IntPtr)0;
        Token = WindowsIdentity.GetCurrent().Token;
        const uint GENERIC_ALL = 0x10000000;
        const int SecurityImpersonation = 2;
        const int TokenType = 1;
        ret = DuplicateTokenEx(Token, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref DupedToken);
        if (ret == false)
        {
            Label1.Text +="DuplicateTokenEx failed with " + Marshal.GetLastWin32Error();
        }
        else
        {
            Label1.Text+= "DuplicateTokenEx SUCCESS";
            STARTUPINFO si = new STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = "";
            string commandLinePath;
            commandLinePath = TextBox1.Text;
            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
            ret = CreateProcessAsUser(DupedToken,null,commandLinePath, ref sa, ref sa, false, 0, (IntPtr)0, "c:\\", ref si, out pi);
            if (ret == false)
            {
                Label1.Text +="CreateProcessAsUser failed with " + Marshal.GetLastWin32Error();
            }
            else
            {
                Label1.Text +="CreateProcessAsUser SUCCESS. The child PID is" + pi.dwProcessId;
                CloseHandle(pi.hProcess);
                CloseHandle(pi.hThread);
            }
            ret = CloseHandle(DupedToken);
            if (ret == false)
            {
                Label1.Text+=Marshal.GetLastWin32Error();
            }
            else
            {
                Label1.Text+="CloseHandle SUCCESS";
            }
        }
    }
    
  12. Nel menu Compila fare clic su Compila soluzione.

  13. Scegliere Avvia dal menu Debug.

  14. Nella pagina WebForm1 digitare il percorso di un processo da avviare. Ad esempio, digitare SystemDriver \Windows\Notepad.exe.

  15. Fare clic su CreaProcesso.

Riferimenti