我试图通过将参数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}}无效。
答案 0 :(得分:1)
在中查看进程特权时,它似乎不起作用 Sysinternals Process Explorer。
Sysinternals Process Explorer显示错误的图像。 DisableAllPrivileges
的例外处理-从令牌中的所有特权中删除SE_PRIVILEGE_ENABLED
属性。但是某些特权也可以具有SE_PRIVILEGE_ENABLED_BY_DEFAULT
属性。例如SeChangeNotifyPrivilege
具有此属性。它保持不变,显示您的图像。但无论如何,SE_PRIVILEGE_ENABLED
或PrivilegeCheck
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
则说特权被禁用。