[英]CreateProcessAsUser - Error 5
I am trying to use CreateProcessAsUser method. 我正在尝试使用CreateProcessAsUser方法。 But I am getting Error code - 5
但我收到错误代码-5
This is what I do . 这就是我要做的。
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.