一、前言
在Windows 9x/Me系统中,屏蔽Ctrl+Alt+Del和各种任务开关键的方法是通过下面的方法实现的:
BOOL bOldState; SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &bOldState, 0);
但在NT平台下,此方法不再适用,即使使用钩子技术也无法拦截到这个组合热键(原因稍后解释)。在网上,可以看到众多高手的解决方案,再此我做个简单的总结,同时提出完美的解决方案,并提供所需的 SellCode 数据供 VC,Delphi等程序员使用,最后考虑到VB在实现这些方面的不便还给出VB完整的源码,相信这是很不错的例子,可以让VB程序员了解更多的技巧。
二、不够完美的解决方案
原理:代理系统相关的DLL,对相关的函数作特殊处理
不足之处:使用不方便!并且效果不佳(屏幕会闪)
下面将具体讨论这种方案:
在NT平台下,用户登陆是使用Winlogon和GINA——Graphical Identification and Authentication,意思是图形化的身份认证。Winlogon是Windows系统的一部分,它专门提供交互式登陆支持,而GINA则是Winlogon用来实现认证的一个DLL——这个DLL就是msgina.dll。WlxInitialize、WlxActivateUserShell便是其中输出,当然不知这两个,还有别的。前者进行自身的初始化,后者激活用户的外壳程序。Windows就是用这个DLL来实现用户名+口令的身份认证的,但是开发人员可以用自己的GINA代替msgina.dll。例如,实现智能卡、视网膜扫描仪、DNA检查等等认证机制来代替输入用户名+口令形式的身份检查。 下面的表格中列出了与GINA有关的全部函数。其中有一个是WlxLoggedOnSAS,当按下Ctrl+Alt+Del 键时,Winlogon便调用这个函数。
(表一)GINA 函数一览表
函数 | 描述 |
WlxActivateUserShell | 激活用户外壳程序 |
WlxDisplayLockedNotice | 允许GINA DLL 显示锁定信息 |
WlxDisplaySASNotice | 当没有用户登陆时,Winlogon调用此函数 |
WlxDisplayStatusMessage | Winlogon 用一个状态信息调用此函数进行显示 |
WlxGetConsoleSwitchCredentials | Winlogon调用此函数读取当前登陆用户的信任信息,并透明地将它们传到目标会话 |
WlxGetStatusMessage | Winlogon 调用此函数获取当前状态信息 |
WlxInitialize | 针对指定的窗口位置进行GINA DLL初始化 |
WlxIsLockOk | 验证工作站正常锁定 |
WlxIslogoffOk | 验证注销正常 |
WlxLoggedOnSAS | 用户已登陆并且工作站没有被加锁,如果此时接收到SAS事件,则Winlogon 调用此函数 |
WlxLoggedOutSAS | 没有用户登陆,如果此时收到SAS事件,则Winlogon 调用此函数 |
WlxLogoff | 请求注销操作时通知GINA DLL |
WlxNegotiate | 表示当前的Winlogon版本是否能使用GINA DLL |
WlxNetworkProviderLoad | 在加载网络服务提供程序收集了身份和认证信息后,Winlogon 调用此函数 |
WlxRemoveStatusMessage | Winlogon 调用此函数告诉GINA DLL 停止显示状态信息 |
WlxScreensaverNotify | 允许GINA与屏幕保护操作交互 |
WlxShutdown | 在关闭之前Winlogon 调用此函数,允许GINA实现任何关闭任务,例如从读卡器中退出智能卡 |
WlxStartApplication | 当系统需要在用户的上下文中启动应用程序时调用此函数 |
WlxWkstaLockedSAS | 当工作站被锁定,如果接收到一个SAS,则Winlogon 调用此函数 |
在默认情况下,GINA显示登陆对话框,用户输入用户名及口令。所以要想屏蔽掉Ctrl+Alt+Del,则可以写一个新的MyGina.dll,其中提供接口调用msgina.dll的函数WlxLoggedOnSAS,从而实现Ctrl+Alt+Del屏蔽。或者编写一个键盘驱动程序来实现。
NT系统允许使用我们自己的 GINA,因此,我们只要写一个这样的DLL,当然其它无关的函数我们可以转调用原GINA库中的函数,只处理WlxLoggedOnSAS这个函数。在此函数中可以结合原子操作,有条件的屏蔽Ctrl+Alt+Del,即如果某个(当然是你规定的)原子存在,你就返回 WLX_SAS_ACTION_NONE, 将将屏幕切换到应用程序桌面,从而好像屏蔽掉CTRL+ALT+DEL ,因此屏幕会闪一下,呵呵。具体的实现就我就不列出来了,毕竟不是本文的主要目的,而且网上大把参考代码的。如何安装这个DLL,也请自个到网上找,蛮多的。
三、不完美解决方案的另类实现
这个方法是我根据上面的原理再改进的,解决它的安装不方便的地方。不过也引出很多弊端。具体实现就是使用进程内存读写函数,以及虚拟内存管理函数,动态修改WinLogon进程中GIAN的函数。如果打开WinLogon进程在下面有讨论,至于如何定位函数及如何读写内存,自个去找资料吧。
四、完美的解决方案
本来用键盘驱动程序能完美解决的,可未免也杀鸡用牛刀,场面搞大了点。其实当你登录后,Winlogon创建一个新的桌面并调用Explorer。,而Winlogon则在另一个名为Winlogon的桌面中,也就是说,NT至少有一个桌面,就是你登录前看到的那个,(题外话:所以写个虚拟桌面工具,就难不倒你啦)。而Ctrl+Alt+Del对系统而言,也不过就是个热键罢了,只是它被定位到Winlogon桌面中去了,同样,它也必然有一个窗口负责处理这个热键消息的,因此,解决方案就出来,如果我们可找到这个窗口并子类化它,呵呵,不就…。(使用我提供的ShellCode代码,在我的电脑上有枚举出Winlogon桌面的四个窗口,其中有一个名为SAS window的窗口,其它是什么IME啦,等等,猜都能猜出啦,SAS windows应该就是啦)。因为我们要子类化WinLogon桌面中的窗口,别无选择的我们应该使用远程线程了,本文使用的是将所有代码注入到WinLogon进程中去,而不是远程挂接DLL的方式,这样在你开发程序过程中,无需任何第三方文件了。(这应该是你乐意的)
用文字描述,还真会难倒我,我们程序员用代码交流就是最好的语言,我起初的开发语言使用的是Win32ASM,之后有改写成VB版的,下面就列出VB版的代码,毕竟高级语言的代码能被大众所阅读。
下载 syshotkey