使用 C++ 挂钩 GetTickCount

发布于 2024-10-14 20:10:17 字数 1283 浏览 7 评论 0原文

我不太擅长 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; 
}

您能看到一些不正确或应该更改的内容吗?任何帮助表示赞赏。谢谢你!

I'm not great at C++, more of a C# and PHP guy. I've been assigned a project that requires me to use GetTickCount and hooking into an application. I need some help as for some reason it's not working as planned... Here is the code for hooking, I know it works because i've used it in projects before. The only thing i'm not so sure about is the GetTickCount part of it. I tried GetTickCount64 thinking that was a fix to my problem (It didn't crash what i was injecting it into) but found out that instead it just wasn't working at all so it didn't crash it.

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

Here is the rest of the code that is used for 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; 
}

Can you see something that is incorrect or that should be changed? Any help is appreciated. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

茶花眉 2024-10-21 20:10:17

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

GetTickCount_orig 是否已设置?

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

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

另外,如果 Detours 不起作用,还有 mhook 库,它的许可要简单得多。

What's the "KeyHooks" thread? If it's expecting to be calling detoured APIs, you ought to detour before creating the thread.

Is GetTickCount_orig getting set at all?

GetTickCount is likely a very, very short API causing problems for Detours (just not enough bytes to do the hooking in).

Your DetourRemove is removing for GetTickCount64, not GetTickCount.

Separately, if Detours isn't working out, there's the mhook library which has far simpler licensing.

年华零落成诗 2024-10-21 20:10:17

不要修改 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 个字节。

Don't modify oldtick !

You have to save it just once, and then

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

EDIT:

Another possible problem is that GetTickCount (at least on my computer, XP 32bit) does not have the standard "hookable" preamle:

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

Without it it can be hooked only from IAT, and this have to be done for each module that calls it. I suspect that DetourFunction works per process, so it hooks APIs using preamble.

To solve this you can either try hooking the IAT of each module, or patch it manually, but then you won't be able to call the original version while it's hooked.

EDIT2: Using jump is the most common way, but this means that we have to overwrite 5 bytes at the beginning of the function. It's main problem isn't the size of function, but the code at its start. Sure, anything can be overwritten, but if you want to be able to call the old function while the hook is on (as in this question), then you have to know what are you overwritting.
You don't want to overwrite half of the opcode, and you have to execute the overwitten part. This means that in generic case you'll need a full disassembler for that.

To simplify that, most functions starts with an additional 2-byte NOP: mov edi, edi, so that their preamble have 5 bytes that are standard and easy to relocate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文