winapiwindows-security

Does SetThreadToken() keep the impersonation token alive?


While the main thread impersonates a client, my code creates a thread and assigns it the impersonation token using SetThreadToken. Then the main thread closes the token.

Specifically, the main thread does this:

  1. Get a primary token using LogonUser.
  2. Get an impersonation token using DuplicateToken from the primary token.
  3. Call ImpersonateLoggedOnUser.
  4. Spawn a secondary thread and call SetThreadToken on the thread with the impersonation token.
  5. RevertToSelf.
  6. CloseHandle on both the impersonation and the primary token.

At this point, the secondary thread is still running. Does the impersonation token remain usable for the secondary thread even though the token handle has been closed in the main thread?


Solution

  • windows kernel use reference counting on objects. the TOKEN is object too. when you assign token to thread (via SetThreadToken) the pointer to TOKEN object is stored in ETHREAD object and additional reference added to TOKEN object. of course kernel cannot rely on close you or not original handle (reference) to TOKEN object. this is general pointer counting rule - if A stored pointer to B in self - it add reference to B, for it will be valid until A use B. the token will be valid until your thread not impersonate another token, or end impersonation or exit. anyway after you assign token to thread you can close handle to it - token remain valid


    if exist interest, how internal SetThreadToken work:

    SetThreadToken call NtSetInformationThread with ThreadImpersonationToken information class. from kernel side implementation called PsAssignImpersonationToken - this api declared in ntifs.h. it implementation call PsImpersonateClient which and reference the passed token. as result it become valid util assigned to thread

    The server thread could already be impersonating a client when PsImpersonateClient is called. If this is the case, the reference count on the token representing that client is decremented.

    but anyway - we not need for this internal knowledge - need general think understand - object reference counting. if pointer to token saved in thread - this token of course must be valid until used by thread. as result it referenced. when thread stop using this token (change pointer or exit) - token dereferenced