Служба RenderFarm для Windows 2008: CreateProcessAsUser «Изоляция сеанса 0» и OpenGL - PullRequest
8 голосов
/ 17 марта 2010

У меня есть устаревшая служба сервера Windows и (порожденное) приложение, которое отлично работает в XP-64 и W2K3, но не работает на W2K8. Я полагаю, что это из-за новой функции " Сеанс 0 ".

Следовательно, я ищу примеры кода / параметры безопасности mojo, которые позволят вам создать новый процесс из службы Windows для Windows 2008 Server, чтобы я мог восстановить (и, возможно, превзойти) предыдущее поведение. Мне нужно решение, которое:

  1. Создает новый процесс в ненулевом сеансе, чтобы обойти ограничения изоляции сеанса 0 (нет доступа к графическому оборудованию из сеанса 0) - официальная строка MS на этом:

Поскольку сессия 0 больше не является пользователем сеанс, сервисы, которые работают в Сессия 0 не имеет доступа к видео драйвер. Это значит что любой попытка оказания услуг графика не получается. Опрос на дисплее разрешение и глубина цвета в сеансе 0 сообщает правильные результаты для система до 1920x1200 максимум 32 бита на пиксель.

  1. Новый процесс получает станцию ​​Windows / рабочий стол (например, winsta0 / default), которую можно использовать для создания контроллеров домена Windows. Я нашел решение (которое запускает OK в интерактивном сеансе) для этого здесь: Запуск интерактивного клиентского процесса в C ++

  2. Окно DC, при использовании в качестве основы для перечисления OpenGL DescribePixelFormat , может находить и использовать формат с аппаратным ускорением (в системе, соответствующим образом оборудованной оборудованием OpenGL.) Примечание что наше текущее решение работает нормально на XP-64 и W2K3, за исключением случаев, когда запущен сеанс служб терминалов (VNC работает нормально.) Решение, которое также позволило процессу работать (т.е. работать с аппаратным ускорением OpenGL, даже когда сеанс служб терминалов работает). open) будет фанатичным, хотя и не обязательным.

В настоящее время я застрял в пункте № 1, и хотя есть некоторые подобные публикации, которые обсуждают это (например, это и это - они не являются подходящими решениями, так как я не гарантирую, что пользовательский сеанс уже вошел в систему, чтобы "взять" идентификатор сеанса, и не запущен с учетной записью LocalSystem (я работаю с учетной записью домена для службы, для которой я могу настроить привилегии в пределах причина, хотя я предпочел бы не увеличивать приоритеты, чтобы включить SeTcbPrivileges.)

Например, вот заглушка, которая, как мне кажется, должна работать, но всегда возвращает ошибку 1314 при вызове SetTokenInformation (даже если AdjustTokenPrivileges не вернул ошибок). Я также использовал несколько альтернативных стратегий, включающих LogonUser (вместо открытие существующего токена процесса), но я не могу заменить идентификатор сеанса.

Я также сомневаюсь в том, чтобы использовать WTSActiveConsoleSessionId во всех случаях (например, если ни один интерактивный пользователь не вошел в систему) - хотя быстрый тест службы, работающей без сеансов, вошедших в систему, по-видимому, возвращал разумное значение сеанса (1 ).

Я удалил обработку ошибок для удобства чтения (все еще немного грязно - извинения)

    //Also tried using LogonUser(..) here
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
                         | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID
                         | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY
                         | TOKEN_DUPLICATE, &hToken)

GetTokenInformation( hToken, TokenSessionId, &logonSessionId, sizeof(DWORD), &dwTokenLength )

DWORD consoleSessionId = WTSGetActiveConsoleSessionId();

/* Can't use this - requires very elevated privileges (LOCAL only, SeTcbPrivileges as well)   
   if( !WTSQueryUserToken(consoleSessionId, &hToken))
...
   */

DuplicateTokenEx(hToken, (TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_SESSIONID | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE), NULL, SecurityIdentification, TokenPrimary, &hDupToken))


    // Look up the LUID for the TCB Name privilege.
LookupPrivilegeValue(NULL, SE_TCB_NAME, &tp.Privileges[0].Luid))

    // Enable the TCB Name privilege in the token.
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(hDupToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, 0))
    {
        DisplayError("AdjustTokenPrivileges");
           ...
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    {
        DEBUG( "Token does not have the necessary privilege.\n");
    } else {
        DEBUG( "No error reported from AdjustTokenPrivileges!\n");
    }                                                                                                                                                                                        // Never errors here

   DEBUG(LM_INFO, "Attempting setting of sessionId to: %d\n", consoleSessionId );

   if (!SetTokenInformation(hDupToken, TokenSessionId, &consoleSessionId, sizeof(DWORD)))
           *** ALWAYS FAILS WITH 1314 HERE ***

Все выходные данные отладки выглядят нормально до вызова SetTokenInformation - я вижу, сеанс 0 - это мой текущий сеанс процесса, и в моем случае он пытается установить сеанс 1 (результат WTSGetActiveConsoleSessionId). (Обратите внимание, что я вошел в окно W2K8 через VNC, а не RDC)

Итак - вопросы:

  1. Является ли этот подход допустимым или все процессы, инициированные службой, преднамеренно ограничены сеансом 0?
  2. Есть ли лучший подход (если не считать «Запуск при входе в систему» ​​и автоматический вход в систему для серверов?)
  3. Что-то не так с этим кодом или другой способ создания токена процесса, где я могу поменять идентификатор сеанса, чтобы указать, что я хочу порождать процесс в новом сеансе? Я попытался использовать LogonUser вместо OpenProcessToken, но это тоже не сработало. (Мне все равно, будут ли все порожденные процессы использовать один и тот же ненулевой сеанс или нет).

Любая помощь высоко ценится - спасибо!

Ответы [ 3 ]

9 голосов
/ 19 марта 2010

Для всех, кто заинтересован в решении этого вопроса:

Я обсуждал эту проблему с MS Support для команды LogonSDK. Похоже, что невозможно полностью олицетворять интерактивного пользователя программно, так что вы получаете физическую консоль и связанные конструкции GDI, и нам, по сути, «просто повезло», что это работало до сих пор. Они подтвердили, что изоляция сеанса 0 была основной причиной регрессии.

Их рекомендация - включить автоматический вход в интерактивный сеанс и реорганизовать службу для взаимодействия с новым клиентским компонентом в интерактивном сеансе. Чтобы устранить этот недостаток безопасности, они рекомендуют использовать замену оболочки, чтобы при входе сервер переводился в режим «Киоск» (например, нет доступа к Проводнику без соответствующих учетных данных и т. Д.)

С другой стороны, это должно решить проблемы, с которыми мы столкнулись во время сеансов обслуживания терминалов, убивающих наше аппаратное ускорение.

Я буду отправлять запрос в MS, рассмотрим этот вид сценария использования «фермы рендеринга» для поддержки «сеанса прокси-пользователя» в будущих выпусках, чтобы сервер мог порождать процессы с аппаратным ускорением без компромисса безопасности, требующего наличия существующего клиентский пользовательский процесс для входа в систему с консоли.

0 голосов
/ 14 августа 2013

farmComm запустит приложения по вашему выбору в сеансе 0 без графического интерфейса пользователя, но с доступом к графическому оборудованию, независимо от того, вошли пользователи или нет. Он также реагирует на действия пользователя в любом активном сеансе (включая сеанс 0 или «безопасный рабочий стол», когда это активный сеанс). Таким образом, он предназначен для запуска приложений, когда пользователи бездействуют, и прекращает их при возобновлении работы пользователя из бездействия, но эти условия запуска можно легко изменить в исходных сценариях AutoHotkey.

https://github.com/r-alex-hall/farmComm

Он порождает приложения в сеансе 0 «невидимо», но его очень легко изменить (измените переменную со значением «hide» на «show»), чтобы увидеть GUI порожденных процессов (если они имеют GUI) , Однако, если они видны, они могут либо вызвать помехи Windows, чтобы увидеть «сообщения» в сеансе 0, и / или быть видимыми только в сеансе 0 (что, по-видимому, включает каждый раз, когда «защищенный рабочий стол» виден - для пример, когда рабочая станция заблокирована, отключена от сеансов пользователей или пользователи не вошли в систему).

На момент написания этой статьи, если какой-либо сеанс удаленного рабочего стола (RDP) начался во время запуска процессов, порожденных farmComm, farmComm завершит эти процессы и попытается повторно запустить их, чтобы ответить на сеанс RDP, что, если они являются приложениями, которые Попытка получить доступ к графическому оборудованию может привести к их сбою (поскольку RDP ограничивает доступ к графическому оборудованию). Возможно, эту проблему RDP тоже можно обойти. , , или вы можете настроить источник так, чтобы он никогда не завершал процессы или никогда не переходил на другие сеансы. (ПРИМЕЧАНИЕ: возможное запланированное изменение состоит в том, чтобы позволить вам создавать сценарии, когда и когда farmComm завершает, не завершает, не приостанавливает или не возобновляет процессы - или в этом отношении, сценарий запускает совершенно другие процессы, когда пользователи выходят из режима ожидания).

Скрипты могут быть скомпилированы в исполняемые файлы, которые в моем дистрибутиве таковы.

Основными элементами этого набора инструментов являются конкретная версия paexec (которая запускает приложения в сеансе 0), а также очень надежные ответы AutoHotkey на действия пользователя (или его отсутствие) и получение системной информации о сеансе. Возможность запуска процессов «скрыт» (без видимого графического интерфейса) также доступна через AutoHotkey.

Раскрытие информации: я написал (или закодировал) farmComm и опубликовал его в открытом доступе.

0 голосов
/ 01 мая 2013

Я не закончил учебный курс, но нашел на сайте Microsoft-MSDN учебник «Обходной путь изоляции Session 0»:

http://msdn.microsoft.com/en-us/windows7trainingcourse_sessionisolation_unit.aspx

У меня та же проблема изоляции сеанса 0, проявленная в запланированной задаче.

...