ドラクエ2の任意コード実行(ACE)の可能性
DQ2はじめに
マドハンドバグで作れるバグアイテム0x6bを戦闘中に使用するとメモリー上の$0b/00a9※からコードを実行させることができますが、大抵はうまく行かずにフリーズ等が起きます。しかし、色々と条件を整えると、サマルトリアの王子の名前をコードとして実行したりそこからゲームパッド入力の領域($4218-$421f)にジャンプしたりする事ができます。こちらとこちらを参考にLsnes上で4つのゲームパッドからの1フレーム分の命令はなんとか実行できたのですが、2フレーム目からは狙った命令が実行されませんでした。原因がよくわからないので、とりあえず方法をまとめておきます。※この記事はSNES ADDRESSで表示します
名前をコードとして実行させる方法
サマルトリアの王子の名前2文字目 ($0160) からコードを実行させる方法
- 条件1.アイテムID0x6bのバグアイテムなしを作成する
- 条件2.右1マス移動後、上か下に1マス移動した位置でエンカウントする($00ee,$00ef の設定)
- 条件3.出現したモンスターが1グループまたは2グループのパーティである ($00aa)
- 条件4.ドラゴンフライやどろにんぎょうなど、右端の出現モンスターが特定のIDである ($00ab)
- 条件1.アイテムID: 0x6bのバグアイテムなしを作成する
- 条件2.右1マス移動後、上か下に1マス移動した位置でエンカウントする
右や下にいるほど値が大きくなり、エンカウント時は 0x70, 78 など 8 刻みの値になります。
WRAM | 説明 |
$00ED | ローレシア王子のX座標(常に0x80) |
$00EE | サマルトリア王子のX座標(0x70から0x90) |
$00EF | ムーンブルクの王女のX座標(0x60から0xA0) |
$00F0 | ローレシア王子のY座標(常に0x80) |
$00F1 | サマルトリア王子のY座標 |
$00F2 | ムーンブルクの王女のY座標 |
条件2の方法でメモリ$00EE = 0x80, $00EF = 0x70となります。
$00EE BRA #$70 ? -> $0160
という命令を実行させてサマルトリアの王子の名前 $015F~$0167 にジャンプする狙いです。
- 条件3.出現したモンスターが1グループまたは2グループのパーティである
グループ数 | 値 | 命令 |
1 | 0x80 | BRA |
2 | 0x90 | BCC |
3 | 0xa0 | LDY #$???? |
4 | 0xb0 | BCS |
- 条件4.ドラゴンフライやどろにんぎょうなど、右端の出現モンスターが特定のIDである
mobID*0x20+0x84E0
という式で計算された値が$00aa, $00abに上書きされて行きます。最後が右端なので出現時に右端の敵のID(mobID)によって$00aa, $00abの値が決まります。
$00aa = 0x40 (RTI命令)とするには、以下のモンスターのいずれかであれば良い事になります。
0x03 | アイアンアント |
0x0b | おおねずみ |
0x13 | スモーク |
0x1b | どろにんぎょう |
0x23 | ドラゴンフライ |
0x2b | ウドラー |
0x33 | ヒババンゴ |
0x3b | メタルハンター |
0x43 | ハーゴンのきし |
0x4b | ギガンテス |
実行ログ
以上の条件を満たした時のLsnesのログです0baafb jsr ($ab00,x) [0babd6] A:0000 X:00d6 Y:0000 S:02f0 D:0000 DB:0b nvMxdizc V:247 H: 230 Y:使用者(0-2) 0b00a9 brk #$80 A:0000 X:00d6 Y:0000 S:02ee D:0000 DB:0b nvMxdizc V:247 H: 292 008c05 rti A:0000 X:00d6 Y:0000 S:02ea D:0000 DB:0b nvMxdIzc V:247 H: 356 0b00ab rti A:0000 X:00d6 Y:0000 S:02ee D:0000 DB:0b nvMxdizc V:247 H: 408 3e00aa bra $00ec [3e00ec] A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b NVMXDIzC V:247 H: 460 3e00ec tsb $80 [000080] A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b NVMXDIzC V:247 H: 482 3e00ee bra $0160 [3e0160] A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b NVMXDIZC V:247 H: 520 3e0160 jmp $4218 [3e4218] A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b NVMXDIZC V:247 H: 582 3e4218 asl a A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b NVMXDIZC V:247 H: 576 3e4219 xce A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b nVMXDIZc V:247 H: 588 3e421a cld A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b nVMXDIZc V:247 H: 600 3e421b stz $64 [000064] A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b nVMXdIZc V:247 H: 612 3e421d wai A:0000 X:00d6 Y:0000 S:02f2 D:0000 DB:0b nVMXdIZc V:247 H: 632
$00ec は次の半マス移動で3人目のキャラクターが向く方向に対応しています。(01:上、02:下、03:左、04:右 )条件2を満たすと右を向くので04となり、
tsb $80 ; Aと$0080で論理和を取り、結果を$0080に代入する
まずそうに見えますがA=0なので何もしないのと同じです
RTIによるスタックのずれ
RTI は割り込みから復帰する命令です。スタックから Processor status register の値1バイト、と戻り先のアドレス(Program Counter 2バイト、Program Bank1バイトの値)をpullします。本来は割り込み命令とRTIの数を一致させるなどしているのでスタックは狂わないですが、無理やりRTIを行っているので変なアドレスに戻ってしまいます。
そのアドレスが偶然 $3e/00aaでした。バンク $00-$3F の$0000-$1fff はメモリのミラーなのでメモリ上のアドレス$00aa を実行することになります。
スタックの説明。
スタックの状態は下表の様になります。$0b00abのrti 実行時、$0baafb jsr命令戻り先を、ステータスレジスタの値とRTI命令の戻り先のプログラムカウンタの下位1バイトとしてpullします。更に data bank の値をプログラムカウンタの上位1バイトとしてpullします。最後に$02f2の値をプログラムバンクとしてpullします。次のpush先は ** のアドレスからになります。戦闘中のアイテム使用ではこれらの値は
address | value | push | pull |
02ec | |||
02ed | |||
02ee* | |||
02ef | fd | $0baafb jsr命令戻り先 | $0b00ab rti P register |
02f0 | aa | $0b00ab rti 戻り先 ( PB&PC) |
|
02f1 | 00 | $0baabf data bank | |
02f2** | 3e | $00de3b jsl命令戻り先 | |
02f3 | de | ||
02f4 | 00 | ||
02f5 | 0d | $00b50b jsr命令戻り先 | |
02f6 | b5 |
名前の文字コード
>3e0160 jmp $4218サマルトリアの王子の名前を「あシこイ」(0f 4c 18 42)にすることでゲームパッドの入力にジャンプしました。一文字目はなんでもいいです。
名前の文字コード表名前の文字コードは濁点、半濁点に1バイト使用するものと仮名とセットで1バイトなものがあります。前者は名前の最後につく0xFFを含めて各キャラ9バイトまでで戦闘中やステータス表示に使われています。後者は5バイトまでで会話中や非戦闘時の呪文やアイテム使用での表示に使われています。リンクの表の0x7b~0xb4に見られる濁点・半濁点付き文字のコードは後者のメモリでしか設定されないようです。
65816 Opcode matrix
1フレーム目はキー入力がフレームをまたいでいて、Bから上までの入力を1フレーム早めるとうまく行きました。どういうわけか2フレーム目最初のbra #$f8;がうまく実行されず別の命令が実行されてしまいました。
3e421e ora [$c4] [000002] A:0000 X:00d6 Y:0000 S:02f1 D:0000 DB:0b nvMxdizc V:240 H: 850 3e4220 brk #$00 A:0000 X:00d6 Y:0000 S:02f1 D:0000 DB:0b nvMxdiZc V:240 H: 894 008c05 rti A:0000 X:00d6 Y:0000 S:02ed D:0000 DB:0b nvMxdIZc V:240 H: 954 3e4222 brk #$00 A:0000 X:00d6 Y:0000 S:02f1 D:0000 DB:0b nvMxdiZc V:240 H:1006 3e4225 brk #$00 A:0000 X:00d6 Y:0000 S:02f1 D:0000 DB:0b nvMxdizc V:240 H:1048
エンディングを呼び出し
$004e = 0xef, $004f = 0xf5 に設定すると、戦闘終了後や非戦闘時の会話窓が閉じた後に夜になりエンディングが始まるようです。ただし、失敗することもあります。他の方法として$0c87 = 5(EDノーエンカノーダメ・NPC), $0d03 = 0x40(シドー撃破フラグ*) としてエンディング状態のローレシア城の王と話す事でエンディングに突入させる事もできます。(*追記:2016/11/21 アドレスミスを訂正)
レジスターの調整
processor status register を0x20に、Data Bank registerを00にして、0x3e をプッシュした状態でrtl命令を実行すればうまくいきそうです。(他に良い方法があるかもしれませんが)SMWのTASとは違ってxce命令の後でc==offだったのでエミュレーションフラグはオフのままでxceは不要なようです。$64が0になると割り込み可能になるようです。
【アセンブリコード】
pea $3e20; stz $64; wai;
plp; pha; plb; stz $64; wai; bra #$f8;
pea $f5ef; stz $64; wai; bra #$f8;
pla; sta $4e; pla; sta $4f; rtl;
【解説:スタックの修正とエンディング開始フラグの設定】
#$3e20をプッシュした上で、Pレジスタを#$20(Aレジスタを8bit)にする
#$3eは最後のrtl時に$00de3eに戻す狙い
データバンクレジスタを00にして$4218に戻す
#$f5efをプッシュして$4218に戻す
$4e, $4fへ#$ef,#$f5を代入してエンディング開始フラグをON
rtlで 00de3eに戻るはず
このようなコードを入力しようと考えていました。
2019年6月5日 dropbox のリンク修正
PR
Comment form
カレンダー
10 | 2024/11 | 12 |
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
最新記事
(12/18)
(04/18)
(09/15)
(09/11)
(06/21)
プロフィール
HN:
bamboo
性別:
非公開
自己紹介:
2010年の3月ごろニコニコ生放送のゲーム放送でRTAを知ってよく見るようになった。
どちらかというとゲームはプレイするものじゃなくてプレイを"みる"ものだと思っている。
逆アセンブル解析というのをかじったものの放置していたが、某放送の影響で解析を再開。
2を初クリアしたのは2011.3.10。ブログの内容はSFC版ドラクエ1・2の解析がメイン。最近はjavascriptとかluaをある程度扱えるようになったので、botでルート検証とかできたらと思いつつも進んでいない。
要点をまとめたり文章書くのが苦手なので記事が長ったらしかったり、日本語のようで日本語でなかったりする。プログラム用語が使えるようになりたいかも。
ツイッター: https://twitter.com/bamb00h
ブログに公開せずツイートのみの情報もあり(twilog)
どちらかというとゲームはプレイするものじゃなくてプレイを"みる"ものだと思っている。
逆アセンブル解析というのをかじったものの放置していたが、某放送の影響で解析を再開。
2を初クリアしたのは2011.3.10。ブログの内容はSFC版ドラクエ1・2の解析がメイン。最近はjavascriptとかluaをある程度扱えるようになったので、botでルート検証とかできたらと思いつつも進んでいない。
要点をまとめたり文章書くのが苦手なので記事が長ったらしかったり、日本語のようで日本語でなかったりする。プログラム用語が使えるようになりたいかも。
ツイッター: https://twitter.com/bamb00h
ブログに公開せずツイートのみの情報もあり(twilog)
ブログ内検索
最古記事
(09/17)
(09/17)
(09/18)
(02/04)
(02/07)
カウンター
忍者アナライズ