Реферат по предмету "Программирование"


Winlogon notification package. Теория и практика

Winlogon
notification package. Теория и практика

Роман Бурда 
Что это такое


В операционных системах линии Windows NT диалоговая
поддержка входа в систему реализована с помощью Winlogon. Он предоставляет
целый ряд полезных интерфейсов. Наиболее известным является GINA (Graphical
Identification and Authentication dll), который обычно используется, когда
нужно изменить стандартный способ аутентификации. Например, реализовать
возможность входа в систему по отпечаткам пальцев, сетчатке глаза или по
электронной карточке. Менее известным, но не менее полезным является Winlogon
notification package. Этот интерфейс реализует возможность обрабатывать события
на вход и выход пользователей, включение и выключение операционной системы и
некоторые другие. К сожалению, последний интерфейс реализован только в
операционных системах Win2000 и выше.
Теория


Winlogon notification package – это dll-библиотеки,
которые получают и обрабатывают события, сгенерированные Winlogon.

Logon – генерируется при входе пользователя в систему
посредством Winlogon + GINA (через консоль, терминал и т. д.). Сообщения не
будут приходить, если пользователь зашел посредством LogonUser.

Logoff – генерируется при выходе пользователя из
системы (если он вошел в систему посредством Winlogon + GINA).

Startup – генерируется при запуске системы, а также
при присоединении терминального клиента.

Shutdown – генерируется перед выключением системы, а
также при отсоединении терминального клиента.

StartScreenSaver – генерируется при запуске screen saver-а. В обработчике этого события запрещено показывать
интерфейс пользователя.

StopScreenSaver – генерируется при остановке screen
saver-а. В обработчике этого события запрещено показывать интерфейс
пользователя.

Lock – генерируется, когда пользователь блокирует
рабочую станцию.

Unlock – генерируется, когда пользователь
разблокировал рабочую станцию, или когда системный администратор снял
блокировку, заставив пользователя выйти из системы.

StartShell – генерируется после того, как пользователь
зашел в систему и сетевые соединения были установлены.

Для реализации Winlogon notification package
необходимо следующее.

Сначала нужно создать динамическую библиотеку, которая
будет импортировать набор функций-обработчиков событий. Прототип этих функций
должен строиться по шаблону:




VOID
FunctionName (PWLX_NOTIFICATION_INFO pInfo);






Как видите, вся информация о данных события хранится в
структуре WLX_NOTIFICATION_INFO.




typedef struct _WLX_NOTIFICATION_INFO


{


  ULONG  Size ;


  ULONG  Flags ;


  PWSTR  UserName ;


  PWSTR  Domain ;


  PWSTR  WindowStation ;


  HANDLE hToken ;


  HDESK  hDesktop ;


  PFNMSGECALLBACK
pStatusCallback;


} WLX_NOTIFICATION_INFO, * PWLX_NOTIFICATION_INFO ;






В этой структуре:

Size – определяет размер структуры в байтах;

Flags – поле зарезервировано и должно устанавливаться
в 0;

UserName – строка, определяющая имя текущего
пользователя. Если событие случилось до входа пользователя в систему, то это
поле равно NULL;

Domain – строка, которая определяет название домена, в
который вошел текущий пользователь. Если событие случилось до входа
пользователя в систему, то это поле равно NULL;

WindowStation – определяет имя оконной станции, в
которой текущий пользователь работает. Если событие случилось до входа
пользователя в систему, то это поле равно NULL;

hToken – дескриптор token-а пользователя. Если событие
случилось до входа пользователя в систему, то это поле равно NULL;

hDesktop – дескриптор Desktop’а для текущего события;

pStatusCallback – зарезервировано для внутреннего
использования.

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

HKEY_LOCAL_MACHINESoftwareMicrosoftWindows
NTCurrentVersionWinlogonNotify

Полный доступ к нему имеют только пользователи с
правами локального администратора. Обыкновенные пользователи не смогут
создавать или изменять подключи и/или значения.




СОВЕТ


Стоит отметить, что этого ключа не
существует в ОС Win9x, но существует недокументированный аналог –
HKEY_LOCAL_MACHINESystemCurrentControlSetcontrolMPRServices. С помощью
этого ключа можно указать процессу mpr.exe (этот процес является некоторым
аналогом Winlogon для Win9x, поскольку также отвечает за вход пользователей в
систему) загружать в свое адресное пространство необходимую динамическую
библиотеку. Таким образом, теоретически можно получить доступ к событиям
входа и выхода пользователя из системы. Для указания библиотеки достаточно
создать подключ с произвольным именем, и уже там указать следующие значения.
‘DLLName’ (REG_SZ)– имя динамической библиотеки или путь к ней, ‘EntryPoint’
(REG_SZ)– точка входа в библиотеку. Ею может быть название любой
экспортируемой функции. ‘StackSize’ (REG_DWORD) – размер стека обычно
устанавливается в 0. После перезагрузки системы указанная библиотека будет
подгружена в адресное пространство mpr.exe. Поскольку в Win9x доступ к
системному реестру имеют все, этот ключ довольно часто используется троянами.
Ведь для них это своего рода автозагрузка. Возможно, именно поэтому Microsoft
не документировала этот механизм.






Для того чтобы подписать динамическую библиотеку на
события Winlogon, необходимо создать подключ с произвольным именем, после чего
указать значения в нем:

DllName (REG_EXPAND_SZ) – имя библиотеки, содержащей
notification package, например Notify.dll;

Impersonate (REG_DWORD) – указывает, должен ли быть
имперсонирован контекст безопасности вошедшего пользователя, когда Winlogon
вызывает функцию-обработчик. (1 – должен быть имперсонирован, 0 – не должен).

Asynchronous (REG_DWORD) – указывает, должен ли
процесс Winlogon создавать отдельный поток для вызова функции-обработчика (1 –
создавать отдельный поток, 0 – не создавать). Фактически, это значение
указывает, как будет работать Winlogon с обработчиком – асинхронно или
синхронно.

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




Имя значения





Пример







Logon





WLEventLogon







Logoff





WLEventLogoff







Startup





WLEventStartup







Shutdown





WLEventShutdown







StartScreenSaver





WLEventStartScreenSaver







StopScreenSaver





WLEventStopScreenSaver







Lock





WLEventLock







Unlock





WLEventUnlock







StartShell





WLEventStartShell






Чтобы изменения вступили в силу, нужно перегрузить
компьютер. Это объясняется тем, что Winlogon загружает dll перед загрузкой
системы.

Практика


Создадим в Visual Studio пример простой программы,
ведущей логи сообщений Winlogon.




ПРИМЕЧАНИЕ


Демонстрационный проект был создан и
скомпилирован в Visual Studio 6.0.






Создадим проект Win32 Dynamic-Link Library с именем
Notify. Укажем визарду разновидность проекта – A simple DLL project. Итак,
создан пустой проект. Укажем используемые заголовочные файлы.




#include



#include







Первый заголовочный файл хранит в себе прототип
WLX_NOTIFICATION_INFO. А второй пригодится в процессе создания логов.

У нас уже есть функция DllMain, любезно
предоставленная визардом. Оставим ее без изменений. Напишем функцию создания
логов. Поскольку структура WLX_NOTIFICATION_INFO содержит в себе Юникод-строки,
будет удобно выводить данные в текстовый файл типа Юникод.




void WriteLog(PWSTR pStrEventName,


         PWLX_NOTIFICATION_INFO
pInfo)


{


  // Первый параметр функции WriteLog будет


  // содержать описание события,


  // а второй - сами данные.


  // Задаем название log-файла


  WCHAR fName[] = L"C:log.txt";


  WCHAR buf[ 1024 ];


  // Готовим строку для логов. Стоит отметить
что если бы


  // был обьявлен макрос STRICT, вывод
hDesktop


  // необходимо было бы делать по другому.


  swprintf(buf, L"Event: %s, User: %s,
Domain: %s,"


    L"Window station: %s,
User token 0x%p,"


    L"Desktop
0x%prn", pStrEventName,


    pInfo->UserName,
pInfo->Domain, pInfo->WindowStation,


    pInfo->hToken,
pInfo->hDesktop);


  // Открываем log-файл для записи.


  HANDLE hFile =
CreateFileW(fName, GENERIC_WRITE,


    FILE_SHARE_READ, NULL,
OPEN_EXISTING,


    FILE_ATTRIBUTE_NORMAL,
NULL);


  DWORD dwWritten;


  // Если такого файла нет, или случилась какая-то другая


  // ошибка, пробуем создать новый файл.


  if (hFile == INVALID_HANDLE_VALUE)


  {


    hFile = CreateFileW(fName,
GENERIC_WRITE,


    FILE_SHARE_READ, NULL,
CREATE_NEW,


    FILE_ATTRIBUTE_NORMAL,
NULL);


    if (hFile ==
INVALID_HANDLE_VALUE)


    {


      // Если файл не создался, сообщаем
пользователю


      // системным звуком о возникновении
ошибки.


      ::MessageBeep(MB_ICONASTERISK);


      return;


    }


    WCHAR data = 0xFEFF;


    // Указываем, что созданный файл будет


    // включать текст типа Юникод.


    if (!WriteFile(hFile, &data,
sizeof(data),


      &dwWritten, NULL))


     
::MessageBeep(MB_ICONASTERISK);


  }


  //Поскольку открытый файл может быть не
пустым,


  //переходим в его конец


  if (SetFilePointer(hFile, 0,
NULL, FILE_END) ==


     INVALID_SET_FILE_POINTER)


  {


   
::MessageBeep(MB_ICONASTERISK);


    return;


  }


  //Записываем строку лога в файл


  if (!WriteFile(hFile, buf, wcslen(buf) *
sizeof(WCHAR),


    &dwWritten, NULL))


   
::MessageBeep(MB_ICONASTERISK);


  //Заканчиваем работу с файлом


  CloseHandle(hFile);


}






Теперь осталось написать функции-обработчики событий.
Ради удобства назовем их так же, как показано в таблице 1.




extern "C" void __stdcall


 
WLEventLogon(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"user
logon", pInfo);


}



extern "C" void __stdcall


 
WLEventLogoff(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"user
logoff", pInfo);


}



extern "C" void __stdcall


   
WLEventStartup(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"system
startup", pInfo);


}



extern "C" void __stdcall


   
WLEventShutdown(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"system
shutdown", pInfo);


}



extern "C" void __stdcall


   
WLEventStartScreenSaver(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"screen saver
started", pInfo);


}



extern "C" void __stdcall


   
WLEventStopScreenSaver(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"screen saver
stopped", pInfo);


}



extern "C" void __stdcall


   
WLEventLock(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"Workstation
locked", pInfo);


}



extern "C" void __stdcall


   
WLEventUnlock(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"Workstation
unlocked", pInfo);


}



extern "C" void __stdcall


   
WLEventStartShell(PWLX_NOTIFICATION_INFO pInfo)


{


  WriteLog(L"User already
loged on and network"


        L" resouces are
avaliable", pInfo);


}






Теперь необходимо экспортировать эти функции для
других приложений. Для этого создадим файл Notify.def и добавим его в проект. В
единственной секции EXPORTS укажем экспортируемые функции




EXPORTS


  WLEventLogon


  WLEventLogoff


  WLEventStartup


  WLEventShutdown


  WLEventStartScreenSaver


  WLEventStopScreenSaver


 
WLEventLock


 
WLEventUnlock


 
WLEventStartShell






После успешной компиляции необходимо подписаться на
события Winlogon.




ПРЕДУПРЕЖДЕНИЕ


Необходимо помнить, что dll исполняется
в адресном пространстве процесса, который ее вызывает. Если dll спровоцирует
исключительную ситуацию, тогда, если не обработать ошибку, работа процесса
будет прекращена. Процесс Winlogon.exe очень чувствителен к таким вещам. При
возникновении ошибки он покажет синий экран смерти, а в случае наличия
соответствующих настроек перегрузит систему. Поэтому настойчиво рекомендуется
тестировать программу на виртуальном компьютере.






Для этого зайдем в реестр и отыщем ключ:

HKEY_LOCAL_MACHINESoftwareMicrosoftWindows
NTCurrentVersionWinlogonNotify

Создадим в нем подключ MyNotify и значения, как
показано на рисунке ниже.

 

Рисунок 1.

Для удобства поместим файл Notify.dll по указанному
пути. После перезагрузки системы приложение начнет создавать логи.




ПРИМЕЧАНИЕ


Если логи не создаются, проверьте, не
используется ли Notify.dll другим процессом (если файл не удается
переименовать – значит, кто-то его использует). Если Notify.dll используется,
а логов нет, скорее всего, неправильно задано одно из значений в названиях
функций-обработчиков, или такие функции не экспортируются динамической
библиотекой. Если Notify.dll не используется, проверьте, правильно ли задан
ключ DllName с названием библиотеки. Возможно, библиотека не зарегистрирована
в системе, или не может быть загружена.





Заключение


Winlogon notification package может пригодиться в
совершенно неожиданных местах. Например, если из системной службы необходимо
получить имена пользователей, работающих в системе. Все, что нужно – это
написать и зарегистрировать в системе dll, которая по запросу передаст данные в
службу (или сама будет передавать эти данные в ответ на некоторые нужные
события).

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

Для подготовки данной работы были использованы
материалы с сайта http://www.rsdn.ru/


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

Поделись с друзьями, за репост + 100 мильонов к студенческой карме :

Пишем реферат самостоятельно:
! Как писать рефераты
Практические рекомендации по написанию студенческих рефератов.
! План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом.
! Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач.
! Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты.
! Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ.

Читайте также:
Виды рефератов Какими бывают рефераты по своему назначению и структуре.