从会话 id 获取正确的令牌
Posted
技术标签:
【中文标题】从会话 id 获取正确的令牌【英文标题】:Getting correct Token from session id 【发布时间】:2015-02-26 12:32:20 【问题描述】:当进程在非管理员用户(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 我的进程的令牌(管理员权限),但它也没有帮助。
【问题讨论】:
【参考方案1】:如果需要调整权限的线程冒充用户,使用OpenThreadToken(GetCurrentThread())
获取被冒充的token。否则,使用OpenProcessToken(GetCurrentProcess())
获取调用进程的token。
【讨论】:
【参考方案2】:您通常需要在您的进程令牌中启用权限,您可以使用 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() - 这是最后一个错误代码有意义的罕见情况之一,即使函数报告成功也是如此。
注意:这是您尝试使用进程令牌失败的最可能原因;如果您没有将代码作为本地系统运行,并且没有重新配置 Windows 以赋予您使用 SE_TCB_NAME 权限的帐户,则对 AdjustTokenPrivileges() 的调用将报告成功但没有效果。
另外,请记住,无论您是否具有 SE_TCB_NAME 权限,如果您在本地系统上下文中运行,则只能使用 WTSQueryUserToken(),即通常只有系统服务或应用程序在系统服务可以使用它。 (我不确定冒充本地系统是否足够。我怀疑不是。)
【讨论】:
以上是关于从会话 id 获取正确的令牌的主要内容,如果未能解决你的问题,请参考以下文章
在获取访问令牌以代表用户执行 API 请求后,保持用户会话和令牌连接的“正确”方式是啥?