델파이로 갈구리질을 하려면 꼭 봐야 하는 강좌(검색해도 이게 제일 확실하고 잘 설명된 자료이다.)가 있습니다.
바로 델파이 고수 중 한분이신 민성기님께서 다가오는 21 세기를 바라보며 쓰신 주옥같은 델파이 후킹 강좌입니다.
지금은 델파이 코리아가 문을 닫고 델마당 강좌란에 퍼온 자료가 남아있어(여러 블로그에서 펌질이 되어 검색하면 다 같은 글이 나올겁니다.) 링크를 겁니다.
민성기도 하는 후킹 3화 링크 : http://www.delmadang.com/community/bbs_view.asp?bbsNo=3&bbsCat=42&indx=196917
이 강좌에서 한가지… 운 없으면(컴파일러가 삽질할 경우) 문제가 생길 수 있는 코드를 정정하고자 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
{ 셀 갈구리질 } function MyShellHook(Code : Integer; wParam : WPARAM; lParam : LPARAM) : LongInt; stdcall; var Buff : array [0..255] of Char; s : String; begin { 파일에 저장된 훅핸들을 읽어온다. } if HShellHook = 0 then ReadData; { 윈도우의 생성과 소멸만 괴롭힌다. 자세한 내용은 도움말을 참조할 것. } if (code = HSHELL_WINDOWCREATED) or (code = HSHELL_WINDOWDESTROYED) then begin { 윈도우의 클래스명을 읽어온다. Code값이 위의 두개의 값일 경우, wParam은 윈도우의 핸들값이 된다. } GetClassName(wParam, Buff, SizeOf(Buff)); { 클래스명이 노트패드라면 메시지박스 보여주기. } if Buff = 'Notepad' then begin if (code = HSHELL_WINDOWCREATED) then S := '메모장이 실행되는구만요~!' else S := '메모장이 끝났구만요~!'; MessageBox(0,PChar(S),'Hook Message',0); end; end; { 다음 훅체인 호출 } Result := CallNextHookEx(HShellHook, Code, wParam, lParam); end; |
제가 작성했던 코드에서는 이전 포스트의 프로세스 아이디로 윈도우 핸들을 얻는 코드를 통해 윈도우 핸들은 얻은 뒤 후킹 DLL 로 핸들 값을 넘겨 위 코드를 이용해 해당 프로그램이 죽는지 사는지 감시하도록 했습니다. (아래 코드 첨부)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
function MyShellHook(Code : Integer; wParam : WPARAM; lParam : LPARAM) : LongInt; stdcall; var Buff : array [0..255] of Char; clsName : array [0..255] of Char; begin if HookData.ApplicationHandle = 0 then // HookData.ApplicationHandle 은 제가 만든 훅 핸들 보관용 구조체입니다. ReadData; if (code = HSHELL_WINDOWCREATED) or (code = HSHELL_WINDOWDESTROYED) then begin GetClassName(wParam, Buff, SizeOf(Buff)); GetClassName(HookData.hApp, clsName, SizeOf(clsName)); // HookData.hApp 에는 감시할 프로그램의 핸들이 들어있습니다. if strPAS(Buff) = strPAS(clsName) then begin if (code = HSHELL_WINDOWCREATED) then begin SendMessage(HookData.ShellHandle, WM_USER + 4, 0, 1); end else begin SendMessage(HookData.ShellHandle, WM_USER + 4, 0, 0); end; end; end; { 다음 훅체인 호출 } Result := CallNextHookEx(HookData.ApplicationHandle, Code, wParam, lParam); end; |
이 코드에서는 클래스명 비교부분에 strPAS 함수를 사용하여 비교하도록 하였습니다.
민성기님 코드의 경우 비교문 우측에 ‘Notepad’ 라는 String 문자열이 있어 좌측 Char 배열을 컴파일러가 비교를 위해 자동 형변환을 하도록 했지만 위 코드에서는 비교문 양쪽 모두 Char 배열이 되어 문자열로 비교하지 않게 됩니다.
strPAS를 통해 String 으로 변환하여 비교하면 문제없이 처리가 됩니다.