Win32-作为普通用户进程启动highestAvailable子进程 [英] Win32 - Launching a highestAvailable child process as a normal user process

查看:167
本文介绍了Win32-作为普通用户进程启动highestAvailable子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设您的Windows用户帐户位于Admin组中,并且启用了UAC,并且您正在以普通用户权限运行某些程序A. A从不要求海拔,也从不接受海拔.现在假设A想要启动程序B,该程序的清单中具有最高的可用率.

Suppose your Windows user account is in the Admin group, UAC is enabled, and you're running some program A with normal user privileges. A never asks for elevation and never receives it. Now suppose A wants to launch program B, which has highestAvailable in its manifest.

  • 如果A调用CreateProcess(B),它将失败并显示错误740(需要海拔")

  • If A calls CreateProcess(B), this will fail with error 740 ("elevation required")

如果A调用ShellExecuteEx(B),则Windows将显示一个UAC框,要求运行B高架.用户可以说是"(在这种情况下B会升高运行),或者否"(在这种情况下启动会失败).

If A calls ShellExecuteEx(B), Windows will display a UAC box asking to run B elevated. The user can say Yes, in which case B will run elevated, or No, in which case the launch will fail.

我的问题是:有没有办法实现第三种选择,即我们不加高就直接发射B?

这似乎在原则上应该是可能的,因为"highestAvailable"表示B 首选以仰角运行,但完全能够在普通用户模式下运行.但是我不知道有什么办法可以实现它.我已经尝试过使用令牌和CreateProcessAsUser()进行各种操作,但这似乎可以归结为:"highestAvailable"似乎始终是指用户帐户中固有的潜在特权,而不是任何显式表示的实际特权.构造的令牌.

It seems like this should be possible in principle, since "highestAvailable" means that B prefers to run with elevation but is perfectly capable of running in normal user mode. But I can't figure out any way to accomplish it. I've tried all sorts of things with tokens and CreateProcessAsUser(), but it all seems to come down to this: "highestAvailable" seems to unalterably refer to the latent privileges inherent in the user account, not the actual privileges expressed in any explicitly constructed token.

我希望实际上有某种方法可以使用CreateProcessAsUser()来做到这一点,而我只是缺少正确构造令牌的窍门.

I'm hoping that there actually is some way to use CreateProcessAsUser() to do this, and that I'm just missing the trick for properly constructing the token.

更新-已解决:下面的__COMPAT_LAYER = RunAsInvoker解决方案效果很好.不过,请注意.这将强制子进程无条件地作为调用者"运行:即使被调用的exe在其清单中指定了"requireAdministrator",它也适用.我认为,当exe指定"requireAdministrator"时,通常最好选择原始的需要海拔高度"错误.我想要标记为"highestAvailable"的程序的RunAsInvoker行为的全部原因是,此类程序明确表示我可以在任何一种模式下正常运行"-因此,让我们继续使用正常的用户模式(如果不方便使用Admin模式).但是"requireAdministrator"是另一回事:此类程序说如果没有提升的特权,我将无法正常运行".对于此类程序,使它们预先失败似乎比强制它们不升高运行更好,这可能会使它们遇到未正确编程处理的特权/访问错误.因此,我认为这里的完整通用解决方案将需要检查应用程序清单,并且仅在清单显示为"highestAvailable"时才应用RunAsInvoker强制.甚至更完善的解决方案是使用在其他地方讨论过的一种技术,在出现"requireAdministrator"程序时,为调用方提供调用UAC的选项,并为用户提供启动提升权限的机会.我可以想象一个带有两个新标记的CreateProcessEx()封面,这些标记分别是将处理过程特权作为最高可用特权"和如果需要提升,则调用UAC". (下面介绍的另一种方法是,钩住NTDLL!RtlQueryElevationFlags()告诉CreateProcess()UAC不可用,对于requireAdministrator程序也有同样的警告.)

Update - solved: the __COMPAT_LAYER=RunAsInvoker solution below works nicely. One caveat, though. This coerces the subprocess to run "as invoker" unconditionally: it applies even if the exe being invoked specifies "requireAdministrator" in its manifest. I think the original "elevation required" error is generally preferable when the exe specifies "requireAdministrator". The whole reason I wanted the RunAsInvoker behavior for programs marked with "highestAvailable" is that such programs are expressly saying "I can function properly in either mode" - so let's go ahead and run in normal user mode when it's inconvenient to use Admin mode. But "requireAdministrator" is a different matter: such programs are saying "I can't function properly without elevated privileges". It seems better to fail up front for such programs than to force them to run un-elevated, which might make them encounter privilege/access errors that they're not properly programmed to handle. So I think a complete, general-purpose solution here would require checking the application manifest, and only applying the RunAsInvoker coercion if the manifest says "highestAvailable". An even completer solution would be to use one of the techniques discussed elsewhere to give the caller an option to invoke UAC when presented with a "requireAdministrator" program and offer the user a chance to launch it elevated. I can imagine a CreateProcessEx() cover with a couple of new flags for "treat process privileges as highest available privileges" and "invoke UAC if elevation is required". (The other approach described below, hooking NTDLL!RtlQueryElevationFlags() to tell CreateProcess() that UAC is unavailable, has exactly this same caveat with respect to requireAdministrator programs.)

(这可能是在说Windows Shell甚至没有提供执行此操作的方法...直接从Shell启动B会给您一个UAC框,该框允许您使用Admin privs启动或完全不启动.如果有任何方法可以实现,UAC框可能会提供第三个按钮,无需特权即可启动.但是同样,这可能只是UX的决定,即第三种选择对平民来说太混乱了.)

(It's probably telling that the Windows shell doesn't even offer a way to do this... launching B directly from the shell would give you the UAC box that lets you either launch with Admin privs or not launch at all. If there were any way to accomplish it, the UAC box might offer a third button to launch without privileges. But then again that could just be a UX decision that the third option is too confusing for civilians.)

(请注意,StackOverflow和Microsoft开发支持网站上有很多帖子,询问一个非常相似的场景,但不幸的是不适用于此处.在这种情况下,您的父程序正在运行,典范的例子是一个安装程序,它会按照安装程序的意愿进行提升运行,它想在退出之前在普通用户级别启动刚刚安装的程序.发布了有关如何执行此操作的代码,我已经基于其中的一些技巧进行了尝试,但这确实是一种不同的情况,解决方案在我的情况下不起作用,最大的区别在于它们是子程序在这种情况下尝试启动时没有标记为最高可用"-该孩子只是正常程序,在正常情况下无需任何UAC即可启动.还有另一个区别,那就是在这些情况下, 这 父级已经运行提升,而在我的方案中,父级正在以普通用户级别运行;这会稍有变化,因为在这种情况下,父进程可以访问一些我无法使用的令牌的特权操作,因为A本身并未提升.但是据我所知,那些特权令牌操作仍然无济于事.事实是,孩子拥有最高的available标志,这是我的方案的关键要素.)

(Note that there are quite a lot of posts on StackOverflow and the Microsoft dev support sites asking about a very similar-seeming scenario that unfortunately doesn't apply here. That scenario is where you have a parent program that's running elevated, and it wants to launch a non-elevated child process. The canonical example is an installer, running elevated as installers tend to do, that wants to launch the program it just installed, at normal user level, just before it exits. There's lots of posted code about how to do that, and I've based my attempts on some of those techniques, but this is really a different scenario and the solutions don't work in my situation. The big difference is that the child program they're attempting to launch in this case isn't marked with highestAvailable - the child is just a normal program that would launch without any UAC involvement under normal circumstances. There's another difference as well, which is that in those scenarios, the parent is already running elevated, whereas in my scenario the parent is running as normal user level; that changes things slightly because the parent process in this other scenario has access to a few privileged operations on tokens that I can't use because A isn't itself elevated. But as far as I can tell those privileged token operations wouldn't help anyway; it's the fact that the child has the highestAvailable flag that's the key element of my scenario.)

推荐答案

__COMPAT_LAYER环境变量设置为

Set the __COMPAT_LAYER environment variable to RunAsInvoker in your process. I don't think this is formally documented anywhere but it works all the way back to Vista.

您也可以通过在注册表中的AppCompatFlags\Layers项下将其设置为永久设置.

You can also make it permanent by setting the it under the AppCompatFlags\Layers key in the registry.

这篇关于Win32-作为普通用户进程启动highestAvailable子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆