我有一些代码,我正在尝试获取当前会话用户令牌:
#include <Wtsapi32.h>
DWORD activeSessionId = WTSGetActiveConsoleSessionId();
HANDLE currentToken;
BOOL queryRet = WTSQueryUserToken(activeSessionId, ¤tToken);
if (!queryRet) {
DWORD err = GetLastError();
return 0;
}
错误值是1314。
到目前为止没有运气,尝试授予当前进程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, ¤tToken);
if (!queryRet) {
DWORD err = GetLastError();
return 0;
}
添加了一些调试信息,但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!
答案 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权限,但已被禁用?您的流程以什么帐户运行?