5

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!

E3pO
  • 493
  • 1
  • 9
  • 21
  • What's the actual problem here? – wj32 Jan 28 '11 at 01:26
  • Crashes the app when trying to inject it. My QueryPerformanceCounter injects fine without problems. – E3pO Jan 28 '11 at 01:36
  • 9
    How about putting `break;` before `case DLL_PROCESS_DETACH`? Because as it's written now - you immediately remove your hook after the initialization – valdo Feb 01 '11 at 06:00

2 Answers2

3

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.

Graham Perks
  • 23,007
  • 8
  • 61
  • 83
  • All Keyhooks is doing is seeing if the user is holding down the shift key. void KeyHooks(void){while(true){makemetrue = false;while(GetAsyncKeyState(0x14)){makemetrue = true;}Sleep(50);}} Also.. I'm not sure if GetTickCount_orig is getting set. When i don't have GetTickCount64 it crashes whatever i'm trying to inject into. – E3pO Feb 01 '11 at 04:28
  • Get out your debugger and see if GetTickCount_orig is set. Also see valdo's point above about the missing break statement (can't believe I didn't see that :) – Graham Perks Feb 01 '11 at 14:43
1

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.

ruslik
  • 14,714
  • 1
  • 39
  • 40
  • I don't think Detours is so stupid that it wouldn't work with arbitrary instructions. Aren't they the ones who came up with the "trampoline" idea for hooking? – wj32 Jan 28 '11 at 02:13
  • @wj32: Then why most of Win32 APIs start with this `mov edi, edi`? – ruslik Jan 28 '11 at 02:18
  • Well it seems like the problem is the `oldtick=(*GetTickCount_orig)(); return oldtick;` – E3pO Jan 28 '11 at 02:21
  • @E3pO: So I am right :) It gets patched by `jmp` unconditionally, so the original function cannot be called while the hook is on. You'll have to do it manually then. – ruslik Jan 28 '11 at 02:31
  • 1
    @ruslik: That's to make patching easier. It doesn't mean patching is impossible without the padding at the start. @E3pO: I think you need to use DetourFunctionWithTrampoline. – wj32 Jan 28 '11 at 04:01
  • It doesn't crash, but i don't think it's doing anything.. I could be wrong. – E3pO Jan 28 '11 at 04:33
  • Possibly someone wouldn't mind private messaging me with their aim or skype? Would be nice to get this figured out. I'm willing to pay. – E3pO Jan 28 '11 at 06:45
  • Can you please explain what's the meaning of the "hookable preamble"? AFAIK, apart from hooking via IAT there exists a way to overwrite the first portion of the function code by `jmp` to another address. This method demands the function to be "long enough" (otherwise other memory becomes overwritten). – valdo Feb 01 '11 at 06:05