洞窟物語の改造
ゲーム改造の練習に洞窟物語を改造してみる。
とりあえずeXeScopeで開いてみると以下のようにデッバガセーブ/消音というメニューがあることが分かる。
この二つのメニューはゲームのプレイ時には表示されていない。Win32 APIを使って削除していると予測する。
次はデバッガの出番。
eXeScopeを閉じてImmunity Debuggerで洞窟物語を開く。
Ctrl+NでAPIの一覧を表示させ、メニューを削除するAPIはDeleteMenuかRemoveMenuしかないのでそれらを探す。
DeleteMenuが見つかった。
DeleteMenuの項目を右クリックし、Find references to importを選ぶ。
すると、以下のような画面が出る。
アドレス00412D58と00412D91が見つかるのでアドレス00412D58の項目をダブルクリックする。
出てきた周辺の逆アセンブルコードリストを眺めると以下のようになっている。
メニューを削除しないようにするには2つのDeteleMenu呼び出し箇所、00412D4D~00412D58、00412D86~00412D91を実行しないようにすればよい。
全てNOPで埋めるのが一番簡単だが書き換えバイト数も多くなり美しくない。
一つ目のDeleteMenuは最初の引数をPUSHしているところをDeteleMenu呼び出し後の場所にJMPするようにし、二つ目のDeleteMenuはアドレス00412D84がJNZ SHORT Doukutsu.00412D97となっていることに着目しこのJNZを強制ジャンプ、JMPに変更するとパッチも小さく済む。
最終的に変更箇所は以下のようになった。
; 一つ目 ; 変更前 00412D4D |. 6A 00 PUSH 0 ; /Flags = MF_BYCOMMAND|MF_ENABLED|MF_STRING 00412D4F |. 68 459C0000 PUSH 9C45 ; |ItemId = 9C45 (40005.) 00412D54 |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] ; | 00412D57 |. 52 PUSH EDX ; |hMenu 00412D58 |. FF15 F0C14800 CALL DWORD PTR DS:[<&USER32.DeleteMenu>] ; \DeleteMenu 00412D5E |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 00412D61 |. 50 PUSH EAX ; /hWnd 00412D62 |. FF15 F4C14800 CALL DWORD PTR DS:[<&USER32.DrawMenuBar>>; \DrawMenuBar ; 変更後 00412D4D EB 0F JMP SHORT Doukutsu.00412D5E 00412D4F |. 68 459C0000 PUSH 9C45 ; |ItemId = 9C45 (40005.) 00412D54 |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] ; | 00412D57 |. 52 PUSH EDX ; |hMenu 00412D58 |. FF15 F0C14800 CALL DWORD PTR DS:[<&USER32.DeleteMenu>] ; \DeleteMenu 00412D5E |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 00412D61 |. 50 PUSH EAX ; /hWnd 00412D62 |. FF15 F4C14800 CALL DWORD PTR DS:[<&USER32.DrawMenuBar>>; \DrawMenuBar ; 二つ目 ; 変更前 00412D84 |. 75 11 JNZ SHORT Doukutsu.00412D97 00412D86 |. 6A 00 PUSH 0 ; /Flags = MF_BYCOMMAND|MF_ENABLED|MF_STRING 00412D88 |. 68 479C0000 PUSH 9C47 ; |ItemId = 9C47 (40007.) 00412D8D |. 8B55 F8 MOV EDX,DWORD PTR SS:[EBP-8] ; | 00412D90 |. 52 PUSH EDX ; |hMenu 00412D91 |. FF15 F0C14800 CALL DWORD PTR DS:[<&USER32.DeleteMenu>] ; \DeleteMenu 00412D97 |> 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 00412D9A |. 50 PUSH EAX ; /hWnd 00412D9B |. FF15 F4C14800 CALL DWORD PTR DS:[<&USER32.DrawMenuBar>>; \DrawMenuBar ; 変更後 00412D84 EB 11 JMP SHORT Doukutsu.00412D97 00412D86 |. 6A 00 PUSH 0 ; /Flags = MF_BYCOMMAND|MF_ENABLED|MF_STRING 00412D88 |. 68 479C0000 PUSH 9C47 ; |ItemId = 9C47 (40007.) 00412D8D |. 8B55 F8 MOV EDX,DWORD PTR SS:[EBP-8] ; | 00412D90 |. 52 PUSH EDX ; |hMenu 00412D91 |. FF15 F0C14800 CALL DWORD PTR DS:[<&USER32.DeleteMenu>] ; \DeleteMenu 00412D97 |> 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 00412D9A |. 50 PUSH EAX ; /hWnd 00412D9B |. FF15 F4C14800 CALL DWORD PTR DS:[<&USER32.DrawMenuBar>>; \DrawMenuBar
変更が終わったら右クリック->Copy to executable->All modificationsで現れるダイアログに対してCopy allを選ぶ。すると、ウィンドウが表示されるので右クリック->Save fileでファイルにセーブする。
セーブしたファイルを起動すると表示されていなかったメニューが表示されていることが確認できた。
*== TARGET_FILE ================ FILENAME Doukutsu.exe * FileSize: 1478656 bytes * LastMod.: 2005/06/12 16:07:12 *=============================== 00012D4D: 6A EB 00012D4E: 00 0F 00012D84: 75 EB