ブラッディウァリアーズ (FC) 任意コード実行案
FC版『ブラッディウァリアーズ』はおそらく任意コード実行が可能と思われる。大まかな手順は以下の通り:
- 仲間重複加入バグまたは難破バグを用いてPT人数を異常な値にする。
- 8 人目以降の不正な仲間に適当なアイテムを装備させ、メモリ内から不正なアイテムを元の装備品として取り出す。
- 適切な不正アイテムを取り出して使用または装備すると、アイテム使用ルーチンテーブルの範囲外が参照され、RAM 領域をコードとして実行できる。
既にある程度知られているとは思うが、まず仲間重複バグについて説明する(難破バグはかなりイベントを進めないと起こせないので省略)。仲間をPTに加えたとき仲間シンボルが主人公シンボルに向けて歩き出すが、その間に再度メニューを開いて話しかけると同じ仲間を重複して加入させることができ、PT人数を異常な値にできる。
ここで、たとえばPT人数が 19 で、PT末尾の仲間 (PT内インデックス 18) にバイクを装備させたとする(カーソルは普通に 19 人分動かせる)。この場合、以下のような挙動になる:
- PTメンバーの冒険者ID配列
$6537-
のインデックス 18 ($6549
) から冒険者IDを取得する。 これは配列外参照であり、主人公の素の攻撃力を冒険者IDとして取得する。 ここでは仮に冒険者IDとして 17 が取得されたとする。 - 冒険者ID 17 の仲間はバイクを装備し、「元々装備していた乗り物」がアイテムとして得られる。
ここでは各冒険者の乗り物配列
$6496-
のインデックス 17 ($64A7
) からアイテムIDを取得する。 これは配列外参照であり、主人公の経験値の bit0-7 をアイテムIDとして取得する。
ここで、得られたアイテムを移動中に使用または装備したとする。本作はアイテムID 0x32 以上については装備しても使用したものとして扱うため、不正アイテムについては使用と装備は等価である (該当コード: PRG 10 $869A
)。アイテム使用時はルーチンテーブル (PRG 10 $86CA
) 内の対応するルーチンが実行されるが、不正アイテムを使用した場合、このルーチンテーブルの範囲外が参照され、場合によっては RAM 領域をコードとして実行させられる。
有力な不正アイテムの一例として 0x6B (「かなしヘり」(「ヘ」はカタカナ))が挙げられる。これは装備可能アイテムであり、装備(=使用)するとアイテム使用ルーチンとして $64C5-
を実行する。$64C5-
は各冒険者の現在HP下位バイトの配列なので、ここは割と制御しやすいと考えられる。
エンディングへ遷移するには PRG 10 のルーチン $8E40
を実行すればよい。幸いこれはアイテム使用ルーチンと同じバンクにあるため、バンク切り替えについては特に考慮しなくてよい。たとえば [0x20, 0x40, 0x8E]
(jsr $8E40
) を実行すればエンディングとなる (エンディングルーチンは戻らないので、jsr
の後のことは考えなくてよい)。
ただし、これを実際に TAS に落とし込むにはいくつかの課題がある:
- 実行すべき最適なコードとその構築法の検討。
制御しやすいメモリ領域として主人公の名前 (
$6400-$6405
) を経由するのは有力そうだが、ここにjsr $8E40
を直接書くことはできないと思われる (名前の文字として 0x40 は使えないため)。 - PT人数を効率よく増やす手法の確立。
PTメンバーの冒険者ID配列
$6537-
の直後には各冒険者の戦闘不能フラグなどがあるが、この辺りの値は 0 または 1 しかないため、不正な冒険者IDを取得するにはPT人数が最低でも 19 は必要と思われる。 筆者が少し試したところ、仲間重複バグで 1 種類のキャラを加入できる回数には限りがあり、オレルビスならば 8 回までは確認できたが、クレイジーホースのように一枚絵が出るタイプのキャラについては 4 回までしか確認できなかった。 サブフレームリセットを導入すればオレルビスのみで事足りると思われるが、これだけのために導入するのもどうかという気はする(これは個人的なこだわりにすぎないが)。