개요 1. 후킹이란? 후킹의정의.. 2 후킹의종류 2 앞으로...2 2. 후킹프로그램을위한사전지식들 Window 에서 data 입력과정.. 3 DLL ( Dynamic Link Library ).. 4 메시지후킹을위해필요한지식들 5 3. 후킹프로그램제작에필요한 API 함수소개 SetWindowsHookEx 함수 5 UnhookWindowsHookEx 함수 5 CallNextHookEx 함수.5 WH_KEYBOARD 후킹함수 6 4. 본격적인후킹프로그램제작 실행화면.7 중요코드살펴보기...8 5. 참고문헌 1
1. 후킹이란? 후킹의정의 후킹 이란, 다른프로세스의실행경로를가로채는것을말한다. 우선 Message Hooking 을이용한프로그램으로서, 사용자가키보드를통해입력할때이를가로채는기술을이용하여가로챈것을만드는이의임의대로가지고놀수도있다. 이프로그램을특정프로그램의비밀번호나, 상대방이작성하는비밀문서혹은메일의내용이나대화창의내용까지확인가능하므로간단한기술이지만사용자에게는자칫치명적일수도있다. 후킹의종류 후킹은그종류가너무도많다. 후킹을하는대상에따라서메시지후킹, API 후킹, 네이티브 API 후킹, 인터럽트후킹등이있다. 또한디바이스드라이버의필터드라이버도후킹의일종이라고할수있다. 이번에살펴볼영역은메시지후킹이다. 이는 SetWindowsHookEx 로이루어지는단순하면서도문서화된방법으로다른윈도우를후킹하는기법이다. 앞으로 SetWindowsHookEx 를통해서할수있는다양한형태의후킹을시도해볼것이다. 키보드입력을모니터링하는 WH_KEYBOARD 훅, 마우스이벤트를모니터링하는 WH_MOUSE 훅, PostMessage 로전달된내용의처리과정을모니터링하는 WH_GETMESSAGE 훅,SendMessage 의처리과정을모니터링하는 WH_CALLWNDPROC, WH_CALLWNDPROCRET 훅, 입력이벤트를저장하고재생하는 WH_JOURNALRECORD, WH_JOURNALPLAYBACK 훅, 각종윈도우관련이벤트를통지받을수있는 WH_CBT 훅, 훅프로시저의수행과정을모니터링하는 WH_DEBUG 훅에관해서차례로살펴볼것이다. 2
2. 후킹프로그램을위한지식들 Window 에서 data 입력과정 우리가게시판과메모장을연상태에서메모장을활성화시킨상태인경우키보드로입력을하는것들은모두메모장으로간다. 어떻게키보드에입력한것이바로메모장으로가는것을알아야한다. 이를알기위해서는일단키보드나마우스로입력되는것들이무엇으로이루어졌는지를알아야한다. Windows 에서발생하는키보드나마우스의입력들은 Message 로이루어진다키보드나마우스에의해 Message 가발생하게되면이 Message 들은 Message Queue 라고하는곳에쌓이게된다. Queue 의특성상먼저들어온놈이먼저나가게되므로활성화된프로세스에게전달되는것이다. 그렇다면어떻게하면프로세스로가는 Message 를가로채서마음대로가지고놀수있을까? 키보드로입력을했을때 Message 는일단어떠한프로세스에도속하지않고, Message Queue 라는곳에쌓이게된다. 여기서중요한사실은특정프로세스에전달되기전이라는점이다. 이를알기위해서는 Windows 의 3 대요소라고하는 user, GDI, kernel 의관계에대해알아야한다. 이 3 대요소들은실제로 User32.dll, GDI32.dll, Kernel32.dll 으로구현되어있다. [ User32.dll ] 일반적으로사용자의입력을받는역할 [ GDI32.dll ] 어딘가에결과를표현하는역할 [ Kernel32.dll ] 실행을위한 Thread 관리, 메모리관리등을담당하는핵심 Module! 특히! User32.dll 은키보드나마우스로부터입력에대한신호가오면 devicedriver 는프로그래머가다룰수있는 API 로프로그래밍을할수있도록 Message 로바꾸어주는일을하기도한다. 이중에서필요한 message 는 WM_KEYDOWN, WM_KEYUP,WM_CHAR 와같은것들이될것이다. 3
DLL ( Dynamic Link Library ) DLL 은 Dynamic Link Library 의약자로, 동적으로연결되어지는라이브러리를의미한다. 실행시에함수가실행파일에연결되며, 실행파일에는호출할함수의정보만포함되어실제함수의코드는복사되지않으므로 SLL( 정적연결 ) 에비해실행파일의크기가작아진다. 하지만실행파일은함수에대한정보만가지고있을뿐실제의코드를가지고있지는않으므로프로그램실행시에 DLL 이꼭있어야한다. 윈도우에서실행된프로세스들은리눅스에서와마찬가지로보호모드에의해각자독립적인메모리공간을갖게된다. 즉, 가상메모리를체계를사용한다는말이다. 하지만, 가상메모리체계에서어떻게다른프로세스의함수를호출할수있을까? 일단결론은불가능하다는것이다. 리눅스에서와마찬가지로한프로세스내에서다른프로세스의변수나함수에접근하는것은불가능하다. 그래서그에따른우회방법으로바로동적라이브러리를사용하는것이다. 특정한한프로그램이동적라이브러리를등록하면, 그등록된라이브러리가이후에실행되는모든프로세스에적용이된다. 바로이특징을이용하면한프로세스가자신의코드에포함되어있지않은함수를실행할수있게되는것이다. 메시지후킹을위해필요한지식들 1. 동적라이브러리를만들수있어야한다. 2. 동적라이브러리안의함수를가져와사용할수있어야한다. 3. SetWindowsHookEx 함수를사용할수있어야한다. 3. 후킹프로그램제작에필요한 API 함수소개 SetWindowsHookEx SetWindowsHookEx 함수는다른주소공간으로초대받기위한등록작업을하는함수이다. 이함수를사용하면시스템은우리가만든 DLL 을특정상황에다른프로세스의주소공간으로넣어준다. # 함수의원형 HHOOK SetWindowsHookEx(int idhook, HOOKPROC lpfn, HINSTANCE hmod, ORD dwthreadid); # 함수인자값설명 idhook : [ 입력 ] 어떤종류의후킹을할것인지지정한다. 다음표에나타나있는값중하나를선택할수있다. 값의미 SendMessage 프로시저가처리되기직전시점을모니터링 WH_CALLWNDPROC 한다. WH_CALLWNDPROCRET SendMessage가처리되고리턴되는시점을모니터링한다. 윈도우생성 / 소멸 / 활성화등의 CBT 기반프로그램에도움이 WH_CBT 될만한정보를통지받을수있다. WH_DEBUG 다른훅프로시저를디버깅하는훅프로시저 4
WH_FOREGROUNDIDLE WH_GETMESSAGE 현재활성화된윈도우쓰레드가유휴상태가될때를감지한다. PostMessage를통해서메시지가메시지큐에들어가는것을모니터링한다. WH_JOURNALPLAYBACK WH_JOURNALRECORD 를통해서기록된내용을재생한다. WH_JOURNALRECORD 키보드 / 마우스등의입력을기록한다. WH_KEYBOARD 키보드입력내용을모니터링한다. WH_KEYBOARD_LL NT/2000/XP: WH_KEYBOARD보다저수준에서키보드입력내용을모니터링한다. WH_MOUSE 마우스입력내용을모니터링한다. NT/2000/XP: WH_MOUSE보다저수준에서마우스입력내용 WH_MOUSE_LL 을모니터링한다. 다이알로그박스, 메뉴, 스크롤바등에서생성되는입력메 WH_MSGFILTER 시지를모니터링한다. WH_SHELL 쉘애플리케이션에유용한정보를통지받는다. 다이알로그박스, 메뉴, 스크롤바등에서생성되는입력메 WH_SYSMSGFILTER 시지를모니터링한다. 호출한쓰레드와같은데스크탑상에존재하는모든윈도우의메시지를감시한다. lpfn: [ 입력 ] 후킹프로시저의주소를넣어준다. hmod: [ 입력 ] 후킹프로시저가존재하는모듈핸들을넣어준다. dwthreadid: [ 입력 ] 후킹할쓰레드의아이디를넣어준다. 이값으로 0을지정하면시스템내의모든쓰레드를후킹한다. 리턴값 : 훅핸들. 성공한경우에는적절한훅핸들을넘겨준다. 실패한경우에는 NU LL을리턴한다. UnhookWindowsHookEx 후킹을종료하고싶을때에는 UnhookWindowsHookEx 함수를호출하면된다. SetWindowsHookEx 함수를통해리턴받은훅핸들을넣어주면된다. # 함수원형 BOOL UnhookWindowsHookEx(HHOOK hhk); # 함수인자값소개 hhk: [ 입력 ] 앞에서소개한 SetWindowsHookEx를통해서리턴받은훅핸들을넣어준다. 리턴값 : 함수가성공한경우에는 TRUE를, 실패한경우에는 FALSE를리턴한다. 이함수를사용할때에한가지주의할점은 UnhookWindowsHookEx를호출하는순간에다른프로세스로인젝트된 DLL이모두빠지는것은아니라는점이다. 인젝트된 dll이분리되는시점은시스템이결정한다. CallNextHookEx 시스템에존재하는모든프로세스가자신과마찬가지로후킹할권리가있다. 또 5
한이러한후킹시스템이잘운영될수있도록자신의후킹작업이완료된다음에는반드시다음후킹프로시저에게제어권을넘겨주어야한다. CallNextHookEx 함수는다음훅프로시저에게제어권을넘기는작업을한다. 통상적으로이함수는훅프로시저의말미에호출한다. # 함수원형 LRESULT CallNextHookEx(HHOOK hhk, int ncode, WPARAM wparam, LPARAM lparam); # 함수인자소개 hhk: 무시된다.NULL 로지정. ncode, wparam, lparam: 후킹프로시저내부로전달된값을그대로넣어주면된다. 리턴값 : 다음후킹프로시저의리턴값이리턴된다. 보통의경우후킹프로시져는여기서리턴되는값을그대로리턴한다. WH_KEYBOARD 후킹함수메시지를처리하는함수는 CALLBACK 타입으로지정된다. CALLBACK이라는것은이함수가사용자에의해호출되는것이아닌, 프로그램에의해호출된다는의미이다. 사용자가함수를호출하지않고, 프로그램이함수를호출하였다. # 함수원형 LRESULT CALLBACK KeyboardProc(int code, WPARAM wparam, LPARAM lparam); # 함수인자 code: [ 입력] code값이 0보다작은경우는훅프로시저를수행하지않고바로 CallNextHookEx를호출한다음리턴해야한다. 이값은다음과같은의미를지닌다. 코드값의미 HC_ACTION wparam과 lparam이키보드정보를담고있다. wparam과 lparam이키보드정보를담고있다. 이값은메시지 HC_NOREMOVE 큐에서메시지가제거되지않을때설정된다 (PeekMessage의 PM_NOREMOVE 플래그가설정된경우다). wparam: [ 입력 ] 현재키보드입력이벤트를일으킨가상키코드. lparam: [ 입력 ] 키보드입력에대한부가정보. 이정보는비트별로다음과같은의미를가진다. 비트의미 0-15 반복횟수. 16-23 스캔코드. 24 현재눌려진키가확장키인지를의미한다. 확장키인경우 1을, 그렇지않은경우 0을가진다. 25-28 예약됨. 29 ALT키가눌려진상태인경우 1 을, 그렇지않은경우 0을가진다. 6
이전키상태. 키가눌려진경우 1을, 그렇지않은경우 0 30 을가진다. 31 키가눌려진경우 0을, 그렇지않은경우 1을가진다. 리턴값 : code가 0보다작은경우는훅프로시저를수행하지않고 CallNextHookEx 를호출한후결과값을리턴해야한다. 그렇지않은경우에도 CallNextHookEx의호출결과를리턴하는것이좋다. 만약키보드메시지처리를중단하고싶다면 CallNextHookEx를호출하지않고 0이아닌값을리턴하면된다. 4. 본격적인 후킹프로그램제작 [ 그림 ] 실행화면중요코드살펴보기 7
4: code가 0이상인경우와후킹정보를전송할윈도우가존재하는경우에만후킹프로시저를수행한다. 8: 확장키가아니고, alt가눌려지지않은상태에서, 키를누른경우를검사한다. 13 15: 가상키코드를적절한형태의아스키코드로변환한다. Control 키는무시한다. 18-24: 대상윈도우로키메시지를전송한다. WPARAM으로는아스키코드롤, lparam으로는넘어온키정보값을전송한다. 대상윈도우가블록될수있기때문에 SendMessageTimeout을사용한다. 위에보낸메시지를처리하는프로그램쪽의메시지핸들러코드는다음과같다. 6-26: 에디터에추가할내용을 buf 에저장한다. 28-30: 에디터의마지막부분에 buf 를추가한다 5. 참고문헌 " 해킹 / 파괴의광학" - 김성우저 "Programming Applications for Windows (4/E)" Jeffrey Ritcher 저 8