이것저것/My_Work

[MFC] - 키보드 후킹

우담바라 2009. 3. 12. 15:07


 
※ 훅킹(Hooking) : 이미 작성 되어 있는 코드의 ㅣ특정 지점을 가로 채서 동작 방식에 변화를 주는 일체의 기술
                       - 인터럽트 가로채기 기법, 메지시 가로채기 등등


※ 메시지를 가로챌 범위에 따라 지역 훅, 시스템 전역 훅으로 구분
  - 지역 훅(Thread Specific)        : 특정 스레드에서 발생하는 메시지들만 전달 받음
  - 시스템 전역 훅(System Wide)  : 시스템의 모든 스레드에서 발생하는 메시지를 받고자 할때는 전역 훅을 설치


※ 훅 프로시저 : 훅 체인에 등록되어 메시지를 감시하는 함수
   원형 Ex) 
                 LRESULT CALLBACK KeyboardProc(int code, WPARM wParam, LPARAM lParam);
인수의값은 전달 받는 메시지타입에 따라 달라 질 수 있다.


※ 훅 프로시저 설치
   HHOOK SetWindowsHookEx( int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);
     - idhook : 설치하고자 하는 훅의 타입을 지정(ex: WH_KEYBOARD 등)
     - lpfn : 훅 프로시저의 번지 ( cf : 전역 후킹을 하고자할 때에는 반드시 분리 된 DLL에 있어야 함, 이때 hMod는 DLL 핸들)
     - hMod : 훅 프로시저를 가진 인스턴스 핸들
     - dwThreadId : 훅 프로시저가 감시할 스레드 ID
       ( 값이 '0' 이면, 시스템의 모든 스레드에서 발생하는 메시자가 훅 프로시저로 전달)
    cf ) 지역 훅 : SetWindowsHookEx(idHook, lpfn, NULL, GetCurrentThreadId());
          전역 훅 : SetWindowsHookEx(idHook, lpfn, hDll, 0);
 
      리턴 값 : 훅 프로시저를 설치 성공 했을 경우 => HHOOK 핸들 리턴(차후 해제시에 사용)
                   훅 프로시저를 설치 실패 했을 경우 => NULL


※ 훅 프로시저 해제
   BOOL UnhookWindowsHookEx(HHOOK hhk);

※ 훅 체인의 다음 훅 프로시저에게 메시지를 전달 하는 함수
    LRESULT CallNextHookEx(HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam);




※  MFC Dialog 환경에서 지역 훅킹 테스트 ※

1. 아래 변수를 전역변수로 선언 및 함수 추가
HHOOK g_hook=NULL;

BOOL CPOPUP::SetHook()
{
if(g_hook != NULL)
UnHook();
g_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, (HINSTANCE)theApp.m_hInstance, NULL);

return TRUE;
}

BOOL CPOPUP::UnHook()
{
if(g_hook != NULL )
{
UnhookWindowsHookEx(g_hook);
}
return TRUE;
}


2. ' BOOL xxxxx::OnInitDialog() ' 함수에다가  훅 프로시저를 등록하는 함수를 추가
SetHook();
cf) 종료 루틴에 UnHook() 추가



3.훅프로시저 작성
  ( 아직 정확한 이유를 모르겠으나, 일반적인 함수 처럼 헤더파일에 프로시저를 선언하고, 메인 소스 파일에 해당 프로시저를 
코딩하니 에러가 발생하고 정상 동작하지 않았다. 임기응변으로, 헤더파일의 선언부분을 제거하고, OnInitDialog() 함수위에 
이 코드를 작성하니 정상 동작 하는 것을 확인하였다. 계속 테스트 중)

 LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
...
세부 코드 작성
...
return CallNextHookEx(g_hook, wParam, lParam);
}

4. Tip !!
키보드 값을 후킹 할 경우(메시지의 종류에 따라 내용은 달라짐),
 wParam => 발생한 키보드의 값
 lParam  => 발생한 이벤트의 정보
바이트 번호    키값        내용
     --------------------------------------------------------------------
             0        Transition Status    Key Down 1
                            Key Up     0
     --------------------------------------------------------------------
             1       Previous Key State 이전에 어떤키가
                               눌려졌는가에대한 값
      --------------------------------------------------------------------
             2       Context Code    Alt키가 눌려지면 1
                                          아니면 0
      --------------------------------------------------------------------
           3-6      Extend Key Flag      확장 키보드에서 키가 눌려지면 1
                                                                                   아니면 0
      --------------------------------------------------------------------
           8-15     OEM Scan Code  키보드 스캔코드
      --------------------------------------------------------------------
          16-31                Repeat Count     킷값의 반복횟수