3

DirectX 9 アプリケーションをフックして、スクリーンショットを取得しようとしています。それが私がすることです:

  1. 引数として渡されたアドレスをDLL に挿入CreateRemoteThreadします。LoadLibraryWこの時点で、ターゲット アプリケーションは既に実行されていると仮定します。
  2. DLL のDllMainI内CreateThreadで、一時的な Direct3D デバイスを作成して VMT を取得します。

    auto pID3D9 = Direct3DCreate9(D3D_SDK_VERSION);
    D3DPRESENT_PARAMETERS pp = { };
    IDirect3DDevice9 *pID3DDevice = NULL;
    auto hr = pID3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL,
        D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &pID3DDevice);
    auto pID3DDevicevt = *reinterpret_cast(pID3DDevice);
  3. EndSceneDirect3D デバイスの関数へのポインターを書き換えようとしても、何も起こりません。

    // ここで '42' は VMT 内の EndScene のインデックスです (笑)
    pID3DDevicevt[42] = my_EndScene;

    注:VirtualProtect書き換える前のポインターと書き換え た後VirtualProtectで、そのコードを省略しただけです。

  4. 私は「古典的な」フックに行き着きます: 元の関数の 6 バイトを書き直して、無条件に関数にジャンプするようにします。次に、元のバイトを復元し、独自の処理を行い、元の関数を呼び出して、関数を再度フックします。できます。

EndSceneDirect3D デバイスの関数へのポインタを書き換えようとしても何も起こらないのはなぜですか?

VMT フックを機能させるには、VMT フックを十分早く配置する必要があるという情報を検索して見ました。それが原因ですか?

4

2 に答える 2

0

あなたの問題はおそらく鉱山(http://stackoverflow.com/questions/14224747/win7-8-dwm-draw-hooking)と非常に似ていますが、私はID3D10Device1を使用しています。Direct3D には、いくつかのメソッドの元の vtable ポインターを定期的に復元する何らかの保護が含まれているようです。

この問題の適切な解決策はまだ見つかりません。回避策は、vtable を定期的に再パッチするバックグラウンド スレッドを実行することです。ただし、CPU を 100% 消費し、すべてのケースをキャッチするわけではありません (競合状態のため)。Yield/Sleep をこのスレッドに入れることはできません。これは、一部の関数呼び出しが見逃されるためです。

ところで、その「「クラシック」フッキング」とは何ですか?私はすでにそれについて読んだことがありますが、x64 プロセスで使用する方法がわかりません (jmp 命令の追加、正しいパラメーターの読み取り、元の関数へのジャンプなど...)。

于 2013-01-12T17:51:54.957 に答える