SetThreadToken() 是否使模拟令牌保持活动状态?

Does SetThreadToken() keep the impersonation token alive?

当主线程模拟客户端时,我的代码创建一个线程并使用 SetThreadToken 为其分配模拟令牌。然后主线程关闭令牌。

具体来说,主线程是这样做的:

  1. 使用 LogonUser 获取主令牌。
  2. 使用 DuplicateToken 从主令牌获取模拟令牌。
  3. 呼叫ImpersonateLoggedOnUser.
  4. 生成辅助线程并使用模拟令牌在该线程上调用 SetThreadToken
  5. RevertToSelf.
  6. CloseHandle 在模拟和主要令牌上。

此时,副线程仍然是运行。即使令牌句柄已在主线程中关闭,模拟令牌是否仍可用于辅助线程?

windows 内核对对象使用引用计数。 TOKEN 也是对象。当您将令牌分配给线程(通过 SetThreadToken)时,指向 TOKEN 对象的指针存储在 ETHREAD 对象中,并且附加引用添加到 TOKEN 对象。当然,内核不能依赖关闭你或不是 TOKEN 对象的原始句柄(引用)。这是一般的指针计数规则 - 如果 A 在自身中存储指向 B 的指针 - 它会添加对 B 的引用,因为它将在 A 使用 [=17= 之前有效].该令牌将一直有效,直到您的线程不模拟另一个令牌、结束模拟或退出。无论如何,在将令牌分配给线程后,您可以关闭它的句柄 - 令牌仍然有效


如果存在兴趣,内部 SetThreadToken 的工作方式:

SetThreadToken 使用 ThreadImpersonationToken 信息调用 NtSetInformationThread class。从内核端 implementation called PsAssignImpersonationToken - this api declared in ntifs.h. it implementation call PsImpersonateClientreference 传递的令牌。结果它成为分配给 thread

的有效 util

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.

但无论如何——我们不需要这种内部知识——需要一般的思考理解——对象引用计数。如果指向令牌的指针保存在线程中 - 这个令牌当然必须有效,直到被线程使用。结果它引用了。当线程停止使用此令牌时(更改指针或退出)- 取消引用令牌