【HOOK技术】键盘钩子
今天对WINDOWS的HOOK技术进行了应用:
主要包括以下:
1,HOOK技术原理的了解;
2,HOOK技术中的常见钩子应用:键盘钩子,鼠标钩子,消息钩子
3,钩子DLL在调用程序EXE中的调试。
首先,HOOK技术中的几个常用函数:
View Code
HHOOK SetWindowsHookEx(
int idHook, // type of hook to install
HOOKPROC lpfn, // address of hook procedure
HINSTANCE hMod, // handle to application instance
DWORD dwThreadId // identity of thread to install hook for
);
View Code
BOOL UnhookWindowsHookEx(
HHOOK hhk // handle to hook procedure to remove
);
其次,工程步骤,第一步,钩子DLL的创建,源代码如下:
View Code
// KeyHook.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include <fstream>
using namespace std;
#define DLLEXPORT extern "C" __declspec(dllimport)
//变量
HHOOK hhkHook =NULL; //定义钩子句柄
HINSTANCE hInstance =NULL; //程序实例
fstream chOut; //输出文件
//导出函数
DLLEXPORT int add(int a, int b); //测试
DLLEXPORT BOOL InstallHook(); //安装钩子
DLLEXPORT BOOL UnInstallHook(); //卸载钩子
//定义函数
LRESULT CALLBACK KeyboardProc(
int code, // hook code
WPARAM wParam, // virtual-key code
LPARAM lParam // keystroke-message information
);
//入口
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hInstance = (HINSTANCE)hModule;
return TRUE;
}
//钩子的实现部分
LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam )
{
if (code == HC_ACTION)
{
//获取当前的按键 wParam
char ch[1] = {0};
ch[0] = wParam;
BOOL bKeyUp = FALSE; //键是否按下或弹起
BOOL bKeyAlt = FALSE; //ALT键
//检查按键的键 lParam
//判断ALT键
if (lParam & 0x20000000)
{
bKeyAlt =TRUE;
}
if (bKeyAlt)
{
//当前按下ALT
::MessageBox(0,"ALT","KeyBoardLocked",MB_OK);
}
//判断键是否按下或弹起
if (lParam & 0x80000000)
{
bKeyUp = TRUE;
}
if (bKeyUp)
{
//当前按键已经弹起
//写文件
chOut.write(ch, 1);
chOut.flush();
}
}
// if(!::FindWindow(0,"KeyBoardLocked"))
// {
// ::MessageBox(0,"键盘已经锁定!!!","KeyBoardLocked",MB_OK);
// }
// return CallNextHookEx(hhkHook, code, wParam, lParam);
return 1; //不调用 CallNextHookEx 将会屏蔽掉键盘
}
BOOL InstallHook()
{
chOut.open("c:\\keyhook.log", ios::app | ios::out);
hhkHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, hInstance, 0);
if (hhkHook != NULL)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL UnInstallHook()
{
if (chOut.is_open)
{
chOut.close();
}
return UnhookWindowsHookEx(hhkHook);
}
第二步,钩子调用程序,源代码如下:
View Code
//变量定义
HMODULE m_hDll = NULL;
typedef BOOL (*INSPROC)(void);
typedef BOOL (*UNINSPROC)(void);
在一个对话框中,添加了两个按钮
View Code
void CKeyHookTestDlg::OnButton1()
{
// TODO: Add your control notification handler code here
m_hDll = LoadLibrary("KeyHook.dll");
if(m_hDll==NULL)
{
MessageBox("fail");
}
else
{
INSPROC instproc;
instproc = (INSPROC)GetProcAddress(m_hDll, "InstallHook");
BOOL bResult = instproc();
}
}
void CKeyHookTestDlg::OnButton2()
{
// TODO: Add your control notification handler code here
UNINSPROC uninstproc;
uninstproc = (UNINSPROC)GetProcAddress(m_hDll, "UnInstallHook");
BOOL bResult = uninstproc();
::FreeLibrary(m_hDll);
m_hDll = NULL;
}
再次,就是调用程序对钩子DLL进行调试。
1,创建工作区间时,DLL工程和EXE工程在一个工作区间;
2,设置EXE工程为"Set as active project";
3,将DLL工程编译后生成的LIB文件,加载到EXE工程中,方法有2个
#pragma comment(lib, "XXX.lib") 或者在"project"->"setting"->"link": "Object/library modules:"设定
4,以上就可以进行调试了。
在这里一个小技巧提示:
1,将DLL工程的dll生成路径设置为EXE工程exe生成路径;
2,将将EXE工程调用lib文件所在路径设置为DLL工程的dll生成路径。