GetTokenInformation 用于检索进程或线程的令牌(Token)信息。Token是一个数据结构,其包含有关进程或线程的安全上下文,代表当前用户或服务的安全标识符和权限信息。GetTokenInformation函数也可以用来获取这些安全信息,通常用于在运行时检查某个进程或线程的权限或安全信息。
该函数原型如下:
BOOL GetTokenInformation( HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength );
|
参数说明:
- TokenHandle:当前进程或线程令牌的句柄。
- TokenInformationClass:表示要检索的Token信息类别,是TOKEN_INFORMATION_CLASS枚举类型的值之一。这个参数的值确定TokenInformation参数的方案,以及返回的信息类型。
- TokenInformation:指向要接收信息的缓冲区的指针。
- TokenInformationLength:要接收的缓冲区的大小(以字节为单位)。
- ReturnLength:实际缓冲区的大小(以字节为单位)。
常见的TokenInformationClass值包括:
- TokenUser:用户标识信息;
- TokenGroups:组信息;
- TokenOwner:所有者信息;
- TokenPrimaryGroup:主组信息;
- TokenPrivileges:特权信息;
- TokenSessionId:会话ID信息。
该函数的返回值为BOOL类型。如果函数执行成功,则返回非零值,否则返回零。如果函数返回零,则可以调用 GetLastError() 函数获取错误代码。
#include <stdio.h> #include <ShlObj.h> #include <Windows.h>
void ShowPrviliges(HANDLE process) { HANDLE hToken; OpenProcessToken(process, TOKEN_QUERY, &hToken);
DWORD dwSize; GetTokenInformation(hToken, TokenPrivileges, NULL, NULL, &dwSize);
char* pBuf = new char[dwSize] {}; GetTokenInformation(hToken, TokenPrivileges, pBuf, dwSize, &dwSize);
TOKEN_PRIVILEGES* pTp = (TOKEN_PRIVILEGES*)pBuf; DWORD dwCount = pTp->PrivilegeCount; LUID_AND_ATTRIBUTES* pluid = pTp->Privileges;
for (int i = 0; i < dwCount; i++, pluid++) { char szName[100] = {}; DWORD dwLen = sizeof(szName); LookupPrivilegeNameA(0, &pluid->Luid, szName, &dwLen); switch (pluid->Attributes) { case 0: printf("ID => %3d \t 状态 => 关闭 \t\t 类型 => %s \n", i, szName); break; case 1: printf("ID => %3d \t 状态 => 默认 \t\t 类型 => %s \n", i, szName); break; case 2: printf("ID => %3d \t 状态 => 开启 \t\t 类型 => %s \n", i, szName); break; case 3: printf("ID => %3d \t 状态 => 默认开启 \t\t 类型 => %s \n", i, szName); break; } } delete pBuf; }
int main(int argc, char* argv[]) { HANDLE LocalProcess = GetCurrentProcess(); ShowPrviliges(LocalProcess);
system("pause"); return 0; }
|
如下所示代码同样是一段权限检索的实现,函数EnumOwner()
接受一个指向进程令牌的句柄,并使用它来检索有关令牌用户的信息。使用GetTokenInformation()
获取一个包含令牌用户的安全标识符(SID
)指针的TOKEN_USER
结构。然后,它使用LocalAlloc()
为SID
分配内存,并使用CopySid()
将SID
复制到该内存中。最后使用LookupAccountSid()
检索与SID
相关联的用户账户的名称。函数返回指向包含账户名称的字符字符串的指针。
在main()
函数中使用OpenProcess()
和PROCESS_QUERY_INFORMATION
标志检索当前进程的句柄。然后,它使用OpenProcessToken()
和TOKEN_QUERY
标志检索进程令牌的句柄。将该句柄传递给EnumOwner()
以检索与令牌相关联的用户账户名称。最后使用printf()
打印账户名称,使用CloseHandle()
关闭令牌句柄,使用CloseHandle()
关闭进程句柄。
#include <stdio.h> #include <Windows.h> #include <TlHelp32.h>
char * __stdcall EnumOwner(HANDLE htoken) { DWORD dwLen; PSID pSid = 0; TOKEN_USER* pWork; SID_NAME_USE use; TCHAR User[256], Domain[256];
GetTokenInformation(htoken, TokenUser, NULL, 0, &dwLen); pWork = (TOKEN_USER*)LocalAlloc(LMEM_ZEROINIT, dwLen); if (GetTokenInformation(htoken, TokenUser, pWork, dwLen, &dwLen)) { dwLen = GetLengthSid(pWork->User.Sid); pSid = (PSID)LocalAlloc(LMEM_ZEROINIT, dwLen); CopySid(dwLen, pSid, pWork->User.Sid); dwLen = 256; LookupAccountSid(NULL, pSid, &User[0], &dwLen, &Domain[0], &dwLen, &use); return User; } return NULL; }
int main(int argc, char* argv[]) { HANDLE ProcessHandle, hToken;
ProcessHandle = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE,GetCurrentProcessId()); if (ProcessHandle != NULL) { if (OpenProcessToken(ProcessHandle, TOKEN_QUERY, &hToken)) { char *token = EnumOwner(hToken); printf("[+] 当前进程身份: %s \n", token); CloseHandle(hToken); CloseHandle(ProcessHandle); } }
system("pause"); return 0; }
|