旧版应用的 AppContainer

AppContainer 环境是一种限制性的进程执行环境,可用于旧应用以提供资源安全性。 AppContainer 应用的进程及其子进程在轻量级应用容器中运行,其中只能访问专门授予它们的资源。 它们使用文件系统和注册表虚拟化进行隔离。 因此,无法在 AppContainer 中实现的应用受到黑客攻击,以允许在有限分配的资源之外执行恶意作。

对于打包和未打包的应用,AppContainer 表示良好的安全工程实践。

提示

AppContainer 最初 LowBox(在 Windows 8 发布之前)命名。 可以在 API 名称(如 NtCreateLowBoxToken)中看到该旧名称。

打包的应用

可以采用使用 MSIX 打包的应用,并轻松地将其配置为在 AppContainer 环境中运行。 通用 Windows 平台 (UWP) 应用自动是 AppContainer 应用。 但是,还可以将打包为 MSIX 的桌面应用配置为 AppContainer 应用。 如果使用 MSIX 打包,则使用 AppContainer 特别容易。 有关详细信息、方案和配置示例,请参阅 MSIX AppContainer 应用

解压缩的应用

未打包的应用也可以在应用容器中运行。 若要在应用容器中创建进程,需要 AppContainer 定义(或配置文件)。 因此,将 AppContainer 与打包的应用配合使用变得更加容易。 为用户注册包时,部署堆栈会调用某些 Win32 API,以便创建必要的 AppContainer 配置文件(例如,CreateAppContainerProfile)。 当你为用户注销包时,部署堆栈会执行删除 AppContainer 配置文件(DeleteAppContainerProfile) 的工作。 如果不打包应用,则必须自己调用这些 Win32 API 来执行相同的作:但它可能很复杂。

大多数使用低压缩级别的未打包应用现在使用 AppContainer 作为提供受限执行环境的更好方法。

当在应用容器中运行的解压缩进程调用 CreateProcess时,子进程通常继承父级的令牌。 该令牌包括完整性级别(IL)和应用容器信息。 最好不要考虑具有提升值/中/低/appContainer 的单个轴。 相反,在应用容器中是第二个和正交属性。 也就是说,如果你 在应用容器中,则完整性级别(IL)始终

使用 AppContainer 环境的好处

AppContainer 环境的主要目标是尽可能多地将应用状态与系统状态分开,同时保持与其他应用的兼容性。 Windows 通过检测和重定向它在运行时对文件系统和注册表所做的某些更改(称为 虚拟化)来完成此作。 AppContainer 应用写入其自己的虚拟注册表和应用程序数据文件夹,并在卸载或重置应用时删除该数据。 其他应用无权访问 AppContainer 应用的虚拟注册表或虚拟文件系统。

因此,AppContainer 环境提供安全的应用沙盒。 隔离应用访问硬件、文件、注册表、其他应用、网络连接和网络资源,而无需特定权限。 单个资源可以面向,而无需公开其他资源。 此外,用户标识通过使用唯一标识进行保护,该标识是用户和应用的串联;使用最低特权模型授予资源。 这可进一步防止模拟用户访问其他资源的应用。

用于测试在应用容器中运行的示例代码

在 C# 或C++项目中,可以使用下面的相应代码示例之一来确定进程是否在应用容器中运行。 对于每个示例,在代码运行后,如果 isAppContainer 的值是非零(或 true),则进程在应用容器中运行。

C# (P/Invoke)

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool OpenProcessToken(
    IntPtr ProcessHandle,
    UInt32 DesiredAccess,
    out IntPtr TokenHandle);

[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetTokenInformation(
    IntPtr TokenHandle,
    uint TokenInformationClass,
    out uint TokenInformation,
    uint TokenInformationLength,
    out uint ReturnLength);

UInt32 TOKEN_QUERY = 0x0008;
IntPtr tokenHandle;

if (!OpenProcessToken(
    GetCurrentProcess(),
    TOKEN_QUERY,
    out tokenHandle))
{
    // Handle the error.
}

uint isAppContainer;
uint TokenIsAppContainer = 29;
uint tokenInformationLength = sizeof(uint);

if (!GetTokenInformation(
    tokenHandle,
    TokenIsAppContainer,
    out isAppContainer,
    tokenInformationLength,
    out tokenInformationLength))
{
    // Handle the error.
}

C++ (WIL)

此示例使用 Windows 实现库(WIL))。 安装 WIL 的简便方法是转到 Visual Studio,单击“项目>管理 NuGet 包...”>浏览,在搜索框中键入或粘贴 Microsoft.Windows.ImplementationLibrary,选择搜索结果中的项,然后单击 安装 安装该项目的包。

#include <wil\token_helpers.h>
...
bool isAppContainer = wil::get_token_is_app_container();

函数 wil::get_token_is_app_container_nothrowwil::get_token_is_app_container_failfast 提供替代的错误处理策略。 有关详细信息,请参阅 wil\token_helpers.h

C++ (规范)

#include <windows.h>
...
HANDLE tokenHandle{};
DWORD isAppContainer{};
DWORD tokenInformationLength{ sizeof(DWORD) };

if (!::OpenProcessToken(
    GetCurrentProcess(),
    TOKEN_QUERY,
    &tokenHandle))
{
    // Handle the error.
}

if (!::GetTokenInformation(
    tokenHandle,
    TOKEN_INFORMATION_CLASS::TokenIsAppContainer,
    &isAppContainer,
    tokenInformationLength,
    &tokenInformationLength
))
{
    // Handle the error.
}

在本部分中

有关将 AppContainer 用于旧版应用的详细信息,请参阅以下主题。

主题 描述
AppContainer 隔离 隔离是 AppContainer 执行环境的主要目标。 通过将应用与不需要的资源和其他应用隔离,恶意作的机会将最小化。 基于最低特权授予访问权限可防止应用和用户访问超出其权限的资源。 控制对资源的访问可保护进程、设备和网络。
实现 AppContainer AppContainer 通过将新信息添加到进程令牌、更改 SeAccessCheck() 来实现,以便默认情况下,所有旧式未修改的访问控制列表 (ACL) 对象都会阻止来自 AppContainer 进程的访问请求,以及应提供给 AppContainers 的重新 ACL 对象。