【发布时间】:2011-01-13 11:31:42
【问题描述】:
有什么方法可以从以管理员身份运行的进程以普通权限运行另一个进程?我想从具有提升权限的进程启动一个具有普通权限的进程,就像它是从资源管理器启动的一样。我尝试过模仿,但没有成功。
【问题讨论】:
标签: winapi
有什么方法可以从以管理员身份运行的进程以普通权限运行另一个进程?我想从具有提升权限的进程启动一个具有普通权限的进程,就像它是从资源管理器启动的一样。我尝试过模仿,但没有成功。
【问题讨论】:
标签: winapi
如果可能,请改用 Larry Osterman 的解决方案(在对 Anders 的回答中的 cmets 中),即,让父进程在没有提升的情况下运行,并从那里启动提升的进程和非提升的进程。
如果这是不可能的,有一种方法应该适用于几乎所有情况,尽管它通常比它的价值更麻烦:
安装并启动系统服务,配置为作为本地系统运行。给它你的远程桌面会话 ID,例如,通过命令行参数或注册表设置,以及你的进程 ID 和你想要运行的命令行。
从系统服务中,使用 GetTokenInformation 和 TokenLinkedToken 从目标进程获取链接令牌。您必须从系统服务执行此操作,因为您需要 SE_TCB_NAME 来获取可用令牌。 (此限制似乎没有记录在案,但与 Windows 中令牌的行为一致。)
或者,如果没有链接的令牌,则使用WTSQueryUserToken 获取用户令牌的副本。我相信这总是给你有限的令牌(如果有的话),但如果你想安全,你可以使用 GetTokenInformation 和 TokenElevationType 检查它是提升的还是有限的令牌;如果是提升的token,可以使用TokenLinkedToken来获取受限的。
如果没有链接令牌 (TokenElevationTypeDefault),您应该按原样使用令牌。发生这种情况的原因可能是用户不是管理员,也可能是因为全局禁用了 UAC,也可能是因为用户使用内置管理员帐户登录。如果用户不是管理员,则令牌已经合适。如果 UAC 被禁用,您应该尊重用户的意图并使用管理令牌。
然后您可以使用系统服务中的 CreateProcessAsUser 或 CreateProcessWithTokenW 来启动新进程。
最后,服务应该自行删除并停止。
至少存在一种极端情况:如果提升的进程是从使用 runas 和非管理凭据启动的命令窗口(或其他进程)启动的。在这种情况下没有拆分令牌,并且原始令牌可能已被删除,因此除非您在提升发生之前捕获了副本(Larry 的解决方案或其变体),否则没有通用方法可以在同一进程中运行子进程最初启动提升的进程的用户上下文。您可以做的最好的事情是登录用户的上下文(通过如上所述的 WTSQueryUserToken),这可能不是最终用户所期望的行为。 (但是,这可能是一个可接受的限制,具体取决于场景。)
【讨论】:
我成功使用的技术是使用 IShellDispatch2::ShellExecute 要求 Explorer 启动进程。由于 Explorer 通常以正常完整性运行,因此这是有效的。诀窍是获取 IShellDispatch2 对象需要一些工作。我按照this blog 中概述的流程进行操作。
【讨论】:
这似乎是一个不错的方法,前提是您不关心 Shell 未运行的情况(例如,可能某些终端服务应用程序仅设置,但我不确定):
http://brandonlive.com/2008/04/27/getting-the-shell-to-run-an-application-for-you-part-2-how/
它获得了 Explorer.exe 的接口,该接口应该在用户的正常上下文中运行,并要求 Explorer 代表它执行命令。这只需使用简单的、记录在案的 COM 接口即可完成,而无需处理进程令牌或代码/DLL 注入。
【讨论】:
不,这是不可能的(有几种 hacky 方法可以做到这一点(注入资源管理器、任务调度程序、SaferAPI+MediumIL 等),但它们都不能在所有情况下工作)
【讨论】:
使用CreateProcessAsUser()。详细信息在链接的 SDK 文档中。
【讨论】:
在 linux 上你可以使用 setuid 来改变程序用户 id
适用于窗户 你可以看看他的: https://serverfault.com/questions/16886/is-there-an-equivalent-of-su-for-windows
【讨论】: