我正在研究用Jeffrey Richter的方法来HOOK API,但是却遇到一个奇怪的问题。
    我现在是照着他的方法来Hook MessageBox,如果我得例程中直接调用::MessageBox,并且是Debug方式就可以正常的HOOK住MessageBox,但是如果是调用的CWnd的MessageBox就不行了,而且如果编译的方式是Release时即时调用的::MessageBox也Hook不到,不知道是怎么回事。
    有没有哪位对这方面有研究,知道是怎么回事?

解决方案 »

  1.   

    这个种HookAPI的方法只有在目标函数在PE文件的import table中时才有用,调用CWnd的MessageBox时,由于没有引入MessageBox函数,所以HOOK不到,在Release时不能hook到说明你的程序有问题。
      

  2.   

    有两个地方要注意:
    1.
     //必须修改相应的页面属性,否则有可能无法写入代码
    VirtualProtect(ppfn,sizeof(pfnNew),PAGE_READWRITE,&dwOldProtect);
    WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew,sizeof(pfnNew), NULL);
    VirtualProtect(ppfn,sizeof(pfnNew),dwOldProtect,0);
    2.
    在debug模式下,你调用CWnd::MessageBox的时候,实际上是在调用从mfc42d.dll导出的CWnd::MessageBox函数,而mfc42d.dll又从user32.dll导入了MessageBox,所以如果你只修改EXE本身的IAT,是不能HOOK到MFC函数的,你要把mfc42d.dll的IAT中的MessageBox地址也改写掉才有用。
      

  3.   

    哦,多谢两位指教。那我还想问一下,那如果我要hook比如::WriteFile等文件I/O函数,是不是都会出现MessageBox的这种问题呢,如果其他程序调用的是CFile的Write函数,那不就是说将会hook不到了?
      

  4.   

    总的来说,所有的文件操作都应该是通过API函数来进行的。不管程序使用了什么库,这个库的实现最终来是要调用API才能实现其功能。所以,你只要把进程中每个模块中的WriteFile都HOOK掉就行了。
      

  5.   

    但是用这种方法那就应该很不保险了,它应该就类似于MessageBox的hook,我也是把所有进程都hook了,但是如果一个进程调用的API是由另一个库导出的,那就没法hook了,我怎么知道一个进程的所有的模块呢?
      

  6.   

    用ToolHelp函数族可以枚举进程中的所有模块:
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); 
    MODULEENTRY32 me32.dwSize = sizeof(MODULEENTRY32); 
    if (Module32First(hModuleSnap, &me32)) 

            do 
            { 
                 //HOOK这个模块中调用的API
            } 
            while (Module32Next(hModuleSnap, &me32)); 
    }