반응형

Microsoft에서는 프로세스간의 주고 받는 메세지를 후킹할 수 있는 함수를 제공한다.
바 로 SetWindowsHookEx()함수이다. 이 함수를 통해 DLL을 특정 프로세스나 모든 프로세스에 Injection할 수 있다.그리고 User-mode(ring 3)에서 동작하는 Keylogger들 대부분이 이 함수를 사용하여 구현된다.(SetWindowsHookEx()함수를 통해 후킹(Hooking)을 할 경우 전역 후킹이 간단하므로 많이 사용한다.)

먼저 SetWindowsHookEx()함수의 원형부터 알아보자.
(MSDN에 있는 내용이다.)

HHOOK SetWindowsHookEx(
    int idHook,
    HOOKPROC lpfn,
    HINSTANCE hMod,
    DWORD dwThreadId
);

첫번째 파라메터인 idHook 변수는 후킹 하고자 하는 메세지의 ID라고 할 수 있다. WH_GETMESSAGE, WH_KEYBOARD 등 다양한 메세지가 있다.(MSDN 참조)
idHook 파라메터에 지정된 값의 이벤트(메세지)가 발생할 경우 훅 프로시저(lpfb 파라메터에 설정된)가 동작하게 된다. 훅 프로시저는 Injection할 DLL(앞으로 Injected.dll이라 부르겠다)에 지정되어 있어야한다.

/* Injected.dll */
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
 /* 원하는 코드 삽입 */
 return CallNextHookEx(0, nCode, wParam, lParam);
};

마 지막에 CallNextHookEx()함수를 호출한 이유는 훅 체인에 있는 다른 훅 프로시저가 해당 메세지를 사용할 수도 있기때문이다. 예를들면 키보드메세지를 후킹하여 Keylogger를 만들었다고 하면 해당 메세지를 후킹 후 로깅을 하고 CallNextHookEx()함수를 통해 처리를 하지 않고 그냥 끝내 버린다면 들통나버릴것이다.

두번째 파라메터는 lpfn이다. 이 파라메터에는 Injected.dll에 지정된  훅 프로시저의 주소값을 지정한다.만약 IdHook에 WH_KEYBOARD를 지정하여 후킹 할경우 해당 훅 프로시저는 KeyboardProc이다. 주소 값을 지정해줘야하는데 하드코딩하여 지정해 줄 수 있지만 LoadLibrary()함수와 GetProcAddress를 이용하여 Injected.dll의 훅 프로시저의 주소를 구할 수 있다.

/* Injector.c */
HMODULE hDll;
unsigned long KeyboardProcAddr;

hDll = LoadLibrary("injected.dll");
KeyboardProcAddr = GetProcAddress(hDll, "KeyboardProc");

다음으로 세번째 파라메터인 hMod를 보자. hMod는 DLL의 핸들(Handle)을 지정해야한다.여기에선 Injected.dll의 핸들을 지정해주면 된다.
이미 Injector.c에서 LoadLibrary("Injected.dll"); 통해 핸들을 얻었으므로 hDll변수를 사용하면 된다.

네 번째 파라메터 dwThreadId는 후킹할 프로세스 즉 Injected.dll을 삽입할 스레드(Thread)의 ID이다. PID라고 하며 해당 파라메터에 0을 지정하면 모든 스레드에 훅(Hook)을 한다는 의미로 전역 훅을 할 수 있다. 특정 스레드에 Injection을 하려고 한다면 "작업관리자"를 통해 PID를 얻어 하드코딩하거나 아래와 같은 방법으로 PID를 얻어 사용할 수 있다.

/* 전역 훅 */
SetWindowsHookEx(WH_KEYBOARD, KeyboardProcAddr, hDll, 0)

/* 지역 훅*/
SetWindowsHookEx(WH_KEYBOARD, KeyboardProcAddr, hDll, GetCurrentThreadID());

dwThreadId 값을 얻기 위한 함수는 많다.

+ Recent posts