こちらはPokémon Past Generation Advent Calendar 2024の5日目の記事となります。
昨年、メールリサイクルバグを利用することによりFRLG単体での任意コード実行が可能であることが示されました。
今回は日本語版RS単体で任意コードを実行したいと思います。通信も電池も使いません。前期版ならルビーでもサファイアでも実行可能なはずです。(一応関数アドレスなどは精査しましたが、デバッグはサファイアでしかしていないのでルビーで不具合があったらごめんなさい)
電池ありでもIDをちゃんと調整すればできますが、この記事では電池無しの場合しか計算していません。
エメラルドのザロクバグやポケモンのメモリ構造、乱数調整やアセンブリを熟知している人向けの解説になっている気がする。
トリガーは?
今回使うのはバグわざ0x201cのアニメーションです。
実行すると0x02030400からのわざアニメが実行されます。これはボックス1の20番目のポケモンが存在するメモリで、ここからボックスの最後までポケモンを置かないことによりボックス名を任意コードとして使用することができます。
ただしこのわざは戦闘画面でわざ名を見ると画面が崩壊し操作不可になり、おまけに命中0です。その為ねこのてでロックオンとこのわざを出す必要があり、非常に面倒。なのでこのわざを使い、もっと簡単に任意コード実行可能なトリガーを呼び出すという段階を踏むことにします(簡単なトリガーについては後述)。
どうやってバグわざを入手する?
エメラルドならザロクバグによるズレた位置へのダメタマゴフラグ付与、FRLGならメールバグによるメモリ破壊がトリガーポケモンの入手方法になっています。しかしRSではこれらは再現不可能。そこで目を付けたのが徘徊バグです。
手持ちが二体以上いるトレーナーに負け、他のポケモンやトレーナーに出会わないようにして徘徊ラティと遭遇します。その状態でラティを倒すと、なぜかさっきのトレーナーの二匹目のポケモンが出てきます。
この時れっきとした野生ポケモンとの戦闘状態であるため、このポケモンを捕獲することができます。
しかし、基本的にはバトルタワー以外での戦闘だと捕獲後にポケモンがダメタマゴへと変化します。
これはNPCと主人公のIDが一致しないため。ここで第三世代のポケモンデータ構造を解説します。
ポケモンのデータ構造
ポケモンデータには暗号化機能が存在し、ポケモンの性格値とIDをxor演算した数値で更にxor演算を行い、データにマスクを掛けます。
マスクされた数値は再度暗号鍵でxorすることで復号できるのですが、復号したデータから計算されるチェックサムが事前に保存されたそれと一致しない場合、ダメタマゴが発生します。
先ほど説明した通り、NPCと主人公のIDが一致しないためダメタマゴ化は避けられないように思えます。
しかし、エメラルドのザロクバグで起きていることは性格値の上書き。暗号鍵に関連する数値を書き換えているのにダメタマゴへと変化せずに、バグポケモンがしっかり発生しています。
元の数値から0x40000000でxor演算がされるようになっているのですが、言うなればこれは復合後のデータでも0x40000000のbitが反転されるようになるということ。
チェックサムは16bit毎に足し合わせて計算され、17bit目以降に溢れた数値は無視されます。元々0x40000000のbitが立っているのが偶数箇所の場合は反転が行われても、桁溢れによりチェックサムが一致するようになっているわけです。
話をRSに戻します。徘徊バグでは性格値ではなくIDが上書きされることになるのですが、だいたい同じことを行えます。
今回のトリガーはわざコード0x201c。わざコード0x01cのすなかけを0x2000で反転させた場合に発現します。
0x2000で反転する場合、0x4000と異なりチェックサムが同じになるのは、元々bitが立っているのが2箇所か10箇所の時のみになります。
0x2000 * 2 = 0x4000, 0x2000 * 10 = 0x14000
なので17bit目以降を無視すれば同じになります。
119ばんどうろにいるオサムの持つツチニンはすなかけをわざ1に覚えており、元々立っている0x2000のbitは経験値(60万タイプのレベル26なので26012 = 0x659c)と捕まえた場所(119ばんどうろのマップIDは0x22、この数値が格納されているのはmiscellaneousブロックの1byte目なので8ビット左シフトされている)の二箇所のみとなっていて条件を満たします。
ID調整
実際に使うIDはこちら。
123387F 44491-51846
待機時間は34分くらいありますが、頑張りましょう。時間がかかるだけで難しくはないです。
ストーリー
ごく普通に殿堂入りまで進めてください、ただし先述のオサムを必ずスルーし、マスターボールも使わないでください。
殿堂入り後
以下のポケモンを用意します。
・レベル40以下ででんこうせっかを覚えたポケモン
ラティに遭遇し体力をギリギリまで削る&倒す用のポケモンです。115ばんどうろで捕まえられるレベル25のオオスバメをレベル30くらいまで育てるのが手ごろでしょうか。第三世代だとスプレーを使っているときには瀕死でない中で一番前のポケモンを参照します。
・ねこのてを覚えたポケモン
エネコがレベル19で覚えるのみです。エネコは116ばんどうろ限定出現で出現率2%なので、サファリゾーンで捕まえたピカチュウをヒワマキシティで交換するのもよいでしょう。(ピカチュウの出現率5%でひらいしんも効きませんが)
・ロックオンを覚えたポケモン
コイル・レアコイル・ノズパス・レジ系が該当。コイルをレベル32にしましょう。ロックオン以外のわざは必ず忘れさせてください。
上記のポケモンを用意出来たら頑張ってラティと遭遇しましょう。キンセツシティ周辺で粘るのが良いと思われます。
一度遭遇したら次は図鑑の分布を見ることで比較的楽に遭遇可能です。キンセツ周辺にいない場合はそらをとぶでリセットできます。
また、「つづきからはじめる」を選択するまでのフレームを調整することで初期位置を乱数調整することも可能です。
でんこうせっかでHPを削るのを繰り替えし、次のでんこうせっかで落ちるというところにしましょう。
NPCのIDを調整する
準備ができたら最後に使ったポケモンセンターをキンセツシティにした状態で
・先頭ひんしにしたでんこうせっか持ち
・ひんしにしたなみのり持ち
・弱いポケモン
の三体を連れて119ばんどうろのオサムの元へと向かいましょう。この長い草むらに隠れているトレーナーは主人公の動きを真似るのですが、上手く調整し話しかけるだけで戦闘に入れるようにしましょう。
レポートしたら再起動し、GBAのロゴが出ている画面でStartボタンとSelectボタンを長押しします。ブートモードへと遷移し読み込みが止まります。
ここで任意のタイマーを用意し、10970Fを入力。タイマー開始と同時にAボタンを押し、そのままAボタンを押すだけで戦闘に入る状況にします。
タイマー終了と共に戦闘に入り、負けてください。そしてキンセツシティまでワープしたら、ラティアスの分布を確認。ゲームをリセットすると見ていたページもリセットされるのですが、一覧ページでStartボタンを押すと「リストのさいごへ」という選択肢が出るので、時短になります。
ラティに遭遇してでんこうせっかで倒すと、なぜかツチニンが出てくるのでマスターボールで捕まえましょう。
捕獲後、手持ちを確認したときに「ダメタマゴ」がいたら失敗です。
ステータスを確認し、ボールからズレを確認します。
ズレ | ボール |
---|---|
-2F | モンスターボール |
-1F | リピートボール |
±0F | ☆ |
+1F | ネストボール |
+2F | スーパーボール |
逆にニックネームが「ツチニン」、アイコンがはてなマークになっている場合成功です。ですが、絶対にステータスを見ないでください。
成功したらコトキタウンに飛び、パソコンで手持ちを
・先頭エネコ
・ロックオンを覚えたポケモン
・バグポケ
にします。
この時、「別のポケモンを掴んだ状態でとバグポケを入れ替える」とフリーズするので気を付けましょう。事前にパソコンの前でレポートを書いた方がいいでしょう。
そしてボックスの名前を編集します。
ボックス番号 | ボックス名 |
---|---|
ボックス1 | _うさゥうい_く |
ボックス2 | アいむけい_lア |
ボックス3 | うぅけえGミ_l |
ボックス4 | ア_い9ぃ_lア |
ボックス5 | ギゥくェあぶ_び |
ボックス6 | アアアュぬおくア |
※_はスペース、lは小文字のL
最後にボックス1の8番目のポケモンにポケモンがいたら別のところに移動させ、レポートしてから101ばんどうろで野生ポケモンとの戦闘に入ります。
エネコにねこのてを使わせます。この時の行動は
・ロックオン
・みねうち
・みだれひっかき
・「ノーマルわざ」という謎のわざ
の四種類がありますが、みだれひっかきで相手を倒した場合は再度ポケモンとエンカウントしましょう。
「ノーマルわざ」は普段の命中率が0なので成功することはありません。
ロックオンが出た場合、またねこのてを使い「ノーマルわざ」が出ることを祈ります。
ロックオン後ノーマルわざが出た場合、二つのパターンがあります。
パターン1 使った瞬間画面の色がめちゃくちゃになる
これは外れの方のわざを引いたパターンです。ソフトリセットも効かないので本体側でリセットしてください。
パターン2 そのまま動きが止まる
こうなった場合は成功です。一見フリーズしたように見えますが、裏で処理が走っていて8~9分後に戦闘から離脱します。10分ほど経っても画面が動かない場合、ボックス名を間違っている可能性があるのでリセットしてから確認してください。
先頭から離脱後、ボックス1の8番目にはてなマークのポケモンがいれば成功です。このポケモンは何なのかというと、「ポケモンを入れ替えるだけでコードを実行する」バグポケモン0xC1AAです。つまりツチニンくんはお役御免です。(一応念のため逃がさない方がいいかもしれません)
Grab ACEについて
ポケモンを入れ替えるだけでコードを実行できるGrab ACEについて解説します。
かなり簡潔に説明すると、種族名が長すぎるバグポケモンを読み込むことで、「ポケモン入れ替え時のアニメーションに関する情報を一時的に保存するメモリを上書きする」ことによって実現しています。0xC1AAの場合は0x02033351からの命令をアセンブリで直接実行できます。
これはボックス6の22番目のポケモンのメモリに該当し、そこからボックス14までポケモンを置くことができなくなります。
これを回避するために、「その位置からボックス名のメモリまでジャンプさせ、ついでに一部のメモリを整理する」というコードを保持したダメタマゴを配置するコードを実行します。(このコードを実行するときも、ボックス6の22番目以降は空にしてください)
ボックス番号 | ボックス名 |
---|---|
ボックス1 | ぃ♂いむけいうぅく |
ボックス2 | アけいぉぅ_lア |
ボックス3 | けいっぅしぶくタ |
ボックス4 | アさぶぶタ_lア |
ボックス5 | さぶギタしぶくチ |
ボックス6 | アすぶNタ_lア |
ボックス7 | いむあミしぶすぎ |
ボックス8 | ア_びアアアアア |
ボックス9 | ぃ♂いぶいむあミ |
ボックス10 | アアアあぶ_びア |
ボックス11 | アアあゥういアア |
ボックス12 | ア7し_いアアア |
ボックス13 | _ヲけくアアアア |
※_はスペース、lは小文字のL
念のためレポートを書き、別のポケモンを掴んだ状態でバグポケモンとの入れ替えを行うと、ボックス6の22番目にダメタマゴが配置されます。これ以降は好きなところにポケモンを置いても構いません。
汎用コード持ちのダメタマゴの配置
ついでにボックス14の30番目に汎用コードを埋め込んだダメタマゴを格納します。コードの終了処理・イベントスクリプトの実行処理・bl命令用の処理を持たせます。
一回目
ボックス番号 | ボックス名 |
---|---|
ボックス1 | リばめぎきべあタ |
ボックス2 | アきべだタ_lア |
ボックス3 | きべゥタくべGタ |
ボックス4 | アlsアアアアア |
ボックス5 | くミいぶすぎ び |
ボックス6 | アアアねお うア |
ボックス7 | アア ヲけくアア |
二回目
ボックス番号 | ボックス名 |
---|---|
ボックス1 | リばぇぎきべあタ |
ボックス2 | アきべだタ lア |
ボックス3 | きべゥタくべGタ |
ボックス4 | アlsアアアアア |
ボックス5 | おべくチいみ い |
ボックス6 | アアアあぃくゥア |
ボックス7 | アア みNタアア |
三回目
ボックス番号 | ボックス名 |
---|---|
ボックス1 | リばざぎlむたぅ |
ボックス2 | アけいあィ lア |
ボックス3 | lむねぅけいあぅ |
ボックス4 | アだィいべ lア |
ボックス5 | だタgsオlみび |
※_はスペース、lは小文字のL、べは全て平仮名
b命令を使い、0x020380e2へとジャンプすることで自動で安全に命令を終了させられます。
また、r0に実行したいスクリプトアドレスを保持している状態で0x020380d0へとジャンプすることでそのスクリプトが実行されます。
一例としてボックス1を「ぶqsゥgとく」にしてコードを実行後、ボックスを閉じることで御三家選択のスクリプトが開かれます。
最後にr4にbl命令で遷移したい関数のアドレスを保持した状態で、0x020380c8へとジャンプすることでその関数を実行し。そして0x0203817aへとジャンプします。これはボックス14の名前の6文字目なので、そこからb命令で好きなアドレスへと戻してあげましょう。
一つ注意点があり、ポケモンを掴んでいる状態で画面が遷移するような処理を行うと、そのポケモンが消えます。一応こうなった場合はセーブデータ全削除中に途中で電源を切ると、一つ前のセーブデータで復帰できるという裏技が有効かもしれません。(完全にデータが消えてしまった場合の保証はしません、ツチニンくんも逃がさず残しておいた方がいいかもしれない理由はこれ)
最後に
こんなことをやるくらいならエメラルドやFRLGでやった方がいいと思います。
一応エメラルドと違いRAM変動がないというのが強みなのですが、それでも情報の多さやチケットの有無で完全に負けています。好事家の方は真似してみてください。
明日の記事はきゆうりさんによる「岐阜前夜祭からくどオフ修学旅行」となります。岐阜が世界三大都市の一角であるというのを風の噂で聞いたのですが本当でしょうか。