これは、夏のブログリレー 26日目の記事です。
2024年8月12~17日に行われたセキュリティ・キャンプ全国大会のS12『ハイパーバイザを自作して仮想化技術やセキュリティについて学ぶゼミ』に参加したのでgitのcommitlogを見ながら参加記を書いていこうと思います。
セキュリティ・キャンプは、IPAが主催する5泊6日の集中型人材発掘事業です。実際に、様々なセキュリティ等の情報分野において最先端で研究や仕事を行っていらっしゃる講師の方々により、非常に高度な講義が今年も行われてました。
今回、自分は全国大会の開発コースのハイパーバイザを自作するコースに参加しました。
成果物の一部があるGitHubリポジトリもあります。(ハイパーバイザのコア部分のみをまとめています)
はじめに
ハイパーバイザの説明記事を書こうとしていたのですが、時間が足りませんでした、、、
今回のコースではaarch64と呼ばれるスマートフォンに入っているCPUと同じ命令セットを搭載したアーキテクチャで動作させることを想定したRustで書かれたハイパーバイザを作成し、QEMUとRaspberry pi 5での動作するようにしました。
実際に作成したもの
OSのパスワード入力状態を検知し、そのパスワードを平文で出力するハイパーバイザを作成しました。
例えばFreeBSDでは普通、passwordを入力しても何も反応しません。
それが、今回のハイパーバイザを動作させるとこのようにpasswordを出力させることが可能になります。
ここからはこのハイパーバイザを作成するまでにどのようなことを学んだかや、直面したバグについて書いて行こうかと思います。
応募課題
セキュリティ・キャンプに参加するには応募課題を解いて、選考に通過する必要があります。
自分の解答とその感想はこちら
事前学習期間
ほとんどの事前学習課題は公開されてます。
事前学習期間では、ハイパーバイザのtype1とtype2の違いなど初歩的な内容から、UARTで文字を出力し、実際にハイパーバイザを自作してstage2_translationができるようにするまでを行いました。ハイパーバイザでもっともデバッグが難しいであろうstage2_translationの部分を本番前に終わらすことができていたため、セキュリティ・キャンプ本番ではハイパーバイザの改造に時間を費やせたのは良かったと思います。
セキュリティ・キャンプ本番
"Password"の⽂字を検知する機構が不安定
passwordの入力状態の検出は、OSから"Password"という文字が送られてくることを検知するだけの非常に簡単な仕組みとなっていたのですが動作が不安定でほとんど動かない状態となっていました。
passwordの検出機構のみの動作確認をしたところ意図した結果であったため、どうやらpasswordという文字がUARTで連続して送られていなさそうだということがわかりました。そのため、UARTで送る文字のすべてを16進数で送ってみることで制御文字が入っていないか確認することにしたところ、ANSI Escape Codeと呼ばれる制御文字が入っていることがわかりました。
これは、出力する位置を指定できたりフォントの色や背景の色を指定することができたりする、画面を見やすくするための制御文字です。これを無視するようなプログラムを実装することによって、QEMUでの実装を行うことができました。
↓↓↓ alpine linux での動作例
Raspberry pi 5で動作させる
QEMUの次は実機で動作させることを目標としていきます。aarch64はweak memory modelと呼ばれるアウト・オブ・オーダーの制御機構が弱いようなメモリモデルを採用しているせいで、権限レベルが異なるようなアウト・オブ・オーダーをしてはいけないところでも先に実行してしまうことでレジスタの値がおかしくなってバグることがあるのですが、これはQEMUはアウト・オブ・オーダーを搭載していないことから実機特有かつ機種依存の問題として現れる非常に厄介な問題となっています。講師がこれまでの経験から直感的にこの問題が発生する場所を見抜くことができたため今回は乗り切れたのですが、info registerなどの便利なデバッグ機能を持たない実機で自分で行うのは相当大変だと思います。
また"Password"の文字検知機構が不安定になった
Raspberry pi 5本体でpl011というUARTデバイスをつかって出力できるOSを探した所、Free BSDがどうやら条件を満たしていそうだということがわかったためFreeBSDでの動作を目標にして実装していたのですが、またPasswordの入力検知機構が不安定になりました。試しに改行文字をFree BSDが出力したらハイパーバイザ側で更にもう1つ改行文字を送ることにして改行が2倍なされるようなプログラムを作成して動作させてみたところ、これもまた5回に1回ぐらい動くという謎の挙動をしてくれました。改行が意図した通りに入る場所に再現性がなかったため非常に困っていたところ、ハイパーバイザはprimary coreの単コアのみでしか動作しないのに対して、FreeBSDはマルチコアで起動してしまっているのが原因だと講師が見抜いたので、実際にsecondary coreの起動をブロックするようにhypervisor側で設定を行ったところ、無事Raspberry pi 5でも動作させることができるようになりました。
おまけ
ここまでで全3日のうち2日をつかってしまっていたため、そこまで大規模なことは1日でできそうになかったため、初日に苦しめられたANSI Escape Codeを使ってカラフルなOSを作ろうと考えつきました。
Linux標準出力やTeratermなど、対応ターミナルを用いることで、下の出力のように自由に文字色を変更できるようになりました。
さらに、OSの出力を自由にいじることができるというハイパーバイザの利点を活用して、OSを強制的にカラフルにするハイパーバイザも作りました。
また、更に調べると背景色も設定することができることがわかったため背景までカラフルにしたり、ターミナルは"\r"を利用すると一番先頭にカーソルを移動できることを利用したりするなど、最終日は成果報告書を書く隙間時間にANSI Escape Codeで色々遊んでいました。
このように、ハイパーバイザの力を使って出力を変化させたり、パスワードを抜き取ったりすることができましたが、動作するOSは全く無改造であることが、ハイパーバイザがセキュリティ向上に役立つ一方で危険性もある理由だと理解することができました。
将来の展望
今回は攻撃者側のハイパーバイザを作成しましたが、ハイパーバイザは本来、セキュリティを高めるために使用されます。将来的にはOSに見せるデバイスを制限するなどセキュリティを強固にする方向に作成したいのですが、今回作成したハイパーバイザはpl011と呼ばれるUARTデバイスを持つaarch64のcpuで、UARTによる出力に対応したOS1つを単コアで動作させるといった非常に限られた条件のみにしか対応できていません。そのため、目下の課題としては次のようなものを考えています。
やりたいこと | 備考 |
---|---|
ACPIの読み取り | MilvusVisor(講師が作ったハイパーバイザ)からほとんどコピペすることで一部動作させた |
複数コア対応 | 今develop branchで作業中 ただ全く関係ないとこでつまずいちゃってる |
OSを2つ以上動かしたい | とりあえず恒等マッピングじゃなくさないと行けない |
PS2デバイスのエミュレート | |
OSの認識するパーティションの制限 |
正直これらもどうすれば実現できるのか全くわかっていないのでもっと調べないと、、、と思っています。
まとめ
今回はハイパーバイザを作ったわけですが自分は初めて低レイヤーを深く触ったため、本当に初歩の初歩な知識すらもあやふやな状態から始めました。講師のPG_MANA先生には、このような状態からハイパーバイザの最低限の理解ができるようにしてくださった上、本番においてもデバッグなどで常に手助けをして頂いて本当に頭が上がりません。ありがとうございました!!! セキュリティ・キャンプでは開発以外にも、共通講義やグループワークもあったのですが、どれも楽しく参加して本当によかったです。