如何获取物理会话的当前用户令牌?

时间:2009-08-17 16:20:38

标签: winapi wtsapi32

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

#include <Wtsapi32.h>

DWORD activeSessionId = WTSGetActiveConsoleSessionId();

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

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

错误值是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运行时使用,这意味着我必须作为服务运行并从那里进行调试...... Doh!

1 个答案:

答案 0 :(得分:8)

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

此权限通常仅由作为本地系统运行的代码保留。如果您的令牌中存在此权限但已禁用,则可以使用AdjustTokenPrivileges启用该权限。由于SE_TCB_NAME可能具有非常危险的权限,因此您应该在使用它后立即再次禁用它。查看您是否拥有此权限的简单方法是使用Process Explorer窗口的Security表中的Process Explorer。

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