著者: Jingdong Industryの Wan Yuxin
幼い頃からマインスイーパゲームを遊んだことがある人も多いと思いますが、コンピューターゲームが少なかった時代に、マインスイーパは最も人気のあるゲームの 1 つになりました。動的デバッグ、リバース エンジニアリング、およびCを使用してマインスイーパ補助ツールを作成し、リバース エンジニアリングとコーディングのスキルを向上させます。
動的デバッグ (分析)
まず、掃海艇プログラムの動的デバッグ (分析) を実行します。
OD ( ollydebugツール)を開き、マインスイーパをODにドラッグ アンド ドロップし、F9で実行します。ctrl +Gで式を入力し、 randを入力し、[OK] をクリックして関数呼び出しにジャンプし、F2でブレークポイントを設定します。 2 つ目は、 API の rand関数を介してブレークスルーを見つけることです。下の図に示すように、マインスイーパ ウィンドウの地雷原の任意の位置 (図の2 が表示されている場所) をクリックし、[復元] ([スマイリー フェイス] ボタン- ) をクリックします。

このとき、次の図に示すように、設定したrandのブレークポイントでODがブレークします。

ランダム関数randを見つけることで、次のスタックはバックトラックし、プッシュ(スタックにプッシュ) のパラメーターを見つけるために上位関数に戻ります。つまり、ランダム生成関数 ( rand ) は、ランダムに生成された高さです。幅、そして雷。K (コール スタック) をクリックしてKコール スタック ウィンドウをポップアップし、スタック ウィンドウ情報を表示し、戻りアドレスを見つけ、Kコール スタック ウィンドウで戻りアドレスをダブルクリックし、前のレイヤーに戻ります。スタック バックトラッキング。下図のスタック情報010036D2 (リターンアドレス)に注意してください。



以下に示すように、単一ステップF8で、レジスタ、データ ウィンドウ、およびスタック ウィンドウの変更、dword ptr ss:[esp+0x4]またはdword ptr ds:[XXX]データ ウィンドウ トラッキング値 ( 000DFC44値は09 ) を観察します。

上位関数に戻って内部の命令を解析すると、先ほどのランダムランドで生成された幅( 09 )がわかりますので、下図のように010036C7番地に注目してください。

最初に、この関数によって返された結果からeaxを分析します. 1 つのステップの後、下の図に示すように、数字09がスタック (アドレス010036D2 )にプッシュされていることがわかります:

上記の分析を通じて、基本的に周囲のランダム関数rand生成が高い、雷数であると推測できます。次の図に示すように、掃海設定 (カスタム地雷原) を変更して、rand関数を正確に見つけてパラメーターを渡し、[OK] をクリックし、[復元 (笑顔- )] ボタンをクリックします。

下の図に示すように、OD を観察します。

プッシュ 0C ( 000DFC84の値は0C )であることがわかり、このrand関数のプッシュ 0C が地雷原の高さであると判断できます。同時に、メモリ領域に大まかな地雷原のグラフィックがはっきりと表示され、上記の方法で0x80が地雷原であることが大まかに推測できます。または、IDAと一緒に解析して、静的解析を行うことで、プログラムのロジックをより直感的に見ることができます。下の図に示すように、次のデータを取得します: ベースアドレス、鉱山番号、およびその他の情報。



上記のコードはおそらく、グローバルな幅0x09 、高さ0x0C 、雷数0x0Aの変数を最初に設定し、2 層のループを判断して幅と高さをランダムに生成することを意味していると思われます。マップ ベース アドレスを取得します: 0x01005340 。下の図を分析すると、地雷は0x0Fではなく、地雷は0x8Fで、壁は0x10であることがわかります。


幅と高さのアドレスを通じて、掃海エリアと地雷の数が印刷され、側壁と地雷をより直感的に区別できます。
次に、Lei をマークする方法を理解することから始めましょう. GetDC関数がWinProcで見られると仮定すると(スタックを介してメッセージ コールバック関数までバックトラックします) 、 Bitbltが使用されることが大まかに推測されます. ODで、式を入力しますの後にctrl+gを押し、「 BitBlt 」と入力し、F2を押してブレークポイントを設定し、掃海エリア内の任意の位置をクリックすると、OD がBitBltの位置でブレークします。
BitBltにはBitBlt関数もありますが、ダブルバッファリングを使って描画しているというのが予備的な判断です。
BitBlt(hDestDC,//宛先DC XDest, //宛先x座標YDest, //宛先y座標10, // 10, //再描画領域の高さと幅hSrcDC, //ソースDC 0, 0, SRCCOPY); / /機雷の座標を計算する操作方法を指定します (座標を表示するには、最初の掃海マスをクリックします)。以下に示すように、側壁に注意する必要があります。


側壁の値を引きます。
-0x04=0x0C(12)-0x10(16)
0x27=0x37(55)-0x10(16)
座標式を取得します: x ( XDest:12 ) =1*0x10(16)-0x04(4) , y ( YDest:55 ) =1*0x10(16)+0x27(39)。
コードの書き方
上記の大まかな分析を通じて、コードを書くことができ、



成果

地雷を取得するために3つの地雷の場所を入力してください(10の壁、8Fの地雷、0Fの地雷なし)

2を入力して、地雷を自動的に除去し、地雷をマークしてマップを開きます

この小さなプロジェクトを通して、まず第一に、ソフトウェアについての一種の逆思考が強化されました。たとえば、この種のパネルを見て、おそらく配列で実装されていると推測し、第二に、私のレイアウトはランダムです。生成され、動的デバッグを通じて、実装方法(開発者の実装アイデア)を理解でき、キーベースアドレス、いくつかの状態(雷、雷、壁なし)を見つけることができ、最後のコーディング段階を理解できますメモリの操作、いくつかの重要な API、ハンドルを取得するための FindWindow、OpenProcessはハンドルを開き、ReadProcessMemory はメモリ情報を読み取り、PostMessage非同期メッセージ モード、CloseHandleはハンドルを閉じます。分析の一部が間違っているか、適切に配置されていません。レンガを撃ってください。さらに逆に、コードを分析することは非常に役立ちます。プログラミングとテストの思考とレベルを広げるだけでなく、プログラムの抜け穴を発見、開発、悪用したり、プログラムにパッチを当てたりすることもできます。この長く険しい道のりで、私の友人たちが懸命に働き、互いに励まし合うことを願っています。