妖怪道中記 隠しパスワード解析「最初の一週間」の裏側

発売から35年、妖怪道中記・隠しパスワード完全解明までの一部始終
~531垓分の1を探し求めた男たち~

 本動画の5:10で「その一週間後、はむさんの手によりパスワード解析ツールの第一弾が完成する」と語られた「一週間」で行った作業を列挙してみました。

 なお、詳細解析情報や解析ツールのソースコードについてはZIPアーカイブにまとめていますので、そちらをご覧ください。
Download : yokai-pack-20211219.zip

工程1:ROMを眺める


 妖怪道中記のROMイメージを見ると、パスワード入力が正解した時に表示されるメッセージと謎の数字の羅列(後にチェックデジットと判明)が順番に格納していることがわかります。
 ところがパスワード本体が平文で全くヒットせず「まさか1987年にハッシュ関数を…?」と若干不安な気持ちに。
 実際にはその想像をはるか超える地獄が待っていようとは……。

工程2:メモリエリアを眺めてアドレス選定


 自作ツールemuhasteをPCEエミュレータootake専用にカスタムし、カーソルを動かしてサーチ、文字を打ったり消したりしてサーチ、入力文字数をサーチ……など、ひたすら地道な作業。

 この時点で「入力した文字の合計数がアドレス$31F6に格納されていること」「アドレス$31DC以降に入力したパスワード列情報があり、文字コードがゲーム独自である」などといった重要な要素が判明します。

工程3:[PCE 6280逆アセンブラ]を用いた解析


 アドレス$31F6に極めて重要なパラメータが格納されていたので、オールドゲームROM研究所のBAB氏作「PCE 6280逆アセンブラ」を用いて、$31F6に触れているルーチンを列挙したところ、下記コードを発見。

D6F7 : AD F6 31 LDA $31F6

 上記アドレス$D6F7からパスワード入力ルーチンが始まっており、Iボタンを押した瞬間にパスワード文字数をチェックしたり、カーソル位置を元に文字コードを生成するといった主要の処理を行っていました。
 なお、この段階ではサブルーチンコールJSR(20 xx xx)などをNOP(EA)で破壊し、実際にゲームを実行して挙動を確認するといった、かなり豪快な方法で各処理内容を調査しています。

工程4:デバッガによるリアルタイム動作解析


 マルチエミュレータMESSがPCエンジンエミュレーションに加え、超強力なデバッガが実装されていたので、下記コマンドからデバッグモードで起動。

>mess.exe pce youkaid -debug

 さらに同デバッガのブレークポイント機能( bpset $D6F7 )でアドレス$D6F7以降の処理を追跡したところ、アドレス$D853以降に露骨なゼロクリア処理を発見。

D853 : 82 CLX ; Xをゼロクリア
D854 : 8E F4 31 STX $31F4 ; 31F4=0
D857 : 8E F5 31 STX $31F5 ; 31F5=0
D85A : 8E F7 31 STX $31F7 ; 31F7=0
D85D : 8E F8 31 STX $31F8 ; 31F8=0
D860 : 8E F9 31 STX $31F9 ; 31F9=0
D863 : 8E FB 31 STX $31FB ; 31FB=0
D866 : A9 01 LDA #$01 ; A=01
D868 : 8D FA 31 STA $31FA ; 31FA=01

 これをデバッガの[Step Info]でひとつずつ追跡したところ、パスワード文字数を格納する$31F6を除く$31F4~$31FBに何らかの演算結果を入れていることが判明。

 また、適当な正解パスワードのラスト1文字を入力した瞬間に処理の終端を確認すると「ROMのメッセージ間に挟まれていた謎の値と、$31F4~$31FBの値が完全一致していた」ことから、PCエンジン版妖怪道中記のスタッフインフォメーションボードのパスワード処理ルーチンは、下記のプロセスであることが確定しました。

1.ユーザがパスワードを入力すると$31DC以降に順番に文字コード値を挿入。
2.それと同時に$31F6に入力文字数をセット。
3.サブルーチン$D853をコールし、$31F4~$31FBの値=チェックデジットを生成。
4.最終チェック処理$D730をコールし、全ての隠しパスワードの設定値と前述のサブルーチンで生成した値を比較。
5.一致するパスワードがあれば正解処理(無敵フラグや画面表示)を行う。

 あとは、チェックルーチン$D853が何をやっているのかを解読し、それを自作プログラムで再現できれば、PCエンジン実機やエミュレータが無くても隠しパスワード解析にチャレンジしたり、実際にパスワードハッキングができる…というわけです。

工程5:パスワード解析ツールを自作

 ここまで解析が進めば、後はプログラミングの時間です。
 ただし一発で完成品が出来るわけもなく、テストモジュールをコツコツ作ります。

 PCエンジンのCPU(HuC6280)用のコードをVisual C++に移植する作業です。
 HuCそのものは6502カスタム版なのでNESの開発ドキュメントあたりも参考になりますが、Googleで”Turbo Graphics 16 opcode”あたりのキーワードで検索して、CPU仕様書を探して勉強するのが無難かなぁと。
(ウチもHuCのCPU仕様書を読んだのはこの作業が初めてだったので、頑張れば何とかなるなる)
 というか、実際の置き換えもかなり力技でした。

HuC(6502) Visual C++
PHA
LDY #$08
ASL A

PHA

stackA[stackApos++]=A;
Y=8;
A = A << 1;
if(A>0xFF){ C=1; A=A&0xFF; }else{C=0;}
stackA[stackApos++]=A;

 スタック操作(PHA)は配列stackA[]と変数stackAposを用いてLIFOの流れを模倣。
 ASL Aを実行すると8ビットのAレジスタを左1ビットシフトし、溢れたビットがキャリーフラグ(C)にセットされるので、これをムリヤリ条件分岐で再現~…というメチャクチャすぎる力技を採用。
 その副産物で「環境依存せず、あらゆる言語に移植できた」ので、ケガの功名というか、まあ良かった(のかなぁ???)

・・

 以下、私が作成した初期の解析ツール群です。

yokai01(没)
 パスワードを入力するとアドレス$31DC~と同じレイアウトの配列を生成するテストプログラム。

yokai02
 yokai01のルーチンの後、妖怪道中記と全く同じ演算を行い$31F4~$31FBの値を生成し、画面に表示するパスワードシミュレータ。
 当初「$31F4と$31F5が一致すればほぼ本物じゃね?」などと安易に考えていたので、ツール名が[$31F4 $31F5 simulator]になっています。

yokai03
 yokai02のルーチンに対し、総当たりで全パターンのパスワードを試行するツール。

yokai04(没)
 yokai02のルーチンに対し、単語を順番に辞書アタックを仕掛けるツール。
 ※よくよく考えると同じ単語が連続するパスワードを解析できないので没。

yokai05
 yokai02のルーチンに対し、完全ランダムの組み合わせで辞書アタックを仕掛けるツール(無駄は多いけど無難)。


 そして、これらの解析結果は私よりもずっと高スキルのエンジニア達に共有され、発売から35年目ついに攻略~……という流れでした。

 当然、こんなプロセスを動画にまとめてもクソ退屈な映像になってしまうわけで。
 難解なシーンをすべてカットして、まるで英雄譚のように綺麗にまとめたシイナさん、超グッジョブでした(‘ω`)