试图了解进程特权属性

Trying to understand process privilege attributes

我正在编写一个可以收集进程权限的日志记录服务,并且我正在尝试了解每个进程权限的属性。让我用这段代码解释一下:

HANDLE hToken;
if(OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
    DWORD dwSize = 0;
    if(!GetTokenInformation(hToken, TokenPrivileges, NULL, dwSize, &dwSize) &&
        ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
    {
        BYTE* pb = new (std::nothrow) BYTE[dwSize];
        if(pb)
        {
            TOKEN_PRIVILEGES* pTPs = (TOKEN_PRIVILEGES*)pb;
            DWORD dwSize2;
            if(GetTokenInformation(hToken, TokenPrivileges, pTPs, dwSize, &dwSize2) &&
                dwSize2 <= dwSize)
            {
                for(UINT i = 0; i < pTPs->PrivilegeCount; i++)
                {
                    //Analyze privilege attributes to understand if it's enabled or disabled?
                    DWORD dwPrivAttr = pTPs->Privileges[i].Attributes;

                    //...
                }
            }

            delete[] pb;
        }
    }

    CloseHandle(hToken);
}

所以让我们看看 TOKEN_PRIVILEGESLUID_AND_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)

看起来它被定义为一个位掩码,但这带来了以下解释这些标志的问题:

  1. ENABLEDENABLED_BY_DEFAULT有什么区别?

  2. 什么是SE_PRIVILEGE_USED_FOR_ACCESS以及如何使用它?

  3. 如果SE_PRIVILEGE_ENABLEDSE_PRIVILEGE_REMOVED都设置了怎么办?或者,重置?

  4. 我只是 运行 一个简单的测试,对于我的过程,SeShutdownPrivilege 权限将这些属性设置为 0。那么这是什么意思呢?

我对这个结构比较困惑,但我暂时只说这些。

谢谢!

按顺序回答您的问题:

  1. ENABLED_BY_DEFAULT 表示该权限是进程启动时启用的权限之一。如果您有 ENABLED 但没有 ENABLED_BY_DEFAULT,则该进程已明确启用该权限。如果您有 ENABLED_BY_DEFAULT 但没有 ENABLED,则该进程已明确禁用该权限。

  2. 根据文档,只要实际使用特权,就会设置 SE_PRIVILEGE_USED_FOR_ACCESS。您可以使用它来进行故障排除,例如,检测您正在设置您实际上没有使用的特权,或者通过实验确定特定系统调用需要哪些特权。 (我从来没有检查过这是否真的像记录的那样运行,尽管我没有理由不这么认为。)

  3. 如果 SE_PRIVILEGE_ENABLEDSE_PRIVILEGE_REMOVED 都已设置,则您在 Windows 中发现了错误。 :-)

    如果 SE_PRIVILEGE_ENABLEDSE_PRIVILEGE_REMOVED 均未设置,则权限存在于令牌中,未被删除,但当前未启用。您可以使用 AdjustTokenPrivileges().

  4. 启用它(或删除它)
  5. 如果该属性为零,则权限存在于令牌中但当前未启用、未被删除、默认情况下未启用且进程从未使用过。

我们中的一些人可能需要被明确告知的是,特权有三种可能的状态,而不仅仅是两种。当我开始研究这些东西时,我认为进程要么拥有特权,要么没有特权。但事实证明,即使进程有特权,它也可以处于禁用状态。换句话说,disabled != 没有。

接下来顺理成章。如果进程的访问令牌中不存在特权,则进程不具有该特权。反之亦然,如果进程没有特权,则特权不会出现在令牌中。

如果进程有权限,进程可以随意启用或禁用它,对吧?为什么这有用?好吧,我猜这允许你在不完全了解它们做什么的情况下调用库函数,如果它们做的比你想象的要多,就让它们失败……不过很奇怪。