> Windows Syscalls
ntoskrnl.exeT1134T1106

NtCreateLowBoxToken

Dérive un token LowBox (AppContainer) à partir d'un token existant — fixe le SID de package et les capabilities qui régulent l'accès au broker IPC.

Prototype

NTSTATUS NtCreateLowBoxToken(
  PHANDLE              TokenHandle,
  HANDLE               ExistingTokenHandle,
  ACCESS_MASK          DesiredAccess,
  POBJECT_ATTRIBUTES   ObjectAttributes,
  PSID                 PackageSid,
  ULONG                CapabilityCount,
  PSID_AND_ATTRIBUTES  Capabilities,
  ULONG                HandleCount,
  PHANDLE              Handles
);

Arguments

NameTypeDirDescription
TokenHandlePHANDLEoutReçoit le handle du nouveau token LowBox.
ExistingTokenHandleHANDLEinToken source. Requiert TOKEN_DUPLICATE. Le LowBox est dérivé de son user/groupes.
DesiredAccessACCESS_MASKinMasque d'accès demandé sur le nouveau token. TOKEN_ALL_ACCESS est typique si l'appelant va ensuite l'assigner.
ObjectAttributesPOBJECT_ATTRIBUTESinAttributs d'objet. SecurityQualityOfService contrôle le niveau d'impersonation si utilisé ainsi.
PackageSidPSIDinSID de package AppContainer — encode l'identité unique de l'app sandboxée, sert à scoper les noms d'objets sous \Sessions\...\AppContainerNamedObjects.
CapabilityCountULONGinNombre d'entrées dans Capabilities. Peut être 0.
CapabilitiesPSID_AND_ATTRIBUTESinTableau de SIDs de capability (internetClient, picturesLibrary, etc.) accordées au LowBox.
HandleCountULONGinNombre de handles dans Handles. Habituellement 0.
HandlesPHANDLEinTableau optionnel de handles d'objets à rattacher au LowBox pour qu'il y accède malgré les restrictions AC normales.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070xA5win10-1507
Win10 16070xA7win10-1607
Win10 17030xAAwin10-1703
Win10 17090xABwin10-1709
Win10 18030xACwin10-1803
Win10 18090xACwin10-1809
Win10 19030xADwin10-1903
Win10 19090xADwin10-1909
Win10 20040xB1win10-2004
Win10 20H20xB1win10-20h2
Win10 21H10xB1win10-21h1
Win10 21H20xB2win10-21h2
Win10 22H20xB2win10-22h2
Win11 21H20xB5win11-21h2
Win11 22H20xB6win11-22h2
Win11 23H20xB6win11-23h2
Win11 24H20xB8win11-24h2
Server 20160xA7winserver-2016
Server 20190xACwinserver-2019
Server 20220xB4winserver-2022
Server 20250xB8winserver-2025

Module noyau

ntoskrnl.exeNtCreateLowBoxToken

APIs liées

CreateAppContainerTokenCreateProcessAsUserNtAssignProcessTokenNtCreateUserProcessDeriveCapabilitySidsFromNameDeriveAppContainerSidFromAppContainerName

Stub du syscall

4C 8B D1            mov r10, rcx
B8 B8 00 00 00      mov eax, 0xB8
F6 04 25 08 03 FE 7F 01   test byte ptr [0x7FFE0308], 1
75 03               jne short +3
0F 05               syscall
C3                  ret
CD 2E               int 2Eh
C3                  ret

Notes non documentées

Sous-tend le bac à sable AppContainer introduit dans Windows 8 et utilisé par toute app Windows Runtime, les processus de contenu d'Edge, le bac à sable du renderer Chrome (quand le mode AppContainer est activé), le runtime Android WSA, et l'hôte WebView2 moderne. La routine noyau SepCreateLowBoxToken prend le token source, copie User/Groups/Privileges, puis empile les attributs LowBox : le SID de package (stocké dans `LowBoxNumberEntry` / `Package` du token) et le tableau de capabilities (stocké comme un groupe spécial avec des attributs adjacents à SE_GROUP_INTEGRITY). Une fois le token résultant assigné à un processus via NtAssignProcessToken ou utilisé avec NtCreateUserProcess, le noyau insère des contrôles d'accès AppContainer : la résolution de nom d'objet est redirigée vers le namespace `\Sessions\<n>\AppContainerNamedObjects\<PackageSid>` par AC ; l'accès réseau est régulé par les capabilities `internetClient` / `privateNetworkClientServer` ; les canaux IPC broker (interfaces RPC réservées aux AppContainers) deviennent atteignables.

Usage courant par les malwares

Majoritairement légitime ; l'usage malveillant existe mais reste rare. Pattern : un processus qui serait sinon bloqué par une interface RPC broker (certains endpoints WinRT broker vérifient le PackageSid de l'appelant et n'acceptent que les principaux AppContainer) appelle NtCreateLowBoxToken avec le PackageSid *attendu* d'une app AC légitime, assigne le token à un enfant helper, et passe par le broker comme s'il était cette app. C'est l'essence de plusieurs PoCs d'évasion sandbox publiés par Project Zero, des chasseurs Google et quelques writeups CTF (notamment des évasions du content process Edge et du RuntimeBroker WSA). Aussi utilisé occasionnellement par l'outillage red-team pour *entrer* volontairement dans un AppContainer — pratique quand l'opérateur veut que son tradecraft ressemble à un enfant Edge normal pour un outil défensif qui whitelist les processus AC.

Opportunités de détection

Microsoft-Windows-Threat-Intelligence n'émet pas d'événement dédié à NtCreateLowBoxToken ; la détection doit s'appuyer sur les effets de bord. Pivot fiable : *création d'un token AppContainer par un processus non AC-aware*. Tout ce qui n'est pas dans une petite liste blanche (svchost.exe hébergeant l'infra AC, MicrosoftEdgeUpdate.exe, RuntimeBroker.exe, BackgroundTaskHost.exe, smsvchost.exe) appelant ce syscall est anormal. Sysmon Event 25 (process tampering) se déclenche parfois sur le NtAssignProcessToken qui suit, quand le nouveau token contredit les déclarations du manifeste du processus. Le provider ETW Microsoft-Windows-Win32k-Power peut montrer le remapping de namespace quand l'enfant LowBox touche `\Sessions\...\AppContainerNamedObjects\<package-inattendu>`. La forge de PackageSid (mismatch entre PackageSid et identité signée de l'exécutable) est l'indicateur comportemental le plus fort.

Exemples de syscalls directs

cVoluntarily enter a LowBox (red-team blend pattern)

// Build a LowBox token tagged with an arbitrary PackageSid, then assign it
// to a helper process so it executes as if it were that AppContainer app.
typedef NTSTATUS(NTAPI* fnNtCreateLowBoxToken)(
    PHANDLE, HANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
    PSID, ULONG, PSID_AND_ATTRIBUTES, ULONG, PHANDLE);

HANDLE BuildLowBox(HANDLE hSourceToken, PSID packageSid) {
    HMODULE n = GetModuleHandleA("ntdll.dll");
    fnNtCreateLowBoxToken p = (fnNtCreateLowBoxToken)
        GetProcAddress(n, "NtCreateLowBoxToken");
    OBJECT_ATTRIBUTES oa = { sizeof(oa) };
    HANDLE hLowBox = NULL;
    NTSTATUS s = p(&hLowBox, hSourceToken, TOKEN_ALL_ACCESS, &oa,
                   packageSid, 0, NULL, 0, NULL);
    return (s == 0) ? hLowBox : NULL;
}

asmx64 direct stub (Win11 24H2 SSN)

; SSN 0xB8 on win11-24h2 / winserver-2025. 9 args — most spill to the stack.
NtCreateLowBoxToken PROC
    mov  r10, rcx
    mov  eax, 0B8h
    syscall
    ret
NtCreateLowBoxToken ENDP

rustAdd internetClient capability to a LowBox

// Capability SIDs are derived from cap names via DeriveCapabilitySidsFromName.
// Here we hard-code S-1-15-3-1 (internetClient) for brevity.
use windows_sys::Win32::Security::PSID;
use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleA, GetProcAddress};

#[repr(C)]
struct SidAndAttributes { sid: PSID, attributes: u32 }

type NtCreateLowBoxToken = unsafe extern "system" fn(
    out: *mut isize, src: isize, access: u32, oa: *mut u8,
    package: PSID, cap_count: u32, caps: *mut SidAndAttributes,
    handle_count: u32, handles: *mut isize,
) -> i32;

pub unsafe fn lowbox_with_internet(
    src: isize, package: PSID, internet_client: PSID,
) -> Option<isize> {
    let n = GetModuleHandleA(b"ntdll.dll\0".as_ptr());
    let addr = GetProcAddress(n, b"NtCreateLowBoxToken\0".as_ptr())?;
    let f: NtCreateLowBoxToken = std::mem::transmute(addr);
    let mut cap = SidAndAttributes { sid: internet_client, attributes: 0x04 /* SE_GROUP_ENABLED */ };
    let mut oa = [0u8; 48];
    let mut out: isize = 0;
    if f(&mut out, src, 0xF01FF, oa.as_mut_ptr(), package, 1, &mut cap, 0, core::ptr::null_mut()) == 0 {
        Some(out)
    } else { None }
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20