Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve como gerar um processo que é executado no contexto do usuário representado.
Versão original do produto: ASP.NET
Número original do KB: 889251
Introdução
Este artigo passo a passo descreve como gerar um processo que é executado no contexto do usuário representado em ASP.NET páginas. Para gerar um processo que é executado no contexto do usuário representado, você não pode usar o System.Diagnostics.Process.Start
método. Isso ocorre porque, no ASP.NET, a representação é executada no nível do thread e não no nível do processo. Portanto, qualquer processo gerado a partir do ASP.NET será executado no contexto do processo de trabalho ASP.NET e não no contexto representado.
Descrição da técnica
Para contornar esse problema, você deve fazer chamadas de invocação de plataforma (P/Invoke) para as seguintes APIs do Win32:
A
CreateProcessAsUser
função cria um processo sob a identidade do token de segurança especificado em um dos parâmetros. No entanto, a chamada para aCreateProcessAsUser
função requer um token primário. Portanto, você deve converter o token representado em um token primário.A
DuplicateTokenEx
função converte um token representado em um token primário. A chamada para aCreateProcessAsUser
função usa esse token primário.
Observação
Para que a chamada para a CreateProcessAsUser
função funcione, os seguintes direitos de usuário de segurança devem ser atribuídos ao usuário representado:
- Em um computador que esteja executando o Windows, atribua o direito de usuário Substituir um token de nível de processo e o direito de usuário Aumentar cotas ao usuário representado.
- Em um computador que esteja executando o Windows Server ou o Windows XP, atribua o direito de usuário Substituir um token de nível de processo ao usuário representado.
Etapas para gerar um processo
A Microsoft oferece exemplos de programação somente para ilustração, sem garantias expressas ou implícitas. Isso inclui, mas não está limitado a, as garantias implícitas de qualidade comercial ou conformidade para uma determinada finalidade. Este artigo supõe que você conhece a linguagem de programação que está sendo demonstrada e as ferramentas usadas nos processos de criação e depuração. Os engenheiros de suporte da Microsoft podem ajudá-lo, fornecendo a explicação da funcionalidade de determinado procedimento, mas não modificarão estes exemplos para fornecer funcionalidade adicional nem criarão procedimentos específicos para atender às suas necessidades específicas. Para gerar um processo que é executado no contexto do usuário representado, siga estas etapas:
No Visual Studio .NET, crie um novo aplicativo Web do Visual C# ASP.NET e nomeie o aplicativo Q889251.
Abra o arquivo WebForm1.aspx na visualização de código.
No arquivo WebForm1.aspx, adicione as instruções a seguir ao bloco de código using.
using System.Runtime.InteropServices; using System.Security.Principal;
Localize a linha de código que se parece com a linha de código a seguir.
public class WebForm1 : System.Web.UI.Page
Após a linha de código identificada na etapa 4, adicione o código a seguir.
[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);
No Gerenciador de Soluções, clique com o botão direito do mouse em WebForm1.aspx e clique em Abrir. O formulário da Web é aberto no modo de design.
No menu Exibir, clique em Código-fonte HTML.
Substitua todo o código existente na janela Código-fonte HTML pelo código a seguir.
<%@ 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> </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>
No menu Exibir, clique em Design.
Clique duas vezes em CreateProcess. O
Button1_Click
método é inserido no código e o código aparece no painel de conteúdo.Substitua o método
Button1_Click
existente pelo código a seguir.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"; } } }
No menu Compilar, clique em Compilar Solução.
No menu Depurar , clique em Iniciar.
Na página WebForm1, digite o caminho de um processo que você deseja iniciar. Por exemplo, digite
SystemDriver \Windows\Notepad.exe
.Clique em CreateProcess.