4

我不擅长 C++,更多的是 C# 和 PHP。我被分配了一个项目,该项目需要我使用GetTickCount并连接到应用程序中。我需要一些帮助,因为由于某种原因它没有按计划工作......这是挂钩的代码,我知道它有效,因为我以前在项目中使用过它。我唯一不太确定的是GetTickCount它的一部分。我试着GetTickCount64认为这是解决我的问题的方法(它没有使我注入的东西崩溃),但发现它根本不起作用,所以它没有崩溃。

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; 
}

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

4

2 回答 2

3

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

GetTickCount_orig 是否已设置?

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

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

另外,如果 Detours 没有成功,还有 mhook 库,它的许可要简单得多。

于 2011-01-31T23:12:46.397 回答
1

不要修改oldtick

你只需要保存一次,然后

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

编辑:

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

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 个标准字节,易于重新定位。

于 2011-01-28T01:31:06.687 回答