DrawGuessHelper:Draw & Guess 向けの DX11 インジェクション補助フレームワーク
DrawGuessHelper は Steam の Draw & Guess 向けに書いた DX11 インジェクション補助だ。ゲームは Unity + Mono 製で、メモリはほぼ丸見え、逆向とインジェクションの練習にちょうどいい。やり方は定石通り:DLL をプロセスに注入し、MinHook で DX11 の Present を hook、ゲームがそのフレームを描き終えた後に Dear ImGui overlay を一枚重ねる。Insert か右 Shift でパネルを呼び出す。ゲームロジックとのやり取りは Mono runtime のリフレクション経由で、スレッドを attach すればそのまま C# オブジェクトを読んでメソッドを呼べる。答え透視のようなクライアントローカルにあるデータを読み出すのも手軽だ。
一番気にかけているのは機能ではなくフレームワークのほうだ。自動描画、答え透視、スコア偽造、改名クールダウンの回避、ネットワーク層の DoS。こういうのはいくらでも並べられるが、自分にとってはどれも「コンテンツ」で、一つ書けば一つ増えるだけだ。核となるのは極めてシンプルなプラグインフレームワーク:一つの IModule インターフェース、一つの ModuleRegistry、それに REGISTER_MODULE マクロで静的な自己登録を行う。新しいものを足すには自己完結したファイルを一つ書いて CMake のリストに放り込むだけで、他は一切触らない。UI パネルはカテゴリごとに自動で伸び、コマンドは自動でリモートインターフェースに繋がる。今こうして積み上がった十八個のモジュールは互いの存在を知らず、一つ変えても他は壊れない。
bridges/ の RemoteBridge はプロセス内に HTTP サービスを立て、127.0.0.1:9099 を listen する。文字列を POST すれば操作できる。
curl -X POST http://127.0.0.1:9099 -d "STATUS"
curl -X POST http://127.0.0.1:9099 -d "ANSWER"
STATUS は状態 JSON を返し、ANSWER は現在の答えを吐き、DRAW/DRAW_STOP は自動描画を制御する。一番飛ばしているのは EVAL static <Class> <Method> で、Mono リフレクションを一本のリモートコマンドとして露出させ、実行時に任意の静的メソッドを呼べる。つまりバックドアを開けたようなものだ。逆向デバッグが楽になり、再コンパイルして注入し直す必要もなく、curl の一行を書き換えて試せる。サービスはローカルループバックにのみバインドし、認証はない。純粋にローカルデバッグ用なので、外部ネットワークには晒さないこと。
技術スタックは C++17 + MSVC、DX11 Present hook に MinHook、ImGui は docking ブランチ、ネットワーク層は Hazel/Photon プロトコル、経済システムは PlayFab の CloudScript が絡む。ハマりどころは Mono 側だ:リフレクション呼び出しの前に必ず attachThread でスレッドを Mono runtime に繋がないと、忘れると即クラッシュする。またローカルキャッシュの変更はサーバーからの配信で上書きされて戻るのを防ぐ必要があるので、キャッシュロックを入れた。
純粋に Unity/Mono クライアントを研究し、逆向とインジェクションを練習するためのおもちゃで、セキュリティ研究と学習のためだけのものだ。コードはこちら https://github.com/dwgx/DrawGuessHelper。