7

I have some code, with which I'm trying to get the current session user token:

#include <Wtsapi32.h>

DWORD activeSessionId = WTSGetActiveConsoleSessionId();

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

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

Value of err is 1314.

Update 1

No luck so far, tried to grant the current process SE_TCB_NAME - but still get same error from 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;
}

Update 2:

Added some more debug info, but prevState.PrivilegeCount is 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;
}

Solution:

Looks like WTSQueryUserToken can only be used when running as LocalSystem, which means I'll have to run as a service and debug from there... Doh!

Nick Bolton
  • 38,276
  • 70
  • 174
  • 242

1 Answers1

11

Error 1314 is ERROR_PRIVILEGE_NOT_HELD. You need SE_TCB_NAME privilege to call WTSQueryUserToken.

This privilege is typically held only by code running as Local System. If this privilege is present in your token, but disabled, you can use AdjustTokenPrivileges to enable it. Since SE_TCB_NAME is a potentially very dangerous privilege to have, you should disable it again immediately after you use it. An easy way to see if you have this privilege is with Process Explorer in the Security table of the process properties window.

Per Update 1 - is AdjustTokenPrivileges return success, but GetLastError() is set to ERROR_NOT_ALL_ASSIGNED? MSDN indicates it could return this if privileges weren't enabled. Can you verify that your process does have SE_TCB_NAME privilege, but it is disabled? What account is your process running as?

Michael
  • 54,279
  • 5
  • 125
  • 144
  • From MSDN: The token does not have one or more of the privileges specified in the NewState parameter. The function may succeed with this error value even if no privileges were adjusted. The PreviousState parameter indicates the privileges that were adjusted. It looks like this function could succeed but not enable privileges. – Michael Aug 17 '09 at 19:08
  • Aha, I can confirm GetLastError() gives ERROR_NOT_ALL_ASSIGNED - but value of adjustRet is TRUE. So, I've populated a TOKEN_PRIVILEGES struct, but the value of PrivilegeCount is 0... Does this mean nothing was changed? See update 2. – Nick Bolton Aug 17 '09 at 19:26
  • @Nick - What account is your process running as? Are you running on a thread thas is impersonating another user? – Michael Aug 17 '09 at 19:29
  • Michael: Normal user account which is a member of Administrators on Vista. I have also tried run as Administrator with no difference. – Nick Bolton Aug 17 '09 at 20:18
  • 1
    Administrators don't have TCB. You need to run as LocalSystem to do this. Are you trying to grab another user's token or your own? – Michael Aug 17 '09 at 20:27
  • Well, I'm trying to launch a process under the user who is in the active session. When deployed, this will be called from a service running as LocalSystem (so there will be no problems there), however, I want to debug it right now, so I need to launch from my user account. I've got the active session ok, but as you know, WTSQueryUserToken gives ERROR_PRIVILEGE_NOT_HELD. – Nick Bolton Aug 17 '09 at 20:39
  • @Nick - No easy way to get around the TCB issue, you need to get your code installed and running as a service. You can still use normal debugging tools to debug a service. – Michael Aug 17 '09 at 20:43
  • You can change the token of the running process. Get the token from the "SamSs" service via 'OpenProcessToken', then make a copy of it via 'DuplicateToken' and then assign that new copy to your running process via 'SetThreadToken'. After that, you can continue as 'local system'. Switch back at any time with 'SetThreadToken' with 2 times a null-pointer. – Carsten Aug 02 '22 at 17:44