4

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

間違っていること、または変更する必要があることがわかりますか? どんな助けでも大歓迎です。ありがとうございました!

4

2 に答える 2

3

「KeyHooks」スレッドとは何ですか? 迂回した API を呼び出すことが予想される場合は、スレッドを作成する前に迂回する必要があります。

GetTickCount_orig はまったく設定されていますか?

GetTickCount は非常に短い API であるため、Detours で問題が発生する可能性があります (フックするのに十分なバイト数がありません)。

DetourRemove は、GetTickCount ではなく、GetTickCount64 を削除しています。

これとは別に、Detours がうまくいかない場合は、ライセンスがはるかに簡単な mhook ライブラリがあります。

于 2011-01-31T23:12:46.397 に答える
1

変更しないでくださいoldtick

一度だけ保存する必要があります。

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

編集:

もう1つの考えられる問題は、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 バイトが含まれます。

于 2011-01-28T01:31:06.687 に答える