Token中有哪些資訊呢?這我們可以從一個api中得到,
GetTokenInformation https://msdn.microsoft.com/en-us/library/windows/desktop/aa446671(v=vs.85).aspx
想要擷取的資訊類别
TOKEN_INFORMATION_CLASS
|
如此在這裡我們一一擷取下這些資訊
1.TOKEN_USER: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379634(v=vs.85).aspx
2.TOKEN_GROUPS: https://msdn.microsoft.com/en-us/library/windows/desktop/aa379624(v=vs.85).aspx
以及各種Attributes的意義
|
3.TOKEN_PRIVILEGE https://msdn.microsoft.com/en-us/library/windows/desktop/aa379630(v=vs.85).aspx
TOKEN_PRIVILEGE 跟USER RIGHTS還是有差別的
typedef struct _TOKEN_PRIVILEGES {
DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
typedef struct _LUID_AND_ATTRIBUTES {
LUID Luid;
DWORD Attributes;
} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
locally unique identifier
(LUID) A 64-bit value that is guaranteed to be unique on the operating system that generated it until the system is restarted.
唯一标志windows某存在對象 "X" 的身份
An LUID_AND_ATTRIBUTES structure can represent an LUID whose attributes change frequently,
LUID_AND_ATTRIBUTES結構體能代表 狀态經常發生變化的LUID,而LUID也可以代表一個PRIVILEGE....
TOKEN_PRIVILEGES在記憶體中的形式
Privilege 常量
https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx
TOKEN_OWNER https://msdn.microsoft.com/en-us/library/windows/desktop/aa379628(v=vs.85).aspx
The TOKEN_OWNER structure contains the default owner security identifier (SID) that will be applied to newly created objects.
上段說明TOKEN_OWNER 結構體包含了一個預設的SID,它被用于新建立的對象---? 核心對象 如EVENT,MUTANT,SEMAPHORE...?,有待校驗
A pointer to a SID structure representing a user who will become the owner of any objects created by a process using this access token. The SID must be one of the user or group SIDs already in the token.
被這個token關聯的程序所建立的對象,被該SID表示的"使用者"擁有,這個"使用者"可以是 個體使用者或者組 ,前提使他們得出現在Token中
注意這個SID代表着的使用者和Toke關聯的使用者不是同一個對象, |
TOKEN_PRIMARY_GROUP https://msdn.microsoft.com/en-us/library/windows/desktop/aa379629(v=vs.85).aspx
The TOKEN_PRIMARY_GROUP structure specifies a group security identifier (SID) for an access token.
該TOKEN_PRIMARY_GROUP 結構體指定了一個 組SID
A pointer to a SID structure representing a group that will become the primary group of any objects created by a process using this access token.
The SID must be one of the group SIDs already in the token.
代表着 組 的一個SID,這個組 将成為 擁有這個TOKEN的程序所建立an的 所有對象 的Primary group
TOKEN_DEFAULT_DACL
A pointer to an ACL structure assigned by default to any objects created by the user. The user is represented by the access token.
一個指向ACL結構體的指針,該結構體在使用者程序建立對象的時候被預設配置設定給該對象,暫時不分析這部分
TOKEN_SOURCE https://msdn.microsoft.com/en-us/library/windows/desktop/aa379631(v=vs.85).aspx
The TOKEN_SOURCE structure identifies the source of an access token
TOKEN_SOURCE 結構體說明了該token的來源
typedef struct _TOKEN_SOURCE {
CHAR SourceName[TOKEN_SOURCE_LENGTH];
LUID SourceIdentifier;
} TOKEN_SOURCE, *PTOKEN_SOURCE;
SourceName
Specifies an 8-byte character string used to identify the source of an access token. This is used to distinguish between such sources as Session Manager, LAN Manager, and RPC Server. A string, rather than a constant, is used to identify the source so users and developers can make extensions to the system, such as by adding other networks, that act as the source of access tokens.
指定8位元組長的字元串,用來表示TOken的來源,這可被用來卻分諸如 Session Manager,LAN Manager,RPC Server等來源,用字元串而不是一個常量
表示,友善使用者,對系統進行擴充,比如添加其他的 網絡,用來作為Token的來源
SourceIdentifier
Specifies a locally unique identifier (LUID) provided by the source component named by the SourceName member. This value aids the source component in relating context blocks, such as session-control structures, to the token. This value is typically, but not necessarily, an LUID.
SourceName成員代表的來源元件 提供的本地唯一辨別符....
TOKEN_TYPE https://msdn.microsoft.com/en-us/library/windows/desktop/aa379633(v=vs.85).aspx
The TOKEN_TYPE enumeration contains values that differentiate between a primary token and an impersonation token.
typedef enum _SECURITY_IMPERSONATION_LEVEL {
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
} SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL;
目前用不着,忽略直接pass
If the access token is not an impersonation token, the function fails.
如果token不是impersionation token函數失敗
TOKEN_SESSIONID
indicates the Terminal Services session identifier that is associated with the token.If the token is associated with the terminal server client session, the session identifier is nonzero.In a non-Terminal Services environment, the session identifier is zero.
If TokenSessionId is set with SetTokenInformation, the application must have the Act As Part Of the Operating System privilege, and the application must be enabled to set the session ID in a token.
上段文字說明,TOEKN_SEESIONID 指出 與該token相關的 終端服務會話Terminal Services session ,如果相關Session是 Terminal Server Client session,則session id非0
,在 非終端 服務的環境下,session id為0,
// TokenInformation.cpp : 定義控制台應用程式的入口點。
//
#include "stdafx.h"
#include <windows.h>
#include <Sddl.h>
#include <locale.h>
VOID RetGroupDwordAttributesToStr(DWORD attributes,LPTSTR szAttributes )
{
UINT len = 0;
if(attributes & SE_GROUP_ENABLED)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_ENABLED | "));
if(attributes & SE_GROUP_ENABLED_BY_DEFAULT)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_ENABLED_BY_DEFAULT | "));
if(attributes & SE_GROUP_INTEGRITY)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_INTEGRITY | "));
if(attributes & SE_GROUP_INTEGRITY_ENABLED)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_INTEGRITY_ENABLED | "));
if(attributes & SE_GROUP_LOGON_ID)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_LOGON_ID | "));
if(attributes & SE_GROUP_MANDATORY)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_MANDATORY | "));
if(attributes & SE_GROUP_OWNER)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_OWNER | "));
if(attributes & SE_GROUP_RESOURCE)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_RESOURCE | "));
if(attributes & SE_GROUP_USE_FOR_DENY_ONLY)
len += wsprintf(szAttributes + len,TEXT("%s"),TEXT("SE_GROUP_USE_FOR_DENY_ONLY | "));
return;
}
VOID RetPrivDwordAttributesToStr(DWORD attributes,LPTSTR szAttrbutes)
{
UINT len = 0;
if(attributes & SE_PRIVILEGE_ENABLED)
len += wsprintf(szAttrbutes,TEXT(" SE_PRIVILEGE_ENABLED |"));
if(attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT)
len += wsprintf(szAttrbutes,TEXT(" SE_PRIVILEGE_ENABLED_BY_DEFAULT |"));
if(attributes & SE_PRIVILEGE_REMOVED)
len += wsprintf(szAttrbutes,TEXT(" SE_PRIVILEGE_REMOVED |"));
if(attributes & SE_PRIVILEGE_USED_FOR_ACCESS)
len += wsprintf(szAttrbutes,TEXT(" SE_PRIVILEGE_USED_FOR_ACCESS |"));
if(szAttrbutes[0] == 0)
wsprintf(szAttrbutes,TEXT(" SE_PRIVILEGE_DISABLED |"));
return ;
}
VOID PrintTokenInfoXX(HANDLE hToken,TOKEN_INFORMATION_CLASS tic )
{
setlocale(LC_ALL,"");
switch(tic)
{
case TokenUser:
{
//The TOKEN_USER structure identifies the user associated with an access token.
//TOKEN_USER 結構體 是用來标志和 Token相關聯的使用者
PVOID ptu = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(
hToken,
tic,
ptu,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
ptu =(LPVOID) calloc(dwRet,1);
if(!GetTokenInformation(
hToken,
tic,
ptu,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenUser資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenUser;
}
MessageBox(0,TEXT("擷取TokenUser資訊失敗"),0,0);
return ;
}
SUCCESS_TokenUser:
LPTSTR lpszSID = NULL;
ConvertSidToStringSid( ((PTOKEN_USER)ptu)->User.Sid,&lpszSID );
_tprintf(TEXT("USER SID: %s\t"),lpszSID);
TCHAR name[MAX_PATH] = {0};
DWORD len1 = MAX_PATH;
DWORD len2 = MAX_PATH;
TCHAR domain[MAX_PATH] = {0};
SID_NAME_USE pnu;
LookupAccountSid(NULL,((PTOKEN_USER)ptu)->User.Sid,name,&len1,domain,&len2,&pnu);
_tprintf(TEXT("USER NAME: %s of domain %s\n"),name,domain);
LocalFree(lpszSID);
free(ptu);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenGroups:
{
PTOKEN_GROUPS ptg = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenGroups,
ptg,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
ptg = (PTOKEN_GROUPS)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenGroups,
ptg,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenGroups資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenGroups;
}
MessageBox(0,TEXT("擷取TokenGroups資訊失敗"),0,0);
return ;
}
SUCCESS_TokenGroups:
for(int i = 0; i < ptg->GroupCount; i++)
{
LPTSTR lpszSID = NULL;
ConvertSidToStringSid((ptg->Groups+i)->Sid,&lpszSID);
_tprintf(TEXT("Group SID is %s\t"),lpszSID);
TCHAR name[MAX_PATH] = {0};
DWORD len1 = MAX_PATH;
DWORD len2 = MAX_PATH;
TCHAR domain[MAX_PATH] = {0};
SID_NAME_USE pnu;
LookupAccountSid(NULL,ptg->Groups[i].Sid,name,&len1,domain,&len2,&pnu);
_tprintf(TEXT("GROUP NAME: %s of domain %s"),name,domain);
TCHAR szAttributes[1024] = {0};
RetGroupDwordAttributesToStr((ptg->Groups + i)->Attributes,szAttributes);
_tprintf(TEXT("\n\t Attributes: %70s"),szAttributes);
_tprintf(TEXT("\n----------------------------------------------------------------------------------------\n"));
LocalFree(lpszSID);
}
free(ptg);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenPrivileges:
{
PTOKEN_PRIVILEGES ppriv = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenGroups,
ppriv,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
ppriv = (PTOKEN_PRIVILEGES)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenPrivileges,
ppriv,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenPrivilege資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenPrivilege;
}
MessageBox(0,TEXT("擷取TokenPrivilege資訊失敗"),0,0);
return ;
}
SUCCESS_TokenPrivilege:
for(int i = 0; i < ppriv->PrivilegeCount; i++)
{
TCHAR lpszPriv[MAX_PATH] = {0};
DWORD dwRet = MAX_PATH;
BOOL n=LookupPrivilegeName(
NULL,
&(ppriv->Privileges[i].Luid),
lpszPriv,
&dwRet
);
_tprintf(TEXT("[%d:]\t%s"),i,lpszPriv);
TCHAR lpszAttrbutes[1024] = {0};
RetPrivDwordAttributesToStr(ppriv->Privileges[i].Attributes,lpszAttrbutes);
_tprintf(TEXT("\n\t %s\n\n"),lpszAttrbutes);
}
free(ppriv);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenOwner:
{
PTOKEN_OWNER ptOwner = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenOwner,
ptOwner,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
ptOwner = (PTOKEN_OWNER)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenOwner,
ptOwner,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenOwner資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenOwner;
}
MessageBox(0,TEXT("擷取TokenOwner資訊失敗"),0,0);
return ;
}
SUCCESS_TokenOwner:;
LPTSTR lpszSID = NULL;
ConvertSidToStringSid(ptOwner->Owner,&lpszSID);
_tprintf(TEXT("OWNER SID: %s\t"),lpszSID);
TCHAR name[MAX_PATH] = {0};
DWORD len1 = MAX_PATH;
DWORD len2 = MAX_PATH;
TCHAR domain[MAX_PATH] = {0};
SID_NAME_USE pnu;
LookupAccountSid(NULL,ptOwner->Owner,name,&len1,domain,&len2,&pnu);
_tprintf(TEXT("OWNER NAME: %s of domain %s\n"),name,domain);
LocalFree(lpszSID);
free(ptOwner);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenPrimaryGroup:
{
PTOKEN_PRIMARY_GROUP ppg = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenPrimaryGroup,
ppg,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
ppg = (PTOKEN_PRIMARY_GROUP)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenPrimaryGroup,
ppg,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenPrimaryGroup資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenPrimaryGroup;
}
MessageBox(0,TEXT("擷取TokenPrimaryGroup資訊失敗"),0,0);
return ;
}
SUCCESS_TokenPrimaryGroup:;
LPTSTR lpszSID = NULL;
ConvertSidToStringSid(ppg->PrimaryGroup,&lpszSID);
_tprintf(TEXT("PRIMARY GROUP SID: %s\t"),lpszSID);
TCHAR name[MAX_PATH] = {0};
DWORD len1 = MAX_PATH;
DWORD len2 = MAX_PATH;
TCHAR domain[MAX_PATH] = {0};
SID_NAME_USE pnu;
LookupAccountSid(NULL,ppg->PrimaryGroup,name,&len1,domain,&len2,&pnu);
_tprintf(TEXT("GROUP NAME: %s of domain %s\n"),name,domain);
LocalFree(lpszSID);
free(ppg);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenDefaultDacl:
break;
case TokenSource:
{
PTOKEN_SOURCE pts = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenSource,
pts,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
pts = (PTOKEN_SOURCE)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenSource,
pts,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenSource資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenSource;
}
MessageBox(0,TEXT("擷取TokenSource資訊失敗"),0,0);
return ;
}
SUCCESS_TokenSource:;
printf("Token Source NAME: %s\n",pts->SourceName);
free(pts);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenType:
{
PTOKEN_TYPE ptt = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenType,
ptt,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
ptt = (PTOKEN_TYPE)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenType,
ptt,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenType資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenType;
}
MessageBox(0,TEXT("擷取TokenType資訊失敗"),0,0);
return ;
}
SUCCESS_TokenType:
_tprintf(TEXT("Token Type: %s\n"),(*ptt) == TokenPrimary?TEXT("TokenPrimary"):TEXT("TokenImpersonation"));
free(ptt);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenImpersonationLevel:
{
PSECURITY_IMPERSONATION_LEVEL psil = NULL;
DWORD dwRet = 0;
if(!GetTokenInformation(hToken,
TokenImpersonationLevel,
psil,
dwRet,
&dwRet
))
{
DWORD error = GetLastError( );
if(error == ERROR_INSUFFICIENT_BUFFER)
{
psil = (PSECURITY_IMPERSONATION_LEVEL)calloc(dwRet,1);
if(!GetTokenInformation(hToken,
TokenImpersonationLevel,
psil,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenImpersonationLevel資訊失敗"),0,0);
return ;
}
goto SUCCESS_TokenImpersonationLevel;
}
MessageBox(0,TEXT("擷取TokenImpersonationLevel資訊失敗,可能原因: 該Token不是Impersonation Token"),0,0);
return ;
}
SUCCESS_TokenImpersonationLevel:
if((*psil) == SecurityAnonymous)
_tprintf(TEXT("TokenImpersonationLevel : %s"),TEXT("SecurityAnonymous"));
else if((*psil) == SecurityIdentification)
_tprintf(TEXT("TokenImpersonationLevel : %s"),TEXT("SecurityIdentification"));
else if((*psil) == SecurityImpersonation)
_tprintf(TEXT("TokenImpersonationLevel : %s"),TEXT("SecurityImpersonation"));
else
_tprintf(TEXT("TokenImpersonationLevel : %s"),TEXT("SecurityDelegation"));
free(psil);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenStatistics:
break;
case TokenRestrictedSids:
break;
case TokenSessionId:
{
DWORD dwSessionID = 0;
DWORD dwRet = sizeof(dwSessionID);
if(!GetTokenInformation(hToken,
TokenSessionId,
&dwSessionID,
dwRet,
&dwRet
))
{
MessageBox(0,TEXT("擷取TokenSessionId資訊失敗"),0,0);
return ;
}
_tprintf(TEXT("Session ID is %08X\n"),dwSessionID);
_tprintf(TEXT("****************************************************************************************************\n"));
_tprintf(TEXT("****************************************************************************************************\n\n\n"));
}
break;
case TokenGroupsAndPrivileges:
break;
case TokenSandBoxInert:
break;
case TokenOrigin:
break;
case TokenElevationType:
break;
case TokenLinkedToken:
break;
case TokenElevation:
break;
case TokenHasRestrictions:
break;
case TokenAccessInformation:
break;
case TokenVirtualizationAllowed:
break;
case TokenVirtualizationEnabled:
break;
case TokenIntegrityLevel:
break;
case TokenUIAccess:
break;
case TokenMandatoryPolicy:
break;
case TokenLogonSid:
break;
case TokenCapabilities:
break;
case TokenUserClaimAttributes:
break;
case TokenDeviceClaimAttributes:
break;
case TokenDeviceGroups:
break;
case TokenRestrictedDeviceGroups:
break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hToken = NULL;
if(!OpenProcessToken(GetCurrentProcess( ),TOKEN_ALL_ACCESS,&hToken))
{
MessageBox(0,TEXT("Token擷取失敗"),0,0);
return 0;
}
TOKEN_INFORMATION_CLASS tic[31] = {
TokenUser,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSandBoxInert,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
TokenCapabilities,
TokenUserClaimAttributes,
TokenDeviceClaimAttributes,
TokenDeviceGroups,
TokenRestrictedDeviceGroups
};
const int total = 31;
for(int i = 0; i < total; i++)
PrintTokenInfoXX(hToken,tic[i]);
return 0;
}