> Windows Syscalls
ntoskrnl.exeT1134T1134.002T1106

NtFilterToken

Crée une copie restreinte (filtrée) d'un token d'accès existant en désactivant des SID, supprimant des privilèges ou ajoutant des SID restreints.

Prototype

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

Arguments

NameTypeDirDescription
ExistingTokenHandleHANDLEinHandle vers le token source (nécessite l'accès TOKEN_DUPLICATE).
FlagsULONGinCombinaison de DISABLE_MAX_PRIVILEGE, SANDBOX_INERT, LUA_TOKEN, WRITE_RESTRICTED.
SidsToDisablePTOKEN_GROUPSinListe optionnelle de SID à marquer en deny-only dans le nouveau token (NULL les laisse activés).
PrivilegesToDeletePTOKEN_PRIVILEGESinListe optionnelle de privilèges à retirer du nouveau token (ex. SeDebugPrivilege, SeImpersonatePrivilege).
RestrictedSidsPTOKEN_GROUPSinListe optionnelle de SID restreints ajoutés au nouveau token ; le noyau les évalue en ET avec chaque DACL.
NewTokenHandlePHANDLEoutReçoit le handle du token filtré nouvellement créé en cas de succès.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
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

Module noyau

ntoskrnl.exeNtFilterToken

APIs liées

CreateRestrictedTokenDuplicateTokenExAdjustTokenPrivilegesNtDuplicateTokenNtAdjustPrivilegesTokenNtSetInformationToken

Stub du syscall

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

Notes non documentées

NtFilterToken est l'implémentation noyau derrière advapi32!CreateRestrictedToken. À partir d'un token source, elle retourne un nouveau token primaire ou d'impersonation avec certains SID passés en deny-only, certains privilèges supprimés, et d'éventuels *SID restreints* attachés. Les SID restreints sont puissants : lors d'un contrôle d'accès, le noyau ET-combine l'accès accordé avec ce que la seule liste de SID restreints aurait permis ; le token résultant peut donc être verrouillé bien en dessous des droits normaux de l'utilisateur. Le SSN dérive presque à chaque mise à jour majeure (`0xD5` sur Win10 1507, `0xED` sur Win11 24H2) : la résolution dynamique est obligatoire.

Usage courant par les malwares

Utilisée légitimement par les sandboxes Chromium / Edge / Acrobat et par les brokers AppContainer. L'usage offensif est réel mais plus rare : un attaquant possédant un token à fort privilège (SYSTEM, ou un utilisateur impersonné avec SeDebugPrivilege) peut volontairement *rétrograder* un processus enfant ou un contexte d'impersonation pour ressembler à un utilisateur peu privilégié — une forme de token demotion qui contourne les détections fondées sur « SYSTEM a fait X ». Quelques frameworks red-team et un petit nombre d'échantillons de recherche enveloppent NtFilterToken précisément pour cette raison. Ce n'est *pas* un signal offensif fort en soi.

Opportunités de détection

La couverture des événements de token est le bon point de départ : les événements 4696/4624 Microsoft-Windows-Security-Auditing révèlent les changements de token de logon, et ETW Microsoft-Windows-Kernel-Audit-API-Calls couvre la création de tokens. Les EDR hookent typiquement NtFilterToken pour alimenter leurs graphes de dérivation de tokens. Signal blue-team utile : NtFilterToken appelée *avec* un token source à fort privilège *depuis* un processus inhabituel (ni navigateur, ni broker). À combiner avec un NtCreateUserProcess + AssignPrimaryToken qui suivent, pour repérer une token demotion délibérée avant exécution du processus enfant.

Exemples de syscalls directs

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),
    );
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20