穴抜けの紐ワープ(任意コード実行)の実践


【穴抜けの紐ワープの概説】

HN「あーもんど」さんの研究調査により、バグ技の戦闘アニメーションを見ることで特定のアドレスの任意コードを実行し、穴抜けの紐使用時の脱出先を自由に変更出来る現象が発見されている。
具体的には、戦闘エフェクト「見る」の状態で適当なダンジョン内で戦闘し、特定のバグ技を使用して戦闘終了後に穴抜けの紐を使うことで、設定した任意の行き先にワープ出来る、というものである。
行き先を最果ての孤島や誕生の島等に設定することで、本来限定配布アイテムがなければ絶対に行けないこれらの隠しダンジョンへアイテムなしで行くことが可能となる。

詳しくはあーもんどさんのサイトを参照していただきたい。
https://pokeglitch.game-info.wiki/d/穴抜けの紐
https://pokeglitch.game-info.wiki/d/穴抜けの紐(ポケモン使用)



【実機Emでの任意コード実行】

Emにて任意コードを実行する手段は幾つか存在するが、今までに調査されていた方法では何れも実機での再現が非常に困難であると言われていた。
そこで、あーもんどさんの紹介されている方法の1つを参考応用し、この度、Emでの任意コード実行を実機で再現する方法を確立することに成功した。

今回私が考えた方法では、ボックスに預けたポケモンの努力値コンディション(H努力値から美しさまでの8バイト)をコードとして使用する。
努力値コンディションを必要値に調整することで穴抜けの紐ワープを実行する命令コードを記述し、そのポケモンをボックスの特定の場所に配置してバグ技の戦闘アニメーションを見ることでスクリプトを実行するのである。

私自身は解析環境もアセンブラの知識も全く持ち合わせていないので、以下に簡単な説明とデータを参考程度に記しておく。

20190620040615cd4.jpeg
↑最果ての孤島行き用の命令コード及びそのアドレス
ボックス内のポケモンは1匹当たり80バイトのデータとして記録される。
その内の48バイトがGAEMブロック内データ(画像のベージュ地の領域)であり、そのブロック配列は性格値%0x18の値で決まっている。

バグ技の中で、戦闘アニメーションが唯一このブロック内データのアドレスを参照することが判明しているのが0x0D1Dであり、具体的にはボックス12の28番目のポケモンの、ブロック内データの始めから(0x020304C0)を読み込む。
ボックス12/28に配置したポケモンのブロック配列がEブロックから始まるパターン(性格値%0x18=0xC〜11)の場合、0x0D1Dを使用するとそのポケモンのH努力値以降のブロック内データを読み込むことになる。
つまり、努力値を調整して任意コードを記述しておけば、0x0D1Dの使用によりその努力値からスクリプトを実行することが出来るのである。

ブロック内データはメモリ上、暗号化されて記録されている為、努力値調整はこの暗号化を考慮して行う必要がある。
暗号化の仕組みは次の通りである。
※^は、XOR(排他的論理和)の演算子

性格値 ^ ID値 ^ 暗号化前データ(ゲーム上データ) = 暗号化データ(メモリ上データ)

つまり、メモリ上データを任意の値に調整するには、ゲーム上のブロック内データの調整は勿論のこと、性格値やID値も特定のものに調整しておく必要がある。

仮に、性格値=ID値であった場合、上記の式から、暗号化前データ=暗号化データとなる。
つまり、ゲーム上のブロック内データの値をそのままメモリ上の値として読み換えることが出来るのである。

また、暗号化の仕組みを逆利用すれば、より少ない必要努力値でコードを記述することも可能となる。
今回の場合、性格値=ID値^0x08006000とすることで、必要努力値の合計が上限510内に収まるようになったり、コンディション調整が一切不要になったりする。



【穴抜けの紐ワープの実践】

上記を踏まえて、実際に実機で穴抜けの紐ワープを実践する方法について記す。
今回は例として"最果ての孤島"へのワープを目的とする。

・0x0D1D作製
まず、任意コード実行に必要なバグ技0x0D1Dを作製していく。

作製には今回、"全振り用の技の作製に使用したマルマイン(ビリリダマ)"を材料ポケモンとして使い回す。
具体的には以下の個体である。

待機時間:1412F
種族:ビリリダマ(Lv25)
性格:せっかち
特性:防音
性格値:0xBB009438
個体値:19-17-30-11-22-18

変化パターン[vi]なのでデータブロックはGAEM→GMAEと変化する。

作製する0x0D1Dについてだが、この技は命中及び最大PPが共に0という特徴を持つ。
このような技を使用する(戦闘アニメーションを見る)には心の目orロックオンが必須であり、またダブルコラプションにより現在PPを1以上に上げた状態で生成する必要がある。


せっかちビリリダマinマスターボール
0xBB009438 19-17-30-11-22-18
体当たり/嫌な音/ソニックブーム/スパーク
EXP15625(Lv25)
調整
せっかちマルマインinマスターボール
雨乞い/なし/なし/なし
H170 B29S13 格23 愛11 賢10 毛艶20
EXP27000以上(Lv30以上)

ダブルコラプション[vi]

臆病マルマインinモンスターボール(内部値0)
0xFB009438 0-0-0-0-0-0
心の目:PP11/0x0D1D:PP10/なし/踏み付け:PP20
EXP27000以上(Lv30以上)

2019062004031774a.jpeg

努力値調整により技1に心の目、技2に0x0D1Dを生成し、コンディション調整により現在PPを1以上の状態にする作製例。
各調整の詳細については上記リンク先を参照願いたい。
尚、実際には経験値は不問で、マルマインへの進化は必須ではない。

心の目と0x0D1Dの現在PPを1以上とする為、可愛さと賢さを1以上に調整する必要がある。
最も簡単な方法は、ザロクの実をNPCと3人で混ぜて出来る灰色ポロック(ここでは"Lv23"とする)を1つ与えることである。
この場合、技4に不要な踏み付けが生成するが、特に問題はない。

このような、最大PPが0である技の現在PPを保持したままポケモンを取り扱う方法についても、上記リンク先に記してあるので一読いただきたい。


・コード用ポケモン入手
次に、コードに使用するポケモンを入手する。

電池切れRSにて、以下の乱数調整を行う。

<ID調整>

・ID:表42070裏11155(ID値:0x2B93A456)

・初期シード:0x5A0

・待機時間:3001F
20190620040324cde.jpeg

<
孵化乱数調整>

・性格値:0x2393C456

・性格値%0x18=0xE(EAGM)

・性格:無邪気

・LID待機時間:48302F→48916F

・生成判定:57

・HID待機時間:44359F→44946F

・個体値:後-1-後-13-先-2
20190620040320ae7.jpeg

上記ID調整を施したセーブデータ(主人公の性別・名前不問)を作成し、育て屋を利用出来るようになるまでストーリーを進める(ムロジム、キンセツジムは無視可能)。

そして相性最高の組み合わせのパッチールを用いて、上記性格値のパッチールを孵化乱数調整にて調達する。
個体値は不問なので、親個体についても適当で構わない。
因みに矢印先のフレームは、DS使用時のエメタイマーへの入力フレームの目安である(追加時間・切り上げ時間0)。

目的のパッチールを孵化出来たら、これを5匹にコピーし、以下の努力値調整を行う。

①:H3 A113 B5 C2 D159 S11
②:H56 A64 C36 D128 S10
③:H26 A80 B39 C36 D128 S65
④:H8 B240 S181
⑤:H40 A55 B6 S10


少しでも努力値を振り間違えたり、指定箇所以外に努力値を振ったりすると成功しないので、慎重に行うこと。
不安であれば、第6世代に輸送しまっさらバッグを使用したり、ポケチェックやKeySAVeなどの解析機能を利用したりすると確実である。


・任意コード実行
ここまでの用意が済むと、いよいよ任意コード実行に移れる。

まず、ボックス12の28番目からボックス13の2番目までに、調整済みのパッチール5匹を①〜⑤の順で並べる。
2019062004031866d.jpeg

穴抜けの紐を用意し、設定で戦闘エフェクトを「見る」にしておく。
そして手持ちの先頭に0x0D1D持ちマルマインを置き、穴抜けの紐を使用可能な適当なダンジョン内にてレポートを書く。
オススメは、アクセスし易く出現ポケモンもクセのないカナシダトンネル内である。
尚、ミュウを捕獲するつもりであれば、この時点で捕獲要員やボール、乱調用BVなどを用意しておくこと。

ダンジョン内で野生ポケモンと戦闘し、心の目を使用した後に0x0D1Dを使用する。
0x0D1Dを使用すると、成功の時には相手に攻撃して戦闘続行、失敗の時にはフリーズ(BGM正常orクラッシュ)したり強制リセットがかかる。
失敗した場合はリセットして再試行。
成功した場合はそのまま戦闘から逃げ、その場で穴抜けの紐を使用する。
成功率は1/32と低いので、根気良く行う。

何もミスがなければ無事最果ての孤島へワープする。
20190620040325ebb.jpeg2019062004032687a.jpeg201906200403263e1.jpeg
実践動画↓


他の場所へワープしたい場合、パッチールの努力値を以下のように変更する。
・南の孤島:②H56→9

・誕生の島:②H56→58

・臍の岩:②H56→66

・殿堂入り部屋(※殿堂入りする):②H56→11,③H26→16