【问题标题】:How can I get the current user token for the physical session?如何获取物理会话的当前用户令牌?
【发布时间】:2009-08-17 16:20:37
【问题描述】:

我有一些代码,我正在尝试获取当前会话用户令牌:

#include <Wtsapi32.h>

DWORD activeSessionId = WTSGetActiveConsoleSessionId();

HANDLE currentToken;
BOOL queryRet = WTSQueryUserToken(activeSessionId, &currentToken);

if (!queryRet) {
    DWORD err = GetLastError();
    return 0;
}

err 的值为 1314。

更新 1

到目前为止没有运气,尝试授予当前进程 SE_TCB_NAME - 但仍然从 WTSQueryUserToken (1314) 收到相同的错误。

HANDLE process = GetCurrentProcess();

HANDLE processToken;
BOOL openTokenRet = OpenProcessToken(
    process, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken);

if (!openTokenRet)
{
    DWORD err = GetLastError();
    return 0;
}

TOKEN_PRIVILEGES tokenPrivs;
BOOL lookupRet = LookupPrivilegeValue(
    NULL, SE_TCB_NAME, &tokenPrivs.Privileges[0].Luid);

if (!lookupRet)
{
    DWORD err = GetLastError();
    return 0;
}

tokenPrivs.PrivilegeCount = 1;
tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

BOOL adjustRet = AdjustTokenPrivileges(
    processToken, FALSE, &tokenPrivs, 0, (PTOKEN_PRIVILEGES)NULL, 0);

if (!adjustRet)
{
    DWORD err = GetLastError();
    return 0;
}

// get the user in the active session
HANDLE currentToken;
BOOL queryRet = WTSQueryUserToken(activeSessionId, &currentToken);

if (!queryRet) {
    DWORD err = GetLastError();
    return 0;
}

更新 2:

添加了更多调试信息,但 prevState.PrivilegeCount 为 0...

TOKEN_PRIVILEGES prevState;
DWORD prevStateLen = 0;

BOOL adjustRet = AdjustTokenPrivileges(
    processToken, FALSE, &tokenPrivs, 
    sizeof(TOKEN_PRIVILEGES), &prevState, &prevStateLen);

DWORD adjustErr = GetLastError();
if (!adjustRet)
{
    return 0;
}

解决方案:

看起来 WTSQueryUserToken 只能在作为 LocalSystem 运行时使用,这意味着我必须作为服务运行并从那里进行调试...呵呵!

【问题讨论】:

    标签: winapi wtsapi32


    【解决方案1】:

    错误 1314 是 ERROR_PRIVILEGE_NOT_HELD。您需要 SE_TCB_NAME 权限才能调用 WTSQueryUserToken。

    此权限通常仅由作为本地系统运行的代码持有。如果此权限存在于您的令牌中,但已禁用,您可以使用 AdjustTokenPrivileges 启用它。由于 SE_TCB_NAME 具有潜在的非常危险的权限,因此您应该在使用后立即再次禁用它。查看您是否拥有此权限的一种简单方法是使用进程属性窗口的安全表中的进程资源管理器。

    每次更新 1 - AdjustTokenPrivileges 返回成功,但 GetLastError() 设置为 ERROR_NOT_ALL_ASSIGNED? MSDN 表示如果未启用权限,它可能会返回此信息。您能否验证您的进程确实具有 SE_TCB_NAME 权限,但它已被禁用?您的进程以什么帐户运行?

    【讨论】:

    • 来自 MSDN:令牌不具有在 NewState 参数中指定的一项或多项权限。即使没有调整权限,该函数也可能会成功并出现此错误值。 PreviousState 参数表示已调整的权限。看起来这个函数可以成功但不能启用权限。
    • 啊哈,我可以确认 GetLastError() 给出了 ERROR_NOT_ALL_ASSIGNED - 但 adjustRet 的值为 TRUE。所以,我填充了一个 TOKEN_PRIVILEGES 结构,但 PrivilegeCount 的值为 0...这是否意味着没有任何改变?请参阅更新 2。
    • @Nick - 您的进程以什么帐户运行?您是否在冒充其他用户的线程上运行?
    • Michael:普通用户帐户,是 Vista 管理员的成员。我也试过以管理员身份运行,没有任何区别。
    • 管理员没有 TCB。您需要以 LocalSystem 身份运行才能执行此操作。你是想抢其他用户的令牌还是你自己的?
    猜你喜欢
    • 2020-12-31
    • 2019-09-12
    • 1970-01-01
    • 2020-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-12
    相关资源
    最近更新 更多