使用DisableAllPrivileges禁用AdjustTokenPrivileges的所有特权?

时间:2018-11-15 06:55:46

标签: security winapi

我试图通过将参数DisableAllPrivileges设置为TRUE来使用#include <Windows.h> #include <cwchar> int main() { auto process = GetCurrentProcess(); HANDLE primary_token; if (OpenProcessToken(process, TOKEN_ADJUST_PRIVILEGES, &primary_token) == FALSE) { fwprintf(stderr, L"OpenProcessToken: failed"); } if (AdjustTokenPrivileges(primary_token, TRUE, nullptr, 0, nullptr, nullptr) == FALSE) { fwprintf(stderr, L"AdjustTokenPrivileges: failed"); } CloseHandle(primary_token); auto event = CreateEventW(nullptr, FALSE, FALSE, nullptr); WaitForSingleObject(event, INFINITE); } 从所有特权中剥离进程:

SE_PRIVILEGE_REMOVED

Sysinternals Process Explorer中查看进程特权时,它似乎不起作用。

我通过查询所有特权并将属性更改为DisableAllPrivileges来解决该问题,但是我不确定为什么将TRUE设置为{{1}}无效。

1 个答案:

答案 0 :(得分:1)

  

在中查看进程特权时,它似乎不起作用   Sysinternals Process Explorer。

Sysinternals Process Explorer显示错误的图像。 DisableAllPrivileges的例外处理-从令牌中的所有特权中删除SE_PRIVILEGE_ENABLED属性。但是某些特权也可以具有SE_PRIVILEGE_ENABLED_BY_DEFAULT属性。例如SeChangeNotifyPrivilege具有此属性。它保持不变,显示您的图像。但无论如何,SE_PRIVILEGE_ENABLEDPrivilegeCheck api中仅使用SePrivilegeCheck属性。因此,您实际上可以有效地禁用令牌中的所有特权,包括SeChangeNotifyPrivilege。所有需要具体特权且令牌中没有SE_PRIVILEGE_ENABLED属性的呼叫-即使存在SE_PRIVILEGE_ENABLED_BY_DEFAULT属性,也会失败。

测试代码

#ifndef RtlPointerToOffset
#define RtlPointerToOffset(B,P) ((ULONG)( ((PCHAR)(P)) - ((PCHAR)(B)) ))
#endif

inline ULONG BOOL_TO_ERROR(BOOL fOk)
{
    return fOk ? NOERROR : GetLastError();
}

volatile UCHAR guz = 0;

void DumpTokenPrivs(HANDLE hToken)
{
    union {
        PVOID buf;
        PTOKEN_PRIVILEGES ptp;
    };

    PVOID stack = alloca(guz);

    ULONG cb = 0, rcb = 0x40;

    ULONG dwError;
    do 
    {
        if (cb < rcb)
        {
            cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
        }

        if (NOERROR == (dwError = BOOL_TO_ERROR(
            GetTokenInformation(hToken, TokenPrivileges, buf, cb, &rcb))))
        {
            ULONG PrivilegeCount = ptp->PrivilegeCount;

            DbgPrint("PrivilegeCount = %u\n", PrivilegeCount);
            if (PrivilegeCount)
            {
                PLUID_AND_ATTRIBUTES Privileges = ptp->Privileges;
                do 
                {
                    WCHAR Name[64];
                    ULONG cch = RTL_NUMBER_OF(Name);
                    if (!LookupPrivilegeNameW(0, &Privileges->Luid, Name, &cch))
                    {
                        _swprintf(Name, L"{%u-%u}", 
                            Privileges->Luid.HighPart, Privileges->Luid.LowPart);
                    }

                    BOOL fResult;
                    PRIVILEGE_SET ps = { 
                        1, PRIVILEGE_SET_ALL_NECESSARY, { 
                            { Privileges->Luid.LowPart, Privileges->Luid.HighPart } 
                        } 
                    };

                    if (!PrivilegeCheck(hToken, &ps, &fResult))
                    {
                        DbgPrint("PrivilegeCheck=%u\n", GetLastError());
                    }

                    DbgPrint("%08x %x %S\n", Privileges->Attributes, fResult, Name);

                } while (Privileges++, --PrivilegeCount);
            }
        }

    } while (dwError == ERROR_INSUFFICIENT_BUFFER);
}

void PrivTest()
{
    HANDLE hToken;

    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
    {
        ULONG rcb;
        TOKEN_LINKED_TOKEN tlk;
        GetTokenInformation(hToken, TokenLinkedToken, &tlk, sizeof(tlk), &rcb);
        CloseHandle(hToken);
        hToken = tlk.LinkedToken;

        DumpTokenPrivs(hToken);

        if (AdjustTokenPrivileges(hToken, TRUE, 0, 0, 0, 0) && GetLastError() == NOERROR)
        {
            DumpTokenPrivs(hToken);
        }
    }

    CloseHandle(hToken);
}

并输出:

PrivilegeCount = 5
00000000 0 SeShutdownPrivilege
00000003 1 SeChangeNotifyPrivilege
00000000 0 SeUndockPrivilege
00000000 0 SeIncreaseWorkingSetPrivilege
00000000 0 SeTimeZonePrivilege
PrivilegeCount = 5
00000000 0 SeShutdownPrivilege
00000001 0 SeChangeNotifyPrivilege
00000000 0 SeUndockPrivilege
00000000 0 SeIncreaseWorkingSetPrivilege
00000000 0 SeTimeZonePrivilege

请注意,通话之前是

00000003 1 SeChangeNotifyPrivilege

表示SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED个属性,PrivilegeCheck表示已启用特权。

通话后是

00000001 0 SeChangeNotifyPrivilege

的意思是SE_PRIVILEGE_ENABLED_BY_DEFAULT个属性,而PrivilegeCheck则说特权被禁用。