> Windows Syscalls
ntoskrnl.exeT1134T1134.002T1106

NtFilterToken

Creates a restricted (filtered) copy of an existing access token by disabling SIDs, deleting privileges, or adding restricted SIDs.

Prototype

NTSTATUS NtFilterToken(
  HANDLE          ExistingTokenHandle,
  ULONG           Flags,
  PTOKEN_GROUPS   SidsToDisable,
  PTOKEN_PRIVILEGES PrivilegesToDelete,
  PTOKEN_GROUPS   RestrictedSids,
  PHANDLE         NewTokenHandle
);

Arguments

NameTypeDirDescription
ExistingTokenHandleHANDLEinHandle to the source token (needs TOKEN_DUPLICATE access).
FlagsULONGinCombination of DISABLE_MAX_PRIVILEGE, SANDBOX_INERT, LUA_TOKEN, WRITE_RESTRICTED.
SidsToDisablePTOKEN_GROUPSinOptional list of SIDs to mark as deny-only in the new token (NULL leaves them enabled).
PrivilegesToDeletePTOKEN_PRIVILEGESinOptional list of privileges to strip from the new token (e.g. SeDebugPrivilege, SeImpersonatePrivilege).
RestrictedSidsPTOKEN_GROUPSinOptional list of restricted SIDs added to the new token; the kernel will AND-check these against every DACL.
NewTokenHandlePHANDLEoutReceives the handle to the newly filtered token on success.

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070xD5win10-1507
Win10 16070xD8win10-1607
Win10 17030xDBwin10-1703
Win10 17090xDCwin10-1709
Win10 18030xDDwin10-1803
Win10 18090xDEwin10-1809
Win10 19030xDFwin10-1903
Win10 19090xDFwin10-1909
Win10 20040xE4win10-2004
Win10 20H20xE4win10-20h2
Win10 21H10xE4win10-21h1
Win10 21H20xE5win10-21h2
Win10 22H20xE5win10-22h2
Win11 21H20xEAwin11-21h2
Win11 22H20xEBwin11-22h2
Win11 23H20xEBwin11-23h2
Win11 24H20xEDwin11-24h2
Server 20160xD8winserver-2016
Server 20190xDEwinserver-2019
Server 20220xE9winserver-2022
Server 20250xEDwinserver-2025

Kernel module

ntoskrnl.exeNtFilterToken

Related APIs

CreateRestrictedTokenDuplicateTokenExAdjustTokenPrivilegesNtDuplicateTokenNtAdjustPrivilegesTokenNtSetInformationToken

Syscall stub

4C 8B D1            mov r10, rcx
B8 ED 00 00 00      mov eax, 0xED
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

Undocumented notes

NtFilterToken is the kernel implementation behind advapi32!CreateRestrictedToken. Given a source token it returns a new primary or impersonation token with selected SIDs flipped to deny-only, selected privileges removed, and optional *restricted SIDs* attached. Restricted SIDs are powerful: when the kernel performs an access check the granted access is ANDed against what the restricted-SID list alone would grant, so the resulting token can be locked far below the user's normal rights. The SSN drifts almost every feature update (`0xD5` on Win10 1507, `0xED` on Win11 24H2), so dynamic resolution is mandatory.

Common malware usage

Used legitimately by the Chromium / Edge / Acrobat sandboxes and by AppContainer brokers. Offensive use is real but rarer: an attacker holding a high-privileged token (SYSTEM, an impersonated user with SeDebugPrivilege) can deliberately *downgrade* a child process or impersonation context to look like a low-privilege user — a form of token demotion that defeats detections keyed on "SYSTEM did X". A handful of red-team frameworks and a small number of malware-research samples wrap NtFilterToken for exactly this reason. It is *not* a strong offensive signal by itself.

Detection opportunities

Token-event coverage is the right place to start: the Microsoft-Windows-Security-Auditing 4696/4624 events surface logon-token changes, and ETW Microsoft-Windows-Kernel-Audit-API-Calls covers token creation. EDRs typically hook NtFilterToken to feed token-derivation graphs. Useful blue-team signal: NtFilterToken called *with* a high-privilege source token *from* an unusual process (non-browser, non-broker). Combine with subsequent NtCreateUserProcess + AssignPrimaryToken to spot deliberate token demotion before child-process execution.

Direct syscall examples

asmx64 direct stub (Win11 24H2 SSN)

; Direct syscall stub for NtFilterToken (SSN 0xED on Win11 24H2 / Server 2025)
NtFilterToken PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 0EDh         ; SSN for win11-24h2
    syscall
    ret
NtFilterToken ENDP

cToken demotion: strip privileges from current token

// Take the current process token and produce a filtered copy with SeDebugPrivilege
// and SeImpersonatePrivilege removed — useful for spawning a less-suspicious child.
HANDLE hCurrent = NULL;
NtOpenProcessToken(NtCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY, &hCurrent);

LUID seDebug, seImpersonate;
LookupPrivilegeValueW(NULL, L"SeDebugPrivilege", &seDebug);
LookupPrivilegeValueW(NULL, L"SeImpersonatePrivilege", &seImpersonate);

struct {
    DWORD            Count;
    LUID_AND_ATTRIBUTES Priv[2];
} toDelete = { 2, {{seDebug, 0}, {seImpersonate, 0}} };

HANDLE hFiltered = NULL;
NtFilterToken(hCurrent,
              DISABLE_MAX_PRIVILEGE,   // also strip every non-mandatory privilege
              NULL,                    // SidsToDisable
              (PTOKEN_PRIVILEGES)&toDelete,
              NULL,                    // RestrictedSids
              &hFiltered);

rustwindows-sys + naked syscall stub

// Cargo: windows-sys = "0.59"  (Win32_Security)
use std::arch::asm;

#[unsafe(naked)]
unsafe extern "system" fn nt_filter_token_stub() {
    asm!(
        "mov r10, rcx",
        "mov eax, 0xED",     // Win11 24H2; resolve dynamically for other builds
        "syscall",
        "ret",
        options(noreturn),
    );
}

MITRE ATT&CK mappings

Last verified: 2026-05-20