解决方案 »

  1.   

    UnHook的时候本来就是MySysCall执行不了呀,会等在EnterCriticalSection(),有什么问题?
    UnHook的时候你
    LeaveCriticalSection()
    DeleteCriticalSection,立马就删除了,MySysCall线程在这LeaveCriticalSection与DeleteCriticalSection两句之间是抢不到cpu片的。
      

  2.   


    是这样的,但是MySysCall在UnHook线程DeleteCriticalSection之后,进入EnterCriticalSection这里会出错,因为这个参数已经是NULL了,另外,即使这里不错的话,那么这个线程在之后会是什么样的流程呢?谢谢。
      

  3.   


    Any thread of the process can use the DeleteCriticalSection function to release the system resources that were allocated when the critical section object was initialized. After this function has been called, the critical section object can no longer be used for synchronization.If a thread terminates while it has ownership of a critical section, the state of the critical section is undefined.If a critical section is deleted while it is still owned, the state of the threads waiting for ownership of the deleted critical section is undefined.
    ”这是一段MSDN的说明。
      

  4.   

    线程1,这是我Hook的函数(执行非常频繁)
    MySysCall(...)
     {
     EnterCriticalSection()
     if (!m_bRunning)
       return;
     ...
     LeaveCriticalSection()
     }线程2,这是卸载Hook,还原SysCall的线程
    UnHook()
     {
     EnterCriticalSection()
     //保证MySysCall函数执行到EnterCriticalSection处
    Sleep(50);
     m_bRunning = False;
     ...
     //还原 syscall 的入口5个字节
    //删除MySysCall中自己创建的资源
    LeaveCriticalSection()
     DeleteCriticalSection
     }你这样定义一个全局的标识不行吗?
      

  5.   

    想安全退出使用只使用一个CriticalSection是做不到的
    可以使用两个event
    一个UnHook激发,在MySysCall里面判断
    等MySysCall释放完资源后,再激发另外一个event,UnHook释放资源
      

  6.   


    还是那个问题啊,在DeleteCriticalSection之后,MySysCall的函数里面执行EnterCriticalSection会发生未知的错误。
      

  7.   


    没办法,我不能让这个SysCall线程退出,不然这个Hook就太坑爹了。
      

  8.   


    你UnHook的时候 先等待MySysCall线程正常退出啊~!
    if (WaitForSingleObject(MySysCall->m_hThread, INFINITE) == WAIT_OBJECT_0)
    {

    }
      

  9.   


    这个线程是不会退出的,我这个Hook相当于热插拔,要能随时注入,随时退出,且不影响目标进程。
      

  10.   


    那你UnHook时候,DeleteCriticalSection操作,是出于什么用途?
      

  11.   


    那你在不用到临界变量的时候再 DeleteCriticalSection 释放啊~你其它的线程还在用,你就释放。。那不杯具才怪~
      

  12.   


    我不释放是可以,但是执行完UnHook函数之后我的DLL会free掉,这时候MySysCall所在的代码区就成了未知地址了,EnterCriticalSection进去执行肯定错。所以我必须保证UnHook之后MySysCall就不应该在执行,跳回到系统自己的代码领域。不知道怎么操作,我快疯了!。。
      

  13.   

    用事件结合的方式:
    HANDLE handle  = NULL;
    MySysCall(...)
    {
    if(handle != NULL)
      WaitForSingleObject(handle ,...);
    EnterCriticalSection()
    ...
    LeaveCriticalSection()
    }UnHook()
     {
     handle  = CreateEvent(...);
     EnterCriticalSection()
     //保证MySysCall函数执行到EnterCriticalSection处
    Sleep(50);
     m_bRunning = False;
     ...
     //还原 syscall 的入口5个字节
    //删除MySysCall中自己创建的资源
    LeaveCriticalSection()
     DeleteCriticalSection
     }
      

  14.   


    是的,我已经这样做了。不过还是有点虚...
    我是这样的:
    HANDLE hCanDelCS=NULL;
    HANDLE hCanFreeDll=NULL;
    BOOL bUnHooking=FALSE;
    MySysCall(...)
    {
    EnterCriticalSection()
    if(bUnHooking)
    {
    SetEvent(hCanDelCS);
    returncode = SysCall(...);
    SetEvent(hCanFreeDLL);
    return returncode;
    }
    ...
    LeaveCriticalSection()
    }线程2,这是卸载Hook,还原SysCall的线程
    UnHook()
    {
    bUnHooking=TRUE;
    EnterCriticalSection()...
    //还原 syscall 的入口5个字节
    //删除MySysCall中自己创建的资源
    if(hCanDelCS)
    watforsingleobject(hCanDelCS,500);
    LeaveCriticalSection()
    DeleteCriticalSection
    if(hCanFreeDll)
    watforsingleobject(hCanDelCS,500);sleep(50);return to dllmain(); //free dll
    }
      

  15.   


    不行吧,既然UnHook已经执行了,那说明MySysCall就没有执行,等到UnHook执行完后LeaveXx后,MySysCall也就不会执行了,因为已经卸载了。
      

  16.   


    mysyscall中会卡在EnterCriticalSection那里,等Unhook LeaveXx之后会继续执行mysyscall,这时候mysyscall代码已经失效了。
      

  17.   

    自己给CriticalSection写个类,每次delete前,禁止再enter的时候,等待CS.LockCount=0然后才DeleteCriticalSection
      

  18.   

    谁有最后的方案?
    求分享
    [email protected]
      

  19.   

    任何线程不允许在执行EnterCriticalSection(...)后不执行LeaveCriticalSection(...)退出
    请重新设计程序思路因为MySysCall()进入了临界区,所以另外的程序是无法进入相同的临界区的,除非建立两个临界区
      

  20.   

    就是要有第三方来干这事,要不然就只能是两个临界区。两个临界区其中一个是公共的,到死都别释放。
    CRITICAL_SECTION g_cs;然后你用于同步的临界区, 你也可以自己包装成结构。
    CRITICAL_SECTION cs;
    bool bFree = false;
    void work_proc()
    {
        EnterCriticalSection(&g_cs);
        if(bFree)
        {
            LeaveCriticalSection(&g_cs);
            return;
        }
        EnterCriticalSection(&cs);
        LeaveCriticalSection(&g_cs);
             ....
        LeaveCriticalSection(&cs);
    }void free_proc()
    {
        EnterCriticalSection(&g_cs);
        DeleteCriticalSection(&cs);
        bFree = true;
        LeaveCriticalSection(&g_cs);
    }这样就可以正常释放了,现在再来说DLL问题,DLL 在FreeLibrary的时候,肯定要回收掉资源,假如你是注入游戏,你担心你DLL回收之后,然后公共的临界区不存在了,我觉得这到不是什么问题。只要你在游戏无法访问同步临界区时,你把HOOK还原掉,就可以了。如果实在担心的话,你可以用VirtualAlloc来分配永久性的临界区内存,另外一点,需要靠HOOK去和游戏同步,本身就不合理了,你还不如HOOK游戏的消息函数来处理还实在点。
      

  21.   

    void free_proc()
     {
         EnterCriticalSection(&g_cs);
         EnterCriticalSection(&cs);
         LeaveCriticalSection(&cs);
         DeleteCriticalSection(&cs);
         bFree = true;
         LeaveCriticalSection(&g_cs);
     }释放应该是这样,上面写少两句。