忍者ブログ

データ置き場

ニコ生RTA放送を見ていて湧いた疑問を調査してアップするかも。ほぼドラクエのみを扱うブログ風のマニアックなサイト

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

ドラクエ2の任意コード実行(ACE)の可能性

はじめに

マドハンドバグで作れるバグアイテム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のバグアイテムなしを作成する
ムーンペタの皮の盾 (ID: 0f) を装備した状態からマドハンドバグによる変換を繰り返すことで作成できます。0x6b を戦闘中に使用するとメモリの$00a9 から実行されます
  • 条件2.右1マス移動後、上か下に1マス移動した位置でエンカウントする
画面上のどの位置に3人のキャラクターがいるかがピクセル単位の座標で管理されています。
右や下にいるほど値が大きくなり、エンカウント時は 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グループのパーティである
メモリの$00aaにはグループごとに表のような値が格納され、命令部として使われます
グループ数 命令
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に戻るはず

このようなコードを入力しようと考えていました。
PR
Comment form
お名前
メールアドレス
URL
タイトル
コメント
  Vodafone絵文字 i-mode絵文字 Ezweb絵文字
パスワード
カレンダー
08 2017/09 10
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
プロフィール
HN:
bamboo
性別:
非公開
自己紹介:
2010年の3月ごろニコニコ生放送のゲーム放送でRTAを知ってよく見るようになった。
どちらかというとゲームはプレイするものじゃなくてプレイを"みる"ものだと思っている。
逆アセンブル解析というのをかじったものの放置していたが、某放送の影響で解析を再開。
2を初クリアしたのは2011.3.10。ブログの内容はSFC版ドラクエ1・2の解析がメイン。最近はjavascriptとかluaをある程度扱えるようになったので、botでルート検証とかできたらと思いつつも進んでいない。
要点をまとめたり文章書くのが苦手なので記事が長ったらしかったり、日本語のようで日本語でなかったりする。プログラム用語が使えるようになりたいかも。
ツイッター: https://twitter.com/bamb00h
ブログに公開せずツイートのみの情報もあり(twilog
バーコード
ブログ内検索
カウンター
忍者アナライズ
  Copyright 2017 データ置き場 All rights reserved.
Template Design by LockHeart|powered by NINJA TOOLS 忍者ブログ [PR]