ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

第21章:Windows消息钩取

2020-07-22 22:33:56  阅读:365  来源: 互联网

标签:hDll 21 Windows 钩子 钩取 DLL hHook NULL DEF


Windows向用户提供GUI,以事件驱动的方式工作.

 

常规的Windows消息流:

发生键盘输入事件时,WM_KeyDown消息被添加到OS消息队列.

OS判断哪个应用程序发生了事件,然后从OS消息队列重取出消息,添加到应用程序的消息队列中.

应用程序监视自身的消息队列,发现新添加的消息后,调用相应的事件处理程序处理.

SetWindowsHookEx()可以实现消息钩取.

第一个参数是钩子类型,例如可以为 WH_KeyBoard ,键盘钩子.

第二个参数是钩子过程,是由操作系统调用的回调函数,说白了就是处理程序.

第三个参数是钩子过程所属的DLL句柄,因为钩子过程需要存在于某个DLL内部.

第四个参数代表想要影响的进程,若为0则影响所有进程.

 

可执行程序加载并安装钩子 -> 其它进程发生硬盘输入事件 -> OS将Dll文件加载到相应得进程内存 -> 调用回调函数

重点看一下HookMain.exe文件的源代码.

#include "stdio.h"
#include "conio.h"
#include "windows.h"

#define    DEF_DLL_NAME        "KeyHook.dll"
#define    DEF_HOOKSTART        "HookStart"
#define    DEF_HOOKSTOP        "HookStop"

typedef void (*PFN_HOOKSTART)();
typedef void (*PFN_HOOKSTOP)();   //声明一个返回值为NULL的函数指针

void main()
{
    HMODULE            hDll = NULL;
    PFN_HOOKSTART    HookStart = NULL;    //定义函数指针
    PFN_HOOKSTOP    HookStop = NULL;    //函数指针赋值为NULL,避免成为野指针
    char            ch = 0;

    // 加载 KeyHook.dll
    hDll = LoadLibraryA(DEF_DLL_NAME);
    if( hDll == NULL )
    {
        printf("LoadLibrary(%s) failed!!! [%d]", DEF_DLL_NAME, GetLastError());
        return;
    }

    // 获取导出函数地址
    HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);   // 将函数返回值转换为自定义的类型
    HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);

    // 开始钩取
    HookStart();
printf("press 'q' to quit!\n"); while( _getch() != 'q' ) ; // 终止钩取 HookStop(); // 卸载KeyHook.dll FreeLibrary(hDll); }
#include "stdio.h"
#include "windows.h"

#define DEF_PROCESS_NAME   "notepad.exe"

HINSTANCE g_hInstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
    switch( dwReason )
    {
        case DLL_PROCESS_ATTACH:
            g_hInstance = hinstDLL;
            break;

        case DLL_PROCESS_DETACH:
            break;    
    }

    return TRUE;
}

LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)    //此处猜测是覆写了KeyBoardProc()函数
{
    char szPath[MAX_PATH] = {0,};
    char *p = NULL;

    if( nCode >= 0 )
    {
        // bit 31 : 0 => press, 1 => release
        if( !(lParam & 0x80000000) )
        {
            GetModuleFileNameA(NULL, szPath, MAX_PATH);
            p = strrchr(szPath, '\\');     //返回字符串中从右侧搜索首次出现字符 \\ 的地址。

           
            if( !_stricmp(p + 1, DEF_PROCESS_NAME) )    //字符串相等时,返回值为0
                return 1;                               //程序为notepad.exe时,直接返回1即不将键盘按键数据传到应用程序
        }
    }

    // 若当前进程名称不是notepad.exe则调用 CallNextHookEx() 函数,将消息传递给应用程序或下一个钩子
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

#ifdef __cplusplus
extern "C" {
#endif
    __declspec(dllexport) void HookStart()             //declspec是针对编译器的关键字,指出相应函数为导出函数
    {
        g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
    }

    __declspec(dllexport) void HookStop()
    {
        if( g_hHook )
        {
            UnhookWindowsHookEx(g_hHook);
            g_hHook = NULL;
        }
    }
#ifdef __cplusplus
}
#endif

 

安装好键盘钩子之后,无论哪个进程发生键盘输入事件,OS会将KeyHook.dll注入到相应进程,而此进程发生键盘事件时也会首先调用执行 KeyHook.KeyboardProc()

Printf()函数看着简单,其实挺复杂的.

 

标签:hDll,21,Windows,钩子,钩取,DLL,hHook,NULL,DEF
来源: https://www.cnblogs.com/Rev-omi/p/13361775.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有