はじめに
ポケモンクリスタルで任意コード実行をするための手段として主に
- バグモード図鑑
- 分類違いわざマシン
の2つが知られています.
今回の記事では 0x1500 制御コードによる任意コード実行のやり方について解説しようと思います.
0x1500 制御コードによる任意コード実行とは
仕組みについては後で述べるのですが 0x15, 0x00 を文字列として表示させようとすることがトリガーとなって発生する任意コード実行です.luckytyphlosion さんが発見したそうです.クリスタルのみで行えるもので金銀ではできないものとなります.
注意 (2023/11/28 追記)
手順についてですが以下の記事で簡単に実行できるようになったのでこちらもご参照ください.
ポケモンクリスタル バイナリエディタ起動 チャート - flag3833753
0x1500 制御コードによる任意コード実行の手順
準備 1: 終端記号のないポケモンの入手
1. どうぐ欄にアイテムを 1 種類以上入手しておく.
2. 一度も満タンになったことのないボックス*1に切り替えてセーブをする.
3. ポケモンを 1 匹預ける.
4. ボックスせいりを選択しセーブする際に「でんげんを きらないで ください」の表示が出た少し後に強制リセットをする.
5. 再開後どうぐ欄を開く.
6. パソコンを開き預けられたポケモンのニックネームが??????のような表示になれば成功です*2.
7. ボックス 1 をニックネーム??????のポケモンのみにする.
もしポケモンが預けられていない場合は強制リセットのタイミングが早すぎたことになります.もし預けたポケモンが手持ちとボックスの両方に複製されてしまった場合は強制リセットのタイミングが少し遅かったことになります.預けたポケモンが手持ちからいなくなっている場合は強制リセットのタイミングが遅すぎたことになります.
ボックスに預けているポケモンの数が多いとタイミングの猶予が少し長くなるので複製になってしまう場合でもそのままトライし続ければ成功率が上がると思います.
実際の強制リセットのタイミングとしては以下の動画が役に立つかもしれないので置いておきます.
unterminated_name_pokemon.mov - Google ドライブ
準備 2: 特定のポケモンの入手
まずはオニスズメを入手します.入手方法としては朝または昼に 46 ばんどうろで出現するのを狙うか,コガネシティ北で「ひきゃく」を入手してください.「ひきゃく」を入手する場合は持っているメールを外してください.
もう 1 匹は候補として以下で紹介するイワークかサンドのどちらかを入手してください.
イワーク
1. 31 ばんどうろで野生のマダツボミを捕まえる.
2. マダツボミをキキョウシティのポケモンセンター左の民家で「ブルブル」と交換してイワークを入手する.
3. イワーク単独でイトマルを 3 匹,キャタピーを 2 匹倒す.
4. イワークに道具は何も持たせずに技の順番を「たいあたり」「いやなおと」にする.
イトマルは夜に 31 ばんどうろで出現,キャタピーは朝または昼に 31 ばんどうろで出現しますが,30, 31 ばんどうろのトレーナーが出してくるキャタピーを倒しても大丈夫です.31 ばんどうろのトレーナーと戦闘する場合はしあいのルールをいれかえタイプにすることを推奨します.また経験値が 256 ~ 511 となっていることを確認してください.
手順
1. 手持ちの 1 匹目をオニスズメ,2 匹目を上で用意したイワーク or サンドにする.3 匹目以降は何でも良いです.
2. 手持ちの 1 匹目のオニスズメに任意コード実行用のメールを持たせる.
3. ポケモンセンターのパソコンの前に立ちセーブをしてリセットを行う.
4. 再開後一歩下に移動しメニューを開いてイワーク or サンドのステータスを見る.
5. 一歩上に移動しメニューを開いてオニスズメに持たせているメールを見る.
6. パソコンを開いてポケモンをひきだすで終端記号のないポケモンを表示する.
以上の手順を行うことで任意コード実行用のメールの文面を実行することができます.
ただしメールの 2 文字目と 3 文字目は実行時に 01 に書き換えられること*3とコードを ret 命令で終了させる前に pop hl 命令を実行する必要があることに注意してコードを組む必要があります.
具体例
例えば任意コード実行用のメールとして以下のものを用意するとオニスズメに「そらをとぶ」を覚えさせてフィールドで使うことができるようになります.動画にすると次のような感じとなります.
0x1500.mov - Google ドライブ
ぼドデの
以下のコードを実行すると図鑑モードを 0C にすることができそのまま次の記事を用いてバイナリエディタの導入ができるようになります.
ポケモンクリスタルにおけるバイナリエディタ - flag3833753
0x1500 制御コードによる任意コード実行の仕組み
先述の通り 0x15, 0x00 を文字列として表示させようとすることが任意コード実行のトリガーとなっています.実際に 0x15 を文字列として表示させようとするとモバイルアダプタ関連の機能を実行させようとします.0x15 を読むとモバイルアダプタ機能のリストへジャンプするために 0x15 の次のアドレスの中身を使用します.有効な中身は 0x01 ~ 0x0F となっています.0x10 以上を読み取った場合は無効として扱われモバイルアダプタ機能を正常に終了させます.しかし 0x00 を読み取った場合はモバイルアダプタ機能を終了させることなく 0xCD46 を実行させます.
では何故 0x15, 0x00 を文字列として表示させようとしたのかというと,終端記号のないポケモンを表示させたのが理由となります.名前を読む際に 0xD05B 以降にポケモンの名前がコピーされてそこから名前を表示します.終端記号が途中で存在すればそこで名前を表示させるのを終了させますが,終端記号がない場合は名前が読み込まれ続けます.上記の手順を行っていると 0xD0C7 まで読まれその後に 0xD0C8 の中身 0x15,0xD0C9 の中身 0x00 が読まれてしまいます.
0xD0C8 の中身が 0x15,0xD0C9 の中身が 0x00 となっている理由はポケモンの 1 番目のオニスズメに持たせているメールを読んでいるからです.メールを読む流れで 0xD0C8 にオニスズメの種族 ID 0x15,0xD0C9 に 1 番目という情報 0x00 が書き込まれます (プログラムの慣習で 0-indexed).
0xCD46 を実行した後は 0xCD63 までは無害な命令が続き,0xCD64 で 0xC0 (ret nz) が実行されます.この命令が実行されると次は 0xD0CA を実行することになります.このアドレスは文字列を読む際に最後に読んだ 0x15, 0x00 の次のアドレスとなります.ちなみに 0xCD64 に 0xC0 を入れるためにゲームを開始して下に移動して手持ちを開くといった動作を行っています.
0xD0CA ~ 0xD0CD は無害な命令となります.0xD0CE からは最後に見たポケモンの情報が記録されており,上記の手順を行っているとイワーク or サンドの情報が書き込まれています.イワーク or サンドの準備では努力値の調整を行っていてプログラムとして実行をすることで 0xF000 に飛ぶようになっています.
0xF000, 0xF001 は無害な命令となっており,0xF002 からは最後に読んだメールの中身となっていて,任意コード実行をすることができるといった流れとなります.ただしボックスを開くことで 0xF003, 0xF004 にはボックスに関係した情報 (どのボックスを開いているかとボックスに預けているポケモンの数) が記録されるといった形となります.
参考文献
参考文献は以下の 2 つとなります.特に上で紹介した手順については 2 つ目の記事をかなり参考にしています.
Acknowledgements
I would like to thank TimoVM, who has provided me with information about the 0x1500 control code arbitrary code execution and has kindly guided me through the actual process.