NtCreateLowBoxToken
Leitet ein LowBox- (AppContainer-)Token aus einem bestehenden Token ab — setzt die Package-SID und Capability-Liste, die den Broker-IPC-Zugriff steuern.
Prototyp
NTSTATUS NtCreateLowBoxToken( PHANDLE TokenHandle, HANDLE ExistingTokenHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PSID PackageSid, ULONG CapabilityCount, PSID_AND_ATTRIBUTES Capabilities, ULONG HandleCount, PHANDLE Handles );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| TokenHandle | PHANDLE | out | Empfängt das Handle des neuen LowBox-Tokens. |
| ExistingTokenHandle | HANDLE | in | Quell-Token. Erfordert TOKEN_DUPLICATE. Das LowBox wird aus seinem User/Groups abgeleitet. |
| DesiredAccess | ACCESS_MASK | in | Auf das neue Token angefragte Zugriffsmaske. TOKEN_ALL_ACCESS ist üblich, wenn der Aufrufer es danach zuweist. |
| ObjectAttributes | POBJECT_ATTRIBUTES | in | Objekt-Attribute. SecurityQualityOfService steuert den Impersonation-Level bei entsprechender Nutzung. |
| PackageSid | PSID | in | AppContainer-Package-SID — kodiert die eindeutige Identität der sandboxed App, scoped Objektnamen unter \Sessions\...\AppContainerNamedObjects. |
| CapabilityCount | ULONG | in | Anzahl der Einträge in Capabilities. Darf 0 sein. |
| Capabilities | PSID_AND_ATTRIBUTES | in | Array von Capability-SIDs (internetClient, picturesLibrary usw.), die dem LowBox gewährt werden. |
| HandleCount | ULONG | in | Anzahl der Handles in Handles. Üblicherweise 0. |
| Handles | PHANDLE | in | Optionales Array von Objekt-Handles, die dem LowBox angehängt werden, damit es darauf zugreifen kann trotz normaler AC-Restriktionen. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0xA5 | win10-1507 |
| Win10 1607 | 0xA7 | win10-1607 |
| Win10 1703 | 0xAA | win10-1703 |
| Win10 1709 | 0xAB | win10-1709 |
| Win10 1803 | 0xAC | win10-1803 |
| Win10 1809 | 0xAC | win10-1809 |
| Win10 1903 | 0xAD | win10-1903 |
| Win10 1909 | 0xAD | win10-1909 |
| Win10 2004 | 0xB1 | win10-2004 |
| Win10 20H2 | 0xB1 | win10-20h2 |
| Win10 21H1 | 0xB1 | win10-21h1 |
| Win10 21H2 | 0xB2 | win10-21h2 |
| Win10 22H2 | 0xB2 | win10-22h2 |
| Win11 21H2 | 0xB5 | win11-21h2 |
| Win11 22H2 | 0xB6 | win11-22h2 |
| Win11 23H2 | 0xB6 | win11-23h2 |
| Win11 24H2 | 0xB8 | win11-24h2 |
| Server 2016 | 0xA7 | winserver-2016 |
| Server 2019 | 0xAC | winserver-2019 |
| Server 2022 | 0xB4 | winserver-2022 |
| Server 2025 | 0xB8 | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
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
Undokumentierte Hinweise
Trägt die in Windows 8 eingeführte AppContainer-Sandbox, die jede Windows-Runtime-App, Edges Content-Prozesse, Chromes Renderer-Sandbox (im AppContainer-Modus), die WSA-Android-Runtime und der moderne WebView2-Host nutzen. Die Kernel-Routine SepCreateLowBoxToken nimmt das Quell-Token, kopiert User/Groups/Privileges und legt darüber die LowBox-Attribute: die Package-SID (gespeichert in `LowBoxNumberEntry` / `Package` des Tokens) und das Capability-Array (als spezielle Gruppe mit Attributen nahe SE_GROUP_INTEGRITY). Sobald das resultierende Token einem Prozess via NtAssignProcessToken zugewiesen oder mit NtCreateUserProcess genutzt wird, fügt der Kernel AppContainer-Access-Checks ein: Objektnamen werden in den per-AC-Namespace `\Sessions\<n>\AppContainerNamedObjects\<PackageSid>` umgeleitet; Netzwerkzugriff wird durch `internetClient` / `privateNetworkClientServer` reguliert; Broker-IPC-Kanäle (für AppContainer reservierte RPC-Interfaces) werden erreichbar.
Häufige Malware-Nutzung
Überwiegend legitim; echte bösartige Nutzung existiert, ist aber selten. Muster: Ein Prozess, der sonst an einer Broker-RPC-Schnittstelle scheitern würde (manche WinRT-Broker-Endpoints prüfen die Aufrufer-PackageSid und akzeptieren nur AppContainer-Principals), ruft NtCreateLowBoxToken mit der *erwarteten* PackageSid einer legitimen AC-App auf, weist das Token einem Helper-Child zu und pivotet durch den Broker, als wäre er diese App. Das ist der Kern mehrerer veröffentlichter Sandbox-Escape-PoCs von Project Zero, Google-Bughuntern und einigen CTF-Writeups (insbesondere Escapes aus Edges Content-Prozess und dem WSA-RuntimeBroker). Vereinzelt auch in Red-Team-Tooling, um *freiwillig* in einen AppContainer einzutreten — praktisch, wenn der Operator möchte, dass sein Tradecraft für ein defensives Tool, das AC-Prozesse whitelistet, wie ein normales Edge-Kind aussieht.
Erkennungsmöglichkeiten
Microsoft-Windows-Threat-Intelligence emittiert kein dediziertes Event für NtCreateLowBoxToken; Detection muss sich auf Seiteneffekte stützen. Hochwertiger Pivot: *Erzeugung eines AppContainer-Tokens durch einen nicht-AC-bewussten Prozess*. Alles außerhalb einer kleinen Whitelist (svchost.exe als AC-Infra-Host, MicrosoftEdgeUpdate.exe, RuntimeBroker.exe, BackgroundTaskHost.exe, smsvchost.exe), das diesen Syscall aufruft, ist anomal. Sysmon-Event 25 (Process Tampering) feuert manchmal beim folgenden NtAssignProcessToken, wenn das neue Token den Manifest-Deklarationen des Prozesses widerspricht. Der ETW-Provider Microsoft-Windows-Win32k-Power kann das Namespace-Remapping zeigen, sobald das LowBox-Child auf `\Sessions\...\AppContainerNamedObjects\<unerwartetes-package>` zugreift. PackageSid-Fälschung (Mismatch zwischen PackageSid und signierter Identität der Executable) ist der stärkste verhaltensbasierte Indikator.
Direkte Syscall-Beispiele
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 ENDPrustAdd 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 }
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20