Что мы знаем про сессии и сервисы в Windows? Да практически ничего, кроме того, что они существуют. Что это за сущности, с чем их едят заматерелые хакеры? Как можно оценить сессию с точки зрения обеспечения защищенности и безопасности в Windows? Сегодня мы об этом и поговорим, попытаемся, так сказать, пролить свет на эту загадку.

 

WARNING

Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.

 

Что имеем?

Как я неоднократно говорил, отсутствие в свободном доступе достаточного/исчерпывающего количества информации относительно какой-либо технологии Windows - однозначный признак того, что архитекторы и разработчики системы хотят сохранить в тайне ее детали, поскольку их раскрытие может скомпрометировать всю систему безопасности. Так, например, обстоят дела с RPC или PatchGuard.

Аналогичная ситуация складывается с сессиями в Windows. Многие айтишники что-то там про них слышали, еще меньшей части компьютерного народа знакомо слова "Session 0".

Понятие "сессии" на самом деле не так сложно. Можно говорить о ней, как о некоем временном промежутке работы совокупности программ для одного пользователя. Но при этом сессии являются важной частью обеспечения безопасности системы и защиты пользовательских данных. Это словно оболочка, связывающая все действия пользователя, запущенные программы и сам десктоп.

Рассмотрим все это поподробнее.

 

Что такое "Сессия"?

Windows изначально проектировалась как многопользовательская система. И это было сделано путем реализации так называемых "терминальных сессий". Здесь надо помнить про то, что "терминальная сессия" и "сессия с момента захода в систему через winlogon.exe" - немного разные вещи. Терминальные сессии создаются и управляются сессионным менеджером smss.exe - процессом, который стартует в системе одним из первых. Winlogon-сессии и процессы как бы "живут внутри" терминальной сессии.

Для того, чтобы получить ID-номер терминальной сессии можно использовать функцию LsaGetLogonSessionData с последующим перечислением Winlogon-сессии посредством функции LsaEnumerateLogonSessions. Также можно получить ID сессии путем вызова GetTokenInformation с параметром TokenSessionId, после получения первичного токена процесса (функция OpenProcessToken). У сессии есть ряд своих приватных структур, которые используются для управления памятью.

У сессии есть свое адресное пространство, которое содержит копии данных, модифицированных драйвером графической подсистемы Win32k.sys, саму копию Win32k.sys, а также немодифицированные данные и различные драйвера, загруженные сессией. У сессии есть пространство вьюшек - виды десктопа.

И, разумеется, у сессии есть свой пул памяти. Между сессиями всех пользователей можно взаимодействовать на программном уровне. Это делается посредством пайпов, сокетов и глобальных эвентов. А вот посылать месседжи в другую сессию не выйдет.

Примечателен и любопытен с точки зрения системной безопасности тот факт, что до появления Windows Vista системные сервисы, winlogon.exe и клиент-серверная подсистема csrss.exe (о которой я уже не раз писал), стартовали как часть "нулевой сессии" ("Session 0") вместе с первым залогиневшимся клиентом, а все последующие залогинившиеся пользователи нумеровались как "Session 1", "Session 2", и т.д. Кстати, сколько у нас там сейчас в интернете остается пользователей ХР? ;).

Так было до Windows Vista...
Так было до Windows Vista...

А теперь самое интересное - эта ситуация стала напоминать забавную историю "кто первый встал - того и тапки", т.е. первый же залогинившийся в систему юзер получал привилегии "Session 0", т.е. мог запросто получить системные права, ведь важнейшие системные сервисы оказывались по соседству с простыми пользовательскими приложениями, такими правами не наделенными. Чем это грозило? Например, злобными shatter-аттаками, когда окну посылается сообщение (да-да, с использованием функции SendMessage) с ядерной начинкой внутри в виде шеллкода, повышающего привилегии. Можно было получить доступ к расшаренным секциям системных процессов, если те были неправильно защищены. Можно было скомпрометировать объекты "\BaseNamedObjects" (кто не знает - в гугл). Одним словом, способов в очередной раз поиздеваться над системой было предостаточно.

Однако, с выпуском Windows Vista, данную лавочку прикрыли. "Session 0" была надежно изолирована от пользовательских приложений. Так думали в Microsoft :).

А так стало после...
А так стало после...

По-другому думал неугомонный румын ("цыган", хотел написать ;)) Алекс Ионеску, которого очень хорошо знают все, кто хоть как-то связан с системным программированием и разработкой ОС по типу Windows. Действительно талантливый чувак, один из разработчиков ReactOS, если мне не изменяет память. Пытливый Ионеску нарыл способ приаттачиться в "Session 0". Способ хоть и весьма условный, однако работающий. В Windows 7 эта проблема была окончательно устранена.

 

Интерактивные сервисы - казнь египетския на голову Microsoft

Windows для прикладных и системных тру-кодеров предоставляет возможность создания сервисов - программ, крутящихся на заднем фоне, особо не мешающих пользователям и что-то там потихоньку считающих. Кто не в теме - в качестве некоего аналога могу привести демоны в *nix-like операционных системах. Ничего сложного в создании Win сервисов нет, документации полно, примеров еще больше, и ими активно пользуются как честные программисты, так и малварщики.

Есть такая возможность создания интерактивного сервиса - с флагом SERVICE_INTERACTIVE_PROCESS при вызове функций CreateService() или ChangeServiceConfig().

Когда менеджер сервисов (services.exe) создает процесс для интерактивного сервиса (сорри за тавтологию :), он присоединяет его к "Winsta0" (начальной рабочей станции, о них - ниже), а не к рабочей станции самого процесса. Чтобы сделать этого, процесс сервиса должен иметь права SYSTEM, потому что потом ему придется взаимодействовать с интерактивным десктопом и самим пользователем. Это может привести к очень плачевным результатам - атакам на повышение привилегий, основываясь на том, что интерактивные процессы функционируют в системе с правами SYSTEM и привилегиями "trusted computing base" (TCB).

Изоляция "Session 0" может привести к проблеме с сервисами, которым необходимо отображение пользовательского интерфейса. Поскольку сервис теперь выполняется в другой сессии (по сравнению с десктопом), пользовательский интерфейс не будет виден конечным пользователям и интерактивный сервис может оказаться в «зависшем» состоянии.

«Пусть говорят!»
«Пусть говорят!»

В Windows Vista решение этой проблемы состоит в том, что пользователям предоставляется возможность временного переключения в "Session 0" для взаимодействия с интерактивным сервисом.

В общем, намудрили товарищи из Microsoft, не смогли переплюнуть золотое правило: "Когда нельзя, но очень хочется, тогда можно".

 

Осторожно, двери закрываются! Следующая станция... "Windows"?

Да-да, системным кодерам должно быть знакомо понятие WindowStation (CreateWindowStation()). Зачем оно нужно? Ну хотя бы для того, чтобы всегда иметь ввиду, что если твой код должен быть внедрен в системный процесс или сервис (посредством подмены контекста потока), он выполняться не будет в силу несоответствия WindowStation, потому у как юзермодных приложений это будет "\Windows\WindowStations\WinSta0", а у сервиса - "\Windows\WindowStations\Service-0x0-3e7$". Это надо обязательно иметь в виду, например при создании кейлоггеров.

Станция Windows
Станция Windows

Как можно получить полный доступ к интерактивной рабочей станции и десктопу «winsta0\default»? Смотрим код:

winstaHandle = OpenWindowStation("winsta0", FALSE, 
WINSTA_ACCESSCLIPBOARD   | 
WINSTA_ACCESSGLOBALATOMS | 
WINSTA_CREATEDESKTOP | 
WINSTA_ENUMDESKTOPS  | 
WINSTA_ENUMERATE | 
WINSTA_EXITWINDOWS   | 
WINSTA_READATTRIBUTES| 
WINSTA_READSCREEN| 
WINSTA_WRITEATTRIBUTES)) ;
SetProcessWindowStation(winstaHandle);
desktopHandle = OpenDesktop("default", 0, FALSE, 
DESKTOP_CREATEMENU | 
DESKTOP_CREATEWINDOW | 
DESKTOP_ENUMERATE| 
DESKTOP_HOOKCONTROL  | 
DESKTOP_JOURNALPLAYBACK | 
DESKTOP_JOURNALRECORD | 
DESKTOP_READOBJECTS | 
DESKTOP_SWITCHDESKTOP | 
DESKTOP_WRITEOBJECTS));

ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
if (!CreateProcessAsUser(
 hToken,
 NULL,
 "cmd.exe",
 NULL,
 NULL,
 FALSE,
 NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
 NULL,
 NULL,
 &si,
 &pi
 ));

Полный вариант кода ты сможешь найти здесь - http://support.microsoft.com/kb/165194

 

INFO

Единственный способ что-то сделать вне своей терминальной сессии — это запустить отдельный процесс в этой сессии посредством CreateProcessAsUser с нужным токеном

 

WWW

Как всегда MSDN тебе на помощь - http://msdn.microsoft.com/en-us/library/windows/desktop/ms687105(v=vs.85).aspx

 

Подытожим...

Тема сессий, рабочих станций и сервисов в Windows далеко не изучена. Уверен, что там если покопаться хорошенько - не одну химеру на свет божий можно будет вытащить.

Отношения между сессиями, Станциями Windows и Десктопами  Windows
Отношения между сессиями, Станциями Windows и Десктопами Windows

В погоне за безопасностью команда Windows хорошенько постаралась осложнить жизнь как простым программистам, так и мальварщикам. С выходом операционок Windows Vista+, начали успешно отваливаться многие коммерческие VNC-решения, перестали работать кейлоггеры. И все это - в силу попыток изолировать рабочие станции, десктопы и сессии друг от друга.

Засим закончу. Удачного компилирования и да пребудет с тобой Сила!

 

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии