You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Windows API和C++获取进程完整性令牌的异常问题

问题分析与修正

核心问题是你没有为TOKEN_MANDATORY_LABEL结构分配有效内存,直接将GetTokenInformation的输出写入了指针变量本身的内存空间,导致后续读取的SID结构完全损坏,进而引发GetSidSubAuthorityCount返回异常指针。

具体错误点拆解

步骤4中,你使用&dwIntegrity作为GetTokenInformation的输出参数,但dwIntegrity是TOKEN_MANDATORY_LABEL*类型——这意味着你把完整的令牌数据写到了指针变量的内存里(通常仅8字节/4字节),而不是指针指向的、足够容纳TOKEN_MANDATORY_LABEL+SID数据的内存区域。这种情况下,dwIntegrity->Label.Sid指向的是无效内存,调用GetSidSubAuthorityCount自然会读取到错误数据。

修正后的完整流程

#include <windows.h>
#include <iostream>

int main() {
    DWORD dwPID = 6084;
    // 1. 获取进程句柄,必须检查返回值
    HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPID);
    if (!hProc) {
        std::cout << "[+] Error: OpenProcess " << GetLastError() << std::endl;
        return 1;
    }

    // 2. 获取令牌句柄,TOKEN_QUERY权限足够
    HANDLE hTok;
    if (!OpenProcessToken(hProc, TOKEN_QUERY, &hTok)) {
        std::cout << "[+] Error: OpenProcessToken " << GetLastError() << std::endl;
        CloseHandle(hProc);
        return 1;
    }

    // 3. 获取所需内存大小
    DWORD dwRetLen = 0;
    if (!GetTokenInformation(hTok, TokenIntegrityLevel, NULL, 0, &dwRetLen)) {
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
            std::cout << "[+] Error: GetTokenInformation (get size) " << GetLastError() << std::endl;
            CloseHandle(hTok);
            CloseHandle(hProc);
            return 1;
        }
    }

    // 4. 分配足够内存存储TOKEN_MANDATORY_LABEL结构
    TOKEN_MANDATORY_LABEL* pIntegrityLabel = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(LocalAlloc(LPTR, dwRetLen));
    if (!pIntegrityLabel) {
        std::cout << "[+] Error: LocalAlloc failed" << std::endl;
        CloseHandle(hTok);
        CloseHandle(hProc);
        return 1;
    }

    // 5. 获取实际的完整性令牌数据
    if (!GetTokenInformation(hTok, TokenIntegrityLevel, pIntegrityLabel, dwRetLen, &dwRetLen)) {
        std::cout << "[+] Error: GetTokenInformation " << GetLastError() << std::endl;
        LocalFree(pIntegrityLabel);
        CloseHandle(hTok);
        CloseHandle(hProc);
        return 1;
    }

    // 6. 正确读取完整性级别
    DWORD subAuthCount = *GetSidSubAuthorityCount(pIntegrityLabel->Label.Sid);
    DWORD integrityLevel = *GetSidSubAuthority(pIntegrityLabel->Label.Sid, subAuthCount - 1);

    std::cout << "[+] Integrity Level: 0x" << std::hex << integrityLevel << std::endl;

    // 7. 清理资源
    LocalFree(pIntegrityLabel);
    CloseHandle(hTok);
    CloseHandle(hProc);

    return 0;
}

额外注意事项

  • 必须检查所有API的返回值,尤其是内存分配和句柄获取操作,避免后续无效操作。
  • 用完句柄和内存后要及时释放,防止资源泄漏。
  • TOKEN_QUERY权限足以获取完整性令牌,不需要额外的TOKEN_QUERY_SOURCE。

内容的提问来源于stack exchange,提问作者Teodor Cristian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:50:58