0

我正在尝试使用 CreateProcessAsUser 方法。但我收到错误代码 - 5

这就是我所做的。

  1. 加载用户配置文件
  2. 重复令牌
  3. 模拟用户
  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
}
}  
4

1 回答 1

0

由于您还在lpDesktopStartupInfo 中指定参数,因此根据以下文档CreateProcessAsUser

...您必须更改默认交互式窗口站和默认桌面的任意访问控制列表 (DACL)。窗口站和桌面的 DACL 必须授予用户访问权限或由 hToken 参数表示的登录会话。

我的猜测是,这是 Access Denied 错误的原因。

但是,同样根据 的文档CreateProcessAsUser,传递的令牌必须是主令牌。但是,您正在创建DuplicateToken仅使用创建模拟令牌的令牌。

因此,您将需要使用创建一个主令牌DuplicateTokenEx,将TokenPrimary(= 1) 作为第 5 个参数传递,CreateProcessAsUser如果即使在桌面和 WindowStation 上设置权限后仍能正常工作,请在调用中使用此令牌。

于 2012-11-08T14:28:04.193 回答