如何创建具有较低完整性级别 (IL) 的新流程?

Posted

技术标签:

【中文标题】如何创建具有较低完整性级别 (IL) 的新流程?【英文标题】:How to create a new process with a lower Integrity Level (IL)? 【发布时间】:2012-03-28 17:18:16 【问题描述】:

似乎从 Windows Vista 开始,具有较低完整性级别 (IL) 的进程无法将消息发送到具有较高完整性级别的进程。从安全的角度来看,这是有道理的,但它破坏了我们的一些进程间通信。

不幸的是,我们有一个遗留应用程序(进程 A)必须以提升的“管理员”权限运行(通过将其快捷方式设置为始终以管理员身份运行来完成)。有时它需要实例化一个单独的应用程序(进程 B)。结果,进程 B 继承了与进程 A 相同的提升特权(和 IL)。问题就在这里。进程 B 的其他独立实例可能没有具有提升的权限,并且所有这些进程 B 实例都需要能够相互发送消息。如果进程 B 的一个实例被提升而另一个没有被提升,这显然会失败。

我知道我们可以使用ChangeWindowMessageFilter API 方法在 UIPI 消息过滤器中打开漏洞,但这似乎不是理想的解决方案。相反,我更愿意让进程 A 生成具有降低权限的进程 B,特别是这样它就可以与其他进程 B 实例进行通信。我认为默认情况下,其他进程 B 实例在“中”IL 上运行,因此我希望进程 A 使用相同的 IL 生成进程 B 实例。

我的搜索使我找到了 CreateProcessAsUserCreateRestrictedToken API 方法,但尽管有这些文档,但令牌和安全描述符等的所有方面仍然让我很困惑。

我在这里也遇到了一些线程(Running a process with lowest possible privileges in winapi 和Dropping privileges in C++ on Windows),但我找不到任何好的代码示例。

谁能提供一些简单但“正确”的代码来帮助我使用适当的 Windows IL 生成子进程?具体来说,我想要一个示例,说明如何获取现有的 Process A 令牌并对其进行转换,使其具有降低的特权(我很确定我可以弄清楚其余的)。我真的不清楚在修改它之前是否需要复制进程的令牌。

【问题讨论】:

是否可以在非提升上下文中运行代理进程?如果是这样,您可以根据需要让代理进程代表进程 A 启动进程 B,或者让进程 A 从代理进程中获取令牌并使用它来启动进程 B。 @HarryJohnston – 我在其他地方读到过类似的解决方案,所以它肯定看起来可行。但是,除非这第三个代理进程 (C) 已经在运行(独立于进程 A),否则我们将回到第一步(如何使用较低权限运行单独的进程)。如果进程 C 正在运行,那么它可能必须在用户登录的整个过程中都在运行,我宁愿避免这种情况。 CreateRestrictedToken 似乎是专门为这种和类似类型的情况提供的,那么我们如何才能删除令牌的 IL? 【参考方案1】:

警告!虽然这种方法对于原始海报来说可能或多或少是可以的,但总的来说它并不是一个好主意。特别要注意(根据评论线程),据报道人为操作的令牌会导致更复杂的应用程序出现问题,因此如果您使用它们,请务必坚持使用基本的 Win32 API。当然也有潜在的安全隐患。

在与 OP 类似的大多数情况下,最好将启动提升的应用程序的快捷方式替换为启动器应用程序。只要提升的应用程序正在运行,启动器就可以保持运行,并为提升的应用程序提供一个自然受限的令牌,以用于启动非提升的进程。


在 MSDN 的 Designing Applications to Run at a Low Integrity Level 文章中有用于启动低完整性进程的代码,类似于您的情况。

首先,您复制流程令牌,因为您不能(或至少不应该)弄乱已被使用的令牌。然后使用SetTokenInformation 和 TokenIntegrityLevel 类来设置完整性级别。示例代码中似乎有一个错误,因为低完整性级别的正确 SID 是 S-1-16-4096 而不是 S-1-16-1024,但无论如何您都需要中等完整性级别,即 S -1-16-8192。这些可以在here找到。

一旦你有这个工作(也就是说,一旦你能够从你的高完整性进程启动中等完整性进程)你应该尝试使用 CreateRestrictedToken 而不是 DuplicateToken 创建新令牌,并删除管理员令牌和所有权限( SeChangeNotifyPrivilege 除外)。否则,新进程将具有中等完整性,但仍具有管理员权限,这可能会使可能在同一会话中运行的任何恶意代码更容易提升其权限。

【讨论】:

不客气。您可能希望使用 GetTokenInformation(与大多数或所有可用信息类)来比较常规的中等完整性进程与提升的进程,以便您可以计算出 UAC 实际执行哪些操作来创建受限令牌。 (详细信息,AFAIK,没有很好的记录。)甚至可以编写一些代码来比较您制作的令牌之一与 UAC 制作的令牌的所有属性,这样您就可以清楚地看到您是否是否忽略了任何事情。 来自 MSDN 的代码不再适用于 Windows 10。新流程仍将被提升。这在 Windows 7 上不会发生。比较 Win 7 和 Win 10 上的 GetTokenInformation(TokenElevation)! 在用令牌试验了很多天后,我突然想到,无论我们如何修改一个令牌,出来的东西都会被破坏。我尝试了一切来调整 High 令牌的所有令牌属性以获取 Medium 令牌,但是当启动具有嵌入式 Internet Explorer 控件的进程时,这会表现得很奇怪。如果你只用计算器测试你的代码,一切都会好的,但如果你需要一个通用的解决方案来处理任何进程,那么所有的令牌操作都会浪费时间。获得中等令牌的唯一可靠方法是 WTSQueryUserToken() 但这需要服务。 我还测试了 CreateRestrictedToken() 和 SaferComputeTokenFromLevel(),但结果始终相同:使用 CreateProcessAsUser() 启动我的进程时,人造令牌的行为与真实介质令牌不同。令人难以置信的是,对于如此重要​​的功能(例如,安装程序想要使用中等 IL 启动已安装的应用程序)没有简单和安全的 API 来在高级进程中获取中等令牌!类似于 ShellExecute(..., "asMedium",...)。不在 Vista 中,也不在 Win 7、8、10 中。我不明白为什么微软让程序员独自完成这项任务? @Elmue 我明白了,很有趣。好吧,令牌是不同的,这绝对是真的 - Process Hacker 显示出很多差异,至少在我创建它的方式上是这样。 Raymond Chen 说we really should be asking Explorer to run the app for us 得到一个未提升的版本。【参考方案2】:

我已使用此处描述的方法来完成此操作。基本思想是让 Explorer 为您运行 Process B。由于 Explorer 通常以中等完整性级别运行,因此这可以满足您的需求。

http://brandonlive.com/2008/04/26/getting-the-shell-to-run-an-application-for-you-part-1-why/ http://brandonlive.com/2008/04/27/getting-the-shell-to-run-an-application-for-you-part-2-how/

第一个链接至少会给你一个很好的背景。

不幸的是,我们有一个遗留应用程序(进程 A)必须以提升的“管理员”权限运行(通过将其快捷方式设置为始终以管理员身份运行来完成)。

一种更简洁的方法是将requestedExecutionLevel 设置为清单。

【讨论】:

我目前无法对此进行测试,但我最担心的是版本兼容性。这是否适用于从 XP 开始的所有 Windows 版本?它是否取决于未来版本中可能出现的任何问题?它看起来也使用了与 Internet Explorer 一起分发的库(请参阅IShellWindows)。如果用户没有安装 IE 怎么办? 此外,进程 A 不是 Visual Studio 项目,而是旧的 C++ Builder 应用程序。我知道如何在 Visual Studio 中设置应用程序清单,但您也可以在其他 C++ 项目中这样做吗? 在 XE2 之前的 C++Builder 版本中,您可以使用 .rc 文件将外部 .manifest 文件链接到项目资源中。 C++Builder XE2 在项目选项中添加了对自定义清单的支持。 @RemyLebeau - 很高兴知道,非常感谢!顺便说一句,你很久以前在 Borland 论坛上为我回答了一个问题。幸运的是,我和你还在身边的其他人分享你的专业知识。 [= @Jeremy:这些都是合理的担忧。对于 XP,您必须为其失败做好准备,这很好,因为 XP 没有完整性级别,所以如果它失败,您只需按照通常的方式启动进程 B(例如,CreateProcess)。我很惊讶 IShellWindows 与 IE 相关联,因为我认为它是由 shell(资源管理器)本身提供的。我不确定卸载 IE 是否真的会删除对象的实现。很有可能不会。【参考方案3】:

我可能没有回答您的完整问题,但正如您提到的有关 CreateProcessAsUser 和 CreateRestrictedToken 的问题。我有一个使用这个 API 的代码。我写的代码是基于下面这样写的。

来源:[Windows Vista for Developers – 第 4 部分 – 用户帐户控制] (http://weblogs.asp.net/kennykerr/Windows-Vista-for-Developers-1320-Part-4-1320-User-Account-Control)!

代码可在以下链接中找到。

示例代码:http://pastebin.com/XMUAehF9

【讨论】:

以上是关于如何创建具有较低完整性级别 (IL) 的新流程?的主要内容,如果未能解决你的问题,请参考以下文章

如何拥有服务 ImpersonateLoggedOnUser 但具有高强制性完整性级别?

创建一个R级别的新变量

具有不同分段级别的 UISlider

如何在 html 中创建具有较低分辨率图像的缩略图

如何允许较低 Android API 级别的用户下载较高 API 级别版本的应用程序?

如何访问在较低(父)级别声明的 Vue 对象的属性?