1. DLL


// Hook.dll
library Hook;

uses
  Windows, Messages, SysUtils, Classes, Forms;

{$R *.res}

var
  gHHOOK: HHOOK=0;
  gHWND: HWND=0;
  gThreadID: DWORD;
  gPID: DWORD;


// 콜백 함수
function HookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
  Result:=0;
  if Code>=0 then begin
    OutputDebugString('눌러졌거나 떼졌거나');
  end;

  if Result=0 then Result:=CallNextHookEx(gHHOOK, Code, wParam, lParam);
end;



// 실행파일에서 호출할 훅 설치 함수
function StartHook(): Boolean; stdcall;
begin
  if
gHHOOK=0 then begin
    // 후킹하고자 하는 윈도우
    gHWND:=FindWindow('클래스', '캡션');
    gPID:=0;
    gThreadID:=GetWindowThreadProcessID(gHWND, gPID);
    gHHOOK:=SetWindowsHookEx(WH_KEYBOARD, @HookProc, hInstance, gThreadId);
  end;
end;

// 실행파일에서 호출할 훅 해제 함수
function StopHook(): Boolean; stdcall;
begin
  if gHHOOK>0 then begin
    UnHookWindowsHookEx(gHHOOK);
    gHHOOK:=0;
  end;
end;


exports
  StartHook name 'StartHook',
  StopHook name 'StopHook';

begin
end.







2. 실행파일


// 전역변수
var
  ghLib: THandle;
  StartHook, StopHook: function: Boolean; stdcall;


// 후킹용 DLL 로딩, 관련 함수 로딩
procedure TForm1.FormCreate(Sender: TObject);
begin
  ghLib:=LoadLibrary('DLL파일경로');
  StartHook:=GetProcAddress(ghLib, 'StartHook');
  StopHook:=GetProcAddress(ghLib, 'StopHook'); 
end;

// 로딩된 DLL 해제
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FreeLibrary(ghLib);
end;

// 버튼 클릭시 훅 설치
procedure TForm1.Button1Click(Sender: TObject);
begin
  StartHook;
end;


// 버튼 클릭시 훅 해제
procedure TForm1.Button2Click(Sender: TObject);
begin
  StopHook;
end;















Posted by bloodguy

댓글을 달아 주세요

  1. 류제원 2022.01.18 15:39  댓글주소  수정/삭제  댓글쓰기

    감사합니다.
    테스트해보니 잘 되네요.
    근데 질문이 있습니다.
    키보드를 하번 누르면 콜백 함수(HookProc)가 2번 실행되는 것 같습니다.
    함수를 아래와 같이 수정 후 테스트 하니 메세지가 2번 뜹니다.
    function HookProc(Code: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    begin
    Result:=0;
    if Code>=0 then begin
    ShowMessage('눌러졌거나 떼졌거나');
    end;

    if Result=0 then Result:=CallNextHookEx(gHHOOK, Code, wParam, lParam);
    end;

    메세지가 1번만 뜨게 할 수는 없을까요?