3DS (CTR): ARM9ハック


#ARM9とは 3DS (以下CTR) にはARM9とARM11の2つのCPUがある.この主な目的は, よりARM11で性能を向上させながら, DSで使用されているARM9で互換性を保つことにあるはずだが, 暗号化処理等をARM9に行わせることによりセキュリティの改善にも役立てている.

#設計上の問題点 ARM9は3DSの全権限を有しており, ほぼすべてのことを行える. 例えばARM9からARM11に任意のコードを実行できることも可能である. つまり, ハッキングの標的となりやすい. もっとも, ARM9の権限を盗まれた時点で他の部分の権限が盗まれていることはほぼ確実なので, この問題は無視できるかもしれない.

#実際にハックする ARM9はARM11に対するいくつかのインターフェイスを持っており, それを介してハックすることになる. その中でも多くを占めるのが_PXI_だ.

##PXI PXIはARM9で実行されるプロセス, _Process9_と対話するためのインターフェイスだ. Process9はいくつかのサービスを持っており, それらがPXIを介して送られたコマンドを実行する. サービスの一覧は3dbrew.orgに載っている.

http://3dbrew.org/wiki/PXI_Services

PXIで扱われるプロトコルも3dbrew.orgで説明されている.

http://3dbrew.org/wiki/PXI_Registers

PXIのコマンドも同様に説明されているが, 一部不完全である.

http://www.3dbrew.org/wiki/Services_API

これを見てわかる通り, コマンドはそれほど多くない. これがARM11と分離したことに依るセキュリティ上の利点である. この少ないコマンドをいかにハックするかが重要になってくる. もちろん, ここの部分のセキュリティが3DSのソフトウェアの中でもっとも堅牢であるはずということは言うまでもない.

とはいっても, ハックできないのかと言われれば, そんなこともない. これは, ハックする人の腕にかかっている.

##攻撃方法 カーネルのハックでメジャーなのは, バッファオーバーフローとTOCTTOU (確認利用時差) の攻撃である. どちらも使い古されたネタではあるが, 完全な対策は困難であり, 同時にハックしやすいのでよく使われる.

###オーバーフロー 想定以上のデータを入力することで, 他のデータを上書きするおなじみの攻撃方法である. しかし, 実際そんな簡単に攻撃が成立するわけではなく, 多くの場合入力を受けた時点で弾かれてしまう.

しかし, 内部でデータを展開する処理が行われている場合には, 展開後のデータのサイズがバッファの大きさを上回り, 攻撃が成立する場合がある. これはTOCTTOUに似た攻撃であるが, 入力時点でのデータに問題がある, すなわち入力を正確に判定することで防げるというのが最大の違いである.

他には数値計算でのオーバーフローを用いることがある. よくある文字列などのバイト列でのバッファオーバーフローは当然対策が行われているが, 数値計算に関する部分では意外と甘い. これには理由があり, どこで確認すればいいかわからない, 攻撃が少ないといったことが挙げられる (経験上) . 配列など, 数値計算の結果が何らかのアドレスに影響している場合, これにより想定外のデータの入力が可能になる.

###TOCTTOU これもPSPハックで頻繁に使われ, 最近ではePSPやWii Uハック, 3DSハックに使われた. やることは単純で, 正規の値を入力し, 確認が行われたあとに不正な値で入れ替えるという方法である. TOCTTOUで重要になるのは, 確認が行われたあと如何にして不正な値に入れ替えるかということである. 特に, 今回は別CPUということになっているから厄介だ. 直接値を代入する以外にも, GPUやそれによるDMAを使うという手がある. 最初から不正な値を代入して例外を発生させ, 例外処理中に攻撃用のデータに差し替えるという技もあるが, これは少し難しい. DSモードでは, 例外処理はハックされないように諸々の処置を行ったあとアプリケーションに渡されるため, これを使うのだ.

##デバッグ 残念ながら, 今のところ「まともな」デバッガはない. その一番の理由はそもそもやろうとしている人が少ないことにある. しかし, 読者のあなたが作ろうとしても困難を極めるだろう. 先述の通り, ARM9とARM11に分離され, ARM9はセキュリティ的に重要な部分しか担当していない. この状況下でネットワークやIRを利用してコンピュータと対話するなんてことは考えないほうがいい. しかし, 私は画面上に例外を表示する例外ハンドラをrxToolsを使って実装した. これを用いることをおすすめする.

###rxTools 画面の制御にもARM11が必要だったので, ARM11のSVC呼び出しをフックしている. そのため, 出力を見るためには何かがSVCを呼びださなければならない. もっとも, 何かしらが常にSVCを呼び出しているはずだが.

例外が発生すると, ハンドラはARM11を用いてフレームバッファをVRAMの先頭 (0x18000000) に設定する. そのあと, VRAMに例外が起きた時のプロセッサの情報をフレームバッファに描画する. それ以外の部分は放置されたままなので, その部分を特定の値でクリアすることで, 背景の色を変更できる. このトリックを使ってデバッグ情報を表示するのもいいだろう. そうしなければVRAMに残されたゴミが表示される.

exception

この砂嵐の部分がゴミである. 次に, 表示される情報について説明する.

####Type 種類である. “Undefined Instruction”は未定義命令, “Data Abort”と”Prefetch Abort”はそれぞれデータ, 命令アクセスの際の違反である. 書き込む命令で”Data Abort”が発生すればExploitできる可能性が高い. 読みだす命令での”Data Abort”や”Pretech Abort”はプログラムをよく解析してExploitできるか調べよう. もしよくわからなかったら, Abortが発生しない値を代入して続行してみるのも良いだろう.

####Registers ARMはr0-r12, SP, LR, PC, CPSRというレジスタを持つ. r0-r12は汎用レジスタであり, SPはスタックポインタ, LRは主に戻りアドレス, PCはプログラムカウンタ, CPSRはカレントプログラムステートレジスタである.

#####r0-r3 関数の引数の格納等に使われる.

#####r4-r12 関数が戻る際に元の値を戻さなければならない.

#####SP 今のところメモリダンプ機能はつけていないが, ダンプするとすればここである.

#####LR これに任意の値を代入できれば高確率でExploitできる.

#####PC パイプラインの都合からか, プログラムカウンタは現在の命令のアドレス + 8 (Thumbであれば現在の命令のアドレス + 4) を指す.

#####CPSR ARMにはThumbと通常のモードの2つのモードがあるので, それを見分ける際に重要になってくる. 他にも様々な情報が格納されているので, よく活用しよう.

#法律 日本だと不正競争防止法で「技術的制限回避装置」の輸入, 譲渡等が違法となっている. ARM9のExploitがこれに含まれるとは思わないが, 用心すること.

#更新 2015/08/22: 攻撃方法を追記. 法律に関する注を更新.

[top]