훅(Hook)
훅은 원하는 정보를 낚아채기 위해 사용하는 도구로, 특정 정보를 엿보거나 가로채기 위해 사용됨. 확장된 의미로 시스템이나 프로그램의 동작 흐름에 개입하여 필요한 정보를 얻거나, 데이터를 조작하는 목적에서도 사용됨
예시
- 어떤 집단에 검문 절차가 3단계로 구성되어 있었는데, 스파이가 검문 절차 하나를 추가해 4단계로 만듦
- 집단 내부의 사람들은 별다른 의심 없이 이 절차를 따르게 되고, 스파이는 이를 통해 필요한 정보를 쉽게 얻을 수 있게 됨
- 이 과정에서 스파이가 추가한 검문 초소 설치 작업을 ‘훅을 건다’ 또는 ‘훅을 설치한다’고 표현함
후킹(Hooking)
후킹은 훅을 통해 실제로 정보를 엿보고 조작하는 행위 자체를 의미함. 훅이 설치된 후 후킹을 통해 중간에서 정보를 가로채거나 데이터를 변경할 수 있음
메시지 훅
메시지 훅은 시스템의 메시지 흐름에 개입하여 중간에서 메시지를 엿보거나 필요 시 조작하는 방식임.
위에서처럼 키보드 메시지 훅이 설치되었으면 OS 메시지 큐와 응용프로그램 메시지 큐 사이에 설치된 훅 체인에 있는 키보드 메시지 훅들이 응용 프로그램보다 먼저 메시지 확인 가능 or 메시지 변경 or 메시지 가로채 아래로 못가도록 함
SetWindowsHookEx()
메시지 훅은 SetWindowsHookEx() API로 구현이 가능함
HHOOK SetWindowsHookEx(
int idHook, //hook type
HOOKPROC lpfn, //hook procedure
HINSTANCE hMod, //위 hook procedure가 속해 있는 DLL 핸들
DWORD dwThreadID //hook을 걸고 싶은 thread의 ID
);
키보드 메시지 후킹 실습
키보드 메시지 후킹은 특정 DLL을 통해 키보드 입력 이벤트를 중간에서 가로채고 엿보는 방법임. 이 실습에서는 KeyHook.dll 파일과 HookMain.exe 프로그램을 사용하여 키보드 메시지 후킹을 설정함
- KeyHook.dll: 훅 프로시저가 정의된 DLL 파일로, 키보드 메시지를 감지하고 가로채는 기능을 수행함
- HookMain.exe: KeyHook.dll을 로딩하고 키보드 훅을 설치하는 프로그램으로, 이 파일이 DLL을 로드한 후 훅을 설정함
동작 과정
- HookMain.exe가 실행되면서 KeyHook.dll을 로딩함
- SetWindowsHookEx() API를 호출하여 키보드 메시지 훅을 설치함
- 키 입력 이벤트가 발생할 때마다 운영체제는 KeyHook.dll을 키 입력 발생 프로세스에 강제로 로딩하여 이벤트를 훅 체인에 연결된 훅 프로시저에서 먼저 처리하도록 함
SetWindowsHookEx()
메시지 훅은 SetWindowsHookEx() API로 구현이 가능함
HHOOK SetWindowsHookEx(
int idHook, // 훅 타입 (WH_KEYBOARD_LL 등)
HOOKPROC lpfn, // 훅 프로시저
HINSTANCE hMod, // 훅 프로시저가 속한 DLL 핸들
DWORD dwThreadID // 훅을 걸고 싶은 스레드의 ID (0일 경우 전체 적용)
);
메시지 훅과 후킹 동작 원리
키보드 메시지 훅이 설정되면, OS 메시지 큐와 애플리케이션 메시지 큐 사이에 설치된 훅 체인이 동작함. 이 체인에 의해 키보드 메시지가 애플리케이션에 전달되기 전에 훅 프로시저에서 먼저 확인, 수정, 또는 차단할 수 있음. 메시지 훅은 애플리케이션보다 먼저 메시지를 확인할 수 있으며, 필요시 메시지를 변경하거나 전달을 차단함으로써 후킹을 수행함
후킹(Hooking)
후킹은 훅을 통해 실제로 정보를 엿보거나 조작하는 행위임. 예를 들어 메시지 후킹은 메시지를 중간에서 가로채거나 조작하는 것을 의미하며, 키보드 메시지 후킹은 키 입력을 중간에서 가로채 키 입력 데이터를 엿보거나 기록하는 것을 의미함
https://github.com/reversecore/book/tree/master/%EC%8B%A4%EC%8A%B5%EC%98%88%EC%A0%9C/03_DLL_Injection/21_Windows_%EB%A9%94%EC%8B%9C%EC%A7%80_%ED%9B%84%ED%82%B9/bin
실습 코드는 위에서 다운로드 받으면 된다
실습 방법
1. HookMain.exe 실행 - 키보드 훅 설치
2. Notepad.exe 실행
: 사용자의 키도 입력 무시함. 프로세스 익스플로러로 노트패드의 프로세스 보면 KeyHook.dll 로딩된 것 확인 가능하다.
3. HookMain.exe 종료 - 키보드 훅 제거
HookMain.exe파일의 소스코드
// HookMain.cpp
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#define DEF_DLL_NAME "KeyHook.dll"
#define DEF_H00KSTART “HookStart"
#define DEF_H00KST0P "HookStop"
typedef void(*PFN_H00KSTART)();
typedef void(*PFN_H00KST0P)();
void main() {
HMODULE hDU = NULL;
PFN_H00KSTART HookStart = NULL;
PFNiHOOKSTOP HookStop = NULL;
char ch = 0;
// KeyHook.dU 로딩
hDU = LoadLibraryA(DEF_DLL_NAME);
// export 함수주소얻기
HookStart =(PFN_H00KSTART)GetProcAddress(hDll, DEF_H00KSTART);
HookStop =(PFN_H00KST0P)GetProcAddress(hDU, DEF_H00KST0P);
// 후킹 시작
HookStart();
// 사용자가 ‘q'를입력할때까지 대기
printf("press 'q' to quit!\n");
while( _getch() != 'q' ) ;
// 후킹 종료
HookStop();
// KeyHook.dll 언로딩
FreeLibrary(hDU);
}
Keyhook.dll파일 로딩해 HookStart()함수를 호출하면 후킹 시작
HookStop()함수를 호출하면 후킹이 종료
DLL 소스코드이다
// KeyHook.cpp
#include "stdio.h"
#include "windows.h"
#define DEF_PROCESS_NAME "notepad.exe"
HINSTANCE g_hlnstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID IpvReserved)
{
switch( dwReason )
{
case DLL_PROCESS_ATTACH:
g_hlnstance = hinstDLL;
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM 1Param)
{
char szPath[MAX_PATH] = {0,};
char *p = NULL;
if( nCode >= 0 )
{
// bit 31: 0 = key press, 1 = key release
if( ! (IParam & 0x80000000) ) // 키보드가눌렀다 떨어질 때
{
GetModuleFileNameA(NULL, szPath, MAX_PATH);
p = strrchr(szPath, AV);
// 현재 프로세스이름을비교해서 만약 notepad.exe라면,
// 메시지는 응용 프로그램 (혹은 다음 훅)으로 전달되지 않음
if( !_stricmp(p + 1, DEF_PROCESS_NAME) )
return 1;
}
}
// 일반적인경우에는 CallNextHookEx()를호출하여
// 응용 프로그램 (혹은 다음 훅)으로 메시지를 전달함
return CallNextHookEx(ghHook, nCode, wParam, IParam);
}
#ifdef _cplusplus
extern "C" {
#endif
_declspec(dllexport) void HookStart()
{
ghHook = SetWindowsHookEx(WHKEYBOARD, KeyboardProc, g_hlnstance, 0);
}
_declspec(dllexport) void HookStop()
{
if( ghHook )
{
UnhookWindowsHookEx(ghHook);
g_hHook = NULL;
}
}
#ifdef _cplusplus
}
#endif
익스포트 함수인 HookStart()함수 호출 시 SetWindowsHookEx()에 의해 키모드 훅 체인에 KeyboardProc() 추가
'공부해요 > 리버싱_핵심원리' 카테고리의 다른 글
23. DLL 인젝션 (1) | 2024.11.04 |
---|---|
22. 악의적인 목적으로 사용되는 키로거 (3) | 2024.11.04 |
20. 인라인 패치 실습 (0) | 2024.10.16 |
19. UPack 디버깅 - OEP 찾기 (0) | 2024.10.16 |
18. UPack PE 헤더 상세 분석 (0) | 2024.10.16 |