• win32汇编-Windows钩子(七)


    钩子可以用来截获系统中的消息流 通过SetWindowsHookEx函数定义了监视函数的位置和监视消息的类型,这样,每当发生我们感兴趣的消息时,Windows就会将消息发送给监视函数,监视函数是一个处理消息的回调函数,也称为“钩子函数”。(会影响系统的性能)

    局部钩子仅钩挂属于自身进程的事件;(SetWindowsHook)

    远程钩子分两种:基于线程的和系统范围的(包括自身)。

                        1 基于线程的远程钩子用来捕获其他进程中某一特定线程的事件;

                        2  系统范围的远程钩子将捕捉系统中所有进程中发生的事件消息。

    钩 子 名 称

    监视消息的类型和时机

    WH_CALLWNDPROC

    每当调用SendMessage函数时,函数将消息发送给目标窗口过程前首先调用钩子函数

    WH_CALLWNDPROCRET

    每当调用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)

     

     

     

     

  • 相关阅读:
    多项式多点求值和插值
    Java Dao设计模式
    (转)HTTP长连接和短连接
    JavaScript——this关键字
    JavaScript——Prototype详探
    JavaScript——特殊点总结
    JavaScript——正则表达式
    JavaScript——Window对象
    JavaScript——this、constructor、prototype
    JavaScript——事件模型
  • 原文地址:https://www.cnblogs.com/xuankuwa/p/3660544.html
Copyright © 2020-2023  润新知