zoukankan      html  css  js  c++  java
  • 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)

     

     

     

     

  • 相关阅读:
    VysorPro助手
    Play 2D games on Pixel running Android Nougat (N7.1.2) with Daydream View VR headset
    Play 2D games on Nexus 6P running Android N7.1.1 with Daydream View VR headset
    Native SBS for Android
    ADB和Fastboot最新版的谷歌官方下载链接
    How do I install Daydream on my phone?
    Daydream Controller手柄数据的解析
    蓝牙BLE传输性能及延迟分析
    VR(虚拟现实)开发资源汇总
    Android(Java)控制GPIO的方法及耗时分析
  • 原文地址:https://www.cnblogs.com/xuankuwa/p/3660544.html
Copyright © 2011-2022 走看看