Windows 使用 Detours 进行 HOOK

一、detours 的下载和编译

1、下载 Detours:GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form.Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form. - GitHub - microsoft/Detours: Detours is a software package for monitoring and instrumenting API calls on Windows. It is distributed in source code form.https://github.com/microsoft/Detours

2、编译

cd Detours\vc
打开 Detours.sln 编译运行

如果编译失败,重定向一下解决方案 

3、编译运行成功之后会生成 detours.lib

4、使用头文件和 detours.lib

二、使用 detours.lib 进行 Hook

这里我们进行 SendMessage 的 Hook,Hook 新定义的输出函数要和原函数参数是一样的

1、进行 API 的 Hook

主要函数

LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer,
                         _In_ PVOID pDetour);

第一个参数是原来的函数的地址,第二个参数是 Hook 之后的函数名称

void Hook() {
    DetourRestoreAfterWith();
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    //这里可以连续多次调用DetourAttach,表明HOOK多个函数
    DetourAttach(&(PVOID&)OldSendMessage, NewSendMessage);
    DetourTransactionCommit();
}

2、取消 Hook

void UnHook() {
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    //这里可以连续多次调用DetourDetach,表明撤销多个函数HOOK
    DetourDetach(&(PVOID&)OldSendMessage, NewSendMessage);
    DetourTransactionCommit();
}

3、具体代码

#include <Windows.h>
#include <iostream>
#include <thread>

#include "detours.h"

HWND hwnd;

static LRESULT(WINAPI* OldSendMessage)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) = SendMessage;
LRESULT WINAPI NewSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
    MessageBox(hwnd, TEXT("就不关闭!"), TEXT("关闭程序"), MB_OK | MB_ICONINFORMATION);
    return 0;
}

void Hook() {
    DetourRestoreAfterWith();
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    //这里可以连续多次调用DetourAttach,表明HOOK多个函数
    DetourAttach(&(PVOID&)OldSendMessage, NewSendMessage);
    DetourTransactionCommit();
}

void UnHook() {
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    //这里可以连续多次调用DetourDetach,表明撤销多个函数HOOK
    DetourDetach(&(PVOID&)OldSendMessage, NewSendMessage);
    DetourTransactionCommit();
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        // MessageBox(hwnd, TEXT("关闭程序!"), TEXT("结束"), MB_OK | MB_ICONINFORMATION);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

int main(void) {
    Hook();
    static TCHAR szAppName[] = TEXT("TextWindow");
    MSG msg;
    WNDCLASS wndclass;
    // wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;                         //窗口样式
    wndclass.lpszClassName = szAppName;                               //窗口类名
    wndclass.lpszMenuName = NULL;                                     //窗口菜单:无
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);    //窗口背景颜色
    wndclass.lpfnWndProc = WndProc;                                   //窗口处理函数
    wndclass.cbWndExtra = 0;                                          //窗口实例扩展:无
    wndclass.cbClsExtra = 0;                                          //窗口类扩展:无
    wndclass.hInstance = GetModuleHandle(0);                                   //窗口实例句柄
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);               //窗口最小化图标:使用缺省图标
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);                 //窗口采用箭头光标
    UnregisterClass(wndclass.lpszClassName, GetModuleHandle(0));
    if (!RegisterClass(&wndclass)) {    
        MessageBox(NULL, TEXT("窗口注册失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName, TEXT("测试窗口"), WS_OVERLAPPEDWINDOW,
        0, 0, 500, 400, NULL, NULL, GetModuleHandle(0), NULL);

    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);
    std::thread close_work = std::thread([&]() {
        for (int i = 0; i < 5; ++i) {
            std::cout << "close work: " << 5 - i << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        }
        ::SendMessage(hwnd, WM_CLOSE, 0, 0);
        });
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    if (close_work.joinable()) {
        close_work.join();
    }
    std::cout << "Finish" << std::endl;
    UnHook();
    getchar();
    return 0;
}

4、运行结果

正常情况下如果不 Hook 的话,5s 过后窗口就退出了,使用 Hook 的话 5s 过后程序也不会退出

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值