鸟人 发表于 2011-6-29 21:59:25

利用重写GINA进行U盘检测认证的开机锁功能

一、原理   
    GINA是WinLogon的可插入部件。Windows操作系统中Winlogon进程负责管理与登录和身份认证相关的安全性工作,包括处理用户的登录与注销、启动用户shell、输入口令、更改口令、锁定与解锁工作站等。Winlogon进程在系统初始化时,启动用户程序之前运行起来,以保证相关操作对其它进程不可见,避免其它进程取得登录敏感数据。启动过程中winlogon.exe会调用GINA,GINA(Graphical Identification and Authentication )是微软windows操作系统提供的安全登录认证和交互登录服务的组件,可为Winlogin提供用户身份识别和验证以及用户帐号和密码的反馈功能。我们在Windows登录过程中看到的欢迎屏幕和登录对话框就是GINA显示的。在系统中GINA是一个可以被替换的动态连接库。该动态连接库默认文件名为 msgina.dll,位于系统system32目录下,主要用以实现操作系统登录进程的验证和身份验证。为了支持更多的交互登录验证方式,GINA是可替换的,我们可以自己开发GINA 动态连接库以实现其它类型的身份验证方法,而且微软也提供了相关文档和例程。
二、接口
    GINA作为一个图形化身份识别和验证的组件,充当系统交互式登录的入口.有些木马也利用GINA进行密码盗取。它们往往编写和系统GINA界面相同的 GINA,然后替换MSGINA.dll。最简单的GINA木马只需写一个接口和原始GINA一样的MSGINA.dll,需要实现的功能就是登录时将密码记录下来,其它所有函数的实现都是去调用原始MSGINA.dll内的同名函数。原始的GINA动态链接库会输出下列函数以供winlogon进程调用,因此在我们的GINA里要么自己实现这些函数,要么直接调用原始GINA DLL里的同名函数:

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

GINA除了要实现以上的函数功能外,也要调用Winlogon提供的一些函数,这些函数也具有相同的Wlx前缀,此处不再赘述。
    三、实现
    GINA函数通常的调用顺序如下:操作系统启动后,Winlogon会加载GINA并首先调用WlxNegotiate函数,该函数实现GINA和 Winlogon版本互相验证的功能。接着会调用WlxInitialize来做初始化操作。初始化完成后,在未有用户登录之前,Winlogon会调用 WlxDisplaySASNotice来显示登录提示,就是常见的"按Ctrl+Alt
+Del键登录"的提示对话框。当用户按提示操作后,Winlogon会调用GINA中的下一个函数:WlxLoggedOutSAS。该函数具体实现对用户登录进行身份验证的功能。也是这次编程中主要需要修改的函数。接下来如果用户身份验证通过,GINA会向Winlogon返回一个标记句柄,以便 Winlogon为该用户配置专用登录会话和默认桌面。接着Winlogon会调用 WlxActivateUserShell,GINA会启动用户shell并返回给Winlogon。这时,用户就可以成功登录到系统中了。本程序主要是在WlxLoggedOutSAS函数中实现U盘的检测、U盘ID的获取和ID值比较等功能。为了不具体实现每一个GINA的导出函数,其余需要被 Winlogon调用的函数采均用直接调用原始GINA动态连接库中的函数的方法来实现,以保证我们的GINA动态链接库具有和原始GINA一样的功能,即使在WlxLoggedOutSAS函数中实现完我们添加的功能后,我们同样要调用原始GINA内的该同名函数,以便将数据正确返回Winlogon。主要代码如下:

导入原始的GINA动态链接库:hMsDll =LoadLibrary(L"msgina.dll");
获得原始DLL的导出函数地址指针,如:
if (hMsDll != NULL)
{
MyWlxNegotiate = (NEGOTIATE) GetProcAddress(hMsDll,"WlxNegotiate");
MyWlxInitialize=(INITIALIZE)GetProcAddress(hMsDll,"WlxInitialize");
... ...;
}
Winlogon需要调用的GINA函数以如下方式实现:
BOOL WINAPI WlxNegotiate(DWORD dwWinLogonVersion, PDWORD pdwDllVersion)
{
      returntheApp.MyWlxNegotiate(dwWinLogonVersion,pdwDllVersion);
}
U盘检测和ID读取比较等验证功能在上一期文章中已经交待清楚,这里就不再赘述。

整个软件实现的功能就是当用户开机登录系统时,弹出要求检测U盘锁的对话框,当用户将U盘插入后,我们编写的GINA会检测该U盘ID与所存ID是否一致,如果一致则跳到用户名密码输入的登陆页面,否则拒绝登录。程序在第一次使用时,会读取U盘ID并存到系统文件夹下,以便之后判断比较。U盘检测比较的实现逻辑与上一期所述完全一致。

    四、安装

    安装过程非常简单,先将生成好的GINA动态连接库拷入系统system32目录下,然后在注册表中添加如下信息:

键值: \HKEY_LOCAL_MACHINE\Software\Microsoft\Windows   NT\CurrentVersion\Winlogon

变量名 : GinaDLL

变量类型:

内容: "生成的GINA DLL文件的名称"

最后重启机器,U盘锁登录界面就会出现。当然,整个安装过程也可以编程自动实现。大家可以利用这个GINA程序

作为模板来随意改变系统的登录认证方式,有兴趣的朋友可以自己动手试试。

leon460 发表于 2011-6-29 22:56:30

回复 1# 鸟人

呵呵,不错,,学习学习

daiyu116 发表于 2011-6-30 14:11:15

先留名收藏,改天再详细看

9f027 发表于 2011-7-8 09:47:00

比较高深的的东西

fqvip1 发表于 2011-8-7 16:37:05

先留名收藏,改天再详细看
页: [1]
查看完整版本: 利用重写GINA进行U盘检测认证的开机锁功能