首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用C++挂接GetTickCount

使用C++挂接GetTickCount
EN

Stack Overflow用户
提问于 2011-01-28 09:23:27
回答 2查看 3.4K关注 0票数 4

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

代码语言:javascript
复制
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的其余代码

代码语言:javascript
复制
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; 
}

你能看到一些不正确的地方或者应该改变的地方吗?任何帮助都是非常感谢的。谢谢!

EN

回答 2

Stack Overflow用户

发布于 2011-02-01 07:12:46

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

GetTickCount_orig已经准备好了吗?

GetTickCount很可能是一个非常、非常短的API,给绕道带来了问题(只是没有足够的字节来完成挂接)。

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

另外,如果Detour不能正常工作,还有一个mhook库,它的许可要简单得多。

票数 3
EN

Stack Overflow用户

发布于 2011-01-28 09:31:07

不要修改oldtick

你只需要保存一次,然后

代码语言:javascript
复制
// accelerating time by factor of "factor"
return oldtick + (realtick - oldtick) * factor;

编辑:

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

代码语言:javascript
复制
8B FF     mov     edi, edi
55        push    ebp
8B EC     mov     ebp, esp

如果没有它,它只能从IAT挂接,并且必须为调用它的每个模块执行此操作。我怀疑DetourFunction是按进程工作的,所以它使用前同步码挂接API。

要解决此问题,您可以尝试挂钩每个模块的IAT,或者手动对其进行修补,但这样就无法在挂钩时调用原始版本。

EDIT2:使用jump是最常见的方式,但这意味着我们必须在函数的开头覆盖5个字节。它的主要问题不是函数的大小,而是它开始时的代码。当然,任何东西都可以被重写,但是如果你想在钩子打开的时候调用旧的函数(就像这个问题一样),那么你必须知道你在重写什么。

你不想重写一半的操作码,你必须执行重写部分。这意味着在一般情况下,你需要一个完整的反汇编程序。

为了简化这一点,大多数函数都从一个额外的2字节NOP:mov edi, edi开始,这样它们的前同步码就有5个字节,这是标准的,很容易重新定位。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4823887

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档