从会话ID获取正确的令牌

时间:2015-02-26 12:32:21

标签: c++ winapi token sid windows-security

我想要实现的是当进程在非管理员用户(用户登录的Windows)下以管理员身份运行时,会话ID中的实际令牌句柄。

        DWORD dwSessionId = 0;
        if (false == ProcessIdToSessionId(dwProcessId, &dwSessionId))
        {
            LOG_ERROR(L"Failed obtaining session id");
            return false;
        }

        HANDLE hToken
        if (false == WTSQueryUserToken(dwSessionId, &hToken))
        {
            LOG_ERROR(L"Failed to obtain session's handle");
            return false;
        }

当我调用WTSQueryUserToken时出现问题,它失败并显示错误1314,这意味着我需要授予具有SE_TCB_NAME权限的调用令牌。

所以我尝试使用以下代码:

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bool bSuccess = DynamicAPI::AdjustTokenPrivileges(
    %%WHICH_TOKEN_EXACTLLY%%,
    FALSE,
    &tp,
    sizeof(TOKEN_PRIVILEGES),
    (PTOKEN_PRIVILEGES)nullptr,
    (DWORD)nullptr);

但我不完全确定应该准确提供哪个令牌。我用 %% WHICH_TOKEN_EXACTLLY %% 占位符标记了它。对于我的测试,我尝试使用AdjustTokenPriviliges我的进程'令牌(管理员权限),但它也没有帮助。

2 个答案:

答案 0 :(得分:1)

如果需要调整权限的线程模拟用户,请使用OpenThreadToken(GetCurrentThread())获取模拟令牌。否则,使用OpenProcessToken(GetCurrentProcess())获取调用进程的令牌。

答案 1 :(得分:0)

您通常需要在流程令牌中启用权限,您可以使用GetProcessToken()函数获取该权限。例外情况是,如果您打算在模拟时使用该权限,则应该在模拟令牌中启用该权限。

我使用此代码启用还原权限:

DWORD enable_restore() 
{    
  // This allows us to override security to delete files

  HANDLE token;
  BOOL flag;

  struct {
    DWORD count;
    LUID_AND_ATTRIBUTES privilege;
  } token_privileges;

  token_privileges.count = 1;
  token_privileges.privilege.Attributes = SE_PRIVILEGE_ENABLED;

  flag = LookupPrivilegeValue(0, SE_RESTORE_NAME, &token_privileges.privilege.Luid);
  if (!flag) return GetLastError();

  flag = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
  if (!flag) return GetLastError();

  flag = AdjustTokenPrivileges(token, 0, (PTOKEN_PRIVILEGES)&token_privileges, 0, 0, 0);
  if (!flag) return GetLastError();

  return 0;    
}

请注意,此代码不会检查是否实际授予了权限。为此,请在调用AdjustTokenPrivileges()之后检查GetLastError() - 这是极少数情况下,即使函数报告成功,上一个错误代码也是有意义的。

NB:这是您尝试使用流程令牌失败的最可能原因;如果您没有将代码作为本地系统运行,并且没有重新配置Windows以授予您使用SE_TCB_NAME特权的帐户,则调用AdjustTokenPrivileges()将报告成功但不起作用。

另外,请记住,无论您是否具有SE_TCB_NAME权限,如果您在本地系统上下文中运行,则只能使用WTSQueryUserToken(),即通常只有系统服务或在上下文中运行的应用程序。系统服务可以使用它。 (我不确定是否足以冒充本地系统。我怀疑不是。)