当主线程模拟客户端时,我的代码创建一个线程并使用SetThreadToken
为其分配模拟令牌。然后主线程关闭令牌。
具体来说,主线程这样做:
- 使用
LogonUser
获取主令牌。 - 使用主令牌中的
DuplicateToken
获取模拟令牌。 - 呼叫
ImpersonateLoggedOnUser
。 - 生成辅助线程并使用模拟令牌在线程上调用
SetThreadToken
。 RevertToSelf
.CloseHandle
模拟令牌和主令牌上。
此时,辅助线程仍在运行。即使主线程中的令牌句柄已关闭,模拟令牌是否仍可用于辅助线程?
Windows 内核对对象使用引用计数。TOKEN
也是对象。 当您将令牌分配给线程(通过SetThreadToken
(时,指向TOKEN
对象的指针存储在ETHREAD
对象中,并向TOKEN
对象添加其他引用。 当然,内核不能依赖于关闭你或不是原始句柄(引用(到TOKEN
对象。 这是一般的指针计数规则 - 如果A
在自身中存储指向B
的指针 -它添加了对B
的引用,因为它将在A
使用B
之前有效。令牌将一直有效,直到线程不模拟另一个令牌,或者结束模拟或退出。无论如何,将令牌分配给线程后,您可以关闭它的句柄 - 令牌仍然有效
如果存在兴趣,内部SetThreadToken
如何工作:
SetThreadToken
使用ThreadImpersonationToken
信息类调用NtSetInformationThread
。 从内核端实现调用PsAssignImpersonationToken
- 此 API 在ntifs.h中声明。 它的实现调用PsImpersonateClient
哪个并引用传递的令牌。 结果,它成为分配给线程的有效实用程序
服务器线程可能已在模拟客户端,当 PsImpersonateClient 被调用。如果是这种情况,参考对表示该客户端的令牌的计数递减。
但无论如何 - 我们不需要这种内部知识 - 需要一般思考理解 - 对象引用计数。 如果指向令牌的指针保存在线程中 - 此令牌当然在被线程使用之前必须有效。 结果它引用了。 当线程停止使用此令牌(更改指针或退出(时 - 令牌取消引用