본문 바로가기
Application/Delphi Lecture

window Hook

by 현이빈이 2008. 7. 24.
반응형
안녕하세요.. 마당쇱니다.

후킹의 강력함을 모두 이용하려면 시스템에 있는 모든 윈도우에 대해서
훅을 걸어서 써야겠지만 간혹 자신의 윈도우 안에서만 후킹을 해야
할 경우가 있습니다.

( 'KeyPreView := true'로는 해결이 안되고 모든 키에 대해서 처리를
 해야 할 경우라든지, 폼위에서(Caption이나 Menu위에서) 움직이는
 마우스의 모든상태를 처리해야 한다든지 하는 경우이겠지요.. )

두 경우의 차이라면 시스템 전반에 훅을 걸 경우에는 DLL에서 걸어야
하지만 후자의 경우에는 DLL이 필요없이 프로젝트 내에서 간단하게
훅을 설치할수 있다는 것입니다.

이때 SetWindowsHookEx에 넣어주어야 할 매개변수가 달라지게 되지요..
가령 후자의 경우에는 ( 내 윈도우 안에만 훅을 설치할때 )

       hMouseHook := SetWindowsHookEx(
                               WH_MOUSE,
                               @MouseHookProc,
                               0,                    <--
                               GetCurrentThreadID    <--
                               );

세번째 인자와 네번째 인자가 DLL에서와 달라지게 됩니다.
위의 경우는 마우스 훅을 걸때의 상황이지요..
가령 키보드 훅을 걸어야 할경우에는 WH_MOUSE대신 WH_KEYBOARD이
들어가게 되구 물론 키보드 훅용 콜백함수를 쓰셔야 할겁니다.
다들 아시겠지만 SetWindowsHookEx의 두번째 인자로 들어가는
콜백함수의 형태는 어떤 후킹이든 동일합니다.
즉 한가지 후킹에 성공하셨다면 다른 종류의 훅도 얼마든지 설치할
수 있습니다.

( 다만 사용하려는 훅에대해 완전히 알고 있어야 사용할 수 있다는 게
 문제이지만... 대부분의 문제는 lParam을 어떻게 이용하느냐 하는
 것인데, windows.pas를 보시면 어느정도 감이 잡힐것 같습니다.
 11495 line부터 각종 훅에 대한 lParam의 구조체 타입이 나와
 있습니다. 물론 각각의 쓰임새는 공부를 하셔야 겠지요..           )


DLL내부에서 즉 시스템 전역에 훅을 설치하실때는 세번째와 네번째
인자를

       hMouseHook := SetWindowsHookEx(
                               WH_MOUSE,
                               @MouseHookProc,
                               HInstance,             <--
                               0                      <--
                               );

로 바꾸고 DLL로 컴파일 하면 됩니다.

결국 내 어플리케이션 안에서 후킹을 걸어서 성공했다면 그 소스를
그대로 DLL로 컴파일 하면 시스템 전반에 걸쳐서 훅을 설치하는 것은
쉽게 이루어 진다는 얘깁니다.


애구 얘기가 엉뚱하게 흘렀네요..

다음은 하나의 윈도우(폼)에 마우스 훅을 걸어서 그 결과를 Caption에
표시하는 예제입니다. 정말로 간단하지요?

다른 훅의 이용도 크게 다르지 않답니다. 다만 헬프가 넘 어렵게 되어
있구, 주위에서 참고로 할 자료를 찾기가 쉽지 않고,
( * 참고로 MSDN에서 Hooking으로 검색을 하면 목록의 제목만 하나씩
 보는데만도 2시간이 넘게 걸릴만큼 Hooking에 대한 자료가 많더군요.. )
Hooking이라는 것에 대한 내면 깊숙한 곳에서 우러나오는 일종의 공포심이
결합하여 시도하기도 전에 포기하는 것 같습니다.

Message Hooking은 윈도우 프로그래밍에서 가장 강력한 테크닉 중
하나입니다.
그러나 Hooking의 구현은 전혀 어렵지 않습니다.

여담으로 API Hooking이라는 테크닉이 있죠..
Message-Hooking이 시스템에 떠도는 메시지들을 가로채는 것이라면
API-Hooking은 시스템에서 어떤 API함수가 불려지면 그걸 가로채는
것이랍니다.
요즘 영한사전류에서 마우스만 갖다대도 글자를 인식하는데 쓰이는
고급기법이죠..
API-Hooking의 강력함에 비하면 Message-Hooking은 새발의 피라고
할 정도입니다.
심병탁님이 API-Hooking를 구현하셨다지요? 참으로 가공할 내공의
소유자가 아닐수 없습니다.
}


unit unit1
.......
.......

implementation

{$R *.DFM}
var hMouseHook : integer = -1;

function MouseHookProc(Code: Integer; wParam: WPARAM;
   lParam: LPARAM): Longint; stdcall;
Begin
    If (Code >= 0) Then
    Begin
       with PMouseHookStruct( lParam )^ do
           Form1.Caption := Format( '[X : %d, Y : %d] [HitTestCode : %d]',
               [ pt.x, pt.y, wHitTestCode ] );
       Form1.Caption := Form1.Caption +
           Format( ' [ wParam : %d]', [ wParam ] );
    End;

    Result := CallNextHookEx(hMouseHook, Code, wParam, lParam);
End;

procedure SetMouseHook( flag : boolean );
Begin
   if not flag then
   begin
       if hMouseHook < 0 then exit;
       UnHookWindowsHookEx(hMouseHook);
       hMouseHook := -1;
   end else
       hMouseHook := SetWindowsHookEx(
                               WH_Mouse,
                               @MouseHookProc,
                               0,
                               GetCurrentThreadID
                               );
End;

procedure TForm1.Button1Click(Sender: TObject);
begin
   SetMouseHook( hMouseHook < 0 );
end;

end.


출처 : 델마당
반응형