api hook 使用中碰到的问题~~

只爱浓茶 2008-10-22 11:09:16
对话框程序通过使用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 来防止重复运行的问题??
...全文
341 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
yaozhu88 2008-11-05
  • 打赏
  • 举报
回复
假如用SetwindowshookEx函数安装了全局钩子。系统会为现有的进程自动加载钩子DLL.但是之后当新建了一个进程。它也会在这个进程中加载钩子DLL吗?
KeSummer 2008-11-05
  • 打赏
  • 举报
回复
要多开,那用Hook那么麻烦。。。把进程里面的那个 Mutex Close掉即可。。。枚举Handle用 ZwQuerySystemInformation
xlt123 2008-10-25
  • 打赏
  • 举报
回复
首先,SetWindowsHookEx是不能实现API HOOK的,微软并没有提供任何HOOK API的函数,
HOOK API与系统提供的HOOK完全是两回事,HOOK API是需要自己写的。

其次,即使你确实已经HOOK了API,仍有下述问题.
将DLL注入进程,必须是进程存在的时候才能注入,如果进程不存在,如何注入?
所以,只有当进程已经启动的时候才能注入,而进程启动后,你又无法控制你注入的时机,
是在CreateMutex执行后,还是在CreateMutex执行前?你无法得知。

如果这一个试验性的东西,就没必要继续了,思路错了。
如果是要解决现实的问题,我提供一种思路。

就是给那个程序加一个壳,这样,才能确保在CreateMutex调用之前挂接它。
wwwhhb4001 2008-10-24
  • 打赏
  • 举报
回复

学习一下
vcPlayer 2008-10-22
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 iwait 的回复:]
另外还有一点,就是我对话框执行的是:

hMutex = CreateMutex(NULL, FALSE, "TestAPP");

可钩子函数得到的lpName 是 MSCTF.Shared.MUTEX.MCG ,说明系统已经自动的将lpName 给改掉了,我猜测就算我在hook 函数中再修改lpName ,系统实际还是会将我的lpName 给改掉,也许在hook 函数中修改 lpName 这个方法不可行

于是我开始钩GetLastError()

钩子函数如下:
VOID WINAPI CModuleScope::MyGetLastError(…
[/Quote]

参考“cnzdgs ”这位大侠的,可能是你勾子下得晚了。你是DLL注入的吗?
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 cnzdgs 的回复:]
SetWindowsHookEx,不是在EXE程序加载时立即载入你的DLL,要等到Hook条件产生时才会载入,所以,在调用CreateMutex的时候,你还没有开始Hook,所以会创建成功。
另外,既然你要让EXE可以重复运行,在CreateMutex的Hook函数中,应该判断Mutex的名称,并设法让其创建成功才对。
[/Quote]


为什么要让其创建成功呢?创建成功了,那第二个实例不是就不能运行了吗?
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
另外还有一点,就是我对话框执行的是:

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个实例运行仍然因为互斥量的存在而失败,应该怎么做呢??
cnzdgs 2008-10-22
  • 打赏
  • 举报
回复
SetWindowsHookEx,不是在EXE程序加载时立即载入你的DLL,要等到Hook条件产生时才会载入,所以,在调用CreateMutex的时候,你还没有开始Hook,所以会创建成功。
另外,既然你要让EXE可以重复运行,在CreateMutex的Hook函数中,应该判断Mutex的名称,并设法让其创建成功才对。
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复


可是,我通过日志发现在第二个实例运行失败后,成功运行的那个窗口又执行了1次 GetLastError 和 CreateMutexA ,这又是什么原因呢?
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 iwait 的回复:]
引用 5 楼 vcPlayer 的回复:
还有,你是根据什么来判断它创建成功的了?万一在你的对话框中又判断了返回NULL句柄也是多开呢?

所以我建议你这样做:


C/C++ codeHANDLE 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", ::GetCu…
[/Quote]

原来是我自己晕了,执行的第2次是因为我自己重复执行 TestApp 时,得到“程序已经运行”的那次
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 vcPlayer 的回复:]
还有,你是根据什么来判断它创建成功的了?万一在你的对话框中又判断了返回NULL句柄也是多开呢?

所以我建议你这样做:


C/C++ codeHANDLE 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);
Log…
[/Quote]

已经按照你的方法试过了,结果还是一样,下面是修改后的函数:

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 啊,奇怪了
vcPlayer 2008-10-22
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 iwait 的回复:]
CreateMutexW 也钩了,只是我的log 没有显示进程调用,这个对话框也是我自己写的一个测试用的,不是UNICODE 的

另外:
不行啊
我的进程中CreateMutex 的代码是这样写的:
HANDLE hMutex;
hMutex = CreateMutex(NULL, FALSE, "TestAPP");

if(GetLastError() == ERROR_ALREADY_EXISTS)
{
MessageBox(NULL,"程序已经运行!","test",0);
return FALSE;
}

我将HOOK截获的 LPCSTR …
[/Quote]

你下药的对象没搞错吧?:)再不行,用内联勾子试试。
yc_8301 2008-10-22
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 iwait 的回复:]
我尝试修改了了CreateMutex的参数 lpName ,用一个随机数代替,结果对话框进程还是不能重复运行
[/Quote]
让 lpName 每次都不同,也不可以吗??
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
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" ,为什么回这样?
vcPlayer 2008-10-22
  • 打赏
  • 举报
回复
还有,你是根据什么来判断它创建成功的了?万一在你的对话框中又判断了返回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);
}
gellf 2008-10-22
  • 打赏
  • 举报
回复
关注
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
我尝试修改了了CreateMutex的参数 lpName ,用一个随机数代替,结果对话框进程还是不能重复运行
vcPlayer 2008-10-22
  • 打赏
  • 举报
回复
还有CreateMutexW,都要勾住。
yeah920 2008-10-22
  • 打赏
  • 举报
回复
帮忙顶。等高手。
只爱浓茶 2008-10-22
  • 打赏
  • 举报
回复
将NULL 作为lpName 传入也不行,第二个实例仍然无法运行,难道真的是窗口在注入前就已经CreateMutex 了?

好生奇怪,哪位兄弟有时间的,留下email ,我把代码发过去让你试试~~~
加载更多回复(2)

15,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧