> Windows Syscalls
ntoskrnl.exeT1134T1106

NtCreateLowBoxToken

Deriva un token LowBox (AppContainer) a partir de un token existente — fija el SID de paquete y las capabilities que gobiernan el acceso al broker IPC.

Prototipo

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

Argumentos

NameTypeDirDescription
TokenHandlePHANDLEoutRecibe el handle del nuevo token LowBox.
ExistingTokenHandleHANDLEinToken origen. Requiere TOKEN_DUPLICATE. El LowBox se deriva de su user/groups.
DesiredAccessACCESS_MASKinMáscara de acceso solicitada sobre el nuevo token. TOKEN_ALL_ACCESS es típica si el llamante luego lo asignará.
ObjectAttributesPOBJECT_ATTRIBUTESinAtributos de objeto. SecurityQualityOfService controla el nivel de impersonación si se usa así.
PackageSidPSIDinSID de paquete AppContainer — codifica la identidad única de la app sandbox, usado para acotar nombres de objeto bajo \Sessions\...\AppContainerNamedObjects.
CapabilityCountULONGinNúmero de entradas en Capabilities. Puede ser 0.
CapabilitiesPSID_AND_ATTRIBUTESinArray de SIDs de capability (internetClient, picturesLibrary, etc.) otorgadas al LowBox.
HandleCountULONGinNúmero de handles en Handles. Normalmente 0.
HandlesPHANDLEinArray opcional de handles de objeto a adjuntar al LowBox para acceder a ellos pese a las restricciones normales AC.

IDs de syscalls por versión de Windows

Versión 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

Módulo del kernel

ntoskrnl.exeNtCreateLowBoxToken

APIs relacionadas

CreateAppContainerTokenCreateProcessAsUserNtAssignProcessTokenNtCreateUserProcessDeriveCapabilitySidsFromNameDeriveAppContainerSidFromAppContainerName

Stub del 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

Notas no documentadas

Es la base del sandbox AppContainer introducido en Windows 8 y usado por toda app del Windows Runtime, los procesos de contenido de Edge, el sandbox del renderer de Chrome (cuando está activo el modo AppContainer), el runtime Android WSA y el host WebView2 moderno. La rutina kernel SepCreateLowBoxToken toma el token origen, copia User/Groups/Privileges y luego apila los atributos LowBox: el SID de paquete (almacenado en `LowBoxNumberEntry` / `Package` del token) y el array de capabilities (almacenado como un grupo especial con atributos cercanos a SE_GROUP_INTEGRITY). Una vez asignado el token resultante a un proceso vía NtAssignProcessToken o usado con NtCreateUserProcess, el kernel inserta comprobaciones de acceso AppContainer: la resolución de nombres de objeto se redirige al namespace `\Sessions\<n>\AppContainerNamedObjects\<PackageSid>` por AC; el acceso a red lo gobiernan las capabilities `internetClient` / `privateNetworkClientServer`; los canales IPC de broker (interfaces RPC reservadas a AppContainers) pasan a ser accesibles.

Uso común por malware

Mayormente legítimo; el uso malicioso existe pero es raro. Patrón: un proceso que de otro modo estaría bloqueado en una interfaz RPC broker (algunos endpoints WinRT broker chequean el PackageSid del llamante y solo aceptan principales AppContainer) llama a NtCreateLowBoxToken con el PackageSid *esperado* de una app AC legítima, asigna el token a un hijo helper y atraviesa el broker como si fuera esa app. Esa es la esencia de varios PoCs de escape de sandbox publicados por Project Zero, cazadores de Google y algunos writeups de CTF (notablemente escapes del proceso de contenido de Edge y del RuntimeBroker WSA). También se ve ocasionalmente en herramientas red-team para *entrar* voluntariamente en un AppContainer — útil cuando el operador quiere que su tradecraft parezca un hijo normal de Edge para una herramienta defensiva que whitelist procesos AC.

Oportunidades de detección

Microsoft-Windows-Threat-Intelligence no emite evento dedicado a NtCreateLowBoxToken; la detección depende de efectos secundarios. Pivote fiable: *creación de un token AppContainer por un proceso no consciente de AC*. Cualquier cosa fuera de una pequeña lista blanca (svchost.exe hospedando infra AC, MicrosoftEdgeUpdate.exe, RuntimeBroker.exe, BackgroundTaskHost.exe, smsvchost.exe) invocando este syscall es anómalo. Sysmon Event 25 (process tampering) a veces se dispara en el NtAssignProcessToken subsiguiente cuando el nuevo token contradice las declaraciones del manifiesto del proceso. El proveedor ETW Microsoft-Windows-Win32k-Power puede mostrar el remapeo de namespace cuando el hijo LowBox toca `\Sessions\...\AppContainerNamedObjects\<paquete-inesperado>`. La forja de PackageSid (mismatch entre PackageSid e identidad firmada del ejecutable) es el indicador conductual más fuerte.

Ejemplos de syscalls directos

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 }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20