win32彙編-Windows鉤子(七)

鉤子能夠用來截獲系統中的消息流 經過SetWindowsHookEx函數定義了監視函數的位置和監視消息的類型,這樣,每當發生咱們感興趣的消息時,Windows就會將消息發送給監視函數,監視函數是一個處理消息的回調函數,也稱爲「鉤子函數」。(會影響系統的性能)shell

局部鉤子僅鉤掛屬於自身進程的事件;(SetWindowsHook)windows

遠程鉤子分兩種:基於線程的和系統範圍的(包括自身)。ide

                    1 基於線程的遠程鉤子用來捕獲其餘進程中某一特定線程的事件;函數

                    2  系統範圍的遠程鉤子將捕捉系統中全部進程中發生的事件消息。性能

 

鉤 子 名 稱spa

監視消息的類型和時機線程

WH_CALLWNDPROC調試

每當調用SendMessage函數時,函數將消息發送給目標窗口過程前首先調用鉤子函數日誌

WH_CALLWNDPROCRETcode

每當調用SendMessage函數時,函數將消息發送給目標窗口過程後再調用鉤子函數

WH_GETMESSAGE

每當調用GetMessage或PeekMessage函數時,函數從程序的消息隊列中獲取一個消息後調用鉤子函數

WH_KEYBOARD

每當調用GetMessage或PeekMessage函數時,若是從消息隊列中獲得的是WM_KEYUP或WM_KEYDOWN消息,則調用鉤子函數(鍵盤消息)

WH_MOUSE

每當調用GetMessage或PeekMessage函數時,若是從消息隊列中獲得的是鼠標消息,則調用鉤子函數(鼠標消息)

WH_HARDWARE

每當調用GetMessage或PeekMessage函數時,若是從消息隊列中獲得的是非鼠標和鍵盤消息,則調用鉤子函數

WH_MSGFILTER

當用戶對對話框、菜單和滾動條有所操做時,系統在發送對應的消息以前調用鉤子函數,這種鉤子只能是局部

WH_SYSMSGFILTER

同WH_MSGFILTER,不過是系統範圍的

WH_SHELL

當Windows shell程序準備接收一些通知事件前調用鉤子函數,如shell被激活和重畫等

WH_DEBUG

用來給其餘鉤子函數除錯(調試)

WH_CBT

當基於計算機的訓練(CBT)事件發生時調用鉤子函數 

WH_JOURNALRECORD

日誌記錄鉤子,用來記錄發送給系統消息隊列的全部消息 只能全局

WH_JOURNALPLAYBACK

日誌回放鉤子,用來回放日誌記錄鉤子記錄的系統事件   只能全局

WH_FOREGROUNDIDLE

系統空閒鉤子,當系統空閒的時候調用鉤子函數,這樣就能夠在這裏安排一些優先級很低的任務

程鉤子的鉤子函數必須位於一個動態連接庫中,並且必須是共享數據段的動態連接庫

鉤子程序通常包括3個功能模塊:

(1)主程序——用來實現界面或者其餘功能。

(2)鉤子回調函數——用來接收系統發過來的消息。

(3)鉤子的安裝和卸載程序。

鍵盤鉤子示例 -(連接庫)

<HookDll.asm>

                   .386

                    .model flat, stdcall

                    option casemap :none

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Include 文件定義

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include         windows.inc

include         user32.inc

includelib      user32.lib

include         kernel32.inc

includelib      kernel32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    .data

hInstance       dd      ?

 

                    .data?

hWnd                dd      ?

hHook           dd      ?

dwMessage       dd      ?

szAscii         db      4 dup (?)

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    .code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

DllEntry            proc        _hInstance,_dwReason,_dwReserved

 

                    Push        _hInstance

                pop     hInstance

                mov     eax,TRUE

                ret

 

DllEntry            Endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 鍵盤鉤子回調函數

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HookProc            proc        _dwCode,_wParam,_lParam

                    local   @szKeyState[256]:byte

 

                    invoke  CallNextHookEx,hHook,_dwCode,_wParam,_lParam

                    invoke  GetKeyboardState,addr @szKeyState

                    invoke  GetKeyState,VK_SHIFT

                    mov     @szKeyState + VK_SHIFT,al

                    mov     ecx,_lParam

                    shr     ecx,16

                    invoke  ToAscii,_wParam,ecx,addr @szKeyState,addr szAscii,0

                    mov     byte ptr szAscii [eax],0

                    invoke  SendMessage,hWnd,dwMessage,dword ptr szAscii,NULL

                    xor     eax,eax

                    ret

 

HookProc            endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 安裝鉤子

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

InstallHook     proc        _hWnd,_dwMessage

 

                push        _hWnd

                pop     hWnd

                    push        _dwMessage

                pop     dwMessage

                invoke  SetWindowsHookEx,WH_KEYBOARD,addr HookProc,\

                        hInstance,NULL

                mov     hHook,eax

                ret

 

InstallHook endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 卸載鉤子

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

UninstallHook   proc

 

                invoke  UnhookWindowsHookEx,hHook

                ret

 

UninstallHook   endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                End     DllEntry
View Code

<HookDll.def>文件中包括了它們的名稱:

 

EXPORTS     HookProc

                InstallHook

                UninstallHook
View Code
   invoke  SetWindowsHookEx,idHook,lpHookProc,hInstance,dwThreadID

   .if     eax

           mov     hHook,eax

   .endif

idHook參數指定鉤子的類型 

 hInstance 指定鉤子回調函數所在DLL的實例句柄

 dwThreadID是安裝鉤子後想監控的線程的ID號 指定爲NULL會被解釋成系統範圍的

 <Main.asm>

 .386

                    .model flat, stdcall

                    option casemap :none

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Include 文件定義

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include         windows.inc

include         user32.inc

includelib      user32.lib

include         kernel32.inc

includelib      kernel32.lib

include         Hookdll.inc

includelib      Hookdll.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Equ 等值定義

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ICO_MAIN            equ     1000

DLG_MAIN            equ     1000

IDC_TEXT            equ     1001

WM_HOOK         equ     WM_USER + 100h

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 代碼段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    .code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_ProcDlgMain        proc        uses ebx edi esi hWnd,wMsg,wParam,lParam

                    local   @dwTemp

 

                mov     eax,wMsg

;********************************************************************

                    .if     eax ==  WM_CLOSE

                            invoke  UninstallHook

                            invoke  EndDialog,hWnd,NULL

;********************************************************************

                    .elseif eax ==  WM_INITDIALOG

                            invoke  InstallHook,hWnd,WM_HOOK

                            .if     ! eax

                                    invoke  EndDialog,hWnd,NULL

                            .endif

;********************************************************************

                    .elseif eax ==  WM_HOOK

                            mov     eax,wParam

                            .if     al == 0dh

                                    mov     eax,0a0dh

                            .endif

                            mov     @dwTemp,eax

                            invoke  SendDlgItemMessage,hWnd,IDC_TEXT,\

                                    EM_REPLACESEL,0,addr @dwTemp

                    .else

                            mov     eax,FALSE

                            ret

                    .endif

                    mov eax,TRUE

                    ret

 

_ProcDlgMain        endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

start:

                    invoke  GetModuleHandle,NULL

                    invoke  DialogBoxParam,eax,DLG_MAIN,NULL,\

                            offset _ProcDlgMain,NULL

                    invoke  ExitProcess,NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    end start
View Code

 

2. 鉤子回調函數

 

如今回過頭來看HookDll.asm程序中的鉤子回調函數,回調函數的寫法通常以下:

 

HookProc            proc        dwCode,wParam,lParam

 

                invoke  CallNextHookEx,hHook,_dwCode,_wParam,_lParam

 

                   ;處理消息的代碼

 

                   mov     eax,返回值

 

                   ret

 

HookProc    endp

 

對於鍵盤鉤子來講,參數的定義以下所示。

   dwCode——鍵盤消息的處理方式。若是是HC_ACTION,表示收到一個正常的擊鍵消息;若是是HC_NOREMOVE,表示對應消息並無從消息隊列中移去(當某個進程用指定PM_NOREMOVE 標誌的PeekMessage函數獲取消息時就是如此)。

   wParam——按鍵的虛擬碼(即Windows.inc中定義的VK_xxx值)。

   lParam——按鍵的重複次數、掃描碼和標誌等數據,不一樣數據位的定義以下:

   位0~15:按鍵的重複次數。

   位16~23:按鍵的掃描碼。

   位24:按鍵是不是擴展鍵(F1與F2等Fx鍵,小鍵盤數字鍵等),若是此位是1表示按鍵是擴展鍵。

   位25~28:未定義。

   位29:若是Alt鍵在按下狀態,此位置1,不然置0。

   位30:按鍵的原先狀態,消息發送前按鍵原來是按下的,此位被設置爲1,不然置0。

   位31:按鍵的當前動做,若是是按鍵按下,那麼此位被設置爲0;按鍵釋放的話被設置爲1

 

日誌記錄鉤子

 

日誌記錄鉤子是一種特殊的鉤子,說它特殊是由於它是遠程鉤子,卻不用放在動態連接庫中,這就爲監視系統範圍的消息提供了方便。

 

 日誌鉤子HOOK鍵盤<RecHook.asm>

 .386

                    .model flat, stdcall

                    option casemap :none

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Include 文件定義

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

include         windows.inc

include         user32.inc

includelib      user32.lib

include         kernel32.inc

includelib      kernel32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; Equ 等值定義

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

ICO_MAIN            equ     1000

DLG_MAIN            equ     1000

IDC_TEXT            equ     1001
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 數據段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    .data?

hInstance       dd      ?

hWinMain            dd      ?

hHook           dd      ?

szAscii         db      32 dup (?)

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 代碼段

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    .code

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 鉤子回調函數

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

HookProc            proc        _dwCode,_wParam,_lParam

                    local   @szKeyState[256]:byte

 

            invoke  CallNextHookEx,hHook,_dwCode,_wParam,_lParam

            pushad

            .if     _dwCode == HC_ACTION

                    mov     ebx,_lParam

                    assume  ebx:ptr EVENTMSG

                    .if     [ebx].message == WM_KEYDOWN

                            invoke  GetKeyboardState,addr @szKeyState

                            invoke  GetKeyState,VK_SHIFT

                            mov     @szKeyState + VK_SHIFT,al

                            mov     ecx,[ebx].paramH

                            shr     ecx,16

                            invoke  ToAscii,[ebx].paramL,ecx,\

                                    addr @szKeyState,addr szAscii,0

                            mov     byte ptr szAscii [eax],0

                            .if     szAscii == 0dh

                            mov     word ptr szAscii+1,0ah

                            .endif

                            invoke  SendDlgItemMessage,hWinMain,IDC_TEXT,\

                                    EM_REPLACESEL,0,addr szAscii

                    .endif

                    assume  ebx:nothing

            .endif

            popad

            ret

 

HookProc            endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

_ProcDlgMain        proc        uses ebx edi esi hWnd,wMsg,wParam,lParam

 

                    mov     eax,wMsg

;********************************************************************

                    .if     eax ==  WM_CLOSE

                            invoke  UnhookWindowsHookEx,hHook

                            invoke  EndDialog,hWnd,NULL

;********************************************************************

                    .elseif eax ==  WM_INITDIALOG

                            push        hWnd

                            pop     hWinMain

                            invoke  SetWindowsHookEx,WH_JOURNALRECORD,\

                                    addr HookProc,hInstance,NULL

                            .if     eax

                                    mov     hHook,eax

                            .else

                                    invoke  EndDialog,hWnd,NULL

                            .endif

;********************************************************************

                    .else

                            mov     eax,FALSE

                            ret

                    .endif

                    mov eax,TRUE

                    ret

 

_ProcDlgMain        endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

start:

                    invoke  GetModuleHandle,NULL

                    mov     hInstance,eax

                    invoke  DialogBoxParam,eax,DLG_MAIN,NULL,\

                            offset _ProcDlgMain,NULL

                    invoke  ExitProcess,NULL

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                    end     start
View Code

因爲再也不須要動態連接庫了,鉤子回調函數HookProc被移到了主程序中,也取消了InstallHook和UninstallHook兩個子程序,相應的內容直接放在WM_INITDIALOG和WM_CLOSE消息中完成。在WM_INITDIALOG消息中用下面的語句完成對鉤子的安裝:

invoke  SetWindowsHookEx,WH_JOURNALRECORD,addr HookProc,hInstance,NULL

 

程序比較重要的一個不一樣點在於日誌鉤子回調函數的參數定義不一樣,在這裏dwCode的參數定義以下:

 

   HC_ACTION——系統準備從消息隊列中移去一條消息,消息的具體信息由lParam參數中指定的EVENTMSG結構定義。

 

   HC_SYSMODALOFF——某個系統模態對話框準備被關閉。

 

   HC_SYSMODALON——某個系統模態對話框準備被創建

咱們關心的是HC_ACTION標誌,這時lParam參數指向一個EVENTMSG結構,其定義爲:

 

EVENTMSG STRUCT

  message   DWORD      ?     ;消息隊列中將要移去的消息ID

  paramL    DWORD      ?     ;消息的wParam參數

  paramH    DWORD      ?     ;消息的lParam參數

  time      DWORD      ?     ;消息發生的事件

  hwnd      DWORD      ?     ;消息對應的窗口句柄

EVENTMSG ENDS

 

因爲日誌記錄鉤子能夠截獲的不只是鍵盤消息,也有鼠標等其餘消息,因此須要有個地方指定消息類型,經過檢測EVENTMSG結構中的消息ID字段就能夠得知截獲的到底是什麼消息。(如按鍵消息ID WM_KEYDOWN)

相關文章
相關標籤/搜索