Кажется, он не работает при просмотре привилегий процесса в Sysinternals Process Explorer.
Sysinternals Process Explorer показывает неправильное изображение.DisableAllPrivileges
работать как исключено - удалить атрибут SE_PRIVILEGE_ENABLED
из всех привилегий в токене.но некоторые привилегии также могут иметь атрибут SE_PRIVILEGE_ENABLED_BY_DEFAULT
.SeChangeNotifyPrivilege
например, имеют этот атрибут.оно останется неизменным, что и покажет ваш образ.но в любом случае только атрибут SE_PRIVILEGE_ENABLED
используется в PrivilegeCheck
или SePrivilegeCheck api.таким образом, вы действительно отключаете все привилегии в своем токене, включая 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
говорят, что привилегия отключена.