使用
调用GUI应用程序[DllImport(
"advapi32.dll",
EntryPoint = "CreateProcessAsUser",
SetLastError = true,
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
private static extern bool CreateProcessAsUser(
IntPtr hToken,
string lpApplicationName,
string lpCommandLine,
ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
bool bInheritHandle,
int dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
bool result = CreateProcessAsUser(
hUserTokenDup,
null,
applicationName + " " + arguments,
ref sa, // pointer to process SECURITY_ATTRIBUTES
ref sa, // pointer to thread SECURITY_ATTRIBUTES
false, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE, // creation flags
IntPtr.Zero, // pointer to new environment block
null, // name of current directory
ref si, // pointer to STARTUPINFO structure
out procInfo); // receives information about new process
从LocalSystem Windows服务工作。 该窗口在用户屏幕中弹出,但进程用户仍然是LocalSystem。有没有办法改变它?
PS 根据要求,我从
获得hUserTokenDup
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
private static extern bool DuplicateTokenEx(
IntPtr ExistingTokenHandle,
uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes,
int TokenType,
int ImpersonationLevel,
ref IntPtr DuplicateTokenHandle);
DuplicateTokenEx(
hPToken,
MAXIMUM_ALLOWED,
ref sa,
(int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
(int)TOKEN_TYPE.TokenPrimary,
ref hUserTokenDup);
答案 0 :(得分:2)
看起来不是使用DuplicateTokenEx来复制当前令牌,而是需要调用LogonUser来获取代表目标用户的令牌。简单地调用DuplicateTokenEx将为本地系统用户创建一个令牌..如果我正确理解你的代码片段。
此外,由于您的目标是交互式用户,请考虑使用 CreateProcessWithLogonW 功能。
答案 1 :(得分:2)
在我的服务中,我在调用WTSGetActiveConsoleSessionId()
之前使用WTSQueryUserToken()
,DuplicationTokenEx()
和CreateProcessAsUser()
,这对我来说很合适。生成的进程在用户帐户中运行,而不是在服务帐户中运行。
答案 2 :(得分:0)
感谢Remy Lebeau提示使用 WTSGetActiveConsoleSessionId()
下面的函数必须从“系统”调用 - 用户就像win-service一样,需要一个正在运行的物理控制台(普通的用户登录会话,没有远程终端会话)。您可以使用此用户安全属性从正在运行的登录会话中的win-service启动新进程。 如果调用者不是“系统”,则无法使用模拟用户启动新进程。
public static bool StartProcessAndBypassUAC(ProcessStartInfo ps, out PROCESS_INFORMATION procInfo)
{
// code based on http://www.codeproject.com/Articles/35773/Subverting-Vista-UAC-in-Both-32-and-64-bit-Archite
uint winlogonPid = 0;
IntPtr hUserTokenDup = IntPtr.Zero, hPToken = IntPtr.Zero, hProcess = IntPtr.Zero;
procInfo = new PROCESS_INFORMATION();
// obtain the currently active session id; every logged on user in the system has a unique session id
uint dwSessionId = WTSGetActiveConsoleSessionId();
if (dwSessionId == 0xFFFFFFFF)
{
// no physical console
return false;
}
if (!WTSQueryUserToken(dwSessionId, ref hPToken))
{
return false ;
}
// Security attibute structure used in DuplicateTokenEx and CreateProcessAsUser
// I would prefer to not have to use a security attribute variable and to just
// simply pass null and inherit (by default) the security attributes
// of the existing token. However, in C# structures are value types and therefore
// cannot be assigned the null value.
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.Length = Marshal.SizeOf(sa);
// copy the access token of the winlogon process; the newly created token will be a primary token
if (!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, ref sa, (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
{
CloseHandle(hProcess);
CloseHandle(hPToken);
return false;
}
// By default CreateProcessAsUser creates a process on a non-interactive window station, meaning
// the window station has a desktop that is invisible and the process is incapable of receiving
// user input. To remedy this we set the lpDesktop parameter to indicate we want to enable user
// interaction with the new process.
STARTUPINFO si = new STARTUPINFO();
si.cb = (int)Marshal.SizeOf(si);
si.lpDesktop = @"winsta0\default"; // interactive window station parameter; basically this indicates that the process created can display a GUI on the desktop
// flags that specify the priority and creation method of the process
int dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
// create a new process in the current user's logon session
bool result = CreateProcessAsUser(hUserTokenDup, // client's access token
null, // file to execute
ps.FileName, // command line
ref sa, // pointer to process SECURITY_ATTRIBUTES
ref sa, // pointer to thread SECURITY_ATTRIBUTES
true, // handles are not inheritable
dwCreationFlags, // creation flags
IntPtr.Zero, // pointer to new environment block
ps.WorkingDirectory, // name of current directory
ref si, // pointer to STARTUPINFO structure
out procInfo // receives information about new process
);
// invalidate the handles
CloseHandle(hProcess);
CloseHandle(hPToken);
CloseHandle(hUserTokenDup);
return result; // return the result
}