我正在尝试使用CreateProcessAsUser方法。但我收到错误代码 - 5
这就是我的工作。
有人可以帮助我吗
此致
代码
# 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 :(得分:0)
由于您还根据CreateProcessAsUser
的文档指定了StartupInfo中的lpDesktop
参数:
...您必须更改默认交互式窗口站和默认桌面的自主访问控制列表(DACL)。窗口站和桌面的DACL必须授予用户或hToken参数表示的登录会话的访问权限。
我的猜测是这是导致拒绝访问错误的原因。
但是,根据CreateProcessAsUser
的文档,传递的令牌必须是主令牌。但是,您使用DuplicateToken
创建令牌,该令牌仅创建模拟令牌。
因此,您需要使用DuplicateTokenEx
创建主令牌,并将TokenPrimary
(= 1)作为第5个参数,并在CreateProcessAsUser
调用中使用此令牌(如果这是即使在桌面和WindowStation上设置权限后也能正常工作。