文章作者:tabby
原始地址:http://blog.csdn.net/tabby/archive/2007/12/25/1966980.aspx

    在编写程序的过程中,我们有时需要实现屏蔽操作系统一些热键的功能,如(Ctrl+Alt+Delete,Ctrl+Shift+Esc等)。网络上有很多关于这方面的资料,总结了一下,一般有如下两个方法:

    1. 通过加载低级键盘钩子(WH_KEYBOARD_LL)截获大部分的系统热键,并屏蔽它。这个方法比较简单,但有个缺陷,那就是对Ctrl+Alt+Delete没有办法。

    2. 通过远程注入DLL到winlogon进程,修改winlogon桌面下SAS窗口的回调函数,从而捕获该窗口的WM_HOTKEY消息,并屏蔽它,可以实现屏蔽ctrl+delete+alt。这个方法相对复杂,可以解决第一点中存在的问题,但是也有缺陷,那就是除了Ctrl+Alt+Delete外,大多数的其它系统热键,(包括Alt+Tab,Ctrl+Esc及左右两个Windows键)都无法屏蔽。

    所以如果我们的程序需要屏蔽大量的系统热键,就应当将以上两个方法结合起来使用。dll注入有很多好处,包括可以实现对我们所运行进程的隐藏,这非常有用。当我们的进程运行后,屏蔽掉了系统热键,当然不想用户随便在进程管理器里面就kill掉,因此将以上两个方法结合的办法就是把代码通通写到dll里面,然后再一起注入到winlogon进程中。

    对于上面所讲的第二点,注入到winlogon进程,没问题,可以很好的完成功能(网上有很多相关的文章及代码)。但对于第一点,如果在一个GUI程序中加载钩子,也没有问题。但现在加载的对象是winlogin进程,这个进程很特殊,它不是GUI进程,也不在系统应用程序所处的Default桌面下,因此在这个进程中加载钩子,需要注意以下几点:

    1. 在需要注入的DLL代码中的DLL_PROCESS_ATTACH后面开启一个新线程,并在该线程中实现修改SAS窗口回调函数的代码以及设置低级键盘钩子。

    2. 由于钩子所在的线程为非GUI线程,因此,必须在该线程成功设置钩子以后主动接收并分发收到的消息,否则钩子将不会钩到任何消息:
[转]屏蔽系统热键的方法总结MSG msg;
[转]屏蔽系统热键的方法总结
while(GetMessage(&msg, NULL, 00))
}


    3. 由于该线程创建时默认与winlogon同属一个桌面(winlogon桌面),而其它包括explorer.exe在内的GUI程序都处在Default桌面,Windows中规定程序只能获得针对同一桌面上创建的窗口消息。所以,要让该线程能接收到用户在Default桌面下操作所产生的消息,必须在该线程中使用如下代码将它的桌面设置为Default桌面:
[转]屏蔽系统热键的方法总结HDESK hDesk = OpenDesktop("Default",0,FALSE,MAXIMUM_ALLOWED);
[转]屏蔽系统热键的方法总结SetThreadDesktop(hDesk);
[转]屏蔽系统热键的方法总结CloseHandle(hDesk);


    我的程序在解决了以上问题之后,能正确将所编写的DLL注入到winlogon进程,并在DLL加载的时候开启线程,设置钩子,替换SAS窗口回调函数。从而实现屏蔽了我所能想到的所有系统热键。

    附:DLL的完整源码(注入该DLL到winlogon进程的源码大家可以在网上找到)
[转]屏蔽系统热键的方法总结#define _WIN32_WINNT 0x0500 //Use WH_KEYBOARD_LL
[转]屏蔽系统热键的方法总结
[转]屏蔽系统热键的方法总结#include 
<windows.h>
[转]屏蔽系统热键的方法总结#include 
<stdio.h>
[转]屏蔽系统热键的方法总结
[转]屏蔽系统热键的方法总结
//SAS window句柄
[转]屏蔽系统热键的方法总结
HWND hSASWnd = NULL;
[转]屏蔽系统热键的方法总结
//原有SAS window回调函数地址
[转]屏蔽系统热键的方法总结
FARPROC FOldProc = NULL;
[转]屏蔽系统热键的方法总结
//起屏蔽作用的新SAS window回调函数
[转]屏蔽系统热键的方法总结
LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
[转]屏蔽系统热键的方法总结
//枚举所有窗体句柄的回调函数
[转]屏蔽系统热键的方法总结
BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam);
[转]屏蔽系统热键的方法总结
[转]屏蔽系统热键的方法总结
//Dll所创建线程的句柄
[转]屏蔽系统热键的方法总结
HANDLE hThread = NULL;
[转]屏蔽系统热键的方法总结
//Dll所创建线程的ID
[转]屏蔽系统热键的方法总结
DWORD dwThreadId = 0;
[转]屏蔽系统热键的方法总结
//Dll所创建线程的线程函数
[转]屏蔽系统热键的方法总结
DWORD WINAPI ThreadFunc();
[转]屏蔽系统热键的方法总结
[转]屏蔽系统热键的方法总结
//_H钩子句柄
[转]屏蔽系统热键的方法总结
HHOOK hHook = NULL;
[转]屏蔽系统热键的方法总结
//_H低级键盘钩子回调函数
[转]屏蔽系统热键的方法总结
LRESULT CALLBACK KeyboardProc(int,WPARAM,LPARAM);
[转]屏蔽系统热键的方法总结
[转]屏蔽系统热键的方法总结
//对外输出字符串
[转]屏蔽系统热键的方法总结
char szOutput[36];
[转]屏蔽系统热键的方法总结
[转]屏蔽系统热键的方法总结BOOL APIENTRY DllMain(HANDLE hMoudle, DWORD dwReason, LPVOID lpReserved)
}

相关文章: