zpcdcsdn 2016-10-27 04:27 采纳率: 0%
浏览 2714

利用detours Hook全局API的问题

在下利用微软的detours写了一个Hook全局MessageBox的dll,代码比较短,先贴下,然后再说问题:

 #include"HookDll.h"
#include <detours.h>
#pragma comment(lib, "detours.lib") 

#pragma data_seg("Shared")
HHOOK mHook = NULL;
HINSTANCE hInstance = NULL;
#pragma data_seg()

int (WINAPI* OLD_MessageBoxW)(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) = MessageBoxW;
int (WINAPI* OLD_MessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) = MessageBoxA;


//自定义的代替函数

int WINAPI NEW_MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType)
{
    int ret = OLD_MessageBoxW(hWnd, L"已经被Hook!", L"Hook", uType);
    return ret;
}

int WINAPI NEW_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
    int ret = OLD_MessageBoxA(hWnd, "已经被Hook", "Hook", uType);
    return ret;
}

//启动Hook
VOID Hook()
{
    DetourRestoreAfterWith();
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    //Hook MessageBoxW和MessageBoxA
    DetourAttach(&(PVOID&)OLD_MessageBoxW, NEW_MessageBoxW);
    DetourAttach(&(PVOID&)OLD_MessageBoxA, NEW_MessageBoxA);

    DetourTransactionCommit();
}

//撤销Hook
VOID UnHook()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    //撤销Hook
    DetourDetach(&(PVOID&)OLD_MessageBoxW, NEW_MessageBoxW);
    DetourDetach(&(PVOID&)OLD_MessageBoxA, NEW_MessageBoxA);

    DetourTransactionCommit();
}

//挂钩函数
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    return CallNextHookEx(mHook, nCode, wParam, lParam);
}

//导出函数,安装一个针对WH_CALLWNDPROC的全局钩子
//WH_CALLWNDPROC:当目标线程调用SendMessage发送消息时,钩子函数被调用
extern "C" __declspec(dllexport) BOOL WINAPI Start()
{   
    mHook = ::SetWindowsHookEx(WH_CALLWNDPROC, CallWndProc, hInstance, 0);
    return mHook != NULL;
}

//卸载钩子
extern "C" __declspec(dllexport) void WINAPI Stop()
{
    ::UnhookWindowsHookEx(mHook);
}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH://当DLL被某个进程加载时,执行该case下的语句体
        {
            //在这里干两件事:1.启动Hook,Hook MessageBox
            //                2.获取本DLL的句柄
            //之所以只调用一次Hook,后面解释
            static int num = 1;
            if (1==num)
            {
                ++num;
                Hook();
            }
            hInstance = (HINSTANCE)hModule;
            break;
        }
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH://当DLL将被卸载时,执行下面的语句体
        {
            //UnHook();   //如果这里加上UnHook(),那MessageBox就不能被Hook了,后面再详述
            break;
        }
    }
    return TRUE;
}

在下在另一个MFC程序中加载上面的DLL,并且调用Start启动钩子。
按照在下的想法,当一个程序(假设为A)调用SendMessage函数发送消息时,系统会强行将该DLL映射到程序A的地址空间,并且执行case DLL_PROCESS_ATTACH下的语句体,即调用Hook函数,Hook程序A的MessageBox。
但事实是这样的:
在下在另一个C++程序中调用MessageBoxW,发现如下情况:
1.如果在case DLL_PROCESS_DETACH的语句体中加上UnHook调用,那么,无论调用多少次MessageBoxW,没有一次是被Hook的。
2.鉴于1,在下猜想可能是在调用MessageBoxW前就先执行UnHook了,于是干脆就将UnHook注释掉了,这是在调用MessageBoxW,发现,第一次调用没有被Hook,而后面再调用MessageBoxW就被Hook了。但这只是在下写的C++程序的表现,对于其它程序,如记事本,还依然没被Hook。
3.修改上面的DLL,不Hook MessageBox了,而改为Hook CopyFileW和Hook CopyFileA,这时,电脑上的复制粘贴都没有被Hook,自己写程序调用CopyFileW也没有被Hook,但是,在调用CopyFileW前调用一次MessageBoxW,后面的CopyFileW就被Hook了。
综上,在下的理解是:程序的一些行为,如调用MessageBox,才会导致调用SendMessage,进而导致加载DLL,这时才Hook相应的API。
在下想要的效果是:只要我运行一个程序(比如前边的启动钩子的MFC程序),电脑上所有的MessageBox都被Hook了。
在下对Windows消息机制不是特别熟悉,不知道在下的想法有问题还是代码写的有问题,还请诸位大神指点一二。在下先行谢过!

  • 写回答

1条回答 默认 最新

  • DRACULAX05 2016-10-27 10:40
    关注

    首先,detour hook只能作用于加载了你这个模块的进程,所以你说的“运行一个程序(比如前边的启动钩子的MFC程序),电脑上所有的MessageBox都被Hook了,这个用你的程序是没办法实现的,你想hook整个系统,只能保证你的dll被所有进程加载,这个比较困难,除非你注入成为资源管理器的插件或者系统必加载的模块
    而你hook SendMessage,不要所想替换整个系统的MessageBox,就是想替换你本进程的MessageBox都有问题,比如说你这个进程根本就不存在消息循环或者所有消息都是用PostMessage的方式发的,你根本hook不到
    我给你一个方案,你做一个资源管理器插件,让系统一启动就加载你,DllMain里hook CreateProcess,在CreateProcess里让目标进程加载你这个dll,然后再hook messagebox,当然即使这样也很难办,因为还有很多程序不是从资源管理器启动的,比如服务
    总而言之,你先搞清楚hook的本质,跨进程hook不是不可以,但是你要有目标进程的权限,把你的dll注入进去

    评论

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?