首页 > 系统相关 >Windows进程令牌相关信息的获取

Windows进程令牌相关信息的获取

时间:2024-07-08 15:33:27浏览次数:14  
标签:status 令牌 HANDLE Windows typedef return 获取 NtClose hToken

代码样例

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <conio.h>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <set>

#include <Windows.h>
#include <WinDef.h>

typedef struct _UNICODE_STRING
{
    USHORT Length;
    USHORT MaximumLength;
    _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES
{
    ULONG Length;
    HANDLE RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG Attributes;
    PVOID SecurityDescriptor; // PSECURITY_DESCRIPTOR;
    PVOID SecurityQualityOfService; // PSECURITY_QUALITY_OF_SERVICE
} OBJECT_ATTRIBUTES, * POBJECT_ATTRIBUTES;

typedef const OBJECT_ATTRIBUTES* PCOBJECT_ATTRIBUTES;

#define InitializeObjectAttributes(p, n, a, r, s) { \
    (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
    (p)->RootDirectory = r; \
    (p)->Attributes = a; \
    (p)->ObjectName = n; \
    (p)->SecurityDescriptor = s; \
    (p)->SecurityQualityOfService = NULL; \
    }

typedef struct _CLIENT_ID {
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID* PCLIENT_ID;

#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023)

typedef NTSTATUS(NTAPI* typedef_RtlGetVersion)(OUT PRTL_OSVERSIONINFOW lpVersionInformation);

typedef NTSTATUS(NTAPI* typedef_NtOpenProcess)(__out PHANDLE ProcessHandle, __in ACCESS_MASK DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes, __in_opt PCLIENT_ID ClientId);

typedef NTSTATUS(NTAPI* typedef_NtClose)(__in HANDLE Handle);

typedef NTSTATUS(NTAPI* typedef_NtQueryInformationToken)(
    IN  HANDLE                  TokenHandle,
    IN  TOKEN_INFORMATION_CLASS TokenInformationClass,
    OUT PVOID                   TokenInformation,
    IN  ULONG                   TokenInformationLength,
    OUT PULONG                  ReturnLength
    );

typedef NTSTATUS(NTAPI* typedef_NtOpenProcessToken)(
    IN  HANDLE      ProcessHandle,
    IN  ACCESS_MASK DesiredAccess,
    OUT PHANDLE     TokenHandle
    );

#define SE_PRIVILEGE_DISABLED                      (0x00000000L)

#ifdef UNICODE
typedef std::wstring String;
#define __T(x)      L ## x
#else
typedef std::string String;
#define __T(x)      x
#endif
typedef String CString;

#include <ntlsa.h>

typedef_NtOpenProcess g_NtOpenProcess;
typedef_NtQueryInformationToken g_NtQueryInformationToken;
typedef_NtOpenProcessToken g_NtOpenProcessToken;
typedef_NtClose g_NtClose;

void initFunc()
{
    g_NtOpenProcess = (typedef_NtOpenProcess)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtOpenProcess");
    g_NtQueryInformationToken = (typedef_NtQueryInformationToken)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationToken");
    g_NtOpenProcessToken = (typedef_NtOpenProcessToken)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtOpenProcessToken");
    g_NtClose = (typedef_NtClose)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtClose");
}

bool getProcessTokenPrivilege(DWORD dwPid, std::map<std::string, DWORD>& result)
{
    // Open a handle to the target process with read access
    HANDLE hProcess = INVALID_HANDLE_VALUE;
    CLIENT_ID client{};
    OBJECT_ATTRIBUTES oa{};
    client.UniqueProcess = ULongToHandle(dwPid);
    oa.Length = sizeof(OBJECT_ATTRIBUTES);

    NTSTATUS status = g_NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION, &oa, &client);
    if (!NT_SUCCESS(status))
    {
        return false;
    }

    // Open a handle to the process token with query access
    HANDLE hToken = INVALID_HANDLE_VALUE;
    status = g_NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
    if (!NT_SUCCESS(status))
    {
        g_NtClose(hToken);
        return false;
    }

    // Get the required size for privilege information
    DWORD tokenInfoLength = 0;
    status = g_NtQueryInformationToken(hToken, TokenPrivileges, NULL, 0, &tokenInfoLength);
    if (STATUS_BUFFER_TOO_SMALL == status && !tokenInfoLength)
    {
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    // Allocate memory for the privilege information
    LPVOID tokenInformation = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tokenInfoLength);
    if (tokenInformation == NULL)
    {
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    // Get the token privileges
    status = g_NtQueryInformationToken(hToken, TokenPrivileges, tokenInformation, tokenInfoLength, &tokenInfoLength);
    if (!NT_SUCCESS(status))
    {
        HeapFree(GetProcessHeap(), 0, tokenInformation);
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    // Cast the retrieved data to TOKEN_PRIVILEGES structure
    const auto privileges = static_cast<TOKEN_PRIVILEGES*>(tokenInformation);

    static constexpr auto fnLuidToString = [](LUID Luid) -> std::string {
        char buffer[_countof("00000000-00000000") + 1] = { '\0' };
        sprintf_s(buffer, sizeof(buffer), "%08x-%08x", Luid.HighPart, Luid.LowPart);
        return std::string(buffer);
        };

    // Loop through each privilege
    for (DWORD i = 0; i < privileges->PrivilegeCount; ++i)
    {
        // Lookup privilege name for better readability (optional)
        std::string privilegeName;

        DWORD dwReturn = 0;
        if (!LookupPrivilegeNameA(NULL, &privileges->Privileges[i].Luid, NULL, &dwReturn) && dwReturn)
        {
            privilegeName.resize(dwReturn);
            if (LookupPrivilegeNameA(NULL, &privileges->Privileges[i].Luid, privilegeName.data(), &dwReturn))
            {
                /**
                 * Attributes:
                 *
                 * #define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x00000001L)
                 * #define SE_PRIVILEGE_ENABLED            (0x00000002L)
                 * #define SE_PRIVILEGE_REMOVED            (0X00000004L)
                 * #define SE_PRIVILEGE_USED_FOR_ACCESS    (0x80000000L)
                 */
                result.insert_or_assign(privilegeName.c_str(), privileges->Privileges[i].Attributes);
            }
            else
            {
                result.insert_or_assign(std::move(fnLuidToString(privileges->Privileges[i].Luid)), privileges->Privileges[i].Attributes);
            }
        }
    }

    // Clean up resources
    HeapFree(GetProcessHeap(), 0, tokenInformation);

    g_NtClose(hToken);
    g_NtClose(hProcess);
    return true;
}

LSA_HANDLE getLookupPolicyHandle()
{
    static LSA_HANDLE cachedLookupPolicyHandle = NULL;
    LSA_HANDLE lookupPolicyHandle;
    LSA_HANDLE newLookupPolicyHandle;

    // Use the cached value if possible.

    lookupPolicyHandle = InterlockedCompareExchangePointer(&cachedLookupPolicyHandle, NULL, NULL);

    // If there is no cached handle, open one.

    if (!lookupPolicyHandle)
    {
        if (NT_SUCCESS([](_Out_ PLSA_HANDLE PolicyHandle, _In_ ACCESS_MASK DesiredAccess, _In_opt_ PUNICODE_STRING SystemName) -> NTSTATUS {
            OBJECT_ATTRIBUTES objectAttributes{};
            InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL);
            return LsaOpenPolicy((PLSA_UNICODE_STRING)SystemName, (PLSA_OBJECT_ATTRIBUTES)&objectAttributes, DesiredAccess, PolicyHandle);
            }(&newLookupPolicyHandle, POLICY_LOOKUP_NAMES, NULL)))
        {
            // We succeeded in opening a policy handle, and since we did not have a cached handle
            // before, we will now store it.

            lookupPolicyHandle = InterlockedCompareExchangePointer(&cachedLookupPolicyHandle, newLookupPolicyHandle, NULL);

            if (!lookupPolicyHandle)
            {
                // Success. Use our handle.
                lookupPolicyHandle = newLookupPolicyHandle;
            }
            else
            {
                // Someone already placed a handle in the cache. Close our handle and use their
                // handle.
                LsaClose(newLookupPolicyHandle);
            }
        }
    }

    return lookupPolicyHandle;
}

std::wstring getSidFullName(PSID Sid, BOOLEAN IncludeDomain, PSID_NAME_USE NameUse)
{
    NTSTATUS status;
    LSA_HANDLE policyHandle;
    std::wstring fullName;
    PLSA_REFERENCED_DOMAIN_LIST referencedDomains;
    PLSA_TRANSLATED_NAME names;

    policyHandle = getLookupPolicyHandle();

    referencedDomains = NULL;
    names = NULL;

    if (NT_SUCCESS(status = LsaLookupSids(
        policyHandle,
        1,
        &Sid,
        &referencedDomains,
        &names
    )))
    {
        if (names[0].Use != SidTypeInvalid && names[0].Use != SidTypeUnknown)
        {
            PWSTR domainNameBuffer = NULL;
            ULONG domainNameLength = 0;

            if (IncludeDomain && names[0].DomainIndex >= 0)
            {
                PLSA_TRUST_INFORMATION trustInfo;

                trustInfo = &referencedDomains->Domains[names[0].DomainIndex];
                domainNameBuffer = trustInfo->Name.Buffer;
                domainNameLength = trustInfo->Name.Length;
            }
            else
            {
                domainNameBuffer = NULL;
                domainNameLength = 0;
            }

            if (domainNameBuffer && domainNameLength != 0)
            {
                fullName.resize(domainNameLength / sizeof(WCHAR) + names[0].Name.Length / sizeof(WCHAR) + sizeof('\\'));
                memcpy(&fullName[0], domainNameBuffer, domainNameLength);
                fullName[domainNameLength / sizeof(WCHAR)] = '\\';
                memcpy(&fullName[domainNameLength / sizeof(WCHAR) + 1], names[0].Name.Buffer, names[0].Name.Length);
            }
            else
            {
                fullName.resize(names[0].Name.Length / sizeof(WCHAR));
                memcpy(&fullName[0], names[0].Name.Buffer, names[0].Name.Length);
            }

            if (NameUse)
            {
                *NameUse = names[0].Use;
            }
        }
    }

    if (referencedDomains) LsaFreeMemory(referencedDomains);
    if (names) LsaFreeMemory(names);

    return fullName;
}

bool getProcessTokenGroup(DWORD dwPid, std::map<std::wstring, DWORD>& result)
{
    HANDLE hProcess = INVALID_HANDLE_VALUE;
    CLIENT_ID client{};
    OBJECT_ATTRIBUTES oa{};
    client.UniqueProcess = ULongToHandle(dwPid);
    oa.Length = sizeof(OBJECT_ATTRIBUTES);

    NTSTATUS status = g_NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION, &oa, &client);
    if (!NT_SUCCESS(status))
    {
        return false;
    }

    HANDLE hToken = INVALID_HANDLE_VALUE;
    status = g_NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
    if (!NT_SUCCESS(status))
    {
        g_NtClose(hToken);
        return false;
    }

    // Get the required size for privilege information
    DWORD tokenInfoLength = 0;
    status = g_NtQueryInformationToken(hToken, TokenGroups, NULL, 0, &tokenInfoLength);
    if (STATUS_BUFFER_TOO_SMALL == status && !tokenInfoLength)
    {
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    // Allocate memory for the privilege information
    PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tokenInfoLength);
    if (Groups == NULL)
    {
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    status = g_NtQueryInformationToken(hToken, TokenGroups, Groups, tokenInfoLength, &tokenInfoLength);
    if (!NT_SUCCESS(status))
    {
        HeapFree(GetProcessHeap(), 0, Groups);
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    for (ULONG i = 0; i < Groups->GroupCount; i++)
    {
        const auto FullName = getSidFullName(Groups->Groups[i].Sid, TRUE, NULL);
        if (!FullName.empty())
        {
            /**
             * Attributes:
             *
             * #define SE_GROUP_MANDATORY                 (0x00000001L)
             * #define SE_GROUP_ENABLED_BY_DEFAULT        (0x00000002L)
             * #define SE_GROUP_ENABLED                   (0x00000004L)
             * #define SE_GROUP_OWNER                     (0x00000008L)
             * #define SE_GROUP_USE_FOR_DENY_ONLY         (0x00000010L)
             * #define SE_GROUP_INTEGRITY                 (0x00000020L)
             * #define SE_GROUP_INTEGRITY_ENABLED         (0x00000040L)
             * #define SE_GROUP_LOGON_ID                  (0xC0000000L)
             * #define SE_GROUP_RESOURCE                  (0x20000000L)
             */
            result.insert_or_assign(FullName, Groups->Groups[i].Attributes);
        }
    }

    HeapFree(GetProcessHeap(), 0, Groups);

    g_NtClose(hToken);
    g_NtClose(hProcess);
    return true;
}

bool isProcessElevated(DWORD dwPid, BOOL& bElevated)
{
    HANDLE hProcess = INVALID_HANDLE_VALUE;
    CLIENT_ID client{};
    OBJECT_ATTRIBUTES oa{};
    client.UniqueProcess = ULongToHandle(dwPid);
    oa.Length = sizeof(OBJECT_ATTRIBUTES);

    NTSTATUS status = g_NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION, &oa, &client);
    if (!NT_SUCCESS(status))
    {
        return false;
    }

    HANDLE hToken = INVALID_HANDLE_VALUE;
    status = g_NtOpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
    if (!NT_SUCCESS(status))
    {
        g_NtClose(hToken);
        return false;
    }

    TOKEN_ELEVATION_TYPE elevationType;
    DWORD size = 0;
    status = g_NtQueryInformationToken(hToken, TokenGroups, &elevationType, sizeof(elevationType), &size);
    if (!NT_SUCCESS(status))
    {
        g_NtClose(hToken);
        g_NtClose(hProcess);
        return false;
    }

    bElevated = (elevationType == TokenElevationTypeFull);

    g_NtClose(hToken);
    g_NtClose(hProcess);
    return true;
}

int main(int argc, char** argv) {
    // Replace with the target process ID
    DWORD processId = GetCurrentProcessId();  // Example process ID
    printf("Process Id: %d \n\n", processId);

    initFunc();

    BOOL bElevated = FALSE;
    isProcessElevated(processId, bElevated);
    printf("Is Process Elevated: %d \n", bElevated);

    std::map<std::string, DWORD> result;
    getProcessTokenPrivilege(processId, result);
    for (const auto& item : result)
    {
        printf("Token Privilege [%s]: 0x%X \n", item.first.c_str(), item.second);
    }

    printf("\n");

    std::map<std::wstring, DWORD> result2;
    getProcessTokenGroup(processId, result2);
    for (const auto& item : result2)
    {
        printf("Token Group [%ws]: 0x%X \n", item.first.c_str(), item.second);
    }

    printf("\n");

    system("pause");
    return 0;
}

标签:status,令牌,HANDLE,Windows,typedef,return,获取,NtClose,hToken
From: https://www.cnblogs.com/PeterZ1997/p/18289979

相关文章

  • 解决计算机中mfc140u.dll没有被指定在windows上运行
    在打开电脑软件时候出现mfc140u.dll丢失或找不到mfc140u.dll怎么办?遇到这个问题相当困扰,mfc140u.dll到底是什么?为什么会出现这个情况,相信很多人都不知道,今天我给大家详细介绍一下mfc140u.dll是什么,为什么会丢失和mfc140u.dll丢失的多种不同解决方法分享!一、mfc140u.dll丢失......
  • Windows服务器系统远程桌面设置多用户同时登录设置方法
    在实际使用我们较多使用的都是windows系统的单用户模式,它意味着当我们登录一个用户的时候如果另外一个用户也在登录,那么就得等待另外一个用户退出后或者强制踢出当前用户,才可以登录我们这个用户,下面大家可以参考下面的文章设置一下 在实际使用我们较多使用的都是windows系......
  • Windows 电脑查看 WiFi 密码的方法都有哪些?
    从设置面板中查看当你使用的是笔记本电脑并且连接WiFi之后可以在设置面板中查看WiFi密码,首先打开设置界面,然后点击网络和Internet,找到WiFi之后点击进入,然后点击管理已知网络。然后点击已经连接好的无线网络。进入之后点击查看WiFi安全密钥区域的显示按钮,就可以看......
  • 在Windows环境下安装Python 3.11的步骤
    在Windows环境下安装Python3.11的步骤相对直接。下面是详细的安装教程:第一步:下载Python3.11安装程序访问Python官方网站的下载页面:https://www.python.org/downloads/在页面中找到适用于Windows的Python3.11版本,点击下载对应你操作系统的安装包。通常,你会看到一个明显......
  • Windows 新增多个显示 不显示下面任务栏
    前言全局说明Windows多个显示不显示下面任务栏一、说明二、问题新增多个显示不显示下面任务栏,之前加的显示,可以正常显示任务栏。三、解决方法:在任务栏上右键--任务栏设置--个性化--任务栏--任务栏行为,先将选中的勾(对号)去掉,然后再勾上,就全显示了。......
  • Install the Operating System of Windows and Linux on the Laptop
    EnvironmentsWindows11Ubuntu24.04LTSLaptop:YogaPro14SARH7AllocatedDiskForUbuntu:146.5GBStepI:DownloadUbuntuPackageDownloadtheUbuntuISOfilefromtheofficialwebsite:https://ubuntu.com/download/desktopJustselecttheversion......
  • windows使用性能监视器监测C盘空间
    windows平台使用系统自带的性能监视器监测C盘空间并发送提醒邮件一、设置任务计划设置任务计划,自动发送邮件任务计划名称“Mail-diskC”方式一:使用bat脚本调用ps1文件任务计划执行bat批处理脚本,调用另一powershell文件该计划任务为后续性能监视器所调用,因此不需要设置触发......
  • JWT令牌
    首先在pom.xml引入依赖<!--jwt坐标--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency>引入测试类......
  • windows版Oracle11g安装记录
    一、下载Oracle 11g数据库安装包已上传至博客园文件中二、安装Oracle11g下载下来是下图这样的两个压缩包:1、解压这两个压缩包到同一个文件夹(切记路径文件不可有中文、空格和不规则字符。):2、将解压好的win64_11gR2_database_2of2\database\stage\Components下的所有文件拷......
  • windows mysql执行sql文件
    背景快速导入数据表或者数据库。解决直接执行sql文件。虽然直接复制内容也行,但是还是执行文件更好一些。登录mysql-uroot-p-Dxxx-D指定数据库的名称。如果不写,可以在进入mysql命令行后,使用usexxx来使用数据库。执行sourcexxx.sql特别注意,哪怕路径里有空......