对话框程序通过使用CreateMutexA 来达到防止重复运行的问题,我想通过APIHOOK 来解决这个问题,使得进程可以重复运行,我用APIHOOK 钩到了 CreateMutexA ,然后直接Return NULL; 可是进程中的CreateMutexA 还是成功创建了互斥对象,好奇怪对话框中的CreateMutex 代码:
===========================================================================
HANDLE   hMutex;   
hMutex   =   CreateMutex(NULL,   FALSE,   "TestAPP");     

if(GetLastError() == ERROR_ALREADY_EXISTS)   
{   
MessageBox(NULL,"程序已经运行!","test",0);   
return   FALSE;   
}     ===========================================================================
钩子函数:
===========================================================================
HANDLE WINAPI CModuleScope::MyCreateMutexA(  LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitiaOwner,  LPCSTR lpName)
{
  char szBuffer[MAX_PATH];
  sprintf_s(szBuffer, "Process (%u%d) CreateMutex Now ! Let's Return NULL", ::GetCurrentProcessId(),u);
  LogMessage(szBuffer);
  return NULL;
  
}
============================================================================
api hook 是以SetWindowsHookEx来实现的,后来我尝试钩住进程的GetLastError() ,在我的钩子函数中直接SetLastError(0),结果还是不行。请问各位大侠,用api hook 应该怎么做才能解决进程通过CreateMutexA 来防止重复运行的问题??

解决方案 »

  1.   

    我尝试修改了了CreateMutex的参数 lpName ,用一个随机数代替,结果对话框进程还是不能重复运行
      

  2.   

    还有,你是根据什么来判断它创建成功的了?万一在你的对话框中又判断了返回NULL句柄也是多开呢?所以我建议你这样做:HANDLE WINAPI CModuleScope::MyCreateMutexA(  LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitiaOwner,  LPCSTR lpName) 

      char szBuffer[MAX_PATH]; 
      sprintf_s(szBuffer, "Process (%u%d) CreateMutex Now ! Let's Return NULL", ::GetCurrentProcessId(),u); 
      LogMessage(szBuffer);   // 改变一下名字,方法是在名字后面附加一个实例ID——nInstances,
      // 这个ID位于你各个实例都可以访问并修改的一个内存区域,如文件映射
      sprintf(szBuffer, _T("%s%u"), lpName, nInstances);
      return CreateMutexA(lpMutexAttributes, bInitiaOwner, lpName);   
      

  3.   

    CreateMutexW 也钩了,只是我的log 没有显示进程调用,这个对话框也是我自己写的一个测试用的,不是UNICODE 的另外:
    不行啊
    我的进程中CreateMutex 的代码是这样写的:
    HANDLE   hMutex;   
    hMutex   =   CreateMutex(NULL,   FALSE,   "TestAPP");     
      
    if(GetLastError() == ERROR_ALREADY_EXISTS)   
    {   
      MessageBox(NULL,"程序已经运行!","test",0);   
      return   FALSE;   
    }     我将HOOK截获的 LPCSTR lpName 打印出来发现,是 MSCTF.Shared.MUTEX.MCG ,并不是我传进去"TestApp" ,为什么回这样?
      

  4.   

    让 lpName  每次都不同,也不可以吗??
      

  5.   


    已经按照你的方法试过了,结果还是一样,下面是修改后的函数:HANDLE WINAPI CModuleScope::MyCreateMutexA(  LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitiaOwner,  LPCSTR lpName)
    {
    char szBuffer[MAX_PATH];
    sprintf_s(szBuffer, "Process (%u_%s) CreateMutex Now !", ::GetCurrentProcessId(),lpName);
    sm_pInstance->LogMessage(szBuffer);

    sprintf_s(szBuffer,"%s%u",lpName,::GetCurrentProcessId());
    return ::CreateMutexA(NULL,FALSE,(LPCSTR)szBuffer);

    }代码运行log日志 如下:
    HookSrv.exe(83604) - ------- Hook server loads HookTool library -------
    TestApp.exe(83636) - Process (83636) CreateMutex Now !
    TestApp.exe(80084) - Process (80084) CreateMutex Now !
    TestApp.exe(80084) - Process (80084) GetLastError()
    TestApp.exe(80084) - The hook engine has been deactivated.
    TestApp.exe(83636) - Process (83636) GetLastError()
    TestApp.exe(83636) - Process (83636) CreateMutex Now !
    TestApp.exe(83636) - The hook engine has been deactivated.
    HookSrv.exe(83604) - ------- Hook server shuts down and unloads HookTool library -------
    通过日志我发现,TestApp 其实是创建了2次互斥量,PID 分别是 83636 和 80084可是TestApp 的代码中,我只调用了一次CreaetMutex 啊,奇怪了
      

  6.   


    原来是我自己晕了,执行的第2次是因为我自己重复执行 TestApp 时,得到“程序已经运行”的那次
      

  7.   

    可是,我通过日志发现在第二个实例运行失败后,成功运行的那个窗口又执行了1次 GetLastError 和 CreateMutexA ,这又是什么原因呢? 
      

  8.   

    SetWindowsHookEx,不是在EXE程序加载时立即载入你的DLL,要等到Hook条件产生时才会载入,所以,在调用CreateMutex的时候,你还没有开始Hook,所以会创建成功。
    另外,既然你要让EXE可以重复运行,在CreateMutex的Hook函数中,应该判断Mutex的名称,并设法让其创建成功才对。
      

  9.   

    另外还有一点,就是我对话框执行的是:hMutex  =  CreateMutex(NULL,  FALSE,  "TestAPP");    可钩子函数得到的lpName 是 MSCTF.Shared.MUTEX.MCG ,说明系统已经自动的将lpName 给改掉了,我猜测就算我在hook 函数中再修改lpName ,系统实际还是会将我的lpName 给改掉,也许在hook 函数中修改 lpName 这个方法不可行于是我开始钩GetLastError()钩子函数如下:
    VOID WINAPI CModuleScope::MyGetLastError()
    {
    char szBuffer[MAX_PATH];
    sprintf_s(szBuffer, "Process (%u) GetLastError()", ::GetCurrentProcessId());
    sm_pInstance->LogMessage(szBuffer);
    if (::GetLastError() == ERROR_ALREADY_EXISTS)
    {
    ::SetLastError(ERROR_SUCCESS);
    }
    }结果还是一样,对话框第2个实例运行仍然因为互斥量的存在而失败,应该怎么做呢??
      

  10.   


    参考“cnzdgs ”这位大侠的,可能是你勾子下得晚了。你是DLL注入的吗?
      

  11.   

    无论第几个实例,都是CreateMutex成功后程序才会继续运行,如果失败就会退出。
    我的意思是让所有实例都创建成功。你可以在Hook函数中,自己调用真正的CreateMutex,把名称参数给NULL,将得到的句柄返回。
      

  12.   

    如果dll注入成功,应该没问题的, 你的替换函数调用了吗?
    注入是在调用CreateMutex之前吗?
      

  13.   

    将NULL 作为lpName 传入也不行,第二个实例仍然无法运行,难道真的是窗口在注入前就已经CreateMutex 了?好生奇怪,哪位兄弟有时间的,留下email ,我把代码发过去让你试试~~~
      

  14.   

    首先,SetWindowsHookEx是不能实现API HOOK的,微软并没有提供任何HOOK API的函数,
    HOOK API与系统提供的HOOK完全是两回事,HOOK API是需要自己写的。其次,即使你确实已经HOOK了API,仍有下述问题.
    将DLL注入进程,必须是进程存在的时候才能注入,如果进程不存在,如何注入?
    所以,只有当进程已经启动的时候才能注入,而进程启动后,你又无法控制你注入的时机,
    是在CreateMutex执行后,还是在CreateMutex执行前?你无法得知。如果这一个试验性的东西,就没必要继续了,思路错了。
    如果是要解决现实的问题,我提供一种思路。就是给那个程序加一个壳,这样,才能确保在CreateMutex调用之前挂接它。
      

  15.   

    要多开,那用Hook那么麻烦把进程里面的那个 Mutex Close掉即可枚举Handle用 ZwQuerySystemInformation 
      

  16.   

    假如用SetwindowshookEx函数安装了全局钩子。系统会为现有的进程自动加载钩子DLL.但是之后当新建了一个进程。它也会在这个进程中加载钩子DLL吗?