zoukankan      html  css  js  c++  java
  • HOOK 技术

    在介绍 截获系统消息钩子 之前,这几个函数是密切相关的:

    SetWindowsHookEx() 介绍:

    功能:将应用程序定义的挂钩过程安装到挂钩链中。

    函数原型:HHOOK SetWindowsHookEx(
                      int   idHook,  // 钩子类型。
                      HOOKPROC  lpfn, // 指向挂钩过程的指针。
                      HINSTANCE   hmod, // 包含 lpfn 参数指向的挂钩过程的 DLL 的句柄。
                      DWORD   dwThreadId // 与挂钩过程关联的线程的标识符。如果为 0,则为全局钩子。
                      );

    返回值:如果函数成功, 则返回值是挂钩过程的句柄。如果函数失败, 返回值为 NULL。

    参数 idHook:

    含义
    WH_CALLWNDPROC 安装的钩子过程监视信息在系统将它们发送给目标窗口之前。
    WH_CALLWNDPROCRET 安装的钩子过程监视信息在系统将它们发送给目标窗口之后。
    WH_KEYBOARD 安装监视击键消息的挂钩过程。
    WH_MOUSE 安装监视鼠标消息的挂钩过程。
    WH_GETMESSAGE 安装用于监视将消息发送给消息队列的挂钩过程
    WH_DEBUG 安装用于调试其他挂钩过程的挂钩过程。

    CallNextHookEx() 介绍:

    功能:将挂钩信息传递到当前挂钩链中的下一个挂钩过程。钩子过程可以在处理钩子信息之前或之后调用此函数。

    函数原型:LRESULT CallNextHookEx(
                      HHOOK  hhk,  // 通常被忽略。
                      int  nCode,  // 传递给当前挂钩过程的挂钩代码。下一个挂钩过程使用此代码来确定如何处理挂钩信息。
                      WPARAM  wParam, // 传递给当前挂钩过程的 wParam 值。此参数的含义取决于与当前挂钩链关联的挂钩的类型。
                      LPARAM  lParam // 传递给当前挂钩过程的 lParam 值。此参数的含义取决于与当前挂钩链关联的挂钩的类型。
                      );

    返回值:此值由链中的下一个挂钩过程返回。当前挂钩过程还必须返回此值。返回值的含义取决于挂钩类型。

    UnhookWindowsHookEx() 介绍:

    功能:移除由 SetWindowsHookEx 函数安装在钩子链中的挂钩过程。

    函数原型:BOOL UnhookWindowsHookEx(
                      HHOOK hhk // 要移除的钩子的句柄。
                      );

    返回值:非零表示成功,零表示失败。

    用户自定义钩子:(生成 dll 文件,并注入到相应的进程)

    #include<windows.h>
    #include<stdlib.h>
    HANDLE hProc;
    FARPROC pfMessageBoxA;
    FARPROC pfMessageBoxW;
    // 注意:自定义函数得和被 HOOK 函数的形式一样,否则会发生异常。
    int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR sl, UINT u); int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR sl, UINT u); BYTE OldMessageBoxACode[5], NewMessageBoxACode[5]; BYTE OldMessageBoxWCode[5], NewMessageBoxWCode[5]; DWORD CurrentProcessId, dwOldProtect;; BOOL BHook = FALSE; BOOL Init(); void HookOn(); void HookOff(); BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: Init(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: HookOff(); break; } return TRUE; } BOOL Init() { HMODULE hModule; DWORD Address; hModule = LoadLibraryA("user32.dll"); pfMessageBoxA = GetProcAddress(hModule, "MessageBoxA"); pfMessageBoxW = GetProcAddress(hModule, "MessageBoxW"); if (pfMessageBoxA == NULL || pfMessageBoxW == NULL) return FALSE; memcpy(OldMessageBoxACode,pfMessageBoxA,5); // 拷贝原来函数地址的前五个字节以备复原。 NewMessageBoxACode[0] = 0xe9; // 即 jmp 指令。 Address = (DWORD)MyMessageBoxA - (DWORD)pfMessageBoxA - 5; // 自定义函数与原函数的偏移地址。 memcpy(NewMessageBoxACode+1,&Address,4); memcpy(OldMessageBoxWCode,pfMessageBoxW,5); NewMessageBoxWCode[0] = 0xe9; Address = (DWORD)MyMessageBoxW - (DWORD)pfMessageBoxW - 5; memcpy(NewMessageBoxWCode+1,&Address,4); CurrentProcessId = GetCurrentProcessId(); HookOn(); return TRUE; } int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR pl, UINT u) { HookOff(); MessageBoxA(hWnd, "请重新安装系统", "重要提示", MB_OK); HookOn(); return TRUE; } int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR pl, UINT u) { HookOff(); MessageBoxW(hWnd, L"请重新安装系统", L"重要提示", MB_OK); HookOn(); return TRUE; } void HookOn() { hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, CurrentProcessId); // 打开进程,关闭内存保护,向内存空间前五个字节写入 jmp 指令,最后打开进程保护。 VirtualProtectEx(hProc, pfMessageBoxA, 5, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProc, pfMessageBoxA, NewMessageBoxACode, 5, 0); VirtualProtectEx(hProc, pfMessageBoxA, 5, dwOldProtect, &dwOldProtect); VirtualProtectEx(hProc, pfMessageBoxW, 5, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProc, pfMessageBoxW, NewMessageBoxWCode, 5, 0); VirtualProtectEx(hProc, pfMessageBoxW, 5, dwOldProtect, &dwOldProtect); CloseHandle(hProc); BHook = TRUE; } void HookOff() { hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, CurrentProcessId); // 同理,只不过是复原内存指令。 VirtualProtectEx(hProc, pfMessageBoxA, 5, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProc, pfMessageBoxA, OldMessageBoxACode, 5, 0); VirtualProtectEx(hProc, pfMessageBoxA, 5, dwOldProtect, &dwOldProtect); VirtualProtectEx(hProc, pfMessageBoxW, 5, PAGE_READWRITE, &dwOldProtect); WriteProcessMemory(hProc, pfMessageBoxW, OldMessageBoxWCode, 5, 0); VirtualProtectEx(hProc, pfMessageBoxW, 5, dwOldProtect, &dwOldProtect); CloseHandle(hProc); BHook = FALSE; }

     注入后,如下图所示:

  • 相关阅读:
    QT基础知识总结(一)
    二叉树知识总结(二)
    二叉树知识总结(一)
    C++ 封装,继承,多态总结
    Win API学习笔记——文件系统(二)
    Win API学习笔记——文件系统(一·)
    Go项目: package project/name is not in GOROOT
    创建`Vue-CLI`项目
    npm与yarn介绍与常用命令
    Powershell-"无法加载文件,因为在此系统上禁止运行脚本"
  • 原文地址:https://www.cnblogs.com/M-Anonymous/p/9737447.html
Copyright © 2011-2022 走看看