Windows Hooking의 경우에는 Windows message queue에 대한 이해가 좀 필요하다.
Windows는 Windows Message Queue를 통해서 각각의 Message를 전달하고, 그 Message에 따라 각기 다른 Action을 행한다.
WM_PAINT의 경우에는 화면을 그리라는 Message가 되고, WM_MOUSE의 경우에는 Mouse의 움직임에 따라 발생되는 Windows
Message이다.
Hooking은 이런 WIndows Message Queue에 Hook을 걸어서, 원래 처리되어야지 되는 함수가 아닌, 사용자 지정 Method에서
처리하게 하는 방법이다. 이것을 이용하면 Ctrl+Alt+Del의 기능도 막아버릴 수 있으며, 마우스를 움직여서 다른 동작을 하는 것도
막는 것이 가능하다. 또한 Mouse나 Keyboard의 모든 기록들을 저장할 수 있기 때문에 Windows에서 Cracking을 하는 경우에
왕왕 사용되는 방법이다.
먼저, WIN32 함수인 SetWindowsHookEx 함수를 DllImport시켜서 가지고 온다. 필요한 Native method의 선언은 다음과 같다.
여기에서 구성된 Hooking method들은 다음과 같다.
Windows는 Windows Message Queue를 통해서 각각의 Message를 전달하고, 그 Message에 따라 각기 다른 Action을 행한다.
WM_PAINT의 경우에는 화면을 그리라는 Message가 되고, WM_MOUSE의 경우에는 Mouse의 움직임에 따라 발생되는 Windows
Message이다.
Hooking은 이런 WIndows Message Queue에 Hook을 걸어서, 원래 처리되어야지 되는 함수가 아닌, 사용자 지정 Method에서
처리하게 하는 방법이다. 이것을 이용하면 Ctrl+Alt+Del의 기능도 막아버릴 수 있으며, 마우스를 움직여서 다른 동작을 하는 것도
막는 것이 가능하다. 또한 Mouse나 Keyboard의 모든 기록들을 저장할 수 있기 때문에 Windows에서 Cracking을 하는 경우에
왕왕 사용되는 방법이다.
먼저, WIN32 함수인 SetWindowsHookEx 함수를 DllImport시켜서 가지고 온다. 필요한 Native method의 선언은 다음과 같다.
001.
internal
delegate
int
HookProc(
int
nCode, IntPtr wParam, IntPtr lParam);
002.
003.
internal
class
NativeMethods
004.
{
005.
/// <summary>
006.
/// Hooking WIN32 API
007.
/// dwThreadId가 0인 경우에는 전역 hook
008.
/// 특정 handler안에서 Hooking을 하는 경우에는 Handle 값을 넣어준다.
009.
/// </summary>
010.
/// <param name="hookType">
011.
/// <param name="callback">Hooking을 한 이후에 받을 method의 주소값 delegate된 method를 넣어줄수 있다.
012.
/// <param name="hMod">
013.
/// <param name="dwThreadId">
014.
/// <returns></returns>
015.
[DllImport(
"user32.dll"
, CharSet = CharSet.Auto)]
016.
public
static
extern
IntPtr SetWindowsHookEx(HookType hookType, HookProc callback, IntPtr hMod,
uint
dwThreadId);
017.
018.
[DllImport(
"user32.dll"
, CharSet = CharSet.Auto)]
019.
public
static
extern
bool
UnhookWindowsHookEx(IntPtr hhk);
020.
021.
[DllImport(
"user32.dll"
, CharSet = CharSet.Auto)]
022.
public
static
extern
int
CallNextHookEx(IntPtr hhk,
int
nCode, IntPtr wParam, IntPtr lParam);
023.
}
024.
025.
internal
static
class
HookCodes
026.
{
027.
public
const
int
HC_ACTION = 0;
028.
public
const
int
HC_GETNEXT = 1;
029.
public
const
int
HC_SKIP = 2;
030.
public
const
int
HC_NOREMOVE = 3;
031.
public
const
int
HC_NOREM = HC_NOREMOVE;
032.
public
const
int
HC_SYSMODALON = 4;
033.
public
const
int
HC_SYSMODALOFF = 5;
034.
}
035.
036.
internal
enum
HookType
037.
{
038.
WH_KEYBOARD = 2,
039.
WH_MOUSE = 7,
040.
WH_KEYBOARD_LL = 13,
041.
WH_MOUSE_LL = 14
042.
}
043.
044.
[StructLayout(LayoutKind.Sequential)]
045.
internal
class
POINT
046.
{
047.
public
int
x;
048.
public
int
y;
049.
}
050.
051.
/// <summary>
052.
/// The MSLLHOOKSTRUCT structure contains information about a low-level keyboard
053.
/// input event.
054.
/// </summary>
055.
[StructLayout(LayoutKind.Sequential)]
056.
internal
struct
MOUSEHOOKSTRUCT
057.
{
058.
public
POINT pt;
// The x and y coordinates in screen coordinates
059.
public
int
hwnd;
// Handle to the window that'll receive the mouse message
060.
public
int
wHitTestCode;
061.
public
int
dwExtraInfo;
062.
}
063.
064.
/// <summary>
065.
/// The MOUSEHOOKSTRUCT structure contains information about a mouse event passed
066.
/// to a WH_MOUSE hook procedure, MouseProc.
067.
/// </summary>
068.
[StructLayout(LayoutKind.Sequential)]
069.
internal
struct
MSLLHOOKSTRUCT
070.
{
071.
public
POINT pt;
// The x and y coordinates in screen coordinates.
072.
public
int
mouseData;
// The mouse wheel and button info.
073.
public
int
flags;
074.
public
int
time;
// Specifies the time stamp for this message.
075.
public
IntPtr dwExtraInfo;
076.
}
077.
078.
internal
enum
MouseMessage
079.
{
080.
WM_MOUSEMOVE = 0x0200,
081.
WM_LBUTTONDOWN = 0x0201,
082.
WM_LBUTTONUP = 0x0202,
083.
WM_LBUTTONDBLCLK = 0x0203,
084.
WM_RBUTTONDOWN = 0x0204,
085.
WM_RBUTTONUP = 0x0205,
086.
WM_RBUTTONDBLCLK = 0x0206,
087.
WM_MBUTTONDOWN = 0x0207,
088.
WM_MBUTTONUP = 0x0208,
089.
WM_MBUTTONDBLCLK = 0x0209,
090.
091.
WM_MOUSEWHEEL = 0x020A,
092.
WM_MOUSEHWHEEL = 0x020E,
093.
094.
WM_NCMOUSEMOVE = 0x00A0,
095.
WM_NCLBUTTONDOWN = 0x00A1,
096.
WM_NCLBUTTONUP = 0x00A2,
097.
WM_NCLBUTTONDBLCLK = 0x00A3,
098.
WM_NCRBUTTONDOWN = 0x00A4,
099.
WM_NCRBUTTONUP = 0x00A5,
100.
WM_NCRBUTTONDBLCLK = 0x00A6,
101.
WM_NCMBUTTONDOWN = 0x00A7,
102.
WM_NCMBUTTONUP = 0x00A8,
103.
WM_NCMBUTTONDBLCLK = 0x00A9
104.
}
105.
106.
/// <summary>
107.
/// The structure contains information about a low-level keyboard input event.
108.
/// </summary>
109.
[StructLayout(LayoutKind.Sequential)]
110.
internal
struct
KBDLLHOOKSTRUCT
111.
{
112.
public
int
vkCode;
// Specifies a virtual-key code
113.
public
int
scanCode;
// Specifies a hardware scan code for the key
114.
public
int
flags;
115.
public
int
time;
// Specifies the time stamp for this message
116.
public
int
dwExtraInfo;
117.
}
118.
119.
internal
enum
KeyboardMessage
120.
{
121.
WM_KEYDOWN = 0x0100,
122.
WM_KEYUP = 0x0101,
123.
WM_SYSKEYDOWN = 0x0104,
124.
WM_SYSKEYUP = 0x0105
125.
}
여기에서 구성된 Hooking method들은 다음과 같다.
01.
private
bool
SetGlobalLLMouseHook()
02.
{
03.
// Create an instance of HookProc.
04.
globalLLMouseHookCallback =
new
HookProc(
this
.LowLevelMouseProc);
05.
06.
hGlobalLLMouseHook = NativeMethods.SetWindowsHookEx(
07.
HookType.WH_MOUSE_LL,
// Must be LL for the global hook
08.
globalLLMouseHookCallback,
09.
// Get the handle of the current module
10.
Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
11.
// The hook procedure is associated with all existing threads running
12.
// in the same desktop as the calling thread.
13.
0);
14.
return
hGlobalLLMouseHook != IntPtr.Zero;
15.
}
16.
17.
public
int
LowLevelMouseProc(
int
nCode, IntPtr wParam, IntPtr lParam)
18.
{
19.
if
(nCode >= 0)
20.
{
21.
// Marshal the MSLLHOOKSTRUCT data from the callback lParam
22.
MSLLHOOKSTRUCT mouseLLHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam,
typeof
(MSLLHOOKSTRUCT));
23.
24.
// Get the mouse WM from the wParam parameter
25.
MouseMessage wmMouse = (MouseMessage)wParam;
26.
27.
// Display the current mouse coordinates and the message
28.
String log = String.Format(
"X = {0} Y = {1} ({2})\r\n"
, mouseLLHookStruct.pt.x, mouseLLHookStruct.pt.y, wmMouse);
29.
tbLog.AppendText(log);
30.
}
31.
32.
// Pass the hook information to the next hook procedure in chain
33.
return
NativeMethods.CallNextHookEx(hGlobalLLMouseHook, nCode, wParam, lParam);
34.
}