Erstellen sie einen Prozess, der im Kontext des benutzers imitierten Benutzer ausgeführt wird, in Microsoft ASP.NET

In diesem Artikel wird beschrieben, wie Sie einen Prozess erstellen, der im Kontext des imitierten Benutzers ausgeführt wird.

              Originale Produktversion: ASP.NET
Ursprüngliche KB-Nummer: 889251

Einführung

In diesem Schritt-für-Schritt-Artikel wird beschrieben, wie Sie einen Prozess erstellen, der im Kontext des imitierten Benutzers auf ASP.NET Seiten ausgeführt wird. Um einen Prozess zu erzeugen, der im Kontext des imitierten Benutzers ausgeführt wird, können Sie die System.Diagnostics.Process.Start -Methode nicht verwenden. Dies liegt daran, dass in ASP.NET der Identitätswechsel auf Threadebene und nicht auf Prozessebene ausgeführt wird. Daher wird jeder Prozess, den Sie aus ASP.NET unter dem Kontext des ASP.NET Workerprozesses und nicht unter dem Kontext des Identitätswechsels ausgeführt.

Beschreibung der Technik

Um dieses Problem zu umgehen, müssen Sie Plattformaufrufe (P/Invoke) an die folgenden Win32-APIs senden:

  • Die CreateProcessAsUser Funktion erstellt einen Prozess unter der Identität des Sicherheitstokens, das in einem der Parameter angegeben ist. Der Aufruf der CreateProcessAsUser Funktion erfordert jedoch ein primäres Token. Daher müssen Sie das Identitätswechseltoken in ein primäres Token konvertieren.

  • Die DuplicateTokenEx Funktion konvertiert ein token imitiert in ein primäres Token. Der Aufruf der CreateProcessAsUser Funktion verwendet dieses primäre Token.

Hinweis

Damit der Aufruf der CreateProcessAsUser Funktion funktioniert, müssen dem benutzer imitierten Benutzer die folgenden Sicherheitsbenutzerrechte zugewiesen werden:

  • Weisen Sie auf einem Computer, auf dem Windows ausgeführt wird, dem imitierten Benutzer die Benutzerrechte Token auf Prozessebene ersetzen und Kontingente erhöhen zu.
  • Weisen Sie auf einem Computer, auf dem Windows Server oder Windows XP ausgeführt wird, dem imitierten Benutzer das Benutzerrecht Token auf Prozessebene ersetzen zu.

Schritte zum Erstellen eines Prozesses

Die Verwendung der hier aufgeführten Informationen, Makro- oder Programmcodes geschieht auf Ihre eigene Verantwortung. Microsoft stellt Ihnen diese Informationen sowie Makro- und Programmlistings ohne Gewähr auf Richtigkeit, Vollständigkeit und/oder Funktionsfähigkeit sowie ohne Anspruch auf Support zur Verfügung. Die zur Verfügung gestellten Makro- und Programmierungsbeispiele sollen lediglich exemplarisch die Funktionsweise des Beispiels aufzeigen. Die Microsoft Support-Spezialisten können bei der Erläuterung der Funktionalität bestimmter Prozeduren helfen, jedoch werden sie diese Beispiele nicht in Bezug auf eine erweiterte Funktionalität verändern, noch werden sie Prozeduren entwickeln, die auf Ihre besonderen Bedürfnisse zugeschnitten sind. Führen Sie die folgenden Schritte aus, um einen Prozess zu erstellen, der im Kontext des imitierten Benutzers ausgeführt wird:

  1. Erstellen Sie in Visual Studio .NET eine neue Visual C#-ASP.NET-Webanwendung, und benennen Sie die Anwendung dann Q889251.

  2. Öffnen Sie die WebForm1.aspx-Datei in der Codeansicht.

  3. Fügen Sie in der WebForm1.aspx-Datei dem using-Codeblock die folgenden -Anweisungen hinzu.

    using System.Runtime.InteropServices;
    using System.Security.Principal;
    
  4. Suchen Sie die Codezeile, die der folgenden Codezeile ähnelt.

    public class WebForm1 : System.Web.UI.Page
    
  5. Fügen Sie nach der in Schritt 4 identifizierten Codezeile den folgenden Code hinzu.

    [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. Klicken Sie Projektmappen-Explorer mit der rechten Maustaste auf WebForm1.aspx, und klicken Sie dann auf Öffnen. Das Webformular wird in der Entwurfsansicht geöffnet.

  7. Klicken Sie im Menü Ansicht auf HTML-Quelle.

  8. Ersetzen Sie den gesamten vorhandenen Code im HTML-Quellfenster durch den folgenden Code.

    <%@ 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. Klicken Sie im Menü Ansicht auf Entwurf.

  10. Doppelklicken Sie auf CreateProcess. Die Button1_Click -Methode wird in den Code eingefügt, und der Code wird im Inhaltsbereich angezeigt.

  11. Ersetzen Sie die vorhandene Button1_Click -Methode durch den folgenden Code.

    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. On the Build menu, click Build Solution.

  13. Klicken Sie im Menü Debuggen auf Start.

  14. Geben Sie auf der Seite WebForm1 den Pfad eines Prozesses ein, den Sie starten möchten. Geben Sie beispielsweise ein SystemDriver \Windows\Notepad.exe.

  15. Klicken Sie auf ErstellenVerarbeiten.

References