본문 바로가기
해킹/API HOOKING

[펌]후킹(hooking)방법중 메시지 후킹과 API 후킹의 차이점이 뭔가요? 그리고 원리가?

by 베리베리 2009. 8. 19.
먼저 메시지후킹과 API후킹의 차이는 운영체제(윈도우즈)에서 지원하느냐, 지원하지 않느냐의 차이가 있습니다. 메시지후킹은 윈도우즈에서 API레벨(함수레벨)로 지원해주는 반면, API후킹은 운영체제에서 지원하는것이 아니라 사용자(프로그램을 만드는 측)가 직접 특정 함수(API)가 호출되는 부분을 감시해서 호출되려는 순간 자신이 만들어 놓은 임의의 함수로 호출위치를 바꿔버리는 매커니즘 입니다.

일단 개념은 위와 같으며 조금 디테일하게 들어가겠습니다.
먼저 메시지훅에 대해서 설명드리자면,
윈도우즈는 메시지 구동방식이라는 말을 윈도우즈 프로그래밍을 공부하신 분이라면 알고계실 겁니다. 이 뜻은 우리가 마우스를 움직였을때나, 키보드를 누르는 행동, 프로그램을 종료하는 시기.. 이런것들이 미리 정해진 시간에 수행되는 것들이 아니라 사용자가 그 이벤트를 언제 발생하느냐에 따라서 윈도우즈가 이 이벤트를 감지하고 그에 따른 적절한 행동을 수행하는 방식으로, 정적(static) 프로그램이라기 보단 동적(dynamic)으로 프로그램이 진행됩니다.

이런 동적으로 발생되는 이벤트(신호)를 적절하게 처리하기 위해서 윈도우즈는 메시지 구동방식을 사용하게 되는데, 이 메시지가 처리되는 방식은 다음과 같습니다.

윈도우즈는 메시지큐 라는 특별한 공간을 비워두고 사용자가 이벤트(메시지)를 발생시키는 행동을 취하면 그 메시지가 어떤 메시지인지를 메시지큐의 입구에 차곡차곡 쌓아두게 됩니다. 그리고 반대편에서는 그 메시지큐의 출구에서 메시지정보를 하나하나씩 꺼내, 이를 적절히 변환하고 해당 윈도우로 메시지를 보내주게 됩니다(메시지를 처리하는 것이 아니라 단지 보내주기만 합니다).

이런 윈도우즈의 매커니즘으로 인해 우리는 메시지 핸들러 방식으로 윈도우 프로그램을 작성하게 됩니다. 메시지 훅은 이러한 메시지가 윈도우로 보내어 질때.. 혹은 메시지큐 안의 메시지를.. 혹은 메시지큐에 메시지가 들어가기 전(NT계열에서만 지원)에 그 메시지를 먼저 가로채는 일련의 행동을 말합니다.

윈도우즈는 SetWindowsHookEx, UnhookWindowsHookEx, CallNextHookEx 등 메시지를 가로채기 위해 필요한 일련의 연산을 묶어놓은 API함수를 사용자가 사용할 수 있도록 제공해 줌으로서, 우리는 간단히 이미 만들어진 기능을 호출해 간단히 메시지를 조작할 수 있습니다. 관련 사용법은 MSDN이나 기타 프로그래밍 커뮤니티에서 찾아보시길 바랍니다.

그리고 API훅은 메시지훅이 메시지를 가로채는 거라면 API훅은 말그대로 API의 호출을 가로채는것을 말합니다. 간단히 메시지훅과 API훅을 구분해 보자면, 메시지훅은 마우스가 움직일때(WM_MOVEMOUSE), 키보드가 눌렸을때(WM_KEYDOWN), 화면이 갱신될때(WM_PAINT)등, 메시지 이벤트에 대해서 훅을 수행하지만, API훅은 ShowWindow API(윈도우를 화면에 보여주는 함수)가 호출될때.. 혹은 CreateWindow(윈도우를 생성하는 함수)가 호출될때 등, Windows의 API함수가 호출될때 API의 루틴이 있는 주소로 이동하지 않고 자신이 원하는 주소로 이동하는 일련의 행동을 말합니다.

대게 윈도우즈 시스템에서 EXE파일, DLL파일, SYS파일등은 그 파일 자체에 윈도우즈의 어떠한 API를 import하는지(사용하는지)의 정보를 담고 있게 됩니다. 이때 import정보엔 import하고 있는 함수의 이름과 주소, 그리고 Ordinal정보를 담고있는 테이블(영역)이 있는데 API훅은 이 import 테이블에 있는 정보중 가로채고자 하는 함수의 주소부분을 바꿔채는 매커니즘 입니다.

예를들어 어떠한 target.exe프로그램에서 ShowWindow를 import하고 있다고 하고 그 주소는 0x7000000 이라고 가정을 해봅시다. 우리는 따로 hook.exe프로그램을 제작해 놓고 이 프로그램이 하는일은 target.exe가 실행이 될때, import테이블을 조사해 우리가 훅하고자 하는 함수의 정보가 기록된 위치를 찾아내고, 해당함수가 호출이 될때 이동되는 주소가 기록되어 있는 정보를 우리가 원하는 주소로 이동하도록 바꿔버립니다. 여기서는 ShowWindow(0x7000000)이라고 했으니 0x7000000의 주소, 혹은 ShowWindow라는 함수가 import-table영역에서 발견되면 우리가 원하는 주소로 바꿔버리면 되겠죠? 우리가 HookWindow함수를 만들어놓고 ShowWindow에 해당하는 주소를 HookWindow에 해당하는 주소로 바꿔버리면 target.exe프로그램이 실행되는 동안에 ShowWindow를 호출하려 한다면 우리가 만든 함수인 HookWindow를 호출하게 될것입니다.

간단히 정리하자면
"import-table에서 해당 API의 정보가 기록된 부분을 찾아 우리가 원하는 주소로 바꿔치기 해버리는 기술"
이라고 정리를 하면 되겠군요.

API 후킹은 이렇게 멋진 기능이지만 꾀나 프로그래밍하기 까다롭습니다. 먼저 윈도우즈에서 사용하는 가상주소관리(Virtual Address Management)는 기본적으로 각각의 프로세스는 상대 프로세스에 대한 접근(access)를 허용하지 않기때문에 윈도우즈의 메모리 매커니즘에 대해 이해가 선행되지 않는다면 API후킹은 좀 어렵다고 봅니다. 그리고 윈도우즈가 사용하는 고유포멧인 PE포멧에 대해서도 알아야 합니다. 프로그램 코드가 컴파일되면 각각의 함수위치는 어디에 위치하게 되는지.. 데이터는 어느 섹션에 위치하게 되는지.. 등등을 알아야 하고, 가장 중요한것은 DLL이 윈도우즈에서 어떻게 사용되는지의 이해가 필수적입니다.

왜냐하면 API 후킹은 대게 자신의 프로세스가 아닌 상대방 프로세스를 조작할 경우엔 Dll-injection 기법(특정DLL을 특정 프로세스에 load하는 기법)과 같이 사용되기 때문입니다.

어디 한곳에 정리해두고 작성한 문서가 아니라 글이 두서가 없습니다. 피곤함에 정리한거라 글작성에 대한 열정보다 자고싶다는 열정이 앞섰나 봅니다

댓글