问题描述:采用全局钩子的方式将dll注入了目标进程,并成功hook了目标进程里的函数Fun。使其调用时会先进入我的函数Fun_My。这些都没有问题。但是在我要卸载钩子的时候,如果刚好代码执行在我的函数Fun_My的代码里。就会崩溃。因为我已经卸载了dll,也就是dll已经不在目标进程里了。这时候Fun_My也是无效的内容了,并不是以前的正确的代码段。所以目标进程就崩溃了。这种情况下,在我的dll执行detach即将卸载的时候,如何确保代码并不在Fun_My里面执行呢。当然我肯定是提前执行了对函数的unhook的,只是最后的一次hook到的函数,可能还在Fun_My里面执行,还没有执行完返回。这就出了问题。大家有遇到过么,或是思考过这个问题,有啥好的处理方法啊,关于技术的意见建议讨论都欢迎。感谢。

解决方案 »

  1.   

    如果是IAT/EAT HOOK,则先恢复导入/导出表,再行卸载。其他方式各有类似恢复手段。
    再有一种则是将代码二进制,然后直接远程注入,这样无dll亦可。
      

  2.   


     多谢回答。和我的问题不太一致啊。如何unhook处理我知道。我意思是,代码正在执行Fun_My的时候。请注意这时候地址是在我的dll的空间里的,因为执行的是Fun_My我的hook函数,如果在Fun_My还没有执行完,还没返回的时候,我做了unhook操作,这时候就会卸载我的dll,可又正在执行dll里的Fun_My函数,执行的代码所在模块被卸载,肯定就崩溃了
      

  3.   

    把卸载部分也做一个导出接口, Hook 部分进入Hook函数的时候设置个标记, 退出时清除
    DLL中卸载时先等待标记无效时再卸载
      

  4.   

    参考WinAPIOverride32源代码?
      

  5.   

    看了WinAPIOverride32源代码,主要是不同的hook方式的实现。针对unhook就是按常规做的,并没有特殊的处理。也就是说,它也存在这个问题。
      

  6.   

    这么看来你hook的函数要么是被频繁调用的,要么是处理耗时较长的,问题本质上就是多线程安全。可模拟COM那样加个引用计数,并在你的处理函数中内置标记unhook
      

  7.   

    你这里卸载dll是为了什么
      

  8.   


    因为我的监测程序关闭了啊。那我做的全局hook,肯定是要unhook的。注入的对应dll自然也会detach
      

  9.   

    你的这个问题类似于 DLL 如何卸载自身的问题。
    在你的函数需要卸载 DLL 的时候,在呼叫卸载函数的时候,压入返回地址,进入你卸载后需要执行的代码。
    在你的卸载函数结束的时候,手动弹出返回堆栈,这样 ret 返回的时候,就可以进入你设定的代码了。
      

  10.   

    感谢回答,你说得是另一个问题了。目前我的问题是,已经卸载后,还有其他地方还在继续调用执行已经不存在的dll地址里的函数,所以崩溃。
      

  11.   

    如果你的DLL没有卸载的话(FreeLibrary)   UnhookWindowsHookEx 应该不会导致程序奔溃, (可以测试下Hook中仅调用 CallNextHookEx 而不作其它任何事)UnHookSafe()

      if(hhk)
      {
        UnhookWindowsHookEx(hhk);
        while(bHookDoing) sleep(0);
        hhk = NULL;
      }
    }写日志 
      

  12.   

     因为注入后hook了目标进程里的其他函数到我自己的函数,如果我的主进程关闭,就需要调用UnhookWindowsHookEx,这时候就导致目标进程里的dll被卸载,但是很可能正执行在我的hook函数里,,而这时我的dll却被卸载,所以崩溃。
      

  13.   

    明白了,那就dll延迟并自卸载
      

  14.   


    目前就是这么做的,加载后不卸载。
    一直觉得这个方式不够优雅,所以提出来和大家讨论讨论。
    因为我调试过其他一些类似的程序,它们确实是卸载了的,而且不会有问题,最少我测试很长时间很多次,没出问题。
    所以看看大家有没有处理这个问题的好建议。
    没什么优雅不优雅的,能解决问题就行,直接freelibrary肯定有隐患,必要时可能得手工清理现场,非是那些搞安全的估计都不清楚,平时工作中用不到也基本不会去试。
    退一步说,卸不卸载与优雅没关系,COM的dll与你的有些类似,可不需要你去卸载。
      

  15.   


    目前就是这么做的,加载后不卸载。
    一直觉得这个方式不够优雅,所以提出来和大家讨论讨论。
    因为我调试过其他一些类似的程序,它们确实是卸载了的,而且不会有问题,最少我测试很长时间很多次,没出问题。
    所以看看大家有没有处理这个问题的好建议。
    没什么优雅不优雅的,能解决问题就行,直接freelibrary肯定有隐患,必要时可能得手工清理现场,非是那些搞安全的估计都不清楚,平时工作中用不到也基本不会去试。
    退一步说,卸不卸载与优雅没关系,COM的dll与你的有些类似,可不需要你去卸载。
    当然有关系,dll一直被占用,不能删除。而且既然dll在,何其关联的一切dll都会被加载,内存占用很大。全局监控,所有进程都会加载,也就是说,所有进程对内存的消耗都会增加。
      

  16.   

    如果功能不复杂,试试shellcode能不能达到目的
      

  17.   

    hook 能不能 使用 临界区 ?
      

  18.   


    可以使用。不过这个问题临界解不了。在另一贴子里也讨论过。http://bbs.csdn.net/topics/392024311