逆向工程核心原理——消息钩取

本文详细介绍了Windows操作系统中的消息钩子(Hook)机制,特别是在GUI环境下,如何通过SetWindowsHookEx函数设置键盘钩子,拦截并控制特定进程(如记事本)的键盘输入。通过示例代码展示了如何创建和卸载动态库(DLL)来实现键盘钩子,当钩子激活时,记事本的键盘输入会被阻止,而其他应用不受影响。用户可以通过输入'q'退出钩子状态,恢复正常输入。
摘要由CSDN通过智能技术生成

钩子(HOOK)

英文Hook一词,翻成中文是“钩子”、“鱼钩”的意思,泛指钓取所需东西而使用的一切工 具。“钩子”这一基本含义延伸发展为“偷看或截取信息时所用的手段或工具”。下面举例向各位 进一步说明“钩子”这一概念。

消息钩取

Windows操作系统向用户提供GUI (Graphic User Interface,图形用户界面),它以事件驱动 (Event Driven方式工作。在操作系统中借助键盘、鼠标,选择菜单、按钮,以及移动鼠标、改 变窗口大小与位置等都是事件(Event )o发生这样的事件时,OS会把事先定义好的消息发送给相 应的应用程序,应用程序分析收到的信息后执行相应动。也就是说,敲击键盘时,消息会从OS移动到应用程序。所谓的“消息钩子

通过Windows消息的钩取

HHOOK SetWindowsHookEx(
    int idHook,                        // hook type
    HOOKpROC lpfn,                // hook procedure
    HINSTANCE hMod,                //hook procedure所属的DLL句柄
    DWORD dwThreadId            //需要挂钩的线程ID,为0时表示为全局钩子(Global Hook)
);

hook proceduce是由操作系统调用的回调函数;安装消息钩子时,钩子过程需要存在于某个DLL内部,且该DLL的示例句柄即为hMod。

使用SetWindowsHookEx()设置好钩子后,在某个进程中生成指定消息时,OS就会将相关的DLL文件强制注入(injection)相应进程,然后调用注册的钩子程序。

我们通过一个HookMain.exe实现对将要注入的dll的控制。

//HookMain.cpp
 
#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)();
 
int main()
{
    HMODULE hDll=NULL;
    PFN_HOOKSTART HookStart=NULL;
    PFN_HOOKSTOP HookStop=NULL;
    char ch=0;
 
    //加载KeyHook.dll
    hDll=LoadLibraryA(DEF_DLL_NAME);
 
    //获取导出函数地址
    HookStart=(PFN_HOOKSTART)GetProcAddress(hDll,DEF_HOOKSTART);
    HookStop=(PFN_HOOKSTART)GetProcAddress(hDll,DEF_HOOKSTOP);
 
    //开始钩取
    HookStart();
 
    //等待直到用户输入“q”
    printf("press 'q' to quit!\n");
    while(_getch()!='q');
 
    //终止钩取
    HookStop();
 
    //卸载KeyHook.dll
    FreeLibrary(hDll);
    return 0;
}

#define DEF_DLL_NAME "D:\\攻防对抗\\Dll2\\Debug\\Dll2.dll" 

dll的路径要替换成自己的路径,填写自己的,并且使用转义字符。

 dll代码,建立动态库

#include "main.h"
#include <winnt.h>
#include <windef.h>
 
// a sample exported function
#define DEF_PROCESS_NAME "notepad.exe"
HINSTANCE g_hInstance=NULL;
HHOOK g_hHook=NULL;
HWND g_hWnd=NULL;
 
// a sample exported function
//LRESULT是一个数据类型,指的是从窗口程序或者回调函数返回的32位值
//lParam wParam 是宏定义,一般在消息函数中带着两个类型的参数,通常用来存储窗口消息的参数。wParam用来存储小段消息,如标志。lParam 通常用于存储消息所需的对象。
LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
    char szPath[MAX_PATH]={0,};
    char *p=NULL;
 
    if (nCode>=0)
    {
        //0=key press,1=key release
        if (!(lParam&0x80000000))//释放键盘按键时
        {
            GetModuleFileNameA(NULL,szPath,MAX_PATH);
            p=strrchr(szPath,'\\');//查找字符在指定字符串中从左面开始的最后一次出现的位置
 
            //比较当前进程名称,若为notepad.exe,则消息不会传递给应用程序(或下一个“钩子”)
            if (!_stricmp(p+1,DEF_PROCESS_NAME))
                return 1;
        }
 
    }
 
    //若非notepad.exe,则调用CallNextHookEx()函数,将消息传递给应用程序(或下一个“钩子”)。
    return CallNextHookEx(g_hHook,nCode,wParam,lParam);
 
}
 
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            g_hInstance=hinstDLL;
            break;
 
        case DLL_PROCESS_DETACH:
            // detach from process
            break;
 
        case DLL_THREAD_ATTACH:
            // attach to thread
            break;
 
        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}
#ifdef __cplusplus
extern "C"
{
#endif
 
 
    __declspec(dllexport) void HookStart()
    {
        //钩子类型、回调函数地址、实例句柄、线程ID
        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

 

打开笔记本

调试,启动DLL和EXE(一定是先调试运行DLL,再调试运行EXE)

会弹出窗口

先向记事本输入,会发现键盘被锁住了,不管输入什么,都不会有输出

但是向浏览器或是WSP输入,都是没有问题的

在窗口里输入"q"回车就能退出

记事本就可以写东西啦 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值