CreateProcessAsUser 与 ShellExecute

发布于 2024-07-05 11:05:30 字数 816 浏览 6 评论 0原文

我需要以另一个用户的身份执行 ShellExecute 某些操作,目前我使用 CreateProcessAsUser 启动一个帮助程序进程,该进程调用 ShellExecute,但这似乎太多了hack(错误的父进程等)有更好的方法吗?

@PabloG:ImpersonateLoggedOnUser 不起作用:

HANDLE hTok;
VERIFY(LogonUser("otheruser",0,"password",LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hTok));
VERIFY(ImpersonateLoggedOnUser(hTok));
ShellExecute(0,0,"calc.exe",0,0,SW_SHOW);
RevertToSelf();
CloseHandle(hTok);

只会以登录用户的身份启动计算,而不是“其他用户”

@1800 信息:CreateProcess/CreateProcessAsUser不同>ShellExecute,在 Vista 上使用 UAC,当您无法控制用户正在执行的程序时,CreateProcess 毫无用处(CreateProcess 将返回错误如果你给它一个 exe 文件,其清单标记为 requireAdmin)

@Brian R. Bondy:我已经知道这个信息(不要误会我的意思,它是好东西),但它不是主题(恕我直言)我问对于 ShellExecuteAsUser ,而不是作为另一个用户启动进程,我已经知道如何做到这一点。

I need to ShellExecute something as another user, currently I start a helper process with CreateProcessAsUser that calls ShellExecute, but that seems like too much of a hack (Wrong parent process etc.) Is there a better way to do this?

@PabloG: ImpersonateLoggedOnUser does not work:

HANDLE hTok;
VERIFY(LogonUser("otheruser",0,"password",LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hTok));
VERIFY(ImpersonateLoggedOnUser(hTok));
ShellExecute(0,0,"calc.exe",0,0,SW_SHOW);
RevertToSelf();
CloseHandle(hTok);

will just start calc as the logged in user, not "otheruser"

@1800 INFORMATION: CreateProcess/CreateProcessAsUser is not the same as ShellExecute, with UAC on Vista, CreateProcess is useless when you don't have control over what program the user is executing (CreateProcess will return with a error if you give it a exe file with a manifest marked as requireAdmin)

@Brian R. Bondy: I already know this info (And don't get me wrong, its good stuff), but it is off topic (IMHO) I am asking for a ShellExecuteAsUser, not about starting processes as another user, I already know how to do that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

蒲公英的约定 2024-07-12 11:05:30

如果您需要 ShellExecute 语义,您可以提供以下内容:

C:\windwos\system32\cmd.exe /k" start"
CreateProcessAsUser 就完成了。

If you need ShellExecute semantics you can feed following:

C:\windwos\system32\cmd.exe /k" start <your_target_to_be_ShellExecuted>"
to CreateProcessAsUser and you are done.

我早已燃尽 2024-07-12 11:05:30

您可以将 ShellExecute 包装在 ImpersonateLoggedOnUser / RevertToSelf

链接之间:
ImpersonateLoggedOnUser: http://msdn.microsoft.com/en -us/library/aa378612(VS.85).aspx
RevertToSelf: http://msdn.microsoft.com/en-us/library/ aa379317.aspx

抱歉,无法使用“()”超链接 URL

You can wrap the ShellExecute between ImpersonateLoggedOnUser / RevertToSelf

links:
ImpersonateLoggedOnUser: http://msdn.microsoft.com/en-us/library/aa378612(VS.85).aspx
RevertToSelf: http://msdn.microsoft.com/en-us/library/aa379317.aspx

sorry, cannot hyperlink URLs with "()"

不气馁 2024-07-12 11:05:30

为什么不直接执行 CreateProcessAsUser 来指定要运行的进程?

您也许还可以使用 SHCreateProcessAsUserW。

Why don't you just do CreateProcessAsUser specifying the process you want to run?

You may also be able to use SHCreateProcessAsUserW.

栩栩如生 2024-07-12 11:05:30

该解决方案实际上取决于您的需求,并且可能非常复杂(完全感谢 Windows Vista)。 这可能超出您的需要,但这将帮助其他人通过搜索找到此页面。

  1. 如果您不需要使用 GUI 运行进程,并且不需要提升
  2. 如果您要运行的用户已登录到会话
  3. 如果您需要使用 GUI 运行进程,并且用户可能或可能未登录
  4. 如果您需要运行带有海拔的进程

关于1:
在 Windows Vista 中,存在称为会话 0 隔离的功能。 所有服务都作为会话 0 运行,并且您不应该在会话 0 中拥有 GUI。第一个登录的用户登录到会话 1。在以前的 Windows 版本(Vista 之前)中,第一个登录的用户也完全在会话 1 中运行。 session 0。

您可以在同一会话中使用不同的用户名运行多个不同的进程。 您可以在此处找到有关会话 0 隔离的好文档。

由于我们正在处理选项 1),因此您不需要 GUI。 因此,您可以在会话 0 中启动进程。

您将需要一个如下所示的调用序列:
LogonUser、ExpandEnvironmentStringsForUser、GetLogonSID、LoadUserProfile、CreateEnvironmentBlock、CreateProcessAsUser。

示例代码可以通过任何搜索引擎找到,或者通过 Google 代码搜索

关于 2: 如果您想要运行该流程的用户已经登录,您只需使用:WTSEnumerateSessions 和 WTSQuerySessionInformation 来获取会话 ID,然后使用 WTSQueryUserToken 来获取用户令牌。 从那里您可以在 CreateProcessAsUser Win32 API 中使用用户令牌。

这是一个很好的方法,因为您甚至不需要以用户身份登录,也不知道用户的用户名/密码。 我相信这只能通过以本地系统帐户运行的服务来实现。

您可以通过 WTSGetActiveConsoleSessionId 获取当前会话。

关于3:
您将遵循与 #1 相同的步骤,但此外您将使用 STARTUPINFO 的 lpDesktop 字段。 将其设置为 winsta0\Default。 您还需要尝试使用 OpenDesktop Win32 API,如果失败,您可以 CreateDesktop。 在使用工作站和桌面句柄之前,您应该对每个句柄使用 SetSecurityInfo 以及 SE_WINDOW_OBJECT 和 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION。

如果相关用户稍后尝试登录,他实际上会看到正在运行的进程。

关于4:
这也可以完成,但它要求您已经在运行提升的进程。 以本地系统帐户运行的服务确实以提升的方式运行。 我也只能通过我想要启动的验证码签名过程来使其工作。 您想要启动的进程还必须有一个与其关联的清单文件,其请求执行级别 level="requireAdministrator"

其他注意事项:

  • 您可以通过 SetTokenInformation 和 TokenSessionId 设置令牌的会话
  • 您无法更改已在运行的进程的会话 ID。
  • 如果没有 Vista,整个过程将会简单得多。

The solution really depends on what your needs are, and can be pretty complex (Thanks fully to Windows Vista). This is probably going to be beyond your need, but this will help others that find this page via search.

  1. If you do not need the process to run with a GUI and you do not require elevation
  2. If the user you want to run as is already logged into a session
  3. If you need to run the process with a GUI, and the user may, or may not be logged in
  4. If you need to run the process with elevation

Regarding 1:
In windows Vista there exists something called session 0 isolation. All services run as session 0 and you are not supposed to have a GUI in session 0. The first logged on user is logged into session 1. In previous versions of windows (pre Vista), the first logged on user was also ran fully in session 0.

You can run several different processes with different usernames in the same session. You can find a good document about session 0 isolation here.

Since we're dealing with option 1), you don't need a GUI. Therefore you can start your process in session 0.

You'll want a call sequence something like this:
LogonUser, ExpandEnvironmentStringsForUser, GetLogonSID, LoadUserProfile, CreateEnvironmentBlock, CreateProcessAsUser.

Example code for this can be found via any search engine, or via Google code search

Regarding 2: If the user you'd like to run the process as is already logged in, you can simply use: WTSEnumerateSessions, and WTSQuerySessionInformation to get the session ID, and then WTSQueryUserToken to get the user token. From there you can just use the user token in the CreateProcessAsUser Win32 API.

This is a great method because you don't even need to login as the user nor know the user's username/password. I believe this is only possible via a service though running as local system account.

You can get the current session via WTSGetActiveConsoleSessionId.

Regarding 3:
You would follow the same steps as #1, but in addition you would use the STARTUPINFO's lpDesktop field. Set this to winsta0\Default. You will also need to try to use the OpenDesktop Win32 API and if this fails you can CreateDesktop. Before using the station and desktop handles you should use SetSecurityInfo on each of them with SE_WINDOW_OBJECT, and GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION.

If the user in question later tries to login, he will actually see the running process.

Regarding 4:
This can be done as well, but it requires you to already be running an elevated process. A service running as local system account does run as elevated. I could also only get it to work by having an authenticode signed process that I wanted to start. The process you want to start also must have a manifest file associated with it with the requestedExecutionLevel level="requireAdministrator"

Other notes:

  • You can set a token's session via SetTokenInformation and TokenSessionId
  • You cannot change the session ID of an already running process.
  • This whole process would be drastically more simple if Vista was not in the equation.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文