Получение правильного токена из идентификатора сеанса

Чего я пытаюсь добиться, так это фактического дескриптора токена из идентификатора сеанса, когда процесс запускается от имени администратора под пользователем, не являющимся администратором (пользователь, вошедший в систему Windows).

        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;
        }

Моя проблема возникает, когда я вызываю WTSQueryUserToken, он завершается с ошибкой 1314, что означает, что мне нужно предоставить вызывающему токену привилегию SE_TCB_NAME.

поэтому я попытался сделать это со следующим кодом:

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);

Но я не совсем уверен, какой именно токен должен быть предоставлен. Я пометил его заполнителем %%WHICH_TOKEN_EXACTLLY%%. Для своих тестов я попытался настроить токен моего процесса AdjustTokenPriviliges (права администратора), но это тоже не помогло.


person igal k    schedule 26.02.2015    source источник


Ответы (2)


Обычно вам нужно включить привилегии в вашем токене процесса, которые вы можете получить с помощью функции GetProcessToken(). Исключением является то, что если вы собираетесь использовать эту привилегию во время олицетворения, вам следует вместо этого включить эту привилегию в токене олицетворения.

Я использую этот код для включения привилегии восстановления:

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;    
}

Обратите внимание, что этот код не проверяет, действительно ли была предоставлена ​​привилегия или нет. Для этого проверьте GetLastError() после вызова AdjustTokenPrivileges() — это один из редких случаев, когда последний код ошибки имеет смысл, даже если функция сообщает об успешном выполнении.

Примечание: это наиболее вероятная причина, по которой ваша попытка использовать токен процесса не удалась; если вы не запускали код как локальную систему и не перенастроили Windows, чтобы предоставить учетной записи, которую вы использовали, привилегию SE_TCB_NAME, вызов AdjustTokenPrivileges() сообщит об успехе, но не будет иметь никакого эффекта.

Кроме того, имейте в виду, что независимо от того, есть ли у вас привилегия SE_TCB_NAME, вы можете использовать WTSQueryUserToken() только в том случае, если вы работаете в контексте локальной системы, т. е. обычно только системная служба или приложение, запущенное в контексте системной службы, может используй это. (Я не уверен, достаточно ли олицетворять локальную систему. Подозреваю, что нет.)

person Harry Johnston    schedule 26.02.2015

Если поток, которому необходимо настроить привилегии, выдает себя за пользователя, используйте OpenThreadToken(GetCurrentThread()) чтобы получить олицетворенный токен. В противном случае используйте OpenProcessToken(GetCurrentProcess()), чтобы получить токен вызывающего процесс.

person Remy Lebeau    schedule 26.02.2015