【问题标题】:IsAdminUser returns incorrect valueIsAdminUser 返回不正确的值
【发布时间】:2017-08-21 13:15:21
【问题描述】:

我正在使用Win32::IsAdminUser() 函数(无法粘贴代码,因为要使其可运行,我必须粘贴整个代码)。它返回 0,我很好奇为什么因为运行它的用户是管理员组的成员,所以我创建了一个小测试函数 (c++) 并在运行之前运行它IsAdminUser 这是代码:

int davai()
{
FILE * fp;

fp = fopen ("C:\\tmp\\davai.txt", "a");
fprintf(fp, "shevedi davai");
fflush(fp);

HANDLE token = NULL;
HANDLE dupToken = NULL;

if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &token))
{
  fprintf(fp, "davai: OpenProcessToken cheijva. %d\n", (int)GetLastError());
  fflush(fp);
}

if (DuplicateTokenEx(token, MAXIMUM_ALLOWED, NULL, SecurityDelegation,
                          TokenPrimary, &dupToken) == 0)
{
  fprintf(fp, "davai: OpenProcessToken DuplicateTokenEx. %d\n", (int)GetLastError());
  fflush(fp);
}

PTOKEN_GROUPS pPrivilegesToken = NULL;
DWORD cbSize = 0;

GetTokenInformation(dupToken, TokenGroups, NULL, 0, &cbSize);

pPrivilegesToken = (PTOKEN_GROUPS) LocalAlloc(LPTR, cbSize);

if (GetTokenInformation(dupToken, TokenGroups, 
                             pPrivilegesToken, cbSize, &cbSize) == FALSE)
{
  fprintf(fp, "davai: GetTokenInformation cheijva. %d\n", (int)GetLastError());
  fflush(fp);
}

char * gio;

for (ULONG i = 0; i < pPrivilegesToken->GroupCount; i++)
{
  if (ConvertSidToStringSid(pPrivilegesToken->Groups[i].Sid, &gio) == 0)
  {
    fprintf(fp, "davai: ConvertSidToStringSid cheijva. %d\n", (int)GetLastError());
    fflush(fp);
  }
 
  fprintf(fp, "Value: %s\n",gio);
  fflush(fp);
}

LocalFree (gio);

return 1;
}

它只打开当前进程令牌,并列出用户参与的所有组。这是我得到的输出:

shevedi davaiValue: S-1-5-21-1018819917-2920201817-244685803-513
Value: S-1-1-0
Value: S-1-5-21-1018819917-2920201817-244685803-1000
Value: S-1-5-32-544
Value: S-1-5-32-545
Value: S-1-5-4
Value: S-1-2-1
Value: S-1-5-11
Value: S-1-5-15
Value: S-1-5-5-0-179095
Value: S-1-2-0
Value: S-1-5-64-10
Value: S-1-16-12288

这很奇怪,因为S-1-5-32-544 代表Administrators 组。我搜索以查找是否有人有类似的问题,但找不到任何东西(我正在运行 Windows 7)。也许你可以帮助我。任何帮助将不胜感激。

【问题讨论】:

  • 你忽略了 group 的属性。你没有检查SE_GROUP_USE_FOR_DENY_ONLY
  • 不仅打印 Sid 还打印来自 SID_AND_ATTRIBUTESAttributes - 之后您可能会明白用户没有 S-1- 5-32-544 真的
  • 好的,我会检查一下
  • 和你所说的DuplicateTokenEx?!直接从原始令牌查询

标签: c windows perl winapi


【解决方案1】:

这很奇怪,因为 S-1-5-32-544 代表管理员 组。

真的 Win32::IsAdminUser() 内部调用 CheckTokenMembership 函数与 SidToCheck == S-1-5-32-544 并返回你 IsMember 结果。但是

如果 SID 存在并且具有 SE_GROUP_ENABLED 属性, IsMember 返回 TRUE;否则,它返回 FALSE。

即使令牌中存在 SID,系统也可能不会使用该 SID 在访问检查中。 SID 可能被禁用或具有 SE_GROUP_USE_FOR_DENY_ONLY 属性。

真的,如果您的用户是管理员组 (S-1-5-32-544) 的成员,但在没有提升的情况下运行(在 UAC 下)S- 1-5-32-544 存在于令牌中,但仅具有 SE_GROUP_USE_FOR_DENY_ONLY 属性

相比之下,提升的管理员有这个 SIDSE_GROUP_ENABLED 属性

所以我猜你不是以管理员身份运行的。 Win32::IsAdminUser() 在这种情况下必须返回 false

【讨论】:

  • 你又救了我:)。我检查并属性是SE_GROUP_USE_FOR_DENY_ONLY。非常感谢你的这种解释:)
  • 请再问一个问题,如果用户(正在运行此代码)以交互方式登录,他的值为 15(十进制表示)并且当用户以批处理方式登录时,以下情况这是有问题的。这是因为交互式登录的用户是 INTERACTIVE 组的成员吗?
  • @Rasty - 如果管理员用户批量登录,他将拥有 S-1-5-32-544SE_GROUP_ENABLED (+several attr ) 与交互式登录相反(将是 SE_GROUP_USE_FOR_DENY_ONLY)。这与管理员 sid 相关。 INTERACTIVEBATCH 不同的组
  • 抱歉造成误解,但我理解交互式登录会产生受限令牌,对吧?
  • @Rasty - 不知道这种差异是/在哪里记录的(我仅凭经验知道这一点),最一般的文件How Access Tokens Work
【解决方案2】:

Win32 中所述:

在 Windows Vista 上,只有当进程实际上以提升的权限运行时,它才会返回非零值。

我将“Vista”理解为“Vista 和更新版本”。

【讨论】:

  • 是的,但我怎样才能证明这真的意味着?除了在每个窗口上测试之外还有其他答案吗?
  • 就是这个意思。
猜你喜欢
  • 2016-10-09
  • 2021-10-26
  • 2015-10-13
  • 2014-12-06
  • 2021-02-01
  • 2021-10-27
  • 2021-02-10
  • 2012-05-11
  • 1970-01-01
相关资源
最近更新 更多