Introduction

이번 시간에는 전역 후킹(Global Hooking)에 대해서 알아보도록 하겠습니다.

C/C++ 에서는 Win32 API를 이용하여 손쉽게 전역 후킹을 할 수 있습니다. 물론 .NET 에서도 Win32 API의 DLL 파일을 Import 하여 후킹이 가능합니다. 하지만 약간의 문제가 있습니다. 지역 후킹이 아닌 전역 후킹에서는 CallBack Procedure 를 DLL 파일로 만들어야 한다는 것이지요. 이런 이유로 .NET 에서는 전역 후킹이 안된다는 이야기가 많이 있습니다. 저 역시 초기에 이런 문제에 부딪혔습니다.

Microsoft 에서 전역 후킹에 대해서 찾아보니 심지어 이런 내용이 있었습니다.

물론 이 이야기가 맞습니다. .NET 에서 전역 후킹(Global Hooking)을 하려면, 이 DLL 을 C/C++ 과 같이 네이트브 코드로 만들고, 이것을 호출하는 방법 밖엔 없습니다.

하지만, 마우스와 키보드에 대한 전역 후킹은 .NET 에서 가능합니다. 다시 말하자면, 마우스와 키보드 이외에는 전역후킹이 불가능 하다는 이야기가 되겠습니다 :) 이 방식은 WH_MOUSE_LL, WH_KEYBOARD_LL 만 지원한다는 이야기입니다.

즉, WH_MOUSE 나 WH_KEYBOARD 는 지원하지 않습니다. 저 역시 예전엔 이 idHook 을 사용하고 왜 안될까 고민했던 것 같습니다.
코드는 다음과 같이 매우 간단합니다. 가독성을 위해서 partial 로 나누어 놓았습니다. 오해 없으시기 바랍니다.


Example

[Win32 API Wrapper]


internal static class Win32   
{   
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]   
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);      
  
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]   
    public static extern bool UnhookWindowsHookEx(int idHook);      
  
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]   
    public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);   
  
    public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);   
}




[구조체 / idHook]


public static partial class MouseHook  
{  
    [StructLayout(LayoutKind.Sequential)] 
    public class POINT  
    {  
        public int x;  
        public int y;  
    }     

    [StructLayout(LayoutKind.Sequential)]  
    public class MouseHookStruct  
    {  
        public POINT point;  
        public int hwnd;  
        public int wHitTestCode;  
        public int dwExtraInfo;  
    }  

    public const int WH_MOUSE_LL = 14;  
} 



[Start Hook]


public static partial class MouseHook  
{  
    private static int hookHandle = 0;     

    public static void StartHook() {  
        if(hookHandle != 0) { return; }  
        hookHandle = Win32.SetWindowsHookEx(WH_MOUSE_LL, CallBack, Marshal.GetHINSTANCE(  
                    Assembly.GetExecutingAssembly().GetModules()[0]), 0);  
    }  

    public static void StopHook() {  
        Win32.UnhookWindowsHookEx(hookHandle);  
    }  

    public static int CallBack(int nCode, IntPtr wParam, IntPtr lParam) {  
        MouseHookStruct mouseInput = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));  
        System.Diagnostics.Debug.WriteLine(mouseInput.pt.x + " : " + mouseInput.pt.y);  
        return Win32.CallNextHookEx(hookHandle, nCode, wParam, lParam);  
    }  
} 




Epilogue

이 포스팅을 포함하여 몇몇 포스팅을 보다가 이런 생각을 하시는 분들이 계실것 같습니다.

'어?! 이거 어디서 본 포스팅 같은데? 어디서 긁어온 것 아냐? 저작권 침해다.'

맞는 말이기도 하고 틀린 말이기도 합니다.
긁어온 것은 맞으나, 저작권 침해는 아니라는 것이죠.
왜냐면 원본글 역시 제가 작성했던 글이거든요 :)

사실 이 글은 http://witstudio.net 에서 제가 작성했던 글을 다시 옮겨온 것입니다. :)
오해 없으시기 바랍니다.


  • Mont Blanc Kuglepen 2014.03.07 12:12

    예어The coaches also want to congratulate all the players for their hard work and dedication this season. Blog. The United States, the third most populous country globally, accounts for about 4.6% of the world's population. And as my brother likes to say, I have street cred.

    The first place of course is the nursery. Crashplan is a crossplattform application which supports Windows, Mac, Linux, and 던가