Подключение GetTickCount с C ++ - PullRequest
       35

Подключение GetTickCount с C ++

4 голосов
/ 28 января 2011

Я не очень хорош в 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; 
}

Можете ли вы увидеть что-то неправильное или это следует изменить? Любая помощь приветствуется. Спасибо!

Ответы [ 2 ]

3 голосов
/ 01 февраля 2011

Что за нить "KeyHooks"?Если он ожидает вызова обходных API, вам следует обойти перед созданием потока.

Установлен ли вообще GetTickCount_orig?

GetTickCount, скорее всего, очень и очень короткий API, вызывающий проблемы для обходов.(просто недостаточно байтов для подключения).

Ваш DetourRemove удаляется для GetTickCount64, а не для GetTickCount.

Отдельно, если Detours не работает, есть библиотека mhook, которая имеетгораздо более простое лицензирование.

1 голос
/ 28 января 2011

Не изменять oldtick!

Вы должны сохранить его только один раз, а затем

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

EDIT:

Другая возможная проблема заключается в том, что 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 байтов, которые являются стандартными и легко перемещаемыми.

...