作者姓名 陸其明
文章原始出處 http://hqtech.nease.net
介紹:改文發表於《程序員》2001年11期
正文
大家知道,Ctrl+Alt+Del是Win2k/NT操作系統默認的系統登錄/注銷組合鍵序列,系統級別很高。在應用程序中,想要屏蔽掉該鍵序列的響應或得到這個“按下”事件,難度是相當大的。本文介紹了一種簡單易行的方法,實現在用戶登錄成功後,按下Ctrl+Alt+Del不再彈出“Windows安全”對話框。
要害詞:GINA(Graphical Identification aNd Authentication)
SAS(Secure Attention Sequence)
一. 開發原理
首先介紹一下WinLogon。windows 2000/NT有三種系統狀態:沒有用戶登錄狀態、用戶成功登錄狀態以及工作站鎖定狀態。WinLogon是Windows 2000/NT操作系統提供交互式登錄支持的組件。WinLogon有三個組成部分:可執行文件winLogon.exe,提供圖形界面認證功能的動態庫Gina Dll,以及一些網絡服務提供動態庫Network Provider Dll。參考模型如下:
winLogon.exe處理一些下層導出的接口函數,而認證策略是在Gina Dll中是獨立設計的。在系統啟動時,Gina Dll被winLogon.exe裝載。Microsoft提供了一個默認的Gina Dll——Winntsystem32msgina.dll,提供了標准的用戶名、密碼認證模式。Gina Dll是可替換的,用戶可以設計自己的Gina Dll,以提供其他如智能卡、視網膜、指紋或其他一些認證機制。
開發自定義的Gina Dll。必須實現並導出與winLogon.exe交互的18個標准函數接口,包括WlxNegotiate、WlxInitialize、WlxLoggedOnSAS等(其他函數接口請參考Msdn)。其中WlxNegotiate是winLogon.exe調用的第一個接口函數,進行必要的版本判定,隨後調用的是WlxInitialize,主要完成winLogon.exe特定版本的函數分派表向Gina Dll的傳遞。筆者還要說明的是WlxLoggedOnSAS函數,這個函數主要的功能是,當winLogon在登錄成功狀態下,接收到SAS事件,於是調用這個函數進行SAS事件的識別以及進行各事件的相應處理。
自定義Gina Dll的使用。比如開發的Gina Dll文件名為MyGina.dll。將該文件放到以下路徑:Winntsystem32。並修改注冊表,如下:
Key Name: HKEY_LOCAL_MACHINESoftwareMicrosoftWindows NTCurrentVersion WinLogon
Value Name: GinaDLL
Value Type: [REG_SZ]
Value: MyGina.dll
重新啟動計算機MyGina.dll即投入使用。
二. 應用實例
應用要求:在用戶登錄成功狀態下,按下Ctrl+Alt+Del時系統不再彈出“Widows安全”對話框。由於並不需要改變用戶名、密碼這種標准的認證模式,所以可以仍然使用msgina.dll中導出的函數接口,而對WlxLoggedOnSAS函數的實現進行必要的改變。
開發環境:Windows 2000,PII 400
開發工具:Microsoft Visual C++ 6.0
開發步驟:
1.新建項目,選擇MFC AppWizard(dll),項目名輸入為MyGina。按下“OK”後,選擇Regular DLL with MFC statically linked,按下“Finish”。
2.使用View->ClassWizard為CmyGinaApp增加InitInstance和ExitInstance兩個函數的覆蓋。注重在Stdafx.h中加入#include <Winwlx.h>。
3.由於要導入msgina.dll的接口函數,所以在MyGina.h中定義接口函數變量類型,如下:
typedef (WINAPI * NEGOTIATE) (DWord,PDWORD);
typedef (WINAPI * IN99vIALIZE) (LPWSTR,HANDLE,PVOID,PVOID,PVOID *);
typedef (WINAPI * ACTIVATE_USHELL) (PVOID,PWSTR,PWSTR,PVOID);
typedef (WINAPI * PARAM_PVOID) (PVOID);
typedef (WINAPI * DISP_STATUS) (PVOID,HDESK,DWORD,PWSTR,PWSTR);
typedef (WINAPI * GET_STATUS) (PVOID,DWORD *,PWSTR,DWORD);
typedef (WINAPI * LogoN_SAS) (PVOID,DWORD,PVOID);
typedef (WINAPI * LogoUT_SAS) (PVOID,DWORD,PLUID,PSID,PDWORD, PHANDLE,WLX_MPR_NOTIFY_INFO,PVOID *);
typedef (WINAPI * NETWORK_LOAD) (PVOID,PWLX_MPR_NOTIFY_INFO);
typedef (WINAPI * SCR_SAVER) (PVOID,BOOL *);
typedef (WINAPI * SHUT_DOWN) (PVOID,DWORD);
typedef (WINAPI * START_APP) (PVOID,PWSTR,PVOID,PWSTR);
typedef (WINAPI * LOCKED_SAS) (PVOID,DWORD);
並在類CmyGinaApp中定義成員變量,如下:
private:
HMODULE hMsDll;
public:
NEGOTIATE MyWlxNegotiate;
IN99vIALIZE MyWlxInitialize;
ACTIVATE_USHELL MyWlxActivateUserShell;
PARAM_PVOID MyWlxDisplayLockedNotice;
PARAM_PVOID MyWlxDisplaySASNotice;
DISP_STATUS MyWlxDisplayStatusMessage;
GET_STATUS MyWlxGetStatusMessage;
PARAM_PVOID MyWlxIsLockOk;
PARAM_PVOID MyWlxIsLogoffOk;
LogoN_SAS MyWlxLoggedOnSAS;
LogoUT_SAS MyWlxLoggedOutSAS;
PARAM_PVOID MyWlxLogoff;
NETWORK_LOAD MyWlxNetworkProviderLoad;
PARAM_PVOID MyWlxRemoveStatusMessage;
SCR_SAVER MyWlxScreenSaverNotify;
SHUT_DOWN MyWlxShutdown;
START_APP MyWlxStartApplication;
LOCKED_SAS MyWlxWkstaLockedSAS;
注重在MyGina.h中說明extern CMyGinaApp theApp;以便於程序其他地方對theApp的引用。
4.在MyGina.cpp中,實現InitInstance如下:
// 得到默認的gina dll
if (hMsDll == NULL)
{
hMsDll = ::LoadLibrary("msgina.dll");
}
// 導入各個接口函數
if (hMsDll != NULL)
{
MyWlxNegotiate = (NEGOTIATE) GetProcAddress(hMsDll,"WlxNegotiate");
MyWlxInitialize = (IN99vIALIZE) GetProcAddress(hMsDll,"WlxInitialize");
MyWlxActivateUserShell=(ACTIVATE_USHELL) GetProcAddress(hMsDll,"WlxActivateUserShell");
MyWlxDisplayLockedNotice=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplayLockedNotice");
MyWlxDisplaySASNotice = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxDisplaySASNotice");
MyWlxDisplayStatusMessage=(DISP_STATUS) GetProcAddress(hMsDll,"WlxDisplayStatusMessage");
MyWlxGetStatusMessage = (GET_STATUS) GetProcAddress(hMsDll,"WlxGetStatusMessage");
MyWlxIsLockOk = (PARAM_PVOID) GetProcAddress(hMsDll,"WlxIsLockOk");
MyWlxIsLogoffOk&nb