SetTokenInformation 失败,显示 24,但长度正确

dai*_*isy 0 c++ winapi

我正在尝试创建提升的SYSTEM令牌,但下面的代码失败:

#include <windows.h>
#include <stdio.h>

BOOL Elevate()
{
    PSID pSID = NULL;
    HANDLE hToken = NULL, hToken2 = NULL;
    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
    {
        fprintf(stderr, "OpenProcessToken(): %d\n", GetLastError());
        goto done;
    }

    if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hToken2))
    {
        fprintf(stderr, "DuplicateTokenEx(): %d\n", GetLastError());
        goto done;
    }

    if (!AllocateAndInitializeSid(
        &NtAuthority,
        1,
        SECURITY_MANDATORY_SYSTEM_RID,
        0,
        0, 0, 0, 0, 0, 0,
        &pSID))
    {
        fprintf(stderr, "AllocateAndInitializeSid(): %d\n", GetLastError());
        goto done;
    }

    if (!SetTokenInformation(hToken2, TokenIntegrityLevel, &pSID, sizeof(pSID)))
    {
        fprintf(stderr, "SetTokenInformation(): %d\n", GetLastError());
        goto done;
    }

done:
    if (pSID)
    {
        FreeSid(pSID);
        pSID = NULL;
    }

    CloseHandle(hToken);
    CloseHandle(hToken2);

    return TRUE;
}

int main(int argc, char** argv)
{
    Elevate();
}
Run Code Online (Sandbox Code Playgroud)

在 上失败SetTokenInformation,错误代码为 24: ERROR_BAD_LENGTH。有谁知道出了什么问题吗?

编辑

雷米·勒博是对的,我在这里找到了一个例子: https: //wiki.sei.cmu.edu/confluence/display/c/WIN02-C.+Restrict+privileges+when+spawning+child+processes

Rem*_*eau 5

根据TOKEN_INFORMATION_CLASS文档

TokenIntegrityLevel
缓冲区接收TOKEN_MANDATORY_LABEL指定令牌完整性级别的结构。

其中TOKEN_MANDATORY_LABEL定义为:

typedef struct _SID_AND_ATTRIBUTES {
#if ...
  PISID Sid;
#else
  PSID  Sid;
#endif
  DWORD Attributes;
} SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;

typedef struct _TOKEN_MANDATORY_LABEL {
  SID_AND_ATTRIBUTES Label;
} TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
Run Code Online (Sandbox Code Playgroud)

因此,您需要给出SetTokenInformation()一个指向 a 的指针TOKEN_MANDATORY_LABEL,而不是指向 a 的指针SID,例如:

#include <windows.h>
#include <stdio.h>

BOOL Elevate()
{
    TOKEN_MANDATORY_LABEL tml = {};
    HANDLE hToken = NULL, hToken2 = NULL;
    SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
    BOOL result = FALSE;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
    {
        fprintf(stderr, "OpenProcessToken(): %ul\n", GetLastError());
        goto done;
    }

    if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hToken2))
    {
        fprintf(stderr, "DuplicateTokenEx(): %ul\n", GetLastError());
        goto done;
    }

    if (!AllocateAndInitializeSid(
        &NtAuthority,
        1,
        SECURITY_MANDATORY_SYSTEM_RID,
        0,
        0, 0, 0, 0, 0, 0,
        &(tml.Label.SID)))
    {
        fprintf(stderr, "AllocateAndInitializeSid(): %ul\n", GetLastError());
        goto done;
    }

    tml.Label.Attributes = ...; // desired integrity level

    if (!SetTokenInformation(hToken2, TokenIntegrityLevel, &tml, sizeof(tml)))
    {
        fprintf(stderr, "SetTokenInformation(): %ul\n", GetLastError());
        goto done;
    }

    result = TRUE;

done:
    if (tml.Label.SID) FreeSid(tml.Label.SID);
    if (hToken) CloseHandle(hToken);
    if (hToken2) CloseHandle(hToken2);

    return result;
}

int main(int argc, char** argv)
{
    Elevate();
}
Run Code Online (Sandbox Code Playgroud)