9

Microsoft Detours Library についていくつか簡単な質問があります。以前に(成功して)使用したことがありますが、この機能について考えただけです:

LONG DetourUpdateThread(HANDLE hThread);

この関数は、トランザクションが完了するまで実際にスレッドを中断することを他の場所で読みました。ほとんどのサンプル コードが次のように呼び出しているため、これは奇妙に思えます。

DetourUpdateThread(GetCurrentThread());

とにかく、どうやらこの関数はスレッドを「登録」して、トランザクションがコミットされたとき (および迂回が行われたとき) に、それらの命令ポインターが「ターゲット関数またはトランポリン関数のいずれかの書き換えられたコード内」にある場合に変更されるようにします。

私の質問は次のとおりです。

トランザクションがコミットするとき、現在のスレッドの命令ポインターは DetourTransactionCommit 関数内にあるでしょうか? もしそうなら、なぜそれを更新するためにわざわざ参加させる必要があるのでしょうか?

また、参加しているスレッドが中断されている場合、現在のスレッドはどのようにして実行を継続できますか (ほとんどのサンプル コードが DetourUpdateThread(GetCurrentThread()); を呼び出すと仮定すると)?

最後に、現在のプロセスのすべてのスレッドを一時停止して、競合状態を回避できますか (スレッドはいつでも作成および破棄される可能性があることを考慮して)。おそらく、これはトランザクションの開始時に行われますか? これにより、スレッドをより安全に列挙することができます (新しいスレッドが作成される可能性は低いと思われるため) が、CreateRemoteThread() はどうでしょうか?

ありがとう、

ポール

参考までに、簡単なサンプルからの抜粋を次に示します。

// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function.  The Sleep target function is referred to
// through the TrueSleep target pointer.
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
        DetourTransactionCommit();
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
        DetourTransactionCommit();
    }
    return TRUE;
}
4

1 に答える 1

9

恥ずかしいこと:ソースが利用可能であることを忘れました!

DetourUpdateThreadは、現在のスレッドの参加を黙って無視します。それ以外の場合、指定されたスレッド中断されます。とにかく、すべてのコード例が現在のスレッドに参加するのはなぜだろうか。これは最初の2つの質問に答えます。

3番目の質問について:次のようにしてすべてのスレッドを一時停止しようとする別の迂回ライブラリを見つけました。

  1. すべてのスレッドのスナップショットを取得する

  2. スナップショットをループして、まだ中断していないスレッドを中断します。

  3. スレッドが一時停止された場合は、1に戻ります(一時停止したスレッドは引き続き追跡されます)。中断されたスレッドがない場合は、完了です。

すべてのスレッドをループでき、それらがすべてすでに中断されている場合(つまり、スナップショットを作成する前から)、それ以上スレッドを作成できなかったと想定しています。ただし、CreateRemoteThreadについてはよくわかりません。

編集:Re:CreateRemoteThread。

「プロセス内の1つのスレッドのみが、一度にDLL初期化またはデタッチルーチンに入ることができます。」CreateRemoteThreadは、「プロセス内の各DLLのエントリポイントへの呼び出しになります」。 http://msdn.microsoft.com/en-us/library/ms682437%28VS.85%29.aspx

DllMain関数を使用している場合、新しいスレッドの実行を開始することはできません(新しいスレッドによって、プロセス内の各DLLのエントリポイントがまだ呼び出されていない場合)。したがって、DllMain関数内で迂回を適用すると、新しいリモートスレッドが作成され、その命令ポインターが書き換えられたターゲット/トランポリン関数内にあるという競合状態から安全になる可能性があります。

ありがとう、

ポール

于 2010-04-14T12:00:05.547 に答える