使用C ++挂钩GetTickCount

时间:2011-01-28 01:23:27

标签: c++ winapi hook detours gettickcount

我不擅长C ++,更像是C#和PHP人。我被分配了一个项目,要求我使用GetTickCount并挂钩到应用程序。我需要一些帮助,因为它没有按计划工作......这是挂钩的代码,我知道它有效,因为我以前在项目中使用它。我唯一不确定的是GetTickCount部分。我试过GetTickCount64认为这是我的问题的解决方法(它没有崩溃我注入它的内容)但发现它只是根本没有工作所以它没有崩溃它。 / p>

bool APIENTRY DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
{
 switch(dwReason)
 {
 case DLL_PROCESS_ATTACH:

  DisableThreadLibraryCalls(hDll);
  CreateThread(0,0, (LPTHREAD_START_ROUTINE)KeyHooks, 0, 0, 0);
  GetTickCount_orig = (DWORD (__stdcall *)(void))DetourFunction((PBYTE)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetTickCount"), (PBYTE)GetTickCount_hooked);

 case DLL_PROCESS_DETACH:
  DetourRemove((PBYTE)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetTickCount"), (PBYTE)GetTickCount_hooked);

  break;
 }
 return true;
}

以下是用于GetTickCount

的其余代码
DWORD oldtick=0;
DWORD (WINAPI *GetTickCount_orig)(void);
DWORD WINAPI GetTickCount_hooked(void)
{ 
 if(oldtick==0)
 {
  oldtick=(*GetTickCount_orig)();
  return oldtick;
 }
 DWORD factor;
 DWORD ret;

 ret = (*GetTickCount_orig)();
 factor = 3.0;
 DWORD newret;

 newret = ret+((oldtick-ret)*(factor-1));

 oldtick=ret;
 return newret; 
}

你能看到不正确或应该改变的东西吗?任何帮助表示赞赏。谢谢!

2 个答案:

答案 0 :(得分:3)

什么是“KeyHooks”主题?如果它希望调用绕道的API,你应该在创建线程之前绕道而行。

GetTickCount_orig是否已完全设置?

GetTickCount可能是一个非常非常短的API,导致Detours出现问题(只是没有足够的字节来挂钩)。

您的DetourRemove正在移除GetTickCount64,而不是GetTickCount。

另外,如果Detours没有运行,那么mhook库的许可证就会简单得多。

答案 1 :(得分:1)

请勿修改oldtick

您只需保存一次,然后

// accelerating time by factor of "factor"
return oldtick + (realtick - oldtick) * factor;

编辑:

另一个可能的问题是GetTickCount(至少在我的电脑上,XP 32bit)没有标准的“可挂钩”的前导码:

8B FF     mov     edi, edi
55        push    ebp
8B EC     mov     ebp, esp

没有它,它只能从IAT挂钩,必须为每个调用它的模块完成。我怀疑DetourFunction每个进程都有效,所以它使用前导码挂钩API。

要解决此问题,您可以尝试连接每个模块的IAT,也可以手动修补它,但是当它被连接时,您将无法调用原始版本。

EDIT2 :使用跳转是最常用的方法,但这意味着我们必须在函数开头覆盖5个字节。它的主要问题不是函数的大小,而是代码的开头。当然,任何东西都可以被覆盖,但如果你想在钩子打开时能够调用旧函数(如本问题所示),那么你必须知道你在覆盖什么。
您不想覆盖一半的操作码,并且您必须执行被覆盖的部分。这意味着在通用情况下,您需要一个完整的反汇编程序。

为了简化这一点,大多数函数都以一个额外的2字节NOP开始:mov edi, edi,因此它们的前导码有5个字节,是标准的,易于重定位。