【发布时间】:2018-10-22 05:58:10
【问题描述】:
假设您的 Windows 用户帐户在 Admin 组中,已启用 UAC,并且您正在以普通用户权限运行某个程序 A。 A 从不要求提升,也从不接受。现在假设 A 想要启动程序 B,它的 manifest 中有highestAvailable。
如果 A 调用 CreateProcess(B),这将失败并出现错误 740(“需要高程”)
如果 A 调用 ShellExecuteEx(B),Windows 将显示一个 UAC 框,要求运行提升的 B。用户可以说是,在这种情况下 B 将运行提升,或者说否,在这种情况下启动将失败。
我的问题是:有没有办法实现第三种选择,即我们只需启动 B 而无需提升?
这似乎在原则上应该是可能的,因为“highestAvailable”意味着B 更喜欢 以海拔运行,但完全能够在正常用户模式下运行。但我想不出任何方法来完成它。我已经用令牌和 CreateProcessAsUser() 尝试过各种事情,但这一切似乎都归结为:“highestAvailable”似乎一成不变地指的是用户帐户中固有的潜在权限,而不是任何明确表达的实际权限构造令牌。
我希望实际上有某种方法可以使用 CreateProcessAsUser() 来执行此操作,而我只是错过了正确构造令牌的技巧。
更新 - 已解决: 下面的 __COMPAT_LAYER=RunAsInvoker 解决方案效果很好。一个警告,不过。这强制子进程无条件地“作为调用者”运行:即使被调用的 exe 在其清单中指定“requireAdministrator”,它也适用。我认为当 exe 指定“requireAdministrator”时,原始的“需要提升”错误通常更可取。我想要标记为“highestAvailable”的程序的 RunAsInvoker 行为的全部原因是,这些程序明确表示“我可以在任何一种模式下正常运行”——所以当使用管理员模式不方便时,让我们继续在普通用户模式下运行。但是“requireAdministrator”是另一回事:此类程序说“如果没有提升的权限,我将无法正常运行”。对于这些程序来说,预先失败似乎比强迫它们运行不提升更好,这可能会使它们遇到他们没有正确编程处理的特权/访问错误。所以我认为这里一个完整的通用解决方案需要检查应用程序清单,并且只有在清单显示“highestAvailable”时才应用 RunAsInvoker 强制。一个更完整的解决方案是使用其他地方讨论的技术之一,当出现“requireAdministrator”程序时,给调用者一个调用 UAC 的选项,并为用户提供启动它的机会。我可以想象一个 CreateProcessEx() 覆盖有几个新标志,用于“将进程权限视为最高可用权限”和“如果需要提升则调用 UAC”。 (下面描述的另一种方法,挂钩 NTDLL!RtlQueryElevationFlags() 以告诉 CreateProcess() UAC 不可用,对于 requireAdministrator 程序具有完全相同的警告。)
(这可能表明 Windows shell 甚至不提供执行此操作的方法...直接从 shell 启动 B 会为您提供 UAC 框,让您可以使用 Admin privs 启动或根本不启动。如果有任何方法可以实现它,UAC 框可能会提供第三个按钮以在没有权限的情况下启动。但话又说回来,这可能只是一个 UX 决定,第三个选项对平民来说太混乱了。)
(请注意,StackOverflow 和 Microsoft 开发人员支持网站上有很多帖子询问一个看起来非常相似的场景,但不幸的是,这并不适用于此。这种场景是您有一个正在运行的父程序提升,并且它想要启动一个非提升的子进程。典型的例子是一个安装程序,像安装程序倾向于做的那样运行提升,它想要在它退出之前以普通用户级别启动它刚刚安装的程序。有很多发布了有关如何做到这一点的代码,我的尝试基于其中一些技术,但这确实是一个不同的场景,解决方案在我的情况下不起作用.最大的区别是它们是子程序在这种情况下尝试启动不标记为highestAvailable - 孩子只是一个正常的程序,在正常情况下会在没有任何UAC参与的情况下启动。还有另一个区别,那就是在那些场景中, 这 父级已经在提升,而在我的场景中,父级以普通用户级别运行;这会稍微改变一些事情,因为在其他场景中的父进程可以访问我无法使用的令牌上的一些特权操作,因为 A 本身并没有提升。但据我所知,这些特权令牌操作无论如何都无济于事。事实上,孩子拥有最高可用标志,这是我的场景的关键元素。)
【问题讨论】:
-
合法的方式不存在。但是,您可以在调用
CreateProcess之前将RtlQueryElevationFlagsapi 挂接到自身进程中(例如通过 DR 寄存器和 vex 处理程序)并将返回的标志设置为 0。在这种情况下,将启动子进程。 -
@RbMm - 谢谢,我会调查的。虽然如果它不是“合法方式”,它可能不是我想要的。我确实从所有有关从提升中启动非提升的相关问题中得到印象,你是对的,但它根本不可能“合法”。
-
确实如此(使用 DR 和 vex 挂钩 api 调用,非常容易实现)但当然这在未来可能会被打破
-
@RbMm - 我读到了。这绝对是正确的,但你确定这是一个黑客攻击是正确的。
-
如果想要我可以发布准备好的代码怎么做。当然破解。但照原样
标签: winapi createprocess elevation createprocessasuser