2011-01-28 5 views
4

Я не очень хорош на C++, больше из C# и PHP-парня. Мне был назначен проект, который требует, чтобы я использовал GetTickCount и подключился к приложению. Мне нужна помощь, потому что по какой-то причине она не работает так, как планировалось ... Вот код для подключения, я знаю, что это работает, потому что я использовал его в проектах раньше. Единственное, о чем я не уверен, это часть его GetTickCount. Я пробовал GetTickCount64, думая, что это было исправление моей проблемы (это не привело к сбою в том, что я вводил в нее), но выяснил, что вместо этого он просто не работал, поэтому он не разбил его.Захват GetTickCount с C++

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

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

+0

В чем проблема? – wj32

+0

Сбой при попытке его ввода. Мой QueryPerformanceCounter легко вводит без проблем. – E3pO

+9

Как насчет ввода 'break;' перед 'case DLL_PROCESS_DETACH'? Потому что, как написано сейчас, вы сразу же удаляете свой крючок после инициализации – valdo

ответ

1

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

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

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

EDIT:

Другая возможная проблема заключается в том, что GetTickCount (по крайней мере, на моем компьютере, XP 32bit) не имеет стандарт «hookable "preamle:

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

+0

Я не думаю, что Detours настолько глупо, что он не будет работать с произвольными инструкциями. Разве это не те, кто придумал идею «батута» для зацепки? – wj32

+0

@ wj32: Тогда почему большинство интерфейсов Win32 начинаются с этого 'mov edi, edi'? – ruslik

+0

Ну, похоже, проблема в том, что «oldtick = (* GetTickCount_orig)(); return oldtick; ' – E3pO

3

Что такое «KeyHooks»? Если он ожидает вызова отложенных API-интерфейсов, вы должны объединиться, прежде чем создавать поток.

Действительно ли установлен GetTickCount_orig?

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

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

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

+0

Все Keyhooks делает это, если пользователь удерживает клавишу shift. void KeyHooks (void) {while (true) {makemetrue = false, while (GetAsyncKeyState (0x14)) {makemetrue = true;} Sleep (50);}} Также .. Я не уверен, что GetTickCount_orig будет установлен. Когда у меня нет GetTickCount64, он сбрасывает все, что я пытаюсь ввести. – E3pO

+0

Выйдите из отладчика и проверьте, установлен ли GetTickCount_orig. Также см. Пункт valdo выше о отсутствующем заявлении break (не могу поверить, что я не видел этого :) –

Смежные вопросы