zoukankan      html  css  js  c++  java
  • 第21章 动态链接库和钩子(2)

    21.5 Windows钩子

    21.5.1 Windows钩子

    钩子是Windows消息处理机制中的一个监视点,应用程序可以在这里安装一个监视子程序,这样就可以在系统中的消息流到达目的窗口过程前监控它们。也就是说,钩子是用来截获系统中的消息流,并送给其他应用程序的处理的。

    21.5.2 钩子的类型

    (1)按作用范围分类

    钩子类型

    说明

    局部钩子

    仅钩挂属于自身进程的事件消息

    ★钩子模块不需要单独的dll,可以放在同一个可执行文件中

    远程钩子

    又分为两种:

    线程钩子(LocalHook)——捕获其它进程中的某一线程的事件

    系统钩子(RemoteHook)——捕获所有进程的消息,也叫全局钩子

    ★钩子回调函数必须放在DLL中:因为只有dll是可以被映射到其他进程的地址空间。这样,HOOK代码才能被系统注入到每个进程里面。在安装这样的钩子后,系统会自动地把该DLL注入到所有的进程空间,这样每个进程发生的特定事件就会被注入进来的Hook代码给拦截。否则,系统是不能从其他进程的地址空间中调用钩子函数,因为两个进程的地址空间是隔离的。

    (2)按事件分类

      ① 键盘钩子和低级键盘钩子可以监视各种键盘消息。

      ② 鼠标钩子和低级鼠标钩子可以监视各种鼠标消息。

      ③ 外壳钩子可以监视各种Shell事件消息。比如启动和关闭应用程序。

      ④ 日志钩子可以记录从系统消息队列中取出的各种事件消息。

      ⑤ 窗口过程钩子监视所有从系统消息队列发往目标窗口的消息。

    (3)常见的钩子

    钩子类型

    说明

    WH_CALLWNDPROC

    WH_CALLWNDPROCRET

    ①WH_CALLWNDPROC:在SendMessage时,当消息到达目标窗口之前,调用钩子函数

    ②WH_CALLWNDPROCRET:在SendMessage时,在消息到达目标窗口之后,调用钩子函数。

    ③WM_CALLWNDPROCRET会收到CWPRETSTRUCT结构体,包含了来自处理消息的窗口过程的返回值,及与这个消息关联的消息参数。

    WH_CBT

    ①激活、建立、销毁、最小化、最大化,移动、改变尺寸等窗口事件

    ②设置输入焦点事件、系统菜单消息

    ③同步系统消息队列、完成系统指令

    ④来自系统消息队列中的移动鼠标,键盘事件

    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

    当Shell程序准备接收一些通知事件前,调用钩子函数。外壳应用程序是不接受WH_SHELL消息的,要用应用程序能够接收WH_SHELL,必须调用SystemParametersInfo函数注册该消息。WM_SHELL共有5种情况:

    ①TaskBar需要重绘某个按钮时

    ②当系统地要显示关于Taskbar的一个程序的最小化形式

    ③当目前的键盘布局状态改变。

    ④当按Ctrl+Esc去执行TaskManager(或相等级别的程序)时。

    ⑤只要有个top-level、unowned窗口被创建、起作用或被摧毁

    WH_DEBUG

    用来给其他钩子函数除错的

    WH_JOURNALRECORD

    用来记录发送给系统消息队列的所有消息,被称为日志记录钩子

    WH_JOURNALPLAYBACK

    用来回放日志记录钩子的系统事件,被称为日志回放钩子。

    WH_FOREGROUNDIDLE

    应用程序的前台线程处于空闲状态时,调用钩子函数,可以在这里安排一些优先级很低的任务

    21.5.3 远程钩子的安装和使用

    (1)钩子程序的结构——3个功能模块

    功能模块

    说明

    ①主程序

    用来实现界面或其他功能

    ②钩子回调函数

    用来接收系统发过来的消息。

    对于局部钩子来说,这模块可以处在同一可执行文件中。

    对于远程钩子,该模块必须放在一个DLL库中。

    ③钩子安装和卸载模块

    没有特别要求,一般也放在动态链接库中。

    (2)钩子的安装:SetWindowsHookEx

    参数

    含义

    int idHook

    见前面表格《常见的钩子类型》

    HOOKPROC lpfn

    钩子函数的指针 ,也即拦截到指定系统消息后的预处理过程,一般定义在DLL中

    HINSTANCE hMod

    应用程序实例的句柄。如果是全局钩子, hInstance是DLL句柄(DllMain中给的模块地址,就是包含HookProc的动态库加载地址。如果该值为0则只勾自己)

    DWORD dwThreadId

    要安装钩子的线程ID,指定被监视的线程,如果明确指定了某个线程的ID就只监视该线程,此时的钩子即为线程钩子;如果该参数被设置为0,则表示此钩子为监视系统所有线程的全局钩子。

    (2)钩子函数及钩子链

      ①LRESULT CALLBACK HookProc(int nCode,WPARAM wParam,LPARAM lParam);

      ②对于不同的钩子类型,钩子函数的参数的含义是不同的,可参照MSDN

      ③Windows系统中可能同时存在多个同类型的钩子,多个程序同时安装同一种钩子的时候,就会将这些钩子组成一个钩子链,最近加入的钩子放在链表的头部,Windows负责为每一种钩子维护一个钩子链。当一个事件发生时,Windows调用最后安装的钩子,然后由当前钩子的回调函数发起调用下一个钩子的动作,这样就可以将消息传递下来。因为,程序中于不感兴趣的消息应通过CallNextHookEx(hKeyHook,nCode,wParam,lParam)函数传递给下一个钩子。

    (3)钩子的卸载:UnhookWindowsHookEx(HHOOK) 函数卸载钩子,其参数为钩子句柄。

    (5)键盘钩子的实例程序

    【HookTest程序】

      ①利用全局鼠标钩子来实现窗口的悬停效果(类似于QQ,当窗口靠左边时,则隐入。当鼠标靠屏幕左边时,渐显出来。

      ②实现全局键盘钩子实现键盘消息的拦截。

     

    /*--------------------------------------------
       键盘钩子 供动态链接库及主程序使用的头文件
               (c)浅墨浓香,2015.6.11
    --------------------------------------------*/
    #pragma once
    #include <Windows.h>
    
    #ifdef _cplusplus
    #ifdef API_EXPORT 
    #define EXPORT   extern "C" __declspec(dllexport)          //当头文件供动态库本身使用时
    #else
    #define EXPORT    extern "C" __declspec(dllimport)         //当头文件供调用库的程序使用时
    #endif
    #else
    #ifdef API_EXPORT 
    #define EXPORT   __declspec(dllexport)                        //当头文件供动态库本身使用时
    #else
    #define EXPORT   __declspec(dllimport)                        //当头文件供调用库的程序使用时
    #endif
    #endif
    
    //安装鼠标钩子
    EXPORT HHOOK InstallMouseHook(HWND hwnd);
    //御载鼠标钩子
    EXPORT void UnInstallMouseHook();
    //鼠标钩子回调函数
    LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
    
    
    //安装鼠标钩子
    EXPORT HHOOK InstallKeyBoardHook(HWND hwnd);
    //御载鼠标钩子
    EXPORT void UnInstallKeyBoardHook();
    //键盘钩子回调函数
    LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam);

    //HookLib.c

    #define API_EXPORT
    #include "HookLib.h"
    
    #define WM_USER_MOUSEHOOK    (WM_USER + 1000)
    #define WM_USER_KEYBOARDHOOK (WM_USER + 1001)
    
    //以下两个变量只供当前进程使用,不需要进程间共享.
    //g_hInst只供安装钩子的进程使用。
    //g_wAscII只调用钩子函数的进程使用。
    WORD  g_wAscII;    //保存每次击键时产生的扫描码转化成的ASCII码             
    HINSTANCE g_hInst; //动态链接库的句柄
    
    //设置自定义数据段(用来做数据在不同进程中的共享区)
    //以下三个变量需要在不同进程共享。
    #pragma data_seg(".myshared") 
    HWND      g_hWnd            = NULL;
    HHOOK     g_hMouseHook        = NULL;
    HHOOK     g_hKeyBoardHook    = NULL;
    #pragma data_seg() 
    
    //设置自定义数据段的属性(可读、可写、可共享)
    #pragma comment (linker,"/SECTION:.myshared,RWS")  //设为可读写、可共享属性
    
    //入口和退出点
    int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
    {
        g_hInst = hInstance;
        return TRUE;
    }
    
    //安装鼠标钩子
    HHOOK InstallMouseHook(HWND hwnd)
    {
        //因为安装钩子的进程与钩子函数的进程可能是不同进程,这个变量将在钩子函数里被使用,
        //所以g_hWnd、g_hMouseHook设为进程间共享的变量
        g_hMouseHook = (HHOOK)SetWindowsHookEx(WH_MOUSE, MouseProc, g_hInst, 0);//最后一个参数为NULL,表示全局钩子
        g_hWnd = hwnd; 
        return g_hMouseHook;
    }
    
    //御载鼠标钩子
    void UnInstallMouseHook()
    {
        UnhookWindowsHookEx(g_hMouseHook);
    }
    
    //鼠标钩子函数
    LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        MOUSEHOOKSTRUCT* ms = (MOUSEHOOKSTRUCT*)lParam;
        CallNextHookEx(g_hMouseHook, nCode, wParam, lParam);
        static POINT ptOld;
    
        if (wParam ==WM_MOUSEMOVE )
        {        
            if (ptOld.x != ms->pt.x && ptOld.y != ms->pt.y)
            {
                ptOld.x = ms->pt.x;
                ptOld.y = ms->pt.y;
                PostMessage(g_hWnd, WM_USER_MOUSEHOOK, wParam, MAKELPARAM(ms->pt.x, ms->pt.y));
            }        
        }
        return 0;
    }
    
    
    //安装键盘钩子
    HHOOK InstallKeyBoardHook(HWND hwnd)
    {
        
        //因为安装钩子的进程与钩子函数的进程可能是不同进程,这个变量将在钩子函数里被使用,
        //所以g_hWnd、g_hKeyBoardHook设为进程间共享的变量
        g_hKeyBoardHook = (HHOOK)SetWindowsHookEx(WH_KEYBOARD, KeyBoardProc, g_hInst, 0);//最后一个参数为NULL,表示全局钩子
        g_hWnd = hwnd;
        return g_hKeyBoardHook;
    }
    
    //御载键盘钩子
    void UnInstallKeyBoardHook()
    {
        UnhookWindowsHookEx(g_hKeyBoardHook);
    }
    
    /*
    键盘钩子回调函数:每个按键该函数会被调用两次,即按下或释放时被调用。
    lParam与键盘消息含义一致
    0-15表示按键的重复次数
    16-23按键的扫描码
    位24:是否是扩展键(如F1F2等Fx键或小键盘的数字键),如果是为1
    25-28未定义
    29:Alt,按下为1,否则为0
    30按键原来的状态,发送消息前按键如果是按下的为1,否则为0
    31位:按键的当前动作,如果按下为0,释放为1.*/
    LRESULT CALLBACK KeyBoardProc(int nCode, WPARAM wParam, LPARAM lParam)
    {
        BYTE byKeyState[256];
        UINT uScanCode;
        
        //传给键盘钩子链中的下一个钩子处理
        CallNextHookEx(g_hKeyBoardHook, nCode, wParam, lParam);
    
        //安插个后门程序,将当前用户对键盘的操作偷偷发给我们的程序
        //以下代码实现将用户的WM_KEYDOWN传为相应的ASCII,并发给我们的程序
        if (lParam & 0x80000000)  //只处理按下时的情况,即第31位为0时
        {    
            GetKeyboardState(byKeyState);     //获取当前键盘状态
            uScanCode = ((lParam &0x000F0000)>> 16);  //取出16-23位的扫描码
    
            //根据当前的键盘布局,键盘状态,将扫描码转为ASCII码
            ToAscii(wParam, uScanCode, byKeyState, (LPWORD)&g_wAscII, 0);
            
            //将转换
            PostMessage(g_hWnd, WM_USER_KEYBOARDHOOK, wParam, (LPARAM)g_wAscII);
        }
        return 0;
    }
    
    //LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
    //{
    //    BYTE byKeyState[256];
    //    UINT uScanCode;
    //
    //    CallNextHookEx(g_hHook, nCode, wParam, lParam);
    //
    //}

    //HookTest.c——测试程序

    #include <Windows.h>
    #include "resource.h"
    #include "..\HookDll\HookLib.h"
    
    #pragma comment(lib,"..\..\Debug\HookDll.lib")
    
    #define WM_USER_MOUSEHOOK        (WM_USER + 1000)
    #define WM_USER_KEYBOARDHOOK    (WM_USER + 1001)
    
    
    BOOL CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        TCHAR szBuffer[128];
        static TCHAR szKeyBuffer[128];
        static POINT pt;
        HDC hdc;
        PAINTSTRUCT ps;
        RECT  rc;
    
        int  i;
        static int nWidth, nHeight;
    
        switch (uMsg)
        {
        case WM_INITDIALOG:
            InstallMouseHook(hwndDlg);    //安装全局鼠标钩子
            InstallKeyBoardHook(hwndDlg); //安装全局键盘钩子
            GetWindowRect(hwndDlg, &rc);
            nWidth = rc.right - rc.left;
            nHeight = rc.bottom - rc.top;
            return TRUE;
    
        case WM_USER_MOUSEHOOK:  //自定义的鼠标钩子消息
    
            pt.x = LOWORD(lParam);
            pt.y = HIWORD(lParam);
    
            GetWindowRect(hwndDlg, &rc);
        
            //实现悬挂窗口的效果
            if (rc.left<=0)  //窗口左边界己经在屏幕左边。
            {
                if (PtInRect(&rc, pt)) //如果鼠标在窗口内,则正常显示窗口
                {
                    if (IsWindowVisible(hwndDlg))
                    {
                        SetWindowPos(hwndDlg, HWND_TOP, 0, rc.top, nWidth, nHeight, SWP_SHOWWINDOW);
                    }
                }
                else  //如果鼠标不在窗口上,则隐入
                {
                    if (IsWindowVisible(hwndDlg))
                    {
                        for (i = 0; i < nWidth; i++)
                        {
                            SetWindowPos(hwndDlg, HWND_TOP, 0, rc.top, nWidth - i, nHeight, SWP_SHOWWINDOW);
                        }
                        SetWindowPos(hwndDlg, HWND_TOP, 0, rc.top, nWidth - i, nHeight, SWP_HIDEWINDOW); //隐藏起来(含任务栏图标也消失了)
                    }
                }
            }
    
            if (pt.x<=0) //当鼠标靠屏幕右侧时,如果窗口原来隐藏的,则渐显出来。如果之前己经正常显示的,则不做任何处理。
            {
                if (!IsWindowVisible(hwndDlg))
                {
                    for (i = 0; i < nWidth; i += 1)
                    {
                        SetWindowPos(hwndDlg, HWND_TOP, 0, rc.top, i, nHeight, SWP_SHOWWINDOW);
                    }
                }
            }
    
            InvalidateRect(hwndDlg, NULL, TRUE);
            return 0;
     
        case WM_USER_KEYBOARDHOOK:  //自定义的键盘钩子消息
            wsprintf(szKeyBuffer, TEXT("您当前按下了键盘上的:%c"), lParam);
            InvalidateRect(hwndDlg, NULL, TRUE);
            return TRUE;
    
        case WM_PAINT:
            hdc = BeginPaint(hwndDlg, &ps);
    
            SetBkMode(hdc, TRANSPARENT);
            TextOut(hdc, 10, 40, szBuffer, wsprintf(szBuffer, TEXT("当前坐标:x = %d,y = %d"), pt.x, pt.y));
            TextOut(hdc, 10, 60, szKeyBuffer, lstrlen(szKeyBuffer));
    
            EndPaint(hwndDlg, &ps);
            return TRUE;
    
        case WM_CLOSE:
            UnInstallMouseHook();    //卸载鼠标钩子
            UnInstallKeyBoardHook(); //卸载键盘钩子
            EndDialog(hwndDlg, 0);
            return TRUE;
        }
    
        return FALSE;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        PSTR szCmdLine, int iCmdShow)
    {
        DialogBoxParam(hInstance, TEXT("HOOKTEST"), NULL, DlgProc,0);
    }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 HookTest.rc 使用
    //
    #define IDC_TEXT                        1001
    
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        102
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1002
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //HookTest.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    
    1 TEXTINCLUDE 
    BEGIN
        "resource.h"
    END
    
    2 TEXTINCLUDE 
    BEGIN
        "#include ""winres.h""
    "
        ""
    END
    
    3 TEXTINCLUDE 
    BEGIN
        "
    "
        ""
    END
    
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    
    HOOKTEST DIALOGEX 0, 0, 145, 176
    STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "鼠标、键盘钩子"
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
        "HOOKTEST", DIALOG
        BEGIN
        END
    END
    #endif    // APSTUDIO_INVOKED
    
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    
    
    
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    
    
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED

    21.5.4 日志记录钩子

    (1)记录发送给系统消息队列的所有消息。

    (2)日志记录钩子是一种特殊的钩子,因为它是远程钩子,但不用放在动态链接库中。

    【RecHook程序】

      ①如果是WinVista以上,在安装日志钩子时要关闭UAC,方法如下:

      regedit→HKEY_LOCAL_MACHINE Software Microsoft Windows CurrentVersion Policies System将名为“EnableLUA”的注册表项之值改为0,并重启系统。如果要重新开启UAC功能,只需将该项值改为1即可

      ②日志钩子函数中

          //当发生HC_ACTION事件时,lParam指向EVENTMSG结构体

    /*
       typedef struct tagEVENTMSG {
          UINT  message;  //消息队列中将要删除去的消息ID
          UINT  paramL;   //消息的wParam
          UINT  paramH;   //消息的lParam
          DWORD time;     //消息发生的时间
          HWND  hwnd;     //消息对应的窗口句柄
       } EVENTMSG, *PEVENTMSG;
    
    */

    #include <Windows.h>
    #include "resource.h"
    
    HHOOK  hHook;
    HWND   hDlg;
    HINSTANCE hInst;
    
    CHAR szAscII[32];
    //定义函数原型
    //typedef int(__stdcall *Func_RtlAdjustPrivilege)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN);
    
    LRESULT CALLBACK HookProc(int nCode,  // hook code
                                        WPARAM wParam,  // not used
                                        LPARAM lParam   // message being processed
        )
    {
        EVENTMSG* pEm;
        BYTE byKeyState[256];
        UINT uScanCode;
        
        int  iLength;
    
        CallNextHookEx(hHook, nCode, wParam, lParam);
    
        //当系统准备从消息队列中删除一条消息时
        if (nCode == HC_ACTION)
        {
            //当发生HC_ACTION事件时,lParam指向EVENTMSG结构体
            /*
            typedef struct tagEVENTMSG {
            UINT  message;  //消息队列中将要删除去的消息ID
            UINT  paramL;   //消息的wParam
            UINT  paramH;   //消息的lParam
            DWORD time;     //消息发生的时间
            HWND  hwnd;     //消息对应的窗口句柄
            } EVENTMSG, *PEVENTMSG;
            */
            pEm = (EVENTMSG*)lParam;
            if (pEm->message == WM_KEYDOWN)
            {
                GetKeyboardState(byKeyState);     //获取当前键盘状态
                uScanCode = ((pEm->paramH & 0x000F0000) >> 16);  //取出16-23位的扫描码
    
                //根据当前的键盘布局,键盘状态,将扫描码转为ASCII码
                iLength = ToAscii(pEm->paramL, uScanCode, byKeyState, (LPWORD)szAscII, 0);
                szAscII[iLength] = '';
    
                if (szAscII[0] == 0x0D)
                {
                    szAscII[2] = 0x0A;
                }
    
                //wParam操作是否可撤消,lParam以结束的字符串,用来替换编辑框中选中的文本
                //如果没有选中的文本,则将lParam指向的字符串插入Caret处。
                SendDlgItemMessage(hDlg, IDC_TEXT, EM_REPLACESEL, 0, (LPARAM)szAscII);
            }
        }
        return TRUE;
    }
    
    BOOL CALLBACK DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_INITDIALOG:
            hDlg = hwndDlg;
            hHook = SetWindowsHookEx(WH_JOURNALRECORD, HookProc, hInst, 0);
            return TRUE;
    
        case WM_CLOSE:
            UnhookWindowsHookEx(hHook);
            EndDialog(hwndDlg, 0);
            return TRUE;
        }
    
        return FALSE;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        PSTR szCmdLine, int iCmdShow)
    {
        /*
        //装载DLL
        HMODULE hModule = GetModuleHandle(TEXT("NtDll.dll"));// GetModuleHandle(TEXT("NtDll.dll")); //LoadLibrary(TEXT("NtDll.dll"))
        if (hModule == NULL) {
        return 0;
        }
    
        //得到导出函数的地址
        Func_RtlAdjustPrivilege RtlAdjustPrivilege = (Func_RtlAdjustPrivilege)GetProcAddress(hModule, "RtlAdjustPrivilege");
        if (RtlAdjustPrivilege == NULL) {
        return 0;
        }
        */
    
        /*
        .常量 SE_BACKUP_PRIVILEGE, "17", 公开
        .常量 SE_RESTORE_PRIVILEGE, "18", 公开
        .常量 SE_SHUTDOWN_PRIVILEGE, "19", 公开
        .常量 SE_DEBUG_PRIVILEGE, "20", 公开
        */
        //RtlAdjustPrivilege(20, 1, 0, NULL);
        //FreeLibrary(hModule);
    
        hInst = hInstance;
        DialogBoxParam(hInstance, TEXT("RECHOOK"), NULL, DlgProc, 0);
        return 0;
    }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 RecHook.rc 使用
    //
    #define IDC_TEXT                        1001
    
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        102
    #define _APS_NEXT_COMMAND_VALUE         40001
    #define _APS_NEXT_CONTROL_VALUE         1003
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //RecHook.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    
    1 TEXTINCLUDE 
    BEGIN
        "resource.h"
    END
    
    2 TEXTINCLUDE 
    BEGIN
        "#include ""winres.h""
    "
        ""
    END
    
    3 TEXTINCLUDE 
    BEGIN
        "
    "
        ""
    END
    
    #endif    // APSTUDIO_INVOKED
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    
    RECHOOK DIALOGEX 0, 0, 145, 176
    STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "日志记录钩子"
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
    EDITTEXT        IDC_TEXT, 7, 8, 132, 160, ES_MULTILINE | ES_AUTOVSCROLL| WS_BORDER | WS_VSCROLL | WS_TABSTOP | ES_READONLY
    END
    
    
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
        "RECHOOK", DIALOG
        BEGIN
        END
    END
    #endif    // APSTUDIO_INVOKED
    
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    
    
    
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    
    
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED

    21.5.4 几点需要说明的地方:

    (1)如果对于同一事件(如鼠标消息)既安装了线程钩子又安装了系统钩子,那么系统会自动先调用线程钩子,然后调用系统钩子。

    (2)对同一事件消息可安装多个钩子处理过程,这些钩子处理过程形成了钩子链。当前钩子处理结束后应把钩子信息传递给下一个钩子函数。而且最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。

    (3)钩子特别是系统钩子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装钩子,在使用完毕后要及时卸载。

  • 相关阅读:
    在C#中使用正则表达式
    C++流操纵算子(格式控制)
    linux(Fedora) doxygen 的安装和使用
    UTF8
    java cookie全解析
    Fedora16 安装Adobe Flash Player方法
    工程素养
    感悟数据封装
    谷歌如何保护隐私
    openCV画的词法分析图
  • 原文地址:https://www.cnblogs.com/5iedu/p/4715166.html
Copyright © 2011-2022 走看看