Overview
SeCreateTokenPrivilege allows a process to call the NtCreateToken syscall and create an entirely new access token from scratch. Unlike token duplication (which copies an existing token), this forges a token with arbitrary user SID, group memberships, privileges, and integrity level. You become whoever you want.
This is one of the most powerful privileges in Windows. It is the digital equivalent of a blank government ID printer.
Who Has It by Default
| Principal | Has SeCreateTokenPrivilege |
|---|---|
NT AUTHORITY\SYSTEM | Yes |
lsass.exe | Yes (the only user-mode process that normally calls NtCreateToken) |
Administrators | No |
| Standard users | No |
| Service accounts | No (unless explicitly granted via secpol.msc or GPO) |
- Custom service accounts with misconfigured security policy
- Third-party authentication/SSO products that create tokens for logged-on users
- Backup/imaging software that restores user profiles with original SIDs
- Compromised LSASS or SYSTEM contexts where you want to forge identities
If you have this privilege, you have won. The only question is what identity to forge. SYSTEM, Domain Admin, Enterprise Admin — pick one.
Check if Enabled
NtCreateToken:
Even when Disabled, the privilege only needs to be present in your token. Disabled is a soft toggle — any process can enable its own privileges via
AdjustTokenPrivileges. If the privilege is not listed at all, you cannot use this technique.How It Works Technically
The NtCreateToken Syscall
NtCreateToken is an undocumented ntdll function that creates a brand new access token. It is the only API that can build a token from individual components rather than deriving one from an existing logon session.
Function signature:
What Each Parameter Controls
| Parameter | What It Does | Exploitation Impact |
|---|---|---|
TokenType | Primary (for process creation) or Impersonation | Use TokenPrimary to spawn processes, TokenImpersonation to steal identity in-thread |
AuthenticationId | Links to a logon session | Use SYSTEM_LUID (0x3e7) or ANONYMOUS_LOGON_LUID (0x3e6) |
User | The token’s user SID | Set to S-1-5-18 (SYSTEM) or any user SID you want to be |
Groups | All group memberships | Add S-1-5-32-544 (Administrators), S-1-5-18 (SYSTEM), domain groups |
Privileges | Every privilege in the token | Add all privileges — SeDebugPrivilege, SeTcbPrivilege, everything |
Owner | Default owner for objects created by the token | Set to Administrators SID |
PrimaryGroup | Primary group for new objects | Set to SYSTEM or Administrators |
DefaultDacl | ACL applied to new objects | Permissive DACL or NULL |
TokenSource | 8-char identifier logged in events | Can set to anything — "NtCreate", "User32", etc. |
Why the Kernel Trusts This
The kernel checks exactly one thing before allowingNtCreateToken: does the calling token have SeCreateTokenPrivilege enabled? If yes, the syscall proceeds and builds whatever token you specify. There is no validation that the SIDs are legitimate, that the user exists, or that the privileges make sense. The kernel trusts you completely.
This is by design — LSASS uses NtCreateToken after authenticating users to build their logon tokens. The assumption is that only LSASS would ever have this privilege.
Why It Is Extremely Dangerous
WithSeCreateTokenPrivilege, you can forge a token that:
- Impersonates any local user —
Administrator,SYSTEM,DefaultAccount - Claims membership in any group —
BUILTIN\Administrators,NT AUTHORITY\SYSTEM,Domain Admins - Holds every privilege — all 35+ Windows privileges enabled, including
SeTcbPrivilege,SeDebugPrivilege,SeAssignPrimaryTokenPrivilege - Operates at SYSTEM integrity — bypasses UAC, mandatory integrity checks
- Uses any logon session — including the SYSTEM logon session (LUID 0x3e7)
- Cannot be distinguished from legitimate tokens — the kernel treats forged tokens identically to tokens created by LSASS
Using token-priv Toolset (hatRiot)
Thetoken-priv project by hatRiot is the primary offensive toolset for exploiting Windows token privileges, including SeCreateTokenPrivilege.
Download
Project Structure
Compile with Visual Studio
Usage — Forge a SYSTEM Token
The tool resolvesNtCreateToken dynamically from ntdll and calls it with attacker-controlled parameters:
The
token-priv toolset focuses on demonstrating each privilege abuse individually. For production use during engagements, you may need to modify the source to customize the forged token’s SIDs, groups, and target process. The whitepaper (abusing_token_priv.pdf) in the repo documents the exact API calls and structures needed.Manual Exploitation — C Implementation
Full implementation ofNtCreateToken to forge an arbitrary token. This is the core technique regardless of which tool you use.
Resolving NtCreateToken
NtCreateToken is not exported by any import library. Resolve it at runtime from ntdll:
Required SID Definitions
Building the TOKEN_GROUPS Structure
Building the TOKEN_PRIVILEGES Structure
Calling NtCreateToken
Forging an Administrators Token
Create a token that identifies as the local Administrator with full group memberships. Use this when you need local admin access on a standalone machine.SIDs Needed
| SID | Identity | Purpose |
|---|---|---|
S-1-5-21-<machine>-500 | Local Administrator | Token user identity |
S-1-5-32-544 | BUILTIN\Administrators | Local admin group |
S-1-1-0 | Everyone | Standard group |
S-1-5-11 | Authenticated Users | Standard group |
S-1-5-4 | INTERACTIVE | Logon type |
S-1-5-15 | This Organization | Standard group |
S-1-16-12288 | High Mandatory Level | Integrity level (bypass UAC) |
Get Machine SID
S-1-5-21-3623811015-3361044348-30300820-500
The machine SID is everything except the final RID: S-1-5-21-3623811015-3361044348-30300820
Forge the Token
Spawn an Admin Shell
Forging a SYSTEM Token
The most common target. SYSTEM has unrestricted access to the local machine.Required Parameters
Full C Code — Forge SYSTEM Token and Spawn cmd.exe
Compile
Forging a Domain Admin Token (Domain Context)
When the compromised machine is domain-joined, you can forge tokens with domain SIDs. This is devastating because no actual authentication to the DC occurs — the forged token is valid locally.Get the Domain SID
CORP\svc_backup S-1-5-21-1234567890-987654321-1122334455-1109
Domain SID: S-1-5-21-1234567890-987654321-1122334455
Key Domain SIDs
| SID | Identity |
|---|---|
S-1-5-21-<domain>-500 | Domain Administrator |
S-1-5-21-<domain>-512 | Domain Admins group |
S-1-5-21-<domain>-519 | Enterprise Admins group |
S-1-5-21-<domain>-516 | Domain Controllers group |
S-1-5-21-<domain>-518 | Schema Admins group |
Forge Domain Admin Token
Impersonating the Forged Token
After forging a token withNtCreateToken, you need to use it. There are three primary methods.
Method 1 — ImpersonateLoggedOnUser (Current Thread)
Apply the token to the current thread. All subsequent API calls in this thread use the forged identity.Method 2 — CreateProcessWithTokenW (New Process)
Spawn a new process running under the forged token. RequiresSeImpersonatePrivilege in the calling token (or being SYSTEM).
Method 3 — CreateProcessAsUserW (New Process, Alternate)
Similar toCreateProcessWithTokenW but requires SeAssignPrimaryTokenPrivilege instead of SeImpersonatePrivilege. If your forged token includes this privilege, use it.
Method 4 — SetThreadToken (Specific Thread)
Apply the forged token to a specific thread rather than usingImpersonateLoggedOnUser:
Combining with SeImpersonatePrivilege
The most practical exploitation chain:SeCreateTokenPrivilege forges the token, SeImpersonatePrivilege lets you spawn processes under it.
Why You Need Both
| Action | Required Privilege |
|---|---|
Call NtCreateToken to forge a token | SeCreateTokenPrivilege |
Call ImpersonateLoggedOnUser | SeImpersonatePrivilege (or the token must be for the caller’s own logon session) |
Call CreateProcessWithTokenW | SeImpersonatePrivilege |
Call CreateProcessAsUserW | SeAssignPrimaryTokenPrivilege |
SeCreateTokenPrivilege without SeImpersonatePrivilege:
- Forge a token that includes SeImpersonatePrivilege in its privileges list
- Use
NtSetInformationThreadwithThreadImpersonationTokento apply the impersonation token to the current thread (this bypasses theSeImpersonatePrivilegecheck in some scenarios) - Or forge a token with
SeAssignPrimaryTokenPrivilegeand useCreateProcessAsUserW
Practical Chain
If You Lack SeImpersonatePrivilege
Forge a new token that includesSeImpersonatePrivilege, then use the lower-level approach:
On modern Windows (10+), the kernel performs additional security checks on impersonation tokens. The
NtSetInformationThread bypass may not work on all builds. Test on the target OS version. If blocked, the most reliable approach is to include SeAssignPrimaryTokenPrivilege in the forged token and use CreateProcessAsUserW.When You Encounter This in the Wild
Service Accounts
Third-party applications sometimes requestSeCreateTokenPrivilege via Group Policy:
Common Scenarios
| Scenario | Why SeCreateTokenPrivilege Exists | Exploitation Path |
|---|---|---|
| Custom SSO/authentication service | Service creates tokens for users after custom auth | Compromise service → forge any token |
| Backup/imaging agent | Restores files with original ownership SIDs | Compromise agent account → forge SYSTEM |
| Virtual Desktop Infrastructure (VDI) | Session broker creates user sessions | Compromise VDI service → forge Domain Admin |
| Legacy COM+ applications | Required for certain COM+ activation scenarios | Compromise the configured identity |
| Misconfigured Group Policy | Admin added a service account manually | Compromise that service account |
Identifying via WinPEAS
Identifying via PowerUp
Identifying via Seatbelt
Detection and Logging
Event IDs
| Event ID | Log | What It Catches |
|---|---|---|
| 4672 | Security | Special privileges assigned to new logon — fires when a logon session receives SeCreateTokenPrivilege |
| 4688 | Security | Process creation — shows the command that spawned the forging tool |
| 4624 | Security | Logon event — the forged token may generate a type 9 (NewCredentials) or type 2 (Interactive) logon |
| 4634 | Security | Logoff — when the forged logon session ends |
| 10 | Sysmon | Process access — if the forging tool opens other processes to inject |
| 1 | Sysmon | Process creation — child process spawned with the forged token |
| 17/18 | Sysmon | Pipe created/connected — if using named pipe impersonation as part of the chain |
What Triggers Alerts
- Event 4672 with
SeCreateTokenPrivilegefor any account other than SYSTEM or LSASS is highly anomalous - Process lineage anomalies — a service account process spawning
cmd.exeas SYSTEM - Token integrity mismatch — a medium-integrity process creating a high-integrity or system-integrity token
- Unusual NtCreateToken syscalls — EDR/ETW can trace syscalls to ntdll
Sysmon Configuration for Detection
ETW Provider for Token Operations
Evasion Notes
- The
TokenSourcefield inNtCreateTokenis logged — set it to something legitimate like"User32 "or"Advapi "instead of a custom string NtCreateTokengoes through the kernel, not a user-mode API — direct syscall stubs (SysWhispers) bypass ntdll hooking- The forged token’s logon session LUID is visible in Event 4624 — using
SYSTEM_LUIDmakes the logon appear as a normal SYSTEM activity - Avoid spawning interactive processes — use
ImpersonateLoggedOnUserfor in-thread operations to reduce process creation events
Quick Reference
| Task | Method | Notes |
|---|---|---|
| Check for privilege | whoami /priv | findstr SeCreateTokenPrivilege | Must be present (Enabled or Disabled) |
| Enable if disabled | AdjustTokenPrivileges | Soft toggle — enable programmatically |
| Forge SYSTEM token | NtCreateToken with User=S-1-5-18, LUID=0x3e7 | Full local machine control |
| Forge Admin token | NtCreateToken with User=S-1-5-21-…-500 | Local administrator |
| Forge Domain Admin | NtCreateToken with User=S-1-5-21-…-500, Groups include -512 | Local access only (no Kerberos TGT) |
| Impersonate in-thread | ImpersonateLoggedOnUser | Needs SeImpersonatePrivilege or same session |
| Spawn process | CreateProcessWithTokenW | Needs SeImpersonatePrivilege |
| Spawn process (alt) | CreateProcessAsUserW | Needs SeAssignPrimaryTokenPrivilege |
| Tooling | token-priv | Pre-built exploitation of token privileges |
| SID | Identity | Common Use |
|---|---|---|
S-1-5-18 | SYSTEM | Token user for max local access |
S-1-5-32-544 | BUILTIN\Administrators | Mandatory group for admin operations |
S-1-5-21-<domain>-500 | Domain Administrator | Domain admin identity |
S-1-5-21-<domain>-512 | Domain Admins | Domain admin group membership |
S-1-5-21-<domain>-519 | Enterprise Admins | Forest-level admin group |
S-1-1-0 | Everyone | Standard group (include for compatibility) |
S-1-5-11 | Authenticated Users | Standard group |
S-1-16-12288 | High Mandatory Level | Integrity level for admin tokens |
S-1-16-16384 | System Mandatory Level | Integrity level for SYSTEM tokens |