gpt4 book ai didi

winapi - 从非交互式服务 (win32/.net/powershell) 启动 UAC 提升进程

转载 作者:行者123 更新时间:2023-12-03 14:52:49 25 4
gpt4 key购买 nike

我正在使用第三方 Windows 服务,该服务通过使用 CreateProcessAsUser() 运行脚本和可执行文件来处理一些自动化任务。由于 UAC 以及通过 API 处理 LUA 提升的方式,我在 Windows Server 2008 上遇到了问题。

该服务作为 LocalSystem 运行,并且没有启用“与桌面交互”。这些进程作为管理员组中的用户运行,但不是管理员帐户(不受许多 UAC 限制)。所有 UAC 的默认设置都已到位。

我可以将任意命令或 powershell 代码传递给服务,但我似乎无法“突破”由服务启动的非提升、非交互式进程。

问题的症结似乎是启动提升进程的唯一(公共(public))API 选项是带有“runas”动词的 ShellExecute(),但据我所知,不能从非交互式调用服务,否则您会收到诸如“此操作需要交互式窗口站”之类的错误。

这里提到了我发现的唯一解决方法:
http://www.eggheadcafe.com/software/aspnet/29620442/how-to-proper-use-sendinp.aspx

In Vista, the official documented way to elevate a process is only using the shell API ShellExecute(Ex)(not CreateProcess or CreateProcessAsUser). So your application must call ShellExecute(Ex) to launch a helper elevated to call SendInput. Furthermore, due to Session 0 isolation, a service can only use CreateProcessAsUser or CreateProcessWithLogonW(can not use ShellExecute(Ex)) to specify the interactive desktop.

..I think there is no direct way to spawn an elevated process from a windows service. We can only first use CreateProcessAsUser or CreateProcessWithLogonW to spawn a non-elevated process into the user session(interactive desktop). Then in the non-elevated process, it may use ShellExecute(Ex) to spawn an elevated process for the real task.



要从 .net/powershell 代码执行此操作,看起来我必须做一些复杂的 P/Invoke 操作才能调用 CreateProcessAsUser 或 CreateProcessWithLogonW,因为 .Net System.Diagnostics.ProcessStartInfo 没有我可以使用的 lpDesktop 等价物设置为“winsta0\default”。而且我不清楚 LocalSystem 是否甚至有权调用 CreateProcessAsUser 或 CreateProcessWithLogonW。

我也看了
http://blogs.msdn.com/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx

Process.Start with different credentials with UAC on

基于所有这些,我得出的结论是,没有直接的方法可以做到这一点。我错过了什么吗?这似乎真的不应该那么难。感觉就像 UAC 从未设计用于处理非交互式用例。

如果有任何 Microsoft 人员最终阅读了这篇文章,我注意到 ShellExecute 在内部处理提升的方式是调用应用程序信息服务 (AIS)。为什么不能通过某些 Win32 或 .NET API 对 AIS 进行相同的调用?
http://msdn.microsoft.com/en-us/library/bb756945.aspx

抱歉,运行时间有点长。感谢您的任何想法。

最佳答案

打破 session 零隔离的“官方”方法是使用终端服务 API 和 CreateProcessAsUser() 的组合。在用户 session 中启动进程。在我以前的工作中,我们就是这样做的,因为我们需要在安装下载的更新之前从服务向用户显示一个对话框所以,我知道它至少在 WinXP、Win2K3、Vista 和 Win7 上有效,但我不要指望 Win 2K8 会有太大的不同。基本上,过程如下:

  • 调用 WTSGetActiveConsoleSessionId()获取事件控制台 session ID(非常重要,因为交互式 session 是 而不是 始终是 session 1,即使在客户端系统上也是如此)。此 API 还将返回 -1 如果没有事件用户登录到交互式 session (即本地登录到物理机,而不是使用 RDP)。
  • 将上一次 API 调用中的 session ID 传递给 WTSQueryUserToken()获取代表用户登录控制台的开放 token 。
  • 调用 DuplicateTokenEx()将模拟 token (来自 WTSQueryUserToken )转换为主 token 。
  • 调用 CreateEnvironmentBlock()为流程创建一个新环境(可选,但如果不这样做,流程将没有环境)。
  • 将第 3 步中的主 token 传递给对 CreateProccessAsUser() 的调用,以及可执行文件的命令行。如果您从第 4 步创建了环境 block ,则必须传递 CREATE_UNICODE_ENVIRONMENT标志以及(总是)。这可能看起来很愚蠢,但如果你不这样做,API 会严重失败(使用 ERROR_INVALID_PARAMTER )。
  • 如果你创建了一个环境 block ,那么你需要调用 DestroyEnvironmentBlock ,否则会产生内存泄漏。该进程在启动时会获得环境 block 的单独副本,因此您只是在破坏本地数据。

  • 瞧! Windows 做了一些内部魔术,您会看到应用程序启动。但是,尽管这将从服务启动和交互过程,但我不确定它是否会绕过 UAC(但不要引用我的话)。换句话说,除非注册表或内部 list 要求这样做,否则它可能不会作为提升的进程启动,即使那样,您仍可能会收到 UAC 提示。如果您从第 3 步获得的 token 是受限 token ,您可以使用 AdjustTokenPrivileges()恢复提升的(完整) token ,但也不要引用我的话。但是,如 MSDN 文档中所述,请注意,无法在尚未拥有权限的 token 上“添加”权限(例如,您无法使用 AdjustTokenPrivileges 将受限用户 token 转换为管理员;底层用户必须是管理员才能开始)。

    从 Win2K 开始,这在技术上是可行的。然而,这真的只有从 WinXP 开始才可行,因为 Win2K 缺少 WTSGetActiveConsoleSessionId()WTSQueryUserToken() API(与 WTSEnumerateProcesses() 一起用于 Win2K Pro)。您可以将 0 硬编码为 session ID(因为在 Win2K 中总是如此),我想您可能能够通过枚举正在运行的进程并复制其中一个 token 来获取用户 token (它应该是具有交互式 SID 存在)。无论如何, CreateProcessAsUser()即使您没有从服务设置中选择“与桌面交互”,在传递交互式用户 token 时也会以相同的方式运行。无论如何,它也比直接从服务启动更安全,因为该进程不会继承神圣的 LocalSystem访问 token 。

    现在,我不知道您的第三方应用程序在运行脚本/进程时是否会执行任何这些操作,但是如果您想从服务中执行此操作,那就是(对于 Vista 或 Win7,这是唯一的方法)克服 session 0 隔离)。

    关于winapi - 从非交互式服务 (win32/.net/powershell) 启动 UAC 提升进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2426594/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com