후킹에는 여러가지 종류가 있다. 그중에서 가장 대표적인 전역 키보드 후킹방법을 설명하겠다. 우선 전체적인 순서는 다음과 같다.
(1) 훅 프로시저 DLL파일을 만든다.
(2) DLL을 로드시킬 프로그램을 작성한다.
www.winapi.co.kr에서 KeyBeep예제를 visual studio 2008에서 돌아가도록 변경한 것이다. 프로젝트 생성부터 차근차근 해보겠다. 먼저 visual studio 2008을 실행시킨다.
프로젝트를 생성한다. [File]-[New]-[Project...]
위치는 C:\HookEx\로 하고, Solution Name은 KeyHook로 한다. KeyHook 솔루션안에 KeyHookDll 프로젝트와 KeyHookApp 프로젝트, 두 개의 프로젝트를 만들것이다. 우선, KeyHookDll 프로젝트를 생성한다. template은 Win32Project로 한다.
Application type는 DLL로 하고, Additional options는 아무것도 체크하지 않는다.
Header Files 폴더에 stdafx.h, targetver.h 파일이, Source Files 폴더에 dllmain.cpp, KeyHookDll.cpp, stdafx.cpp 파일이 생성되었다. KeyHookDll.cpp 파일에 다음과 같이 작성한다.
#include "stdafx.h"
HINSTANCE gModule=NULL;
HHOOK hKeyHook=NULL;
LRESULT CALLBACK KeyHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode>=0) {
SendMessage(hWndBeeper,WM_USER+1,wParam,lParam);
}
return CallNextHookEx(hKeyHook,nCode,wParam,lParam);
}
extern "C" __declspec(dllexport) void InstallHook(HWND hWnd)
{
hKeyHook=SetWindowsHookEx(WH_KEYBOARD_LL,KeyHookProc,gModule,NULL);
}
extern "C" __declspec(dllexport) void UninstallHook()
{
UnhookWindowsHookEx(hKeyHook);
}
dllmain.cpp 파일에는 다음과 같이 작성한다.
#include "stdafx.h" extern HINSTANCE gModule; BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: gModule = hModule; break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
KeyHookApp프로젝트에 KeyHookApp.cpp파일을 생성하여 다음과 같이 소스를 작성한다.
#include < windows.h >
#include < tchar.h >
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=_T("KeyHookApp");
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst=hInstance;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=(WNDPROC)WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=NULL;
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,600,130,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
hWndMain=hWnd;
while(GetMessage(&Message,0,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
extern "C" __declspec(dllimport) void InstallHook(HWND hWnd);
extern "C" __declspec(dllimport) void UninstallHook();
typedef void (* INSTALL_HOOK)(HWND);
typedef void (* UNINSTALL_HOOK)(void);
INSTALL_HOOK installHook;
UNINSTALL_HOOK uninstallHook;
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static HINSTANCE hinstDLL = NULL;
static TCHAR msg1[128];
static TCHAR msg2[128];
static TCHAR msg3[128];
KBDLLHOOKSTRUCT *kb;
switch(iMessage) {
case WM_CREATE:
hinstDLL=LoadLibrary(_T("..\\Release\\KeyHookDll.dll"));
installHook=(INSTALL_HOOK)GetProcAddress(hinstDLL,"InstallHook");
uninstallHook=(UNINSTALL_HOOK)GetProcAddress(hinstDLL,"UninstallHook");
_stprintf_s(msg1,128,_T("hinstDLL:%d, installHook:%p, uninstallHook:%p"),hinstDLL,installHook,uninstallHook);
installHook(hWnd);
return 0;
case WM_USER+1:
BYTE kb_state[256];
kb =( KBDLLHOOKSTRUCT*)lParam;
TCHAR key_state[64];
switch(wParam){
case WM_KEYDOWN:
_stprintf_s(key_state,64,_T("%s"),_T("WM_KEYDOWN"));break;
case WM_KEYUP:
_stprintf_s(key_state,64,_T("%s"),_T("WM_KEYUP"));break;
case WM_SYSKEYDOWN:
_stprintf_s(key_state,64,_T("%s"),_T("WM_SYSKEYDOWN"));break;
case WM_SYSKEYUP:
_stprintf_s(key_state,64,_T("%s"),_T("WM_SYSKEYUP"));break;
default: _stprintf_s(key_state,64,_T("%s"),_T("Unexpected KeyState"));
}
_stprintf_s(msg2,128,_T("Key Message : %s, lParam : %x "),key_state,lParam);
_stprintf_s(msg2,128,_T("입력된 키:%d, lParam : %x "),wParam,lParam);
_stprintf_s(msg3,128,_T("vkCode : %c(%d), scanCode : %d"),kb->vkCode,kb->vkCode,kb->scanCode);
InvalidateRect(hWnd,NULL,TRUE);
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
TextOut(hdc,10,10,msg1,lstrlen(msg1));
TextOut(hdc,10,30,msg2,lstrlen(msg2));
TextOut(hdc,10,50,msg3,lstrlen(msg3));
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
uninstallHook();
FreeLibrary(hinstDLL);
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
이제 해당 프로젝트를 Build한 후 C:\HookEx\Release폴더에 KeyHookDll.dll과 KeyHookApp.exe가 있는지 확인하고, KeyHookApp.exe를 실행시킨다.
'c/c++' 카테고리의 다른 글
quick sort (0) | 2011.09.08 |
---|---|
키보드 전역 후킹 (0) | 2011.08.29 |
Console API 모음 (MSDN) (0) | 2011.07.14 |
Console API를 이용하여 더블버퍼링 (0) | 2011.07.14 |
쓰레드를 이용한 행렬 곱연산 (0) | 2010.09.16 |