Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

windows-token

Crates.io Docs.rs License: MIT

RAII wrappers over the Win32 access-token surface — OpenProcessToken, DuplicateTokenEx, ImpersonateLoggedOnUser, SetThreadToken, AdjustTokenPrivileges. The single hard invariant: dropping an ImpersonationGuard calls RevertToSelf — always, including on unwind. Hand-written impersonation code (Rubeus-style) forgets this on early returns; here it is structurally impossible.

Status

0.1.0-dev — pre-alpha, expect breaking changes before 0.1.0. Part of the icedracon Rust offensive-AD ecosystem.

What it does

Handle-owning wrappers around the token API described in the Access Tokens section of the Windows security model (see processthreadsapi.h and the TOKEN_INFORMATION_CLASS enumeration). Correctly reads ERROR_NOT_ALL_ASSIGNED from GetLastError on nominal AdjustTokenPrivileges success — the one thing every hand-rolled "enable SeDebugPrivilege" snippet on the internet gets wrong.

Usage

use windows_token::{Token, Privilege};

fn main() -> windows_token::Result<()> {
    let tok = Token::open_current_process()?;

    // Enable SeChangeNotifyPrivilege (normal users always hold this).
    let _prev = tok.enable_privilege(Privilege::SeChangeNotify)?;

    // Impersonation with guaranteed revert:
    {
        let _g = tok.impersonate_on_thread()?;
        // ...do work under the impersonated identity...
    } // <- RevertToSelf on drop, including on panic

    println!("user = {}",   tok.user_sid()?);
    println!("il   = {:?}", tok.integrity_level()?);
    Ok(())
}

What works / what does not (this version)

  • Working:
    • Token::open_current_process / Token::open_process(pid, access) around OpenProcessToken.
    • Token::duplicate(ty, level) -> owned DuplicateTokenEx handle.
    • Token::enable_privilege(Privilege::…) via LookupPrivilegeValueW + AdjustTokenPrivileges with correct ERROR_NOT_ALL_ASSIGNED handling.
    • Token::impersonate_on_thread() / set_on_current_thread() returning an ImpersonationGuard (Drop = RevertToSelf).
    • Token::user_sid() / integrity_level() via GetTokenInformation(TokenUser | TokenIntegrityLevel).
  • Stubbed / next milestone:
    • OpenThreadToken is not yet wired (only OpenProcessToken).
    • No LookupAccountSidW — SIDs render as S-1-... strings only.
    • No CreateProcessAsUserW / restricted-token helpers.
    • No integration tests against a real DC; only smoke tests on GetCurrentProcess().

Dependencies

S-tier posture — narrow feature set on windows, no serde / log / async runtime.

  • windows 0.58 with only Win32_Security, Win32_System_Threading, Win32_Security_Authentication_Identity, Win32_Foundation enabled.
  • windows-core 0.58 for Result / Error interop.
  • thiserror 2 for error boilerplate.

Related icedracon crates

  • windows-lsa — LSA ticket cache access; typical pattern is impersonate_on_thread then read the target LUID's cache.
  • windows-sspi-shim — SSPI Negotiate ergonomics; the impersonated identity flows straight into SspiClient::for_spn.
  • windows-scm — local Service Control Manager wrapper, for the SYSTEM-side of the same workflows.

Together these enable "run adhammer as yourself" and impersonation-based lateral-movement tooling without dragging in Impacket or Rubeus.

License

MIT © 2026 zevs

About

Part of the icedracon Rust security ecosystem — pre-alpha, see README

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages