主要令牌和模拟令牌之间有什么区别
What's the difference between a Primary Token and an Impersonation Token
一些 Windows API return 一个主要令牌和一些 return 一个模拟令牌。一些 API 需要主令牌,而其他 API 需要模拟令牌。
例如,LogonUser
通常 return 是主要标记,除非使用 LOGON32_LOGON_NETWORK
作为登录类型 (dwLogonType
):
In most cases, the returned handle is a primary token that you can use in calls to the CreateProcessAsUser function. However, if you specify the LOGON32_LOGON_NETWORK flag, LogonUser returns an impersonation token that you cannot use in CreateProcessAsUser unless you call DuplicateTokenEx to convert it to a primary token.
SetThreadToken
requires an impersonation token while ImpersonateLoggedOnUser
这似乎做几乎相同的事情需要任何一个。
CreateProcessAsUser
and CreateProcessWithTokenW
both require a primary token and both note a primary token can be acquired from an impersonation token by calling DuplicateTokenEx
,但是令牌类型 是什么意思?
词汇表如下:
An access token contains the security information for a logon session. The system creates an access token when a user logs on, and every process executed on behalf of the user has a copy of the token. The token identifies the user, the user's groups, and the user's privileges. The system uses the token to control access to securable objects and to control the ability of the user to perform various system-related operations on the local computer. There are two kinds of access token, primary and impersonation.
An access token that is typically created only by the Windows kernel. It may be assigned to a process to represent the default security information for that process.
An access token that has been created to capture the security information of a client process, allowing a server to "impersonate" the client process in security operations.
但这并不是完全有用。似乎有人想使用像“内核”这样的大男孩词,但这只会引发更多问题,例如主令牌还可以用于什么(除了分配给进程)以及除了内核之外还有谁可以创建访问权限代币?
(他们的意思是微软认为内核只是内核模式下运行的一部分,还有执行等,或者他们的意思是用户模式代码也可以创建令牌?无论如何,即使用户模式代码可以创建令牌,它也必须通过系统调用来完成,就像任何对象管理器对象一样,因此无论如何令牌实际上都是在内核模式下创建的。)
无论如何,这并没有回答基本问题:令牌类型之间有什么区别? 不是它们可能的用途或它们是如何通常创建的。
一位朋友向我介绍了 Keith Brown 的 Programming Windows Security,他完全回答了这个问题。
主令牌可以也应该称为进程令牌,模拟令牌可以也应该称为线程令牌。主要令牌只能附加到进程,模拟令牌只能附加到线程。就这样。它们确实可以使用 DuplicateTokenEx
自由转换(显然,假设您对要转换的句柄具有必要的访问权限)。
从书中的第 115 页开始:
BOOL DuplicateTokenEx(
HANDLE ExistingToken, // in
DWORD DesiredAccess, // in
LPSECURITY_ATTRIBUTES Attributes, // in, optional
SECURITY_IMPERSONATION_LEVEL ImpLevel, // in
TOKEN_TYPE Type, // in
PHANDLE NewToken); // out
...
The Type
parameter is a historical artifact. If you look at the definition of the TOKEN_TYPE
enumeration, you'll find that tokens have been taxonomized into two categories: impersonation versus primary tokens. Don't get hung up on this nomenclature; the meaning is actually much simpler than it sounds. Impersonation tokens can only be attached to threads, and primary tokens can only be attached to processes. That's all it means. The process token obtained earlier via OpenProcessToken was therefore a primary token.
In very early versions of Windows NT (3.x), there were much more severe restrictions on what you could do with a token, depending on where you originally got it from, and hence the token type was introduced to track the intended usage of the token. Because this text assumes you're using Windows NT 4.0 or greater, just think of an impersonation token as a "thread token", and a primary token as a "process token", and use DuplicateTokenEx
to convert between the two whenever necessary. Windows NT 4.0 tore down the boundaries between the two by introducing DuplicateTokenEx
; the Windows NT 3.x version of this function, DuplicateToken
, was hardcoded to only produce impersonation tokens. In fact, now you should be able to see the silly bug that causes the first call to SetThreadToken
to fail: the code is attempting to attach a primary token (the one obtained from the process) to a thread (which requires an impersonation token). That's a no-no. To fix both the logical problem and the silly historical problem, here's the corrected code:
严格来说不是问题的答案但在问题中提到的其他内容:
- 显然
ImpersonateLoggedOnUser
更进一步,将主要标记转换为模拟标记,而 SetThreadToken
则不费吹灰之力。为什么?谁知道?可能出于同样的原因,一些 API 在调用期间启用特权,而其他 API 则要求调用者自行启用特权。
LogonUser
(和 LsaLogonUser
)可能 return 网络登录的模拟令牌,因为假设通常由谁执行网络登录(例如,从第 83 页开始)。
- 您可以使用未记录的 NTDLL 函数
ZwCreateToken
从用户模式创建令牌,这需要非常不寻常的权限(特别是唯一的 SE_CREATE_TOKEN_NAME
)。你可能不应该...
一些 Windows API return 一个主要令牌和一些 return 一个模拟令牌。一些 API 需要主令牌,而其他 API 需要模拟令牌。
例如,LogonUser
通常 return 是主要标记,除非使用 LOGON32_LOGON_NETWORK
作为登录类型 (dwLogonType
):
In most cases, the returned handle is a primary token that you can use in calls to the CreateProcessAsUser function. However, if you specify the LOGON32_LOGON_NETWORK flag, LogonUser returns an impersonation token that you cannot use in CreateProcessAsUser unless you call DuplicateTokenEx to convert it to a primary token.
SetThreadToken
requires an impersonation token while ImpersonateLoggedOnUser
这似乎做几乎相同的事情需要任何一个。
CreateProcessAsUser
and CreateProcessWithTokenW
both require a primary token and both note a primary token can be acquired from an impersonation token by calling DuplicateTokenEx
,但是令牌类型 是什么意思?
词汇表如下:
An access token contains the security information for a logon session. The system creates an access token when a user logs on, and every process executed on behalf of the user has a copy of the token. The token identifies the user, the user's groups, and the user's privileges. The system uses the token to control access to securable objects and to control the ability of the user to perform various system-related operations on the local computer. There are two kinds of access token, primary and impersonation.
An access token that is typically created only by the Windows kernel. It may be assigned to a process to represent the default security information for that process.
An access token that has been created to capture the security information of a client process, allowing a server to "impersonate" the client process in security operations.
但这并不是完全有用。似乎有人想使用像“内核”这样的大男孩词,但这只会引发更多问题,例如主令牌还可以用于什么(除了分配给进程)以及除了内核之外还有谁可以创建访问权限代币?
(他们的意思是微软认为内核只是内核模式下运行的一部分,还有执行等,或者他们的意思是用户模式代码也可以创建令牌?无论如何,即使用户模式代码可以创建令牌,它也必须通过系统调用来完成,就像任何对象管理器对象一样,因此无论如何令牌实际上都是在内核模式下创建的。)
无论如何,这并没有回答基本问题:令牌类型之间有什么区别? 不是它们可能的用途或它们是如何通常创建的。
一位朋友向我介绍了 Keith Brown 的 Programming Windows Security,他完全回答了这个问题。
主令牌可以也应该称为进程令牌,模拟令牌可以也应该称为线程令牌。主要令牌只能附加到进程,模拟令牌只能附加到线程。就这样。它们确实可以使用 DuplicateTokenEx
自由转换(显然,假设您对要转换的句柄具有必要的访问权限)。
从书中的第 115 页开始:
BOOL DuplicateTokenEx( HANDLE ExistingToken, // in DWORD DesiredAccess, // in LPSECURITY_ATTRIBUTES Attributes, // in, optional SECURITY_IMPERSONATION_LEVEL ImpLevel, // in TOKEN_TYPE Type, // in PHANDLE NewToken); // out
...
The
Type
parameter is a historical artifact. If you look at the definition of theTOKEN_TYPE
enumeration, you'll find that tokens have been taxonomized into two categories: impersonation versus primary tokens. Don't get hung up on this nomenclature; the meaning is actually much simpler than it sounds. Impersonation tokens can only be attached to threads, and primary tokens can only be attached to processes. That's all it means. The process token obtained earlier via OpenProcessToken was therefore a primary token.In very early versions of Windows NT (3.x), there were much more severe restrictions on what you could do with a token, depending on where you originally got it from, and hence the token type was introduced to track the intended usage of the token. Because this text assumes you're using Windows NT 4.0 or greater, just think of an impersonation token as a "thread token", and a primary token as a "process token", and use
DuplicateTokenEx
to convert between the two whenever necessary. Windows NT 4.0 tore down the boundaries between the two by introducingDuplicateTokenEx
; the Windows NT 3.x version of this function,DuplicateToken
, was hardcoded to only produce impersonation tokens. In fact, now you should be able to see the silly bug that causes the first call toSetThreadToken
to fail: the code is attempting to attach a primary token (the one obtained from the process) to a thread (which requires an impersonation token). That's a no-no. To fix both the logical problem and the silly historical problem, here's the corrected code:
严格来说不是问题的答案但在问题中提到的其他内容:
- 显然
ImpersonateLoggedOnUser
更进一步,将主要标记转换为模拟标记,而SetThreadToken
则不费吹灰之力。为什么?谁知道?可能出于同样的原因,一些 API 在调用期间启用特权,而其他 API 则要求调用者自行启用特权。 LogonUser
(和LsaLogonUser
)可能 return 网络登录的模拟令牌,因为假设通常由谁执行网络登录(例如,从第 83 页开始)。- 您可以使用未记录的 NTDLL 函数
ZwCreateToken
从用户模式创建令牌,这需要非常不寻常的权限(特别是唯一的SE_CREATE_TOKEN_NAME
)。你可能不应该...