程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> Win2K/NT下屏蔽Ctrl+Alt+Del的響應(VC)

Win2K/NT下屏蔽Ctrl+Alt+Del的響應(VC)

編輯:關於C++

大家知道,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——Winnt\system32\msgina.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。將該文件放到以下路徑:Winnt\system32。並修改注冊表,如下:

Key Name: \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ 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 * INITIALIZE)   (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;
   INITIALIZE    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 = (INITIALIZE)   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      = (PARAM_PVOID)   GetProcAddress(hMsDll,"WlxIsLogoffOk");
   MyWlxLoggedOnSAS    = (LOGON_SAS)    GetProcAddress(hMsDll,"WlxLoggedOnSAS");
   MyWlxLoggedOutSAS    = (LOGOUT_SAS)   GetProcAddress(hMsDll,"WlxLoggedOutSAS");
   MyWlxLogoff        = (PARAM_PVOID)   GetProcAddress(hMsDll,"WlxLogoff");
   MyWlxNetworkProviderLoad=(NETWORK_LOAD)GetProcAddress(hMsDll,"WlxNetworkProviderLoad");
   MyWlxRemoveStatusMessage=(PARAM_PVOID) GetProcAddress(hMsDll,"WlxRemoveStatusMessage");
   MyWlxScreenSaverNotify = (SCR_SAVER)  GetProcAddress(hMsDll,"WlxScreenSaverNotify");
   MyWlxShutdown       = (SHUT_DOWN)    GetProcAddress(hMsDll,"WlxShutdown");
   MyWlxStartApplication   = (START_APP)    GetProcAddress(hMsDll,"WlxStartApplication");
   MyWlxWkstaLockedSAS  = (LOCKED_SAS)   GetProcAddress(hMsDll,"WlxWkstaLockedSAS");
   }

實現ExitInstance如下:

  // 卸載dll
   if (hMsDll != NULL)
   {
     ::FreeLibrary(hMsDll);
     hMsDll = NULL;
   }

5.實現接口函數。由於本應用仍然保持msgina.dll的大部分操作,所以MyGina.dll的接口函數的實現較為簡單。重點需要注意的是WlxLoggedOnSAS函數的實現。當在成功登錄狀態下,不管接收到什麼SAS事件,該函數直接返回WLX_SAS_ACTION_NONE而不做其他處理。由於實現的函數較多(必須的18個),筆者僅列出代表性的五個,其余的依理類推。

// Winlogon.exe調用的gina dll中的第一個函數
// 使gina dll確認是否支持當前版本的Winlogon.exe
// 傳遞給winlogon.exe需要那個版本的接口函數
BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion)
{
// 直接調用從msgina.dll中導入的函數
   return theApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);
}
// 初始化,winlogon.exe向gina dll傳遞需要版本的接口函數分配表
BOOL WINAPI WlxInitialize(LPWSTR  lpWinsta,
              HANDLE  hWlx,
              PVOID   pvReserved,
              PVOID   pWinlogonFunctions,
              PVOID *  pWlxContext
              )
{
// 直接調用從msgina.dll中導入的函數
   return theApp.MyWlxInitialize(lpWinsta,hWlx,pvReserved,pWinlogonFunctions,pWlxContext);
}
// 當系統處於鎖定狀態時,Winlogon.exe調用該函數
// 顯示一些信息,如鎖定者、鎖定時間等
VOID WINAPI WlxDisplayLockedNotice(PVOID pWlxContext)
{
   theApp.MyWlxDisplayLockedNotice(pWlxContext);
}
// 在系統關閉之前,Winlogon.exe調用該函數
// 允許gina dll處理一些系統關閉前的處理
VOID WINAPI WlxShutdown(PVOID pWlxContext, DWORD ShutdownType)
{
   theApp.MyWlxShutdown(pWlxContext,ShutdownType);
}
// 當系統處於登陸成功,沒有鎖定的狀態下
// Winlogon接收到SAS事件,於是調用該函數
// 現屏蔽所有事件,直接返回
int WINAPI WlxLoggedOnSAS(PVOID pWlxContext,
              DWORD dwSasType,
              PVOID pReserved)
{
   return WLX_SAS_ACTION_NONE;
}

6.將MyGina.dll中實現的所有接口函數,在MyGina.def中定義導出。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved