【问题标题】:AdjustTokenPrivileges: ERROR_NOT_ALL_ASSIGNED after successAdjustTokenPrivileges:成功后出现ERROR_NOT_ALL_ASSIGNED
【发布时间】:2018-04-23 01:00:51
【问题描述】:

我的代码有一个循环,它使用 AdjustTokenPrivileges 来启用 SE_DEBUG_NAME 权限并将其删除。 每次我运行它时,第一组启用/禁用是成功的,但是在第一个循环之后,其余的启用/删除组为 AdjustTokenPrivileges 提供 ERROR_NOT_ALL_ASSIGNED。 机器是 Windows 10 专业版 64 位。编译后的 exe 以“以管理员身份运行”模式运行。 请帮忙。

以下代码在循环中。

TOKEN_PRIVILEGES priv = { 0,0,0,0 };
HANDLE hToken = NULL;
LUID luid = { 0,0 };
BOOL Status = true;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
    Status = false;
    goto EXIT;
}
if (!LookupPrivilegeValueW(0, lpszPrivilege, &luid)) {
    Status = false;
    goto EXIT;
}
priv.PrivilegeCount = 1;
priv.Privileges[0].Luid = luid;
priv.Privileges[0].Attributes = bEnablePrivilege ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
if (!AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0)) {
    Status = false;
    goto EXIT;
}
std::cout << "priv:" << GetLastError() << std::endl; //gives 0(no error) on first pair of enable/disable, then 0x514, which is ERROR_NOT_ALL_ASSIGNED, on the following loops.
EXIT:
if (hToken)
    CloseHandle(hToken);
return Status;

【问题讨论】:

    标签: c++ windows winapi visual-c++ privileges


    【解决方案1】:

    MSDN 告诉你原因:

    SE_PRIVILEGE_REMOVED

    由于该权限已从令牌中删除,因此尝试重新启用该权限会导致警告 ERROR_NOT_ALL_ASSIGNED,就好像该权限从未存在过一样。

    将属性设置为 0 以禁用。 MSDN有一个例子here...

    【讨论】:

    • 谢谢。我现在了解如何禁用它。但如果可能的话,我仍然想删除并重新添加权限。
    • 你不能在令牌中添加东西,一旦它消失了,它就永远消失了。当您需要打开和关闭时,只需禁用即可。
    • 一般来说,在多线程进程中,最好通过复制模拟令牌来仅为当前线程启用权限。在这种情况下,可以删除特权,因为您可以简单地恢复为进程令牌。这样做的原因可能与 Windows API 在某些情况下如何自动为当前线程启用特权有关。删除特权可确保不会发生这种情况。
    • @eryksun 但是您不能在旧版本中删除它们。我通常编写一个返回初始状态的包装器,因此只有最后一个线程在每个线程都完成后才真正禁用该特权。我相信 Windows 也是这样做的。
    • 删除权限是很久以前引入的,大约在 2003 年。对于 Windows,它曾经在 Server 2003 SP1 之前使用BasepAcquirePrivilege。运行时库在 Server 2003 SP2 中获得了RtlAcquirePrivilege。默认情况下,这使用当前的模拟,或模拟进程令牌(即自 Vista 以来的RtlImpersonateSelfEx)。可选标志支持首先恢复到自我并直接使用进程令牌(意味着恢复到自我)。在使用重复模拟令牌的常见情况下,RtlReleasePrivilege 只需恢复为自己。
    【解决方案2】:

    感谢安德斯,

    换行

    priv.Privileges[0].Attributes = bEnablePrivilege ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
    

    priv.Privileges[0].Attributes = bEnablePrivilege ? SE_PRIVILEGE_ENABLED : NULL;
    

    修复了代码。但是代码现在只启用/禁用特权。 正如 MSDN 所说

    特权的移除是不可逆的

    所以我无法删除它并重新添加它。

    【讨论】:

    • 你不能,你必须选择一个;禁用或删除。
    • DWORD Attributes 字段赋值为 0 以禁用该权限。 NULL 在语义上是为指针保留的(例如 (void *) 0(char *) 0),并且可能在某些编译器上将其分配给整数可能是错误的。
    猜你喜欢
    • 2013-08-04
    • 2012-11-08
    • 2022-10-07
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-26
    • 2021-01-31
    相关资源
    最近更新 更多