近來一直在自學Windows Hook相關的知識,已經嘗試多種注入方式。尤其對消息鉤子方式很感興趣,因為看到Spy++能夠截獲系統中絕大多數應用的消息流,就很想知道它的工作原理,打算制作屬于自己的Spy++。
消息鉤子簡言之就是Windows處理消息的一個平臺,用戶可以在此平臺獲取或過濾所需應用的消息(例如某鼠標位置,鍵盤擊下等),這些被監控的消息都會在目標窗口處理函數之前被截獲。系統在拿到消息后會問你:這是不是你想要的消息?如果是,則恭喜你,你可以在回調函數里做相應操作了。消息鉤子主要由三部分組成:鉤子安裝函數鉤子回調函數鉤子卸載函數HHOOK WINAPI SetWindowsHookEx(_In_ int idHook,_In_ HOOKPROC lpfn,_In_ HINSTANCE hMod,_In_ DWORD dwThreadId
);SetWindowsHookExx1
HHOOK WINAPI SetWindowsHookEx(2 ?
_In_ ?
int idHook,3 ?
_In_ ?
HOOKPROC lpfn,4 ?
_In_ ?
HINSTANCE hMod,5 ?
_In_ ?
DWORD dwThreadId6);參數1-idHook:這個函數代表了你要安裝鉤子的種類,比如鍵盤鉤子,鼠標鉤子,窗體鉤子等等。以下我列了一張表,結合MSDN供大家參考。
| 鉤子類型 | 釋義 |
| WH_CALLWNDPROC(4) | 此類型的鉤子,可以讓你監控發送到窗口過程的消息。
|
| WH_CALLWNDPROCRET(12) | 此類型的鉤子,可以讓你監控到已被目標窗體處理的消息。 |
| WH_CBT(5) | 此類型的鉤子十分繁雜,可監控的消息很多。例如窗口創立,銷毀,最大最小化,移動等。 |
WH_DEBUG(9)
| 此類型鉤子,可以決定能否讓系統調用與其他Hook關聯的子程序。說白了,這就是個調試鉤子,可以用來調試其他安裝好的鉤子。 |
| WH_FOREGROUNDIDLE(11) | 此類型鉤子,可以在前臺線程空閑時執行低優先級的任務,當然了,線程空閑是由系統決定的。 |
| WH_GETMESSAGE(3) | 此類型的鉤子,可以截獲消息隊列中的所有消息。例如GetMessage,PeekMessage函數的返回消息。 |
WH_JOURNALPLAYBACK (1) | 此類型的鉤子,可以插入消息到消息隊列。除此,這個鉤子可以記錄下來連續的鼠標及鍵盤事件,以用來回放。 |
WH_JOURNALRECORD(0)
| 此類型的鉤子,用以監視發往系統隊列的輸入事件,這是個全局鉤子,不可用于線程。 |
| WH_KEYBOARD(2) | 此類型的鉤子,顧名思義,用于監視鍵盤擊下,彈起消息。通過GetMessage,PeekMessage函數返回。(請注意,根據我的實驗結果,這個鉤子僅對本程序有效) |
WH_KEYBOARD_LL(13)
| 此類型的鉤子,是底層設備鉤子,除具備WH_KEYBOARD的功能,可以記錄所有的鍵盤輸入,包括熱鍵。 |
WH_MOUSE(7)
| 此類型的鉤子,顧名思義,用于監視輸入到消息隊列的鼠標消息。通過GetMessage,PeekMessage函數返回。(只能獲得鉤子所在模塊的消息)
|
WH_MOUSE_LL(14)
| 此類型的鉤子,是底層設備鉤子,除具備WH_KEYBOARD的功能,可以記錄系統中所有的鼠標消息。
|
WH_MSGFILTER(-1)
| 此類型的鉤子,可以監視由對話框、消息框、菜單條、或滾動條中的輸入事件引發的消息。
|
WH_SHELL(10)
| 此類型的鉤子,可以監視各種Shell事件信息,例如應用程序的啟動,關閉等等。 |
WH_SYSMSGFILTER(6)
| 此類型的鉤子,是強化版的WH_MSGFILTER,可以監視系統中所有應用程序的此類消息。 |
參數2-HOOKPROC lpfn:此參數是鉤子回調函數的地址,對應上述不同種類的鉤子類型,其鉤子回調函數原型基本是一致的。請見下(需要注意的是,wParam和lParam針對不同類型的鉤子,傳遞參數所代表意義不同,因種類繁多,請各位查閱MSDN):LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam
)
{// process event...return CallNextHookEx(NULL, nCode, wParam, lParam);
}121
LRESULT CALLBACK HookProc(2 ?
int nCode, 3 ?
WPARAM wParam, 4 ?
LPARAM lParam5)6{7 ? 8 ? ...910 ?
return CallNextHookEx(
NULL,
nCode,
wParam,
lParam);11}nCode:int,此參數指示Hook例程是否需要處理消息,如果nCode為HC_ACTION,則需要處理;如果小于0,不予處理,須調用CallNextHookEx函數返回。wParam與lParam:針對不同類型的鉤子,代表的意義不同,但總體是針對當前類型鉤子的消息。后面以例子做出驗證。參數3-HINSTANCE hMod:包含Hook例程的Dll所在模塊基址。參數4-DWORD dwThreadId:所要注入程序的主線程ID。如果此項填0,則代表鉤子為系統鉤子,基本所有在運行的進程都會被注入。如果此項指定線程ID,則是有針對性的線程鉤子。返回值:HHOOK類型的句柄。
請見上。BOOL WINAPI UnhookWindowsHookEx(_In_ HHOOK hhk
);1
BOOL WINAPI UnhookWindowsHookEx(2 ?
_In_ ?
HHOOK hhk3);參數:SetWindowsHookEx的返回值。
首先我們要明確下,鉤子從安裝到回顯的流程編寫Dll,在Dll中實現我們所需要的鉤子回調函數及安裝函數。Dll中除了要編寫與鉤子相關的處理函數,也要編寫與顯示程序通信的模塊,以便驗證鉤子消息的正確性。Dll需要導出鉤子啟動函數與卸載函數。回顯程序處理已安裝鉤子發送的信息。至此,框架已經明了,我們分步拆解完成這個小項目。(整體代碼請見附件,VS2013編譯)typedef struct COMMPACK
{int nType;//Hook類型WPARAM wParam;//參數1LPARAM lParam;//參數2TCHAR szMsg[16];//額外的字符串信息,取決于具體鉤子
} COMMPACK, *PCOMMPACK;//與回顯程序通訊的包結構typedef struct HOOKSTC
{int nType;//Hook類型HOOKPROC hkproc;//Hook回調HHOOK hhook;//Hook句柄
} HOOKSTC, *PHOOKSTC;HOOKSTC m_Array4Hooks[NHOOKNUMS] = { 0 };//創建多鉤子類型的結構體數組enum { M_CALLWNDPROC, M_CBT, M_DEBUG, M_GETMESSAGE, M_KEYBOARD, M_MOUSE, M_MSGFILTER };//鉤子類型枚舉enum { IDHCBT_ACTIVATE, IDHCBT_CLICKSKIPPED, IDHCBT_CREATEWND, IDHCBT_DESTROYWND, IDHCBT_KEYSKIPPED,IDHCBT_MINMAX, IDHCBT_MOVESIZE, IDHCBT_QS, IDHCBT_SETFOCUS, IDHCBT_SYSCOMMAND, IDUnknown
};//CBT鉤子的消息群221
typedef struct COMMPACK2{3
int nType;4
WPARAM wParam;5
LPARAM lParam;6
TCHAR szMsg[
16];7}
COMMPACK,
*PCOMMPACK;89
typedef struct HOOKSTC10{11
int nType;12
HOOKPROC hkproc;13
HHOOK hhook;14}
HOOKSTC,
*PHOOKSTC;1516
HOOKSTC m_Array4Hooks[
NHOOKNUMS]
= {
0 };1718
enum {
M_CALLWNDPROC,
M_CBT,
M_DEBUG,
M_GETMESSAGE,
M_KEYBOARD,
M_MOUSE,
M_MSGFILTER };1920
enum {
IDHCBT_ACTIVATE,
IDHCBT_CLICKSKIPPED,
IDHCBT_CREATEWND,
IDHCBT_DESTROYWND,
IDHCBT_KEYSKIPPED,21
IDHCBT_MINMAX,
IDHCBT_MOVESIZE,
IDHCBT_QS,
IDHCBT_SETFOCUS,
IDHCBT_SYSCOMMAND,
IDUnknown22};
LRESULT WINAPI m_CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{if (nCode < 0)return CallNextHookEx(m_Array4Hooks[M_CBT].hhook, nCode, wParam, lParam);CHAR szCode[16] = { 0 };PCOMMPACK pCP = new COMMPACK;pCP->nType = M_CBT;switch (nCode){case HCBT_ACTIVATE://系統要激活一個窗口pCP->lParam = (LPARAM)IDHCBT_ACTIVATE;pCP->wParam = IDHCBT_ACTIVATE;break;case HCBT_CLICKSKIPPED://系統已經從系統消息隊列中刪除了一個鼠標消息pCP->lParam = (LPARAM)IDHCBT_CLICKSKIPPED;pCP->wParam = IDHCBT_CLICKSKIPPED;break;case HCBT_CREATEWND://一個窗口將要被創建pCP->lParam = (LPARAM)IDHCBT_CREATEWND;pCP->wParam = IDHCBT_CREATEWND;break;case HCBT_DESTROYWND://一個窗口將要被銷毀pCP->lParam = (LPARAM)IDHCBT_DESTROYWND;pCP->wParam = IDHCBT_DESTROYWND;break;case HCBT_KEYSKIPPED://系統已從系統消息隊列中刪除了一個鍵盤消息pCP->lParam = (LPARAM)IDHCBT_KEYSKIPPED;pCP->wParam = IDHCBT_KEYSKIPPED;break;case HCBT_MINMAX://一個窗口將被最小化或最大化pCP->lParam = (LPARAM)IDHCBT_MINMAX;pCP->wParam = IDHCBT_MINMAX;break;case HCBT_MOVESIZE://一個窗口將被移動或改變尺寸pCP->lParam = (LPARAM)IDHCBT_MOVESIZE;pCP->wParam = IDHCBT_MOVESIZE;break;case HCBT_QS://系統已從系統消息隊列中取到一個WM_QUEUESYNC 消息pCP->lParam = (LPARAM)IDHCBT_QS;pCP->wParam = IDHCBT_QS;break;case HCBT_SETFOCUS://一個窗口將要獲得鍵盤焦點pCP->lParam = (LPARAM)IDHCBT_SETFOCUS;pCP->wParam = IDHCBT_SETFOCUS;break;case HCBT_SYSCOMMAND://一個系統命令將被執行pCP->lParam = (LPARAM)IDHCBT_SYSCOMMAND;pCP->wParam = IDHCBT_SYSCOMMAND;break;default://其他pCP->lParam = (LPARAM)IDUnknown;pCP->wParam = IDUnknown;break;}m_Com(pCP);//與回顯程序通信delete pCP;return CallNextHookEx(m_Array4Hooks[M_CBT].hhook, nCode, wParam, lParam);
}561571
LRESULT WINAPI m_CBTProc(
int nCode,
WPARAM wParam,
LPARAM lParam)2{3
if (
nCode < 0)
return CallNextHookEx(
m_Array4Hooks[
M_CBT].
hhook,
nCode,
wParam,
lParam);4
CHAR szCode[
16]
= {
0 };5
PCOMMPACK pCP = new COMMPACK;6
pCP->nType = M_CBT;7
switch (
nCode)8
{9
case HCBT_ACTIVATE:10
pCP->lParam = (
LPARAM)
IDHCBT_ACTIVATE;11
pCP->wParam = IDHCBT_ACTIVATE;12
break;13
case HCBT_CLICKSKIPPED:14
pCP->lParam = (
LPARAM)
IDHCBT_CLICKSKIPPED;15
pCP->wParam = IDHCBT_CLICKSKIPPED;16
break;17
case HCBT_CREATEWND:18
pCP->lParam = (
LPARAM)
IDHCBT_CREATEWND;19
pCP->wParam = IDHCBT_CREATEWND;20
break;21
case HCBT_DESTROYWND:22
pCP->lParam = (
LPARAM)
IDHCBT_DESTROYWND;23
pCP->wParam = IDHCBT_DESTROYWND;24
break;25
case HCBT_KEYSKIPPED:26
pCP->lParam = (
LPARAM)
IDHCBT_KEYSKIPPED;27
pCP->wParam = IDHCBT_KEYSKIPPED;28
break;29
case HCBT_MINMAX:30
pCP->lParam = (
LPARAM)
IDHCBT_MINMAX;31
pCP->wParam = IDHCBT_MINMAX;32
break;33
case HCBT_MOVESIZE:34
pCP->lParam = (
LPARAM)
IDHCBT_MOVESIZE;35
pCP->wParam = IDHCBT_MOVESIZE;36
break;37
case HCBT_QS:38
pCP->lParam = (
LPARAM)
IDHCBT_QS;39
pCP->wParam = IDHCBT_QS;40
break;41
case HCBT_SETFOCUS:42
pCP->lParam = (
LPARAM)
IDHCBT_SETFOCUS;43
pCP->wParam = IDHCBT_SETFOCUS;44
break;45
case HCBT_SYSCOMMAND:46
pCP->lParam = (
LPARAM)
IDHCBT_SYSCOMMAND;47
pCP->wParam = IDHCBT_SYSCOMMAND;48
break;49
default:50
pCP->lParam = (
LPARAM)
IDUnknown;51
pCP->wParam = IDUnknown;52
break;53
}54
m_Com(
pCP);55
delete pCP;56
return CallNextHookEx(
m_Array4Hooks[
M_CBT].
hhook,
nCode,
wParam,
lParam);57}
LRESULT WINAPI m_KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{if ((nCode < 0 || !((DWORD)lParam & 0x40000000)))return CallNextHookEx(m_Array4Hooks[M_KEYBOARD].hhook, nCode, wParam, lParam);PCOMMPACK pCP = new COMMPACK;pCP->lParam = lParam;pCP->wParam = wParam;//這個值就是按鍵的VirtualKeypCP->nType = M_KEYBOARD;m_Com(pCP);//與回顯程序通訊delete pCP;return CallNextHookEx(m_Array4Hooks[M_KEYBOARD].hhook, nCode, wParam, lParam);
}111
LRESULT WINAPI m_KeyboardProc(
int nCode,
WPARAM wParam,
LPARAM lParam)2{3
if ((
nCode < 0 || !((
DWORD)
lParam & 0x40000000)))
return CallNextHookEx(
m_Array4Hooks[
M_KEYBOARD].
hhook,
nCode,
wParam,
lParam);4
PCOMMPACK pCP = new COMMPACK;5
pCP->lParam = lParam;6
pCP->wParam = wParam;7
pCP->nType = M_KEYBOARD;8
m_Com(
pCP);9
delete pCP;10
return CallNextHookEx(
m_Array4Hooks[
M_KEYBOARD].
hhook,
nCode,
wParam,
lParam);11}
void m_Com(PCOMMPACK& pCP, int addi)
{hTarget = ::FindWindow(NULL, L"HookApp");//尋找回顯程序窗口標題COPYDATASTRUCT stcCDS;//采用WM_COPYDATA消息方式進程間通訊stcCDS.cbData = sizeof(COMMPACK);stcCDS.dwData = addi;stcCDS.lpData = pCP;//打包消息結構體::SendMessage(hTarget, WM_COPYDATA, 0, (LPARAM)&stcCDS);
}1
void m_Com(
PCOMMPACK& pCP,
int addi)2{3
hTarget = ::
FindWindow(
NULL,
L"HookApp");4
COPYDATASTRUCT stcCDS;5
stcCDS.
cbData = sizeof(
COMMPACK);6
stcCDS.
dwData = addi;7
stcCDS.
lpData = pCP;8
::
SendMessage(
hTarget,
WM_COPYDATA,
0, (
LPARAM)
&stcCDS);9}
void InitHooks()
{hTarget = ::FindWindow(NULL, L"HookApp");m_Array4Hooks[M_CALLWNDPROC].hkproc = m_CallWndProc;m_Array4Hooks[M_CALLWNDPROC].nType = WH_CALLWNDPROC;m_Array4Hooks[M_CBT].hkproc = m_CBTProc;m_Array4Hooks[M_CBT].nType = WH_CBT;//m_Array4Hooks[M_DEBUG]->hkproc = m_DebugProc;//m_Array4Hooks[M_DEBUG]->nType = WH_DEBUG;//m_Array4Hooks[M_GETMESSAGE]->hkproc = m_GetMsgProc;//m_Array4Hooks[M_GETMESSAGE]->nType = WH_GETMESSAGE;m_Array4Hooks[M_KEYBOARD].hkproc = m_KeyboardProc;m_Array4Hooks[M_KEYBOARD].nType = WH_KEYBOARD;m_Array4Hooks[M_MOUSE].hkproc = m_MouseProc;m_Array4Hooks[M_MOUSE].nType = WH_MOUSE;//m_Array4Hooks[M_MSGFILTER]->hkproc = m_MessageFilterProc;//m_Array4Hooks[M_MSGFILTER]->nType = WH_MSGFILTER;for (int i = 0; i < NHOOKNUMS; ++i){m_Array4Hooks[i].hhook = 0;}
}x1
void InitHooks()2{3
hTarget = ::
FindWindow(
NULL,
L"HookApp");4
m_Array4Hooks[
M_CALLWNDPROC].
hkproc = m_CallWndProc;5
m_Array4Hooks[
M_CALLWNDPROC].
nType = WH_CALLWNDPROC;6
m_Array4Hooks[
M_CBT].
hkproc = m_CBTProc;7
m_Array4Hooks[
M_CBT].
nType = WH_CBT;8
9
10
11
12
m_Array4Hooks[
M_KEYBOARD].
hkproc = m_KeyboardProc;13
m_Array4Hooks[
M_KEYBOARD].
nType = WH_KEYBOARD;14
m_Array4Hooks[
M_MOUSE].
hkproc = m_MouseProc;15
m_Array4Hooks[
M_MOUSE].
nType = WH_MOUSE;16
17
18
for (
int i = 0;
i < NHOOKNUMS;
++i)19
{20
m_Array4Hooks[
i].
hhook = 0;21
}22}
void InstallHook(DWORD dwProcessID)
{g_dwThreadID = GetThreadInfo(dwProcessID);//由注入器傳入指定注入進程ID,遍歷獲得主線程IDInitHooks();//初始化鉤子for (int i = 0; i < NHOOKNUMS; ++i){if (m_Array4Hooks[i].hkproc == NULL)continue;m_Array4Hooks[i].hhook = SetWindowsHookEx(m_Array4Hooks[i].nType, m_Array4Hooks[i].hkproc, g_Module, g_dwThreadID);}
}void UnInstallHook()
{for (int i = 0; i < NHOOKNUMS; ++i){UnhookWindowsHookEx(m_Array4Hooks[i].hhook);}
}121
void InstallHook(
DWORD dwProcessID)2{3
g_dwThreadID = GetThreadInfo(
dwProcessID);45
InitHooks();67
for (
int i = 0;
i < NHOOKNUMS;
++i)8
{9
if (
m_Array4Hooks[
i].
hkproc == NULL)
continue;10
m_Array4Hooks[
i].
hhook = SetWindowsHookEx(
m_Array4Hooks[
i].
nType,
m_Array4Hooks[
i].
hkproc,
g_Module,
g_dwThreadID);11
}12}1314
void UnInstallHook()15{16
for (
int i = 0;
i < NHOOKNUMS;
++i)17
{18
UnhookWindowsHookEx(
m_Array4Hooks[
i].
hhook);19
}20}
DWORD GetThreadInfo(DWORD dwProcessID)
{HANDLE hSnThread = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);if (hSnThread == INVALID_HANDLE_VALUE) {return 0;}// 開始遍歷線程THREADENTRY32 threadEntry = { sizeof(THREADENTRY32) };// 獲取快照中的第一個線程的信息Thread32First(hSnThread, &threadEntry);DWORD dwSuspendCount = 0;do {// 判斷遍歷到的線程是否屬于這個進程的.if (threadEntry.th32OwnerProcessID == dwProcessID) {return threadEntry.th32ThreadID;}// 獲取快照中的下一個線程信息} while (Thread32Next(hSnThread, &threadEntry));return 1;
}251
DWORD GetThreadInfo(
DWORD dwProcessID)2{3
HANDLE hSnThread = CreateToolhelp32Snapshot(
TH32CS_SNAPTHREAD,
0);4
if (
hSnThread == INVALID_HANDLE_VALUE) {5
return 0;6
}78
9
THREADENTRY32 threadEntry = {
sizeof(
THREADENTRY32) };1011
12
Thread32First(
hSnThread,
&threadEntry);1314
DWORD dwSuspendCount = 0;15
do {1617
18
if (
threadEntry.
th32OwnerProcessID == dwProcessID) {19
return threadEntry.
th32ThreadID;20
}21
22
}
while (
Thread32Next(
hSnThread,
&threadEntry));23
return 1;24}
EXTERN_C _declspec(dllexport) void InstallHook(DWORD dwProcessID);
EXTERN_C _declspec(dllexport) void UnInstallHook();1
EXTERN_C _declspec(
dllexport)
void InstallHook(
DWORD dwProcessID);2
EXTERN_C _declspec(
dllexport)
void UnInstallHook();
至此DLL部分結束,開始回顯程序的消息處理BOOL CHookAppDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{// TODO: 在此添加消息處理程序代碼和/或調用默認值static int nIndex = 0;PCOMMPACK pCP = new COMMPACK;pCP = (PCOMMPACK)pCopyDataStruct->lpData;switch (pCP->nType)//根據消息的類型進行定義{case M_CALLWNDPROC:{}break;case M_CBT:{static int nIndex = 0;CString strCallWndProc;switch (pCP->wParam){case IDHCBT_ACTIVATE:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_ACTIVATE", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_CLICKSKIPPED:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_CLICKSKIPPED", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_CREATEWND:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_CLICKSKIPPED", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_DESTROYWND:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_DESTROYWND", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_KEYSKIPPED:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_KEYSKIPPED", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_MINMAX:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_MINMAX", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_MOVESIZE:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_MOVESIZE", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_QS:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_QS", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_SETFOCUS:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_SETFOCUS", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDHCBT_SYSCOMMAND:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"HCBT_SYSCOMMAND", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case IDUnknown:{strCallWndProc.Format(L"CBT [%d] - nCode: %s, tsk: %ld ", nIndex, L"Unknown", pCP->wParam);strCallWndProc += L"\r\n";m_StrCBT += strCallWndProc;UpdateData(FALSE);++nIndex;}break;default:break;}}break;case M_DEBUG:{}break;case M_GETMESSAGE:{}break;case M_KEYBOARD:{static int nIndex = 0;CString strCallWndProc;strCallWndProc.Format(L"KEYBOARD [%d] - VK: %c ", nIndex, char(pCP->wParam));strCallWndProc += L"\r\n";m_StrKeyBoard += strCallWndProc;UpdateData(FALSE);++nIndex;}break;case M_MOUSE:{}break;case M_MSGFILTER:{}break;default:break;}return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}
x1
BOOL CHookAppDlg::OnCopyData(
CWnd* pWnd,
COPYDATASTRUCT* pCopyDataStruct)2{3
4
static int nIndex = 0;5
PCOMMPACK pCP = new COMMPACK;6
pCP = (
PCOMMPACK)
pCopyDataStruct->lpData;78
switch (
pCP->nType)9
{10
case M_CALLWNDPROC:11
{1213
}
break;1415
case M_CBT:16
{17
static int nIndex = 0;18
CString strCallWndProc;19
switch (
pCP->wParam)20
{21
case IDHCBT_ACTIVATE:22
{23
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_ACTIVATE",
pCP->wParam);24
strCallWndProc += L"\r\n";25
m_StrCBT += strCallWndProc;26
UpdateData(
FALSE);27
++nIndex;28
}
break;29
case IDHCBT_CLICKSKIPPED:30
{31
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_CLICKSKIPPED",
pCP->wParam);32
strCallWndProc += L"\r\n";33
m_StrCBT += strCallWndProc;34
UpdateData(
FALSE);35
++nIndex;36
}
break;37
case IDHCBT_CREATEWND:38
{39
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_CLICKSKIPPED",
pCP->wParam);40
strCallWndProc += L"\r\n";41
m_StrCBT += strCallWndProc;42
UpdateData(
FALSE);43
++nIndex;44
}
break;45
case IDHCBT_DESTROYWND:46
{47
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_DESTROYWND",
pCP->wParam);48
strCallWndProc += L"\r\n";49
m_StrCBT += strCallWndProc;50
UpdateData(
FALSE);51
++nIndex;52
}
break;53
case IDHCBT_KEYSKIPPED:54
{55
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_KEYSKIPPED",
pCP->wParam);56
strCallWndProc += L"\r\n";57
m_StrCBT += strCallWndProc;58
UpdateData(
FALSE);59
++nIndex;60
}
break;61
case IDHCBT_MINMAX:62
{63
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_MINMAX",
pCP->wParam);64
strCallWndProc += L"\r\n";65
m_StrCBT += strCallWndProc;66
UpdateData(
FALSE);67
++nIndex;68
}
break;69
case IDHCBT_MOVESIZE:70
{71
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_MOVESIZE",
pCP->wParam);72
strCallWndProc += L"\r\n";73
m_StrCBT += strCallWndProc;74
UpdateData(
FALSE);75
++nIndex;76
}
break;77
case IDHCBT_QS:78
{79
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_QS",
pCP->wParam);80
strCallWndProc += L"\r\n";81
m_StrCBT += strCallWndProc;82
UpdateData(
FALSE);83
++nIndex;84
}
break;85
case IDHCBT_SETFOCUS:86
{87
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_SETFOCUS",
pCP->wParam);88
strCallWndProc += L"\r\n";89
m_StrCBT += strCallWndProc;90
UpdateData(
FALSE);91
++nIndex;92
}
break;93
case IDHCBT_SYSCOMMAND:94
{95
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"HCBT_SYSCOMMAND",
pCP->wParam);96
strCallWndProc += L"\r\n";97
m_StrCBT += strCallWndProc;98
UpdateData(
FALSE);99
++nIndex;100
}
break;101
case IDUnknown:102
{103
strCallWndProc.
Format(
L"CBT [%d] - nCode: %s, tsk: %ld ",
nIndex,
L"Unknown",
pCP->wParam);104
strCallWndProc += L"\r\n";105
m_StrCBT += strCallWndProc;106
UpdateData(
FALSE);107
++nIndex;108
}
break;109
default:110
break;111
}112
}
break;113
case M_DEBUG:114
{115116
}
break;117
case M_GETMESSAGE:118
{119120
}
break;121
case M_KEYBOARD:122
{123
static int nIndex = 0;124
CString strCallWndProc;125
strCallWndProc.
Format(
L"KEYBOARD [%d] - VK: %c ",
nIndex,
char(
pCP->wParam));126
strCallWndProc += L"\r\n";127
m_StrKeyBoard += strCallWndProc;128
UpdateData(
FALSE);129
++nIndex;130
131
}
break;132
case M_MOUSE:133
{134 ? ? ? ?135
}
break;136
case M_MSGFILTER:137
{138139
}
break;140141
default:142
break;143
}144145
return CDialogEx::OnCopyData(
pWnd,
pCopyDataStruct);146}147
注入器部分代碼:BOOL _Inject_::m_WindowsHook(PWCHAR pszDllName, LPCSTR pszDllProc, DWORD dwPID)
{typedef void* (*HookOnProto)(DWORD);//聲明導出函數原型HookOnProto HookOn;hInstDll = LoadLibrary(pszDllName);if (hInstDll == NULL)return FALSE;HookOn = (HookOnProto)GetProcAddress(hInstDll, pszDllProc);//從指定Dll導出所需函數if (HookOn == NULL)return FALSE;HookOn(dwPID);//鉤子安裝return TRUE;
}BOOL _Inject_::m_UnWinHook(PWCHAR pszDllName, LPCSTR pszDllProc)
{typedef void* (*HookOffProto)(void);HookOffProto HookOff;HookOff = (HookOffProto)GetProcAddress(hInstDll, pszDllProc);if (HookOff == NULL)return FALSE;HookOff();
}241
BOOL _Inject_::m_WindowsHook(
PWCHAR pszDllName,
LPCSTR pszDllProc,
DWORD dwPID)2{3
typedef void* (
*HookOnProto)(
DWORD);4
HookOnProto HookOn;5
hInstDll = LoadLibrary(
pszDllName);6
if (
hInstDll == NULL)
return FALSE;78
HookOn = (
HookOnProto)
GetProcAddress(
hInstDll,
pszDllProc);9
if (
HookOn == NULL)
return FALSE;1011
HookOn(
dwPID);1213
return TRUE;14}1516
BOOL _Inject_::m_UnWinHook(
PWCHAR pszDllName,
LPCSTR pszDllProc)17{18
typedef void* (
*HookOffProto)(
void);19
HookOffProto HookOff;2021
HookOff = (
HookOffProto)
GetProcAddress(
hInstDll,
pszDllProc);22
if (
HookOff == NULL)
return FALSE;23
HookOff();24}
效果演示:(以注入notepad++為例)安裝消息鉤子前
安裝消息鉤子后
由于鉤子種類繁多,我暫時沒有全部實現,有興趣的各位可以在我的基礎上試試其他的,代碼寫的不好,讓各位見笑了,如有錯誤,也懇請各位指正。
來自為知筆記(Wiz)
轉載于:https://www.cnblogs.com/B166ER/p/7839870.html
總結
以上是生活随笔為你收集整理的消息钩子学习工程的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。