めいくりぷとのブログ

技術的なことやゲームのことやら・・・

WDDM Hook (2)

Direct3D DDIは、OpenGL ICDとは違って、グラフィックドライバ自体にテーブルは無くd3dx.dllにドライバのテーブルがあるみたいですね...(ICD同様にグラフィックドライバ自体にテーブルが用意されているものだと勘違いしておりました。)


まずDDIの関数テーブル自体が、グラフィックドライバのテーブル関数(?) CreateDevice関数 によって初期化されますし、同じ所にあるものだと普通思いますよね...


一見どうでも良いようにも思えますが...
少し前のプロテクターにはD3D関数テーブルの整合性チェックがあっても、ドライバの関数テーブルのチェックは殆ど無かったため問題はありませんでした。ですが、最近のものはd3dx.dll自体にメモリチェックがあったりするので、どうでも良いとは言い切れません。


どうにかグラフィックドライバ自体に存在するドライバ関数?だけで完結したいですよね..


一応、DDIの各ドライバ関数の第一引数 HANDLE hDeviceにDisplay Device(関数テーブル?)のポインタが格納されており、それに対応した関数が呼ばれているので、何とかなるような気もしますけどね。


また何か進展があれば記事にしたいと思います。以上


追記:
よくよく考えれば、D3D DDIの各ドライバ関数をフックしなくても、各ドライバ関数へのテーブル自体をすり替えてしまえば、ポインタチェック?とかはされない限りは、CRCがあっても問題ありません。(.exeは別みたいですが。)


関数テーブル上の関数は、asm上では call dword ptr [eax+04] とかで呼ばれため、
テーブル自体の書き換えは、直接メモリを書き換える訳でもないので検出が難しいみたいですね。
出来るとすれば、関数ポインタ先が、メモリ内or外、またはBase Relocation (.dll+XXXX) などが挙げられるようです。


他にもポインタ自体のチェックがありますが、プロテクタがそのポインタを読み込む前に書き換えてしまえば難なく突破出来てしまいます。
良く海外フォーラム等にWallhackなどが落ちていますよね。モノによってはプロテクタの有無に関わらず、そのまま使えたりするものもありますよね。そうです、そういうことです。


少し話が逸れますが、関数テーブルの書き換えによって行うチートの検出は難しいと思いました。


更に追記:
冒頭にグラフィックドライバ自体に関数テーブルが用意されてないだとか書きましたが、OpenAdapterはグラフィックドライバの関数テーブルの他に、D3Dの何らかの関数テーブルの初期化時にも呼ばれることが分かりました。
今までは決め打ちでやっていたため、D3Dの何らかの関数テーブルの方を取得してたみたいです。