> Windows Syscalls
ntoskrnl.exeT1134T1134.001T1068

NtAdjustGroupsToken

Aktiviert oder deaktiviert Gruppen (SIDs) in einem Access-Token oder setzt Gruppen-Attribute auf ihren Default-Zustand zurück.

Prototyp

NTSTATUS NtAdjustGroupsToken(
  HANDLE         TokenHandle,
  BOOLEAN        ResetToDefault,
  PTOKEN_GROUPS  NewState,
  ULONG          BufferLength,
  PTOKEN_GROUPS  PreviousState,
  PULONG         ReturnLength
);

Argumente

NameTypeDirDescription
TokenHandleHANDLEinToken-Handle, geöffnet mit TOKEN_ADJUST_GROUPS-Zugriff (und TOKEN_QUERY, falls PreviousState angefordert).
ResetToDefaultBOOLEANinTRUE setzt jedes Gruppen-Attribut auf seinen Default zurück (NewState wird ignoriert); FALSE wendet NewState an.
NewStatePTOKEN_GROUPSinArray von SID_AND_ATTRIBUTES, das angewendet wird. Attribute schalten typischerweise SE_GROUP_ENABLED / SE_GROUP_ENABLED_BY_DEFAULT um.
BufferLengthULONGinGröße des PreviousState-Puffers in Bytes. 0 übergeben, wenn PreviousState NULL ist.
PreviousStatePTOKEN_GROUPSoutOptionaler Puffer, der den vorherigen Gruppen-Attributsatz empfängt, damit der Aufrufer später zurücksetzen kann.
ReturnLengthPULONGoutEmpfängt die in PreviousState geschriebenen Bytes (oder die benötigten bei STATUS_BUFFER_TOO_SMALL).

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x6Awin10-1507
Win10 16070x6Awin10-1607
Win10 17030x6Bwin10-1703
Win10 17090x6Bwin10-1709
Win10 18030x6Bwin10-1803
Win10 18090x6Bwin10-1809
Win10 19030x6Bwin10-1903
Win10 19090x6Bwin10-1909
Win10 20040x6Cwin10-2004
Win10 20H20x6Cwin10-20h2
Win10 21H10x6Cwin10-21h1
Win10 21H20x6Cwin10-21h2
Win10 22H20x6Cwin10-22h2
Win11 21H20x6Cwin11-21h2
Win11 22H20x6Cwin11-22h2
Win11 23H20x6Cwin11-23h2
Win11 24H20x6Cwin11-24h2
Server 20160x6Awinserver-2016
Server 20190x6Bwinserver-2019
Server 20220x6Cwinserver-2022
Server 20250x6Cwinserver-2025

Kernel-Modul

ntoskrnl.exeNtAdjustGroupsToken

Verwandte APIs

AdjustTokenGroupsCheckTokenMembershipNtAdjustPrivilegesTokenNtFilterTokenNtDuplicateTokenNtOpenProcessToken

Syscall-Stub

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

Die Kernel-Seite der Win32-API `AdjustTokenGroups`. Geschwister von `NtAdjustPrivilegesToken` — Privilegien leben in TOKEN_PRIVILEGES, Gruppenmitgliedschaft in TOKEN_GROUPS. `NtAdjustGroupsToken` kann keinen SID zu einem Token *hinzufügen*; es kann nur die bereits im Token vorhandenen SIDs (enabled, disabled, deny-only oder restricted) aktivieren, deaktivieren oder auf den Default zurücksetzen. Um das Attribut SE_GROUP_USE_FOR_DENY_ONLY eines SIDs abzuschalten, muss man typischerweise zuerst `NtFilterToken` aufrufen, um eine Nicht-Deny-Variante zu erzeugen. Jeder SID in NewState wird mit einer Attributes-Maske gepaart (SE_GROUP_ENABLED, SE_GROUP_ENABLED_BY_DEFAULT, SE_GROUP_OWNER, SE_GROUP_USE_FOR_DENY_ONLY); SE_GROUP_ENABLED auf einem zuvor deaktivierten SID aktiviert ihn.

Häufige Malware-Nutzung

**Group-SID-Reaktivierung für Privilege-Escalation-Ketten**: das kanonische Setup ist ein Angreifer, der ein Token gestohlen hat (über SeImpersonatePrivilege, Rotten/Juicy Potato, PrintSpoofer, etc.), das BUILTIN\Administrators als Deny-Only-SID enthält (typischer Zustand unter UAC-Split-Token IL Medium). Der Angreifer ruft NtFilterToken oder Token-Duplizierung, um eine Nicht-Deny-Variante zu erzeugen, dann NtAdjustGroupsToken, um SE_GROUP_ENABLED auf dem Administrators-SID wieder anzuschalten — sofortige Admin-Gruppenmitgliedschaft am Live-Thread ohne interaktiven UAC-Prompt. Seltener wird es genutzt, um einen SID zu unterdrücken, den der Angreifer nicht evaluiert wissen will (Logging-Gruppen-SID deaktivieren, das beim Dateizugriff Extra-Auditing triggert). Dokumentiert in offensiven Toolchains rund um die Familien AlwaysInstallElevated und SeImpersonatePrivilege.

Erkennungs­möglichkeiten

Microsoft-Windows-Security-Auditing Event-ID 4672 (Spezialprivilegien zugewiesen) und 4673 (privilegierter Dienst aufgerufen) helfen bei der Privilege-Seite; die Gruppen-Adjust-Seite wird nur indirekt über 4670 (Berechtigungen auf einem Objekt geändert) abgedeckt. EDRs, die Token-Modifikations-Primitiven tracken, zeigen eine Sequenz wie (NtOpenProcessToken auf einem höher privilegierten Prozess → NtDuplicateToken → NtFilterToken → NtAdjustGroupsToken → NtSetInformationThread(ImpersonationToken)) als Token-Abuse-Kette. Die verteidiger-freundliche Invariante: legitime Prozesse rufen NtAdjustGroupsToken so gut wie nie auf, um einen zuvor deaktivierten High-Privilege-SID zu *aktivieren*; Auditoren, die den Token-Zustand beim Prozess-Erzeugen snapshotten und mit dem Laufzeitzustand vergleichen, können das Delta flaggen. ETW Microsoft-Windows-Kernel-Audit-API-Calls zeigt den Syscall in moderatem Volumen.

Direkte Syscall-Beispiele

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtAdjustGroupsToken (SSN 0x6C on Win10 2004+/Win11)
NtAdjustGroupsToken PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 6Ch          ; SSN — stable across modern builds
    syscall
    ret
NtAdjustGroupsToken ENDP

cPrivesc — re-enable BUILTIN\Administrators in a stolen token

// Assumes hTok came from NtDuplicateToken + NtFilterToken (non-deny variant).
// Re-enable SE_GROUP_ENABLED on the Administrators SID in-place.
#include <windows.h>
#include <winternl.h>

static VOID EnableAdminsGroup(HANDLE hTok) {
    SID_IDENTIFIER_AUTHORITY nt = SECURITY_NT_AUTHORITY;
    PSID adminSid = NULL;
    AllocateAndInitializeSid(&nt, 2,
        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0, &adminSid);

    BYTE buf[sizeof(TOKEN_GROUPS) + sizeof(SID_AND_ATTRIBUTES)];
    TOKEN_GROUPS* tg = (TOKEN_GROUPS*)buf;
    tg->GroupCount = 1;
    tg->Groups[0].Sid = adminSid;
    tg->Groups[0].Attributes = SE_GROUP_ENABLED; // flip the bit

    // Win32 wrapper -> NtAdjustGroupsToken
    AdjustTokenGroups(hTok, FALSE, tg, 0, NULL, NULL);
    FreeSid(adminSid);
}

cSnapshot then restore previous group state

// Defensive / red-team utility: change group state, do work, restore exactly.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI *pNtAdjustGroupsToken)(
    HANDLE, BOOLEAN, PTOKEN_GROUPS, ULONG, PTOKEN_GROUPS, PULONG);

VOID WithToggledGroup(HANDLE hTok, TOKEN_GROUPS* desired) {
    pNtAdjustGroupsToken NtAdjustGroupsToken = (pNtAdjustGroupsToken)
        GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtAdjustGroupsToken");
    BYTE prev[4096]; ULONG ret = 0;
    NtAdjustGroupsToken(hTok, FALSE, desired,
                        sizeof(prev), (PTOKEN_GROUPS)prev, &ret);
    DoWorkWithToggledGroups();
    NtAdjustGroupsToken(hTok, FALSE, (PTOKEN_GROUPS)prev,
                        0, NULL, NULL); // revert exact prior state
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20