簡體   English   中英

CreateProcessAsUser-錯誤5

[英]CreateProcessAsUser - Error 5

我正在嘗試使用CreateProcessAsUser方法。 但我收到錯誤代碼-5

這就是我要做的。

  1. LoadUserProfile
  2. DuplicateToken
  3. 模擬用戶
  4. CreateProcessAsUser-具有重復令牌

有人可以幫我嗎

問候

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

由於還要在StartupInfo中指定lpDesktop參數,因此請參考CreateProcessAsUser的文檔:

...您必須同時更改默認交互式Window Station和默認桌面的自由訪問控制列表(DACL)。 窗口站和桌面的DACL必須將訪問權限授予hToken參數代表的用戶或登錄會話。

我的猜測是這是“訪問被拒絕”錯誤的原因。

但是,同樣根據CreateProcessAsUser的文檔,傳遞的令牌也必須是主令牌。 但是,您正在使用DuplicateToken創建令牌,而DuplicateToken僅創建模擬令牌。

因此,您將需要使用DuplicateTokenEx創建主要令牌,並將TokenPrimary (= 1)作為第5個參數,並在CreateProcessAsUser調用中使用此令牌,即使在設置Desktop和WindowStation的權限后仍可以使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM