У меня есть устаревшая служба сервера Windows и (порожденное) приложение, которое отлично работает в XP-64 и W2K3, но не работает на W2K8. Я полагаю, что это из-за новой функции " Сеанс 0 ".
Следовательно, я ищу примеры кода / параметры безопасности mojo, которые позволят вам создать новый процесс из службы Windows для Windows 2008 Server, чтобы я мог восстановить (и, возможно, превзойти) предыдущее поведение. Мне нужно решение, которое:
- Создает новый процесс в ненулевом сеансе, чтобы обойти ограничения изоляции сеанса 0 (нет доступа к графическому оборудованию из сеанса 0) - официальная строка MS на этом:
Поскольку сессия 0 больше не является пользователем
сеанс, сервисы, которые работают в
Сессия 0 не имеет доступа к
видео драйвер. Это значит что любой
попытка оказания услуг
графика не получается. Опрос на дисплее
разрешение и глубина цвета в сеансе
0 сообщает правильные результаты для
система до 1920x1200 максимум
32 бита на пиксель.
Новый процесс получает станцию Windows / рабочий стол (например, winsta0 / default), которую можно использовать для создания контроллеров домена Windows. Я нашел решение (которое запускает OK в интерактивном сеансе) для этого здесь: Запуск интерактивного клиентского процесса в C ++
Окно 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)
Итак - вопросы:
- Является ли этот подход допустимым или все процессы, инициированные службой, преднамеренно ограничены сеансом 0?
- Есть ли лучший подход (если не считать «Запуск при входе в систему» и автоматический вход в систему для серверов?)
- Что-то не так с этим кодом или другой способ создания токена процесса, где я могу поменять идентификатор сеанса, чтобы указать, что я хочу порождать процесс в новом сеансе? Я попытался использовать LogonUser вместо OpenProcessToken, но это тоже не сработало. (Мне все равно, будут ли все порожденные процессы использовать один и тот же ненулевой сеанс или нет).
Любая помощь высоко ценится - спасибо!