What I'm trying to achieve is the actual Token handle from the session ID when the process runs as admin under non admin user(windows logged in user).
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;
}
My problem occurs when i call WTSQueryUserToken, it fails with error 1314 which means i need to grant the calling token with a SE_TCB_NAME privilege.
so i tried doing so with the following code:
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);
But I'm not entirely sure which token should be provided exactly. I have marked it with %%WHICH_TOKEN_EXACTLLY%% placeholder. For my tests i tried to AdjustTokenPriviliges my process' token(administrator's privileges), but it didn't help either.
You usually need to enable privileges in your process token, which you can obtain with the GetProcessToken() function. The exception is that if you intend to use the privilege while impersonating then you should enable the privilege in the impersonation token instead.
I use this code to enable restore privilege:
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;
}
Note that this code does not check whether the privilege was actually granted or not. To do that, check GetLastError() after calling AdjustTokenPrivileges() - this is one of the rare cases where the last error code is meaningful even if the function reports success.
NB: this is the most likely reason why your attempt to use your process token failed; if you were not running the code as local system, and have not reconfigured Windows to give the account you were using SE_TCB_NAME privilege, the call to AdjustTokenPrivileges() will have reported success but had no effect.
Also, keep in mind that regardless of whether you have SE_TCB_NAME privilege, you can only use WTSQueryUserToken() if you are running in the local system context, i.e., typically only a system service or an application run within the context of a system service can use it. (I'm not sure whether or not it is sufficient to be impersonating local system. I suspect not.)