Seaside Laboratory

Posts

KFX をバッファーオーバーランで破壊する

KFX の command.lst 読み込みアルゴリズムは少々特殊なため、投入するデータによってはバッファーオーバーランが発生してしまう。実際、どれだけ影響が出るのか興味があったので実験してみることにした。

仕組み

KFX はコマンドの最後に攻撃ボタン (pPkK) が来ることを期待しているので、攻撃ボタンが含まれていないコマンドの長さは未定義になる。

攻撃ボタンが見つかった時点で探索は終了。
攻撃ボタンが見つからない場合は延々と探索が続く。

読み込みバッファーは再利用されるので、直前に読み込んだ文字列の影響で運良く停止することもある。

直前に読み込んだ "HEAD-PRESS" という文字列の "P" に反応して停止。

この後にはコマンド変換処理が控えており、コマンドの長さがバッファーサイズを超えているとバッファーオーバーランが発生する。

事前準備

適当な KFX 用キャラの command.lst を開き、末尾に以下の行を加える。

CmdNum--Command--Cancel--Std-AmnNum--Vx--Comment
   129 222222222  00111  001      0   0  ;

CmnNum が KFX の上限値である 129 になっているのは、comamnd.lst 末尾でバッファーオーバーランを発生させることで、破壊する範囲を広げるため。Command は非攻撃ボタンであれば何でも良い。

また、バッファー再利用の影響がでないよう以下の対策も行っている。

  • 手前の行で読み込んだ Command が完全に上書きされるよう最長の 9 文字を設定。
  • 余計な文字列が入らないよう Comment は全て削除、ヘッダー行は限界 (1 文字) まで縮める。

実験結果

メモリの内容は変化するので実行の度に結果は変わってしまうが、実行を何度か繰り返したところ、7 以下に収まるべきのコマンドインデックスが 3169 という大きな値になり、不可解な現象が発生した。

ステージが変色。
次のステージへ進んだらキャラまで変色した。

command.lst データの隣にはスプライト (IDirectDrawSurface) があり、バッファーオーバーランによるメモリ破壊でステージスプライトに異常が発生したものと思われる。

この結果から、不正なコマンド (拡張コマンドを含む) による影響は無視できないくらいに大きい、ということが分かった。ただ、バッファーオーバーランを起きやすくしたのと逆のことを行えば緩和することも可能で、例えば最初の行にある Comment にそれなりの長さの "p" を書いておけば、バッファーオーバーランが発生したとしても影響範囲を最小限に留めることができる。

ちなみに、実験に使用した KFX は以下の点で通常のものとは異なる。

  • 現在の環境でも動くよう最低限の修正が加えられている。
  • デバッガーで値を監視するために Debug モードで動かしている。

配布されている実行ファイルで再現するとは限らないので、その点はご了承いただきたい。