3のパート1
あなたがリバースエンジニアリングに真剣であるならば-トレーナーとチートエンジンを忘れてください。
優れたリバースエンジニアは、最初にOS、コアAPI関数、プログラムの一般的な構造(実行ループとは何か、Windows構造、イベント処理ルーチン)、ファイル形式(PE)を知る必要があります。Petzoldのクラシックな「Programming Windows」は、オンラインMSDNだけでなく(www.amazon.com/exec/obidos/ISBN=157231995X)にも役立ちます。
最初に、地雷原初期化ルーチンを呼び出すことができる場所について考える必要があります。私は次のことを考えました:
- ゲームを起動すると
- 幸せそうな顔をクリックすると
- 「ゲーム」->「新規」をクリックするか、F2キーを押したとき
- レベル難易度を変更したとき
F2加速器コマンドをチェックすることにしました。
アクセラレータ処理コードを見つけるには、ウィンドウメッセージ処理手順(WndProc)を見つけます。CreateWindowExとRegisterClassの呼び出しによって追跡できます。
読むには:
IDAの[インポート]ウィンドウを開き、「CreateWindow *」を見つけてそこにジャンプし、「Jump xref to operand(X)」コマンドを使用して、それが呼び出される場所を確認します。呼び出しは1つだけです。
ここで、RegisterClass関数とそのパラメーターWndClass.lpfnWndProcを探します。私の場合、関数にはすでにmainWndProcという名前を付けています。
.text:0100225D mov [ebp+WndClass.lpfnWndProc], offset mainWndProc
.text:01002264 mov [ebp+WndClass.cbClsExtra], edi
.text:01002267 mov [ebp+WndClass.cbWndExtra], edi
.text:0100226A mov [ebp+WndClass.hInstance], ecx
.text:0100226D mov [ebp+WndClass.hIcon], eax
.text:01002292 call ds:RegisterClassW
関数名でEnterキーを押します( 'N'を使用して名前をより適切な名前に変更します)
今見てください
.text:01001BCF mov edx, [ebp+Msg]
これはメッセージIDであり、F2ボタンを押した場合はWM_COMMAND値が含まれます。あなたはそれが111hと比較される場所を見つけることです。これは、IDAでedxをトレースダウンするか、WinDbgで条件付きブレークポイントを設定して、ゲームでF2を押すことで実行できます。
どちらの方法でも
.text:01001D5B sub eax, 111h
.text:01001D60 jz short loc_1001DBC
111hを右クリックして、「記号定数」->「標準記号定数を使用」を使用し、WM_と入力してEnterキーを押します。あなたは今持っているべきです
.text:01001D5B sub eax, WM_COMMAND
.text:01001D60 jz short loc_1001DBC
これは、メッセージID値を見つける簡単な方法です。
アクセラレータの処理を理解するには、以下を確認してください。
単一の回答にはかなりの量のテキストです。興味があれば、別の投稿をいくつか書けます。長い地雷の地雷原はバイトの配列[24x36]として保存され、0x0Fはバイトが使用されていないことを示します(小さいフィールドを再生)、0x10-空のフィールド、0x80-地雷。
3のパート2
では、F2ボタンを押しましょう。
F2ボタンが押されたときのキーボードアクセラレータの使用によると、wndProc関数
... WM_COMMANDまたはWM_SYSCOMMANDメッセージを受け取ります。wParamパラメータの下位ワードには、アクセラレータの識別子が含まれています。
OK、すでにWM_COMMANDが処理される場所を見つけましたが、対応するwParamパラメータ値を決定する方法は?ここでリソースハッカーが活躍します。バイナリをフィードすると、すべてが表示されます。アクセラレータテーブルのように。
代替テキストhttp://files.getdropbox.com/u/1478671/2009-07-29_161532.jpg
F2ボタンがwParamの510に対応していることがわかります。
次に、WM_COMMANDを処理するコードに戻りましょう。wParamをさまざまな定数と比較します。
.text:01001DBC HandleWM_COMMAND: ; CODE XREF: mainWndProc+197j
.text:01001DBC movzx eax, word ptr [ebp+wParam]
.text:01001DC0 mov ecx, 210h
.text:01001DC5 cmp eax, ecx
.text:01001DC7 jg loc_1001EDC
.text:01001DC7
.text:01001DCD jz loc_1001ED2
.text:01001DCD
.text:01001DD3 cmp eax, 1FEh
.text:01001DD8 jz loc_1001EC8
コンテキストメニューまたは 'H'キーボードショートカットを使用して10進値を表示すると、ジャンプを確認できます
.text:01001DBC HandleWM_COMMAND: ; CODE XREF: mainWndProc+197j
.text:01001DBC movzx eax, word ptr [ebp+wParam]
.text:01001DC0 mov ecx, 528
.text:01001DC5 cmp eax, ecx
.text:01001DC7 jg loc_1001EDC
.text:01001DC7
.text:01001DCD jz loc_1001ED2
.text:01001DCD
.text:01001DD3 cmp eax, 510
.text:01001DD8 jz loc_1001EC8 ; here is our jump
これは、いくつかのprocを呼び出し、wndProcを終了するコードチャンクにつながります。
.text:01001EC8 loc_1001EC8: ; CODE XREF: mainWndProc+20Fj
.text:01001EC8 call sub_100367A ; startNewGame ?
.text:01001EC8
.text:01001ECD jmp callDefAndExit ; default
それは新しいゲームを開始する機能ですか?最後の部分でそれを見つけてください!乞うご期待。
3のパート3
その関数の最初の部分を見てみましょう
.text:0100367A sub_100367A proc near ; CODE XREF: sub_100140C+CAp
.text:0100367A ; sub_1001B49+33j ...
.text:0100367A mov eax, dword_10056AC
.text:0100367F mov ecx, uValue
.text:01003685 push ebx
.text:01003686 push esi
.text:01003687 push edi
.text:01003688 xor edi, edi
.text:0100368A cmp eax, dword_1005334
.text:01003690 mov dword_1005164, edi
.text:01003696 jnz short loc_10036A4
.text:01003696
.text:01003698 cmp ecx, dword_1005338
.text:0100369E jnz short loc_10036A4
レジスタeaxとecxに読み込まれ、別の2つの値(dword_1005164、dword_1005338)と比較される2つの値(dword_10056AC、uValue)があります。
WinDBGを使用して実際の値を見てみましょう( 'bp 01003696';休憩 'p eax; p ecx')-私にとって地雷原の寸法のように見えました。カスタム地雷原のサイズで遊んでみると、最初のペアは新しい次元であり、2番目-現在の次元であることがわかりました。新しい名前を設定しましょう。
.text:0100367A startNewGame proc near ; CODE XREF: handleButtonPress+CAp
.text:0100367A ; sub_1001B49+33j ...
.text:0100367A mov eax, newMineFieldWidth
.text:0100367F mov ecx, newMineFieldHeight
.text:01003685 push ebx
.text:01003686 push esi
.text:01003687 push edi
.text:01003688 xor edi, edi
.text:0100368A cmp eax, currentMineFieldWidth
.text:01003690 mov dword_1005164, edi
.text:01003696 jnz short loc_10036A4
.text:01003696
.text:01003698 cmp ecx, currentMineFieldHeight
.text:0100369E jnz short loc_10036A4
少し後で新しい値が現在の値を上書きし、サブルーチンが呼び出されます
.text:010036A7 mov currentMineFieldWidth, eax
.text:010036AC mov currentMineFieldHeight, ecx
.text:010036B2 call sub_1002ED5
そしてそれを見たとき
.text:01002ED5 sub_1002ED5 proc near ; CODE XREF: sub_1002B14:loc_1002B1Ep
.text:01002ED5 ; sub_100367A+38p
.text:01002ED5 mov eax, 360h
.text:01002ED5
.text:01002EDA
.text:01002EDA loc_1002EDA: ; CODE XREF: sub_1002ED5+Dj
.text:01002EDA dec eax
.text:01002EDB mov byte ptr dword_1005340[eax], 0Fh
.text:01002EE2 jnz short loc_1002EDA
私は地雷原の配列を見つけたと完全に確信していました。360xバイト長の配列(dword_1005340)を0xFで初期化するサイクルの原因。
360h = 864なのはなぜですか?その行の下にはいくつかの手がかりがあり、行は32バイトを取り、864は32で割ることができるため、配列は27 * 32のセルを保持できます(UIは最大24 * 30のフィールドを許可しますが、境界の配列の周りに1バイトのパディングがあります)。
次のコードは地雷原の上部と下部の境界線(0x10バイト)を生成します。私はあなたがその混乱の中でループ反復を見ることができることを望みます;)私は紙とペンを使わなければなりませんでした
.text:01002EE4 mov ecx, currentMineFieldWidth
.text:01002EEA mov edx, currentMineFieldHeight
.text:01002EF0 lea eax, [ecx+2]
.text:01002EF3 test eax, eax
.text:01002EF5 push esi
.text:01002EF6 jz short loc_1002F11 ;
.text:01002EF6
.text:01002EF8 mov esi, edx
.text:01002EFA shl esi, 5
.text:01002EFD lea esi, dword_1005360[esi]
.text:01002EFD
.text:01002F03 draws top and bottom borders
.text:01002F03
.text:01002F03 loc_1002F03: ; CODE XREF: sub_1002ED5+3Aj
.text:01002F03 dec eax
.text:01002F04 mov byte ptr MineField?[eax], 10h ; top border
.text:01002F0B mov byte ptr [esi+eax], 10h ; bottom border
.text:01002F0F jnz short loc_1002F03
.text:01002F0F
.text:01002F11
.text:01002F11 loc_1002F11: ; CODE XREF: sub_1002ED5+21j
.text:01002F11 lea esi, [edx+2]
.text:01002F14 test esi, esi
.text:01002F16 jz short loc_1002F39
そして、残りのサブルーチンは左と右の境界を描画します
.text:01002F18 mov eax, esi
.text:01002F1A shl eax, 5
.text:01002F1D lea edx, MineField?[eax]
.text:01002F23 lea eax, (MineField?+1)[eax+ecx]
.text:01002F23
.text:01002F2A
.text:01002F2A loc_1002F2A: ; CODE XREF: sub_1002ED5+62j
.text:01002F2A sub edx, 20h
.text:01002F2D sub eax, 20h
.text:01002F30 dec esi
.text:01002F31 mov byte ptr [edx], 10h
.text:01002F34 mov byte ptr [eax], 10h
.text:01002F37 jnz short loc_1002F2A
.text:01002F37
.text:01002F39
.text:01002F39 loc_1002F39: ; CODE XREF: sub_1002ED5+41j
.text:01002F39 pop esi
.text:01002F3A retn
WinDBGコマンドをスマートに使用すると、地雷原のクールなダンプ(カスタムサイズ9x9)を提供できます。国境をチェック!
0:000> db /c 20 01005340 L360
01005340 10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005360 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005380 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053a0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053c0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010053e0 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005400 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005420 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005440 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005460 10 0f 0f 0f 0f 0f 0f 0f-0f 0f 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
01005480 10 10 10 10 10 10 10 10-10 10 10 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054a0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054c0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
010054e0 0f 0f 0f 0f 0f 0f 0f 0f-0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f ................................
うーん、トピックを閉じるには別の投稿が必要なようです