2012-11-08 3 views
0

CreateProcessAsUser 메서드를 사용하려고합니다. 하지만 오류 코드가 나타납니다 - 5CreateProcessAsUser - 오류 5

이것은 내가하는 일입니다.

  1. LoadUserProfile
  2. DuplicateToken
  3. ImpersonateUser를
  4. 에 CreateProcessAsUser - duplicateToken

누군가가 나를 도울 수

감사와

코드

# Start-of C# section 
$createPocess = @' 
using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 
using Microsoft.Win32; 
using System.IO; 
using System.Security.Principal; 

namespace CreateProcessUtility 
{ 
    class Win32 
    { 
    #region "CONTS" 
    const UInt32 INFINITE = 0xFFFFFFFF; 
    const UInt32 WAIT_FAILED = 0xFFFFFFFF; 


    #endregion 

    #region "ENUMS" 

    [Flags] 
    public enum LogonType 
    { 
     LOGON32_LOGON_INTERACTIVE = 2, 
     LOGON32_LOGON_NETWORK = 3, 
     LOGON32_LOGON_BATCH = 4, 
     LOGON32_LOGON_SERVICE = 5, 
     LOGON32_LOGON_UNLOCK = 7, 
     LOGON32_LOGON_NETWORK_CLEARTEXT = 8, 
     LOGON32_LOGON_NEW_CREDENTIALS = 9 
    } 

    [Flags] 
    public enum LogonProvider 
    { 
     LOGON32_PROVIDER_DEFAULT = 0, 
     LOGON32_PROVIDER_WINNT35, 
     LOGON32_PROVIDER_WINNT40, 
     LOGON32_PROVIDER_WINNT50 
    } 

    #endregion 

    #region "STRUCTS" 

    [StructLayout(LayoutKind.Sequential)] 
    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; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct PROCESS_INFORMATION 
    { 
     public IntPtr hProcess; 
     public IntPtr hThread; 
     public Int32 dwProcessId; 
     public Int32 dwThreadId; 
    } 

    #endregion 

    #region "FUNCTIONS (P/INVOKE)" 

    [StructLayout(LayoutKind.Sequential)] 
    public struct ProfileInfo { 
     public int dwSize; 
     public int dwFlags; 
     public String lpUserName; 
     public String lpProfilePath; 
     public String lpDefaultPath; 
     public String lpServerName; 
     public String lpPolicyPath; 
     public IntPtr hProfile; 
    } 



    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    public static extern Boolean LogonUser 
    (
     String lpszUserName, 
     String lpszDomain, 
     String lpszPassword, 
     LogonType dwLogonType, 
     LogonProvider dwLogonProvider, 
     out IntPtr phToken 
    ); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern Boolean CreateProcessAsUser 
    (
     IntPtr hToken, 
     String lpApplicationName, 
     String lpCommandLine, 
     IntPtr lpProcessAttributes, 
     IntPtr lpThreadAttributes, 
     Boolean bInheritHandles, 
     Int32 dwCreationFlags, 
     IntPtr lpEnvironment, 
     String lpCurrentDirectory, 
     ref STARTUPINFO lpStartupInfo, 
     out PROCESS_INFORMATION lpProcessInformation 
    ); 


    [DllImport("kernel32.dll", SetLastError = true)] 
    public static extern UInt32 WaitForSingleObject 
    (
     IntPtr hHandle, 
     UInt32 dwMilliseconds 
    ); 

    [DllImport("kernel32", SetLastError=true)] 
    public static extern Boolean CloseHandle (IntPtr handle); 

    [DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    public static extern bool LoadUserProfile(IntPtr hToken, ref ProfileInfo lpProfileInfo); 

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); 

    #endregion 

    #region "FUNCTIONS" 

    public static void LaunchCommand2(string strCommand, string strDomain, string strName, string strPassword) 
    { 
     // Variables 
     WindowsIdentity m_ImpersonatedUser; 
     IntPtr tokenDuplicate = IntPtr.Zero; 
     PROCESS_INFORMATION processInfo = new PROCESS_INFORMATION(); 
     STARTUPINFO startInfo = new STARTUPINFO(); 
     Boolean bResult = false; 
     IntPtr hToken = IntPtr.Zero; 
     UInt32 uiResultWait = WAIT_FAILED; 
     string executableFile = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"; 
     const int SecurityImpersonation = 2; 


     try 
     { 
      // Logon user 
      bResult = Win32.LogonUser(
       strName, 
       strDomain, 
       strPassword, 
       Win32.LogonType.LOGON32_LOGON_INTERACTIVE, 
       Win32.LogonProvider.LOGON32_PROVIDER_DEFAULT, 
       out hToken 
      ); 
      if (!bResult) { throw new Exception("Logon error #" + Marshal.GetLastWin32Error()); } 


      #region LoadUserProfile 
        ProfileInfo currentProfile = new ProfileInfo(); 
        currentProfile.dwSize = Marshal.SizeOf(currentProfile); 
        currentProfile.lpUserName = strName; 
        currentProfile.dwFlags = 1;       
        Boolean bResult2 = LoadUserProfile(hToken, ref currentProfile); 
        Console.WriteLine(bResult2); 

        if (!bResult2) { throw new Exception("LoadUserProfile error #" + Marshal.GetLastWin32Error()); } 
        Console.WriteLine(currentProfile.hProfile + "----"+IntPtr.Zero); 


        if (currentProfile.hProfile == IntPtr.Zero){ 
         Console.WriteLine("LoadUserProfile() failed - HKCU handle was not loaded. Error code: " + 
          Marshal.GetLastWin32Error()); 
         throw new Exception("LoadUserProfile error #" + Marshal.GetLastWin32Error()); 
        } 
      #endregion 


      // Create process 
      startInfo.cb = Marshal.SizeOf(startInfo); 
      startInfo.lpDesktop = "winsta0\\default"; 

      Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name); 


      if (DuplicateToken(hToken, SecurityImpersonation, ref tokenDuplicate) != 0){ 
      m_ImpersonatedUser = new WindowsIdentity(tokenDuplicate); 

       if(m_ImpersonatedUser.Impersonate() != null){ 
        Console.WriteLine("After Impersonation succeeded: " + Environment.NewLine + 
                "User Name: " + 
                WindowsIdentity.GetCurrent(TokenAccessLevels.MaximumAllowed).Name + 
                Environment.NewLine + 
                "SID: " + 
                WindowsIdentity.GetCurrent(TokenAccessLevels.MaximumAllowed).User. 
                 Value); 
        Console.WriteLine(m_ImpersonatedUser); 
       } 


       bResult = Win32.CreateProcessAsUser(
       tokenDuplicate, 
       executableFile, 
       strCommand, 
       IntPtr.Zero, 
       IntPtr.Zero, 
       false, 
       0, 
       IntPtr.Zero, 
       null, 
       ref startInfo, 
       out processInfo 
      ); 
      if (!bResult) { throw new Exception("CreateProcessAsUser error #" + Marshal.GetLastWin32Error()); } 

     } 

      // Wait for process to end 
      uiResultWait = WaitForSingleObject(processInfo.hProcess, INFINITE); 
      if (uiResultWait == WAIT_FAILED) { throw new Exception("WaitForSingleObject error #" + Marshal.GetLastWin32Error()); } 
     } 
     finally 
     { 
      // Close all handles 
      CloseHandle(hToken); 
      CloseHandle(processInfo.hProcess); 
      CloseHandle(processInfo.hThread); 
     } 
    } 

    #endregion 
} 
// Interface between powershell and C#  
public class CreateProcessCaller 
{ 
    public static void modifyEnvParamWrapper2(string strCommand, string strDomain, string strName, string strPassword) 
    { 
     Win32.LaunchCommand2(strCommand, strDomain, strName, strPassword); 
    } 
} 
} 

'@ 
# End-of C# section 


Add-Type -TypeDefinition $createPocess -Language CSharp -IgnoreWarnings 


Function modifyEnvParamWOWindow([String]$command, [String]$strDomain, [String]$strName, [String]$strPassword) { 

try { 
    [CreateProcessUtility.CreateProcessCaller]::modifyEnvParamWrapper2($command, $strDomain, $strName, $strPassword) 
    return $True 
} catch { 
    write-host "Unable to modify regestry entry: " $_ 
    return $False 
} 
} 
+0

실제 코드를 표시하십시오. – Iridium

+0

http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx –

+0

안녕하세요.이 오류는 AccessDenied를 의미합니다. 그러나 사용자는 Administrators 그룹에 속하므로 문제가되지 않아야합니다. – ajax

답변

0

당신은 또한 CreateProcessAsUser에 대한 설명서 당은 STARTUPINFO의 lpDesktop 매개 변수를 지정하고 있기 때문에 :

이 ... 당신이 상호 작용하는 기본 모두의 DACL (임의 액세스 제어 목록)을 변경해야합니다 창 스테이션 및 기본 데스크탑. 윈도우 스테이션 및 데스크톱 용 DACL은 hToken 매개 변수로 표시되는 사용자 또는 로그온 세션에 대한 액세스 권한을 부여해야합니다.

내 생각 엔 이것이 액세스 거부 오류의 원인입니다.

그러나 설명서의 내용도 CreateProcessAsUser 인 경우 전달 된 토큰은 기본 토큰이어야합니다. 그러나 가장 토큰 만 생성하는 DuplicateToken을 사용하여 토큰을 만듭니다.

그래서 당신은 전달 DuplicateTokenEx를 사용하여 주 토큰을 만들어야합니다 TokenPrimary (= 1) 5 매개 변수이는 데스크톱 및 WindowStation에 대한 사용 권한을 설정 한 후도 작동하는 경우 CreateProcessAsUser 호출이 토큰을 사용하는 등 .

+0

몇 분 동안 시도 :-) 감사합니다 – ajax

+0

lpDesktop을 null로 변경했습니다. powershell과 같은 명령을 실행 해 보았습니다. - 사용자 myUser - domain - password를 사용하여 mkdir C : \ myTemp을 각각 입력했습니다. 폴더가 생성되지 않았으므로 실패합니다 – ajax

+0

@ajax 잠재적으로 다른 문제입니다. CreateProcessAsUser 호출이 이제 성공합니까? 프로세스가 생성됩니까? 디렉토리를 생성하려고 시도하고 실패합니까? – Iridium