如何获取原始用户令牌? UAC、清单、安装程序

Posted

技术标签:

【中文标题】如何获取原始用户令牌? UAC、清单、安装程序【英文标题】:How to get original user token? UAC, manifest, installer 【发布时间】:2013-12-13 13:54:54 【问题描述】:

我们有一个附加清单和选项“level="requireAdministrator" 的程序。 在标准用户(不是管理员)下启动程序后,它会升级为管理员用户,从那一刻起 SHGetFolderPath(0,CSIDL_LOCAL_APPDATA,0,SHGFP_TYPE_CURRENT,@buf)) 返回管理员本地目录,而不是用户最初启动的位置。 当然,我们可以将标准用户令牌作为第三个参数传递给 SHGetFolderPath,但是我们如何在提升的程序中获取它呢? 有什么办法吗?

当然,由于这个问题,我们还有另一个问题。如何使用 ShellExecute 启动另一个程序而不是提升程序中的管理员?当然我们可以使用 CreateProcessWithTokenW 但仍然存在令牌问题(如何获取此令牌)。 现在我们正在寻找 IShellDispatch2 接口并尝试以管理员身份使用资源管理器启动应用程序,但有些事情告诉我这是错误的方式。

我知道我们必须以标准用户身份启动程序,然后使用 com 对象只提升应该以管理员权限执行的部分代码。但是,主要问题仍然是令牌。

还有一个想法是使用“level="asInvoker" 制作清单并以标准用户身份启动第一个程序,检测所有本地用户路径并将其作为参数传递给带有 runas 和 SEE_MASK_NOCLOSEPROCESS 选项的 ShellExecuteEx 并运行相同的程序,但作为admin。提升的程序退出后,我们可以以管理员身份执行非提升程序中的任何程序。这是正确的方式吗?

【问题讨论】:

【参考方案1】:

可能有点晚了,但您的替代选择是正确的选择。一旦程序被提升,就没有可靠的方法来启动另一个程序但没有提升,甚至不知道是什么用户启动了它,如果它是使用不同的凭据完成的。

所有这些问题的一般解决方案是将程序拆分为 2 个不同的进程(可以根据需要在 1 或 2 个不同的 .EXE 中实现)。 “主”程序,即用户运行的程序,在没有提升的情况下运行,表现为asInvoker,然后它又启动第二个“工作”进程,表现为requireAdministrator。主进程可以通过命令行、未命名管道、窗口消息或任何其他形式的 IPC 将数据从原始用户传递给第二个用户,而工作进程则执行所有仅管理员操作。当需要生成另一个非提升程序时,您可能希望通知回主进程。

【讨论】:

【参考方案2】:

来自 Raymond Chen:

How can I launch an unelevated process from my elevated process and vice versa?

从未提升的流程转到提升的流程很容易。您可以通过passing the runas verb 将进程提升到 ShellExecute 或 ShellExecuteEx。

走另一条路比较棘手。一方面,要正确删除高程特性确实很难使用您的令牌。还有一件事,即使你能做到,也不是正确的做法,因为未提升的用户可能与提升的用户不同。

这里的解决方案是返回 Explorer 并要求 Explorer 为您启动程序。由于 Explorer 以原始未提升用户身份运行,因此程序将以原始未提升用户身份运行。

我试图从 C++ 中翻译代码,但它太繁琐而无法管理。

简短的版本是:很难。

【讨论】:

以上是关于如何获取原始用户令牌? UAC、清单、安装程序的主要内容,如果未能解决你的问题,请参考以下文章

安装更改不要求 UAC 权限

如何在启动程序且 UAC 被禁用时强制提示输入凭据?

如何在启用 UAC 的 Windows 服务中调用 LogonUser() 以获取不受限制的完整令牌?

如何获取 Windows SYSTEM 用户令牌

解决pyinstaller在单一文件时无法正确添加权限清单问题,(UAC,uac_admin,manifest,asInvoker,python,requireAdministrator)

升级使用 installshield 创建的安装时,UAC 弹出红色