简体   繁体   English

CreateProcessAsUser-错误5

[英]CreateProcessAsUser - Error 5

I am trying to use CreateProcessAsUser method. 我正在尝试使用CreateProcessAsUser方法。 But I am getting Error code - 5 但我收到错误代码-5

This is what I do . 这就是我要做的。

  1. LoadUserProfile LoadUserProfile
  2. DuplicateToken DuplicateToken
  3. ImpersonateUser 模拟用户
  4. CreateProcessAsUser - with duplicateToken CreateProcessAsUser-具有重复令牌

Can someone help me out 有人可以帮我吗

Regards 问候

Code

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

Since you are also specifying the lpDesktop parameter in the StartupInfo, per the documentation for CreateProcessAsUser : 由于还要在StartupInfo中指定lpDesktop参数,因此请参考CreateProcessAsUser的文档:

...you must change the discretionary access control list (DACL) of both the default interactive window station and the default desktop. ...您必须同时更改默认交互式Window Station和默认桌面的自由访问控制列表(DACL)。 The DACLs for the window station and desktop must grant access to the user or the logon session represented by the hToken parameter. 窗口站和桌面的DACL必须将访问权限授予hToken参数代表的用户或登录会话。

My guess is that this is the cause of the Access Denied error. 我的猜测是这是“访问被拒绝”错误的原因。

However, also per the documentation for CreateProcessAsUser , the token passed must be a primary token. 但是,同样根据CreateProcessAsUser的文档,传递的令牌也必须是主令牌。 You are however creating the token using DuplicateToken which only creates impersonation tokens. 但是,您正在使用DuplicateToken创建令牌,而DuplicateToken仅创建模拟令牌。

So you will need to create a primary token using DuplicateTokenEx , passing TokenPrimary (= 1) as the 5th parameter, and use this token in your CreateProcessAsUser call if this is to work even after setting the permissions on the Desktop and WindowStation. 因此,您将需要使用DuplicateTokenEx创建主要令牌,并将TokenPrimary (= 1)作为第5个参数,并在CreateProcessAsUser调用中使用此令牌,即使在设置Desktop和WindowStation的权限后仍可以使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM