FFRIエンジニアブログ

株式会社FFRIセキュリティのエンジニアが執筆する技術者向けブログです

UEFI ブートキット入門

はじめに

基礎技術研究部の松尾です。

PC やサーバーの電源を入れた際、まずはじめに実行されるのが Basic Input/Output System (BIOS) というシステムファームウェアです。 もし BIOS が攻撃者に乗っ取られたら、その後に起動される OS 等を好き勝手に改ざんできる事になります。

この、BIOS に感染するマルウェアの事を「ブートキット (Bootkit)」と呼びます。

そこまでして感染させる必要があるのかと思う方も多いと思いますが、ブートキットは机上の話ではなく、数は少ないものの実際に観測されている脅威です。 確かに民間企業を狙うマルウェアであれば、BIOS まで狙うのはオーバーキルだと思います。しかし、安全保障に関わる領域、クラウドや Trusted Execution Environment (TEE) 等のハイパーバイザーベースのセキュリティが絡む領域においては特に重要度が増しています。

ここでは、BIOS の基本を紹介し、実際に世に出回ったブートキットの仕組みを紹介します。

なお、現在のほぼ全ての BIOS は、Unified Extensible Firmware Interface (UEFI) 仕様に基づいて実装されているため、ここでは UEFI BIOS のみに焦点を当てます。

UEFI BIOS の基本

この章では、セキュリティの文脈において重要となる UEFI BIOS の基本知識について紹介します。

BIOS の役割は、「ハードウェアを初期化し、OS を起動する事」です。
BIOS の中の複数のモジュールがそれぞれ別々のハードウェアを初期化し、それへのアクセスを抽象化したインターフェースを準備します。 ブートローダーは、最後にそれらのインターフェースを利用して外部デバイス (SSD やネットワーク) から OS を見つけ、それを起動します。

BIOS の作りを定める UEFI 仕様では、PC の電源が入れられてからシャットダウンするまでのフェーズを以下のように定義しています。 (厳密には、UEFI の Platform Initialization (PI) 仕様 で定められています)

UEFI のフェーズ (引用元: UEFI PI 仕様 p254)

この内 Run Time (RT) フェーズが普段私たちの作業しているフェーズなので、Transient System Load (TSL) フェーズ以前が BIOS が活発に動作しているフェーズになります。各フェーズで動作する BIOS モジュールの事を、DXE モジュール、BDS モジュールのように呼びます。 現在 2025 年までで出てきている UEFI ブートキットは、DXE モジュールか TSL モジュールのどちらかの形式を取っています。

BIOS の格納場所についてですが、TSL 以降のモジュールは普通のファイルと同じくディスクに、BDS 以前のモジュールはマザーボード上の SPI フラッシュチップに格納されています。また、DXE モジュールの一部は外部デバイスの Option ROM と呼ばれるフラッシュチップに格納されています。

SPI フラッシュチップ

Option ROM

DXE フェーズでは、まず初めに DxeCore と呼ばれるコンポーネントが実行され、それ以降の DXE モジュールはこの DxeCore により見つけ出され、実行されていきます。この DXE モジュールがほとんどのハードウェアデバイスへのアクセスを抽象化します。具体的には、IO 空間へのアクセスを抽象化して、UEFI プロトコル (DiskIoProtocol, HttpProtocol...) という形でアクセスできるようにします。

DxeCore は、DXE モジュールが共通して用いる機能を UEFI サービスとして提供しています。UEFI サービスはブートサービスランタイムサービスの二種類の大別できます。UEFI サービス *1 のうち、ブートサービスは OS 起動後には使えなくなります。厳密には、ブートサービスの 1 つに ExitBootServices という関数があり、これを OS ローダー (winload.efi) が呼ぶ事でブートサービスが使えなくなります。逆に言えば、攻撃者の DXE モジュールがこの ExitBootServices 関数をフックする事により、OS ローダーが実行されるタイミングで悪性コードを実行し OS を改ざんできます。フックについての仕組みは補足の章を参照してください。

UEFI サービスのもう 1 つであるランタイムサービスは、OS 起動後にもメモリに常駐する BIOS モジュールであり、ランタイム DXE モジュールと呼ばれています。ただし、このランタイム DXE モジュールは、OS 起動後ではカーネルドライバーと同じような扱い/権限の ring 0 となります。 後述する SMM モジュールより権限は低くなります。

DXE モジュール周りの概要

DXE フェーズでは、DXE モジュール以外にも SMM モジュールという特殊な BIOS モジュールがロードされます。System Management Mode (SMM) は、x86 系の CPU における最高権限の実行モードで、電源管理等の重要な処理を行うために用意されています。CPU は、System Management Interrupt (SMI) という割り込みが発生した時にのみこのモードに切り替わります。そして、SMM モジュールで定義されている SMI ハンドラー (割り込みハンドラー) を実行します。SMM モジュールは、SMM 以外の実行モードでのアクセスがハードウェア的に禁止されたメモリ領域 SMRAM に置かれており、OS 起動後もメモリに常駐しています。逆に、SMM モジュールは任意の物理アドレス空間にアクセスできるため (SMM Isolation が有効でない場合)、その権限の強さから ring -2 と呼ばれています (ring -1 のハイパーバイザーを任意にメモリ上で改ざんできる)。

SMM の概要

BIOS モジュールの第三者による改ざんを防ぐ仕組みとして、セキュアブートがあります。セキュアブートは、BIOS ベンダー等が BIOS モジュールにつけた署名を検証しながらブートする仕組みです。もし攻撃者が BIOS モジュールを改ざんした場合、署名にはそのハッシュ値の情報も含まれるためこの改ざんが検知されます。ユーザーランドやカーネル (カーネルドライバー) と違って、基本的に BIOS はユーザーがいじる事を想定していません。ゆえに、例え正規のユーザーであっても BIOS をいじればセキュアブートで弾かれます。ただし、PC の出荷前に BIOS が改ざんされていて、その状態を正しい状態として署名されていた場合は、セキュアブートでこの改ざんを検知できません。

UEFI ブートキット

執筆時点で確認されている、実世界に出回った UEFI ブートキットは以下のものがあります。

発見年 感染タイプ ブートキット名 目的 補足
2018 SPI LoJax 悪性 exe をブート中にディスク書き込み
2020 SPI MosaicRegressor 悪性 exe をブート中にディスク書き込み
2020 SPI Trickboot Trickbot に BIOS の書き込み用コードが見られただけで使われて無い
2021 ESP FinSpy 正規の exe に悪性処理を挿入
2021 ESP Especter DSE 無効化、悪性 sys 投下
2022 SPI MoonBounce 悪性 sys 投下
2022 SPI CosmicStrand PatchGuard 無効化、カーネルシェルコード挿入
2022 ESP BlackLotus Bitlocker/HVCI/WindowsDefender 無効化、セキュアブートバイパス、悪性 sys 投下
2024 ESP Bootkitty ドライバー署名無効化、悪性 so 挿入 学生がセキュリティのプロジェクトで作った物だった
  • exe: Windows のユーザーランドの実行ファイル
  • sys: Windows のカーネルドライバー
  • so: Linux の共有オブジェクト

UEFI ブートキットのタイプは、どこにブートキットの実体があるかで二種類に大別できます。

  1. SPI フラッシュ感染型: SPI フラッシュチップ内に、BDS フェーズ以前の BIOS モジュールを追加/改ざんする事で感染する
  2. ESP 感染型: TSL フェーズ以降のモジュールが格納されるディスク上の Efi System Partition (ESP) と呼ばれるパーティションに感染する

ざっくり言うと、SPI 感染型の方がステルスで永続性も高いのですが、感染するのが難しいです。
ステルスである理由は、ディスクに比べ、SPI フラッシュを解析する技術がまだあまり普及していないためです。 OS は BIOS をいじる必要が無いので、SPI フラッシュにアクセスする API 等を用意していません。ゆえに、OS 上で動作するアンチウイルス製品には SPI フラッシュを読み取って解析する機能が無い物もあり、必ず確認されるディスク上の感染型に比べてステルス性が高いと言えます。 また、仮に検知できたとしても、OS やアンチウイルス製品は SPI フラッシュの内容を変更して排除できないため、永続性も保てます。 これは、SPI フラッシュは、OS が起動されるより前のフェーズにて BIOS によりハードウェア的にロックされてしまうからです。ちなみに、SPI 感染型のブートキットは、このロックをきちんと行っていない BIOS を狙ったり、ロックの仕組みをバイパスする Speed Racer という手法を用いています。

一方 ESP 感染型は、ディスク上にあるブートローダー (ブートマネージャー) の実体である bootmgfw.efi を改ざん/置き換える事で感染します。

UEFI ブートキットが行う悪性挙動は、現在までで出てきている物だと以下の 2 パターンです。

  1. ブート中にユーザーランドマルウェア (exe) をディスクに書き込む
  2. OS のセキュリティ機構を無効化して、カーネルドライバー (sys) や exe をインジェクトしたりシェルコード実行したりする

ブート中にわざわざディスク書き込みを行う理由は、ブート中の処理内容は OS のセキュリティ機構やアンチウイルス製品が干渉不可能だからです。 実際にブート中で行われた悪性挙動は、ユーザーランドマルウェアの書き込みだけです。これは、Simple File System Protocol を用いて行われています。基本的にこのプロトコルはブートローダーを外部デバイスから探すために用いられています。そして、UEFI ではその外部デバイスのファイルシステムが File Allocation Table (FAT32) でないといけないとされています。一方で、Windows が用いるファイルシステムは主に NT File System (NTFS) です。ゆえに、これを行うためには NTFS 用の Simple File System Protocol をインストールする DXE モジュールが必要です。Lojax や MosaicRegressor では、後ほど紹介する vector-edk の NtfsDxe を用いて、このプロトコルを用意しています。

実在するブートキットではディスク書き込みしかしていませんが、ブート中にファイルを暗号化するランサムウェアなどの研究も発表されています。

続いて、2. のタイプでは、最終的に C2 通信等の悪性処理をカーネルやユーザーランドで行っていて、BIOS ではそれが弾かれないようにセキュリティ機構を無効化したりするなどの補助をしているに過ぎません。これは、直接カーネルにルートキットを仕込んだりカーネルエクスプロイトを行ったりしても、後述する OS のセキュリティ機構の発展によりそれが阻止されてしまうからです。ゆえに、さらにその下の BIOS に感染してこれを無効化しようといういたちごっこの歴史が反映されています。

OS のセキュリティ機構のうち、Windows の機構で上述のブートキットがバイパスする物だと以下があります。

機構名 機構の説明 ブートキットで用いられているバイパス方法
Driver Signature Enforcement (DSE) カーネルドライバーの署名を確認する Windows の機能 nt!SepInitializeCodeIntegrity をパッチ
Patch Guard Windows カーネルの重要な構造体の改ざんを検知する機能 nt!KiFilterFiberContext をすぐリターンさせる
HyperVisor Code Integrity (HVCI) 書き込みかつ実行可能なページの作成を禁止する等のメモリのアクセス権限周りの Windows の機構。VBS の一部 レジストリの HypervisorEnforcedCodeIntegrity0 にする。VbsPolicyDisabled UEFI 変数を変更する。
Bitlocker ディスクを暗号化する Windows の機能 WMI メソッド DisableKeyProtectorsDisableCount=0 で呼ぶ
Windows Defender Windows に搭載されているアンチウイルス WdBoot.sys & WdFilter.sys をすぐリターンさせる
  • nt!*** は OS のカーネルの実行ファイル ntoskrnl.exe に実装されている関数 *** という意味です。

このうち、BlackLotus というブートキットのみが行っている HVCI と Bitlocker のバイパス手法は BIOS だからできる手法ではありません。ブートキットのインストーラーがユーザーランドで実行するものです。 その他のバイパス手法は、全て「OS がメモリにロードされているがまだ実行されてない間に OS をパッチする」という点で共通しており、これは BIOS に感染したからできる手法です。 仮にカーネルルートキットやカーネルエクスプロイトが同じ事を行う場合、OS が実行された後にパッチをする事になります。しかし、コードの改ざんは HVCI に、データの改ざんは Patch Guard に防がれるためできません。つまり、OS が起動してセキュリティ機構が有効化される前にこれらをパッチする必要があるため、BIOS に感染する必要があります。

OS の起動には、以下のように複数のモジュールが関わっています。ゆえに、ブートキットの大部分のコードは、最初に感染したモジュールから次のモジュールに感染するための処理になっています。具体的に説明すると、前のモジュール (A) が次のモジュール (B) をある関数 (Fa) で実行するなら、A の関数 Fa をフックすれば、次に実行される B の内容を改ざんできます。B を改ざんして、次のモジュール (C) を実行する関数 (Fb) をフックすれば、C を改ざんできます。このように、連鎖的にフックをかけるフックチェーンを利用し、最終的に ntoskrnl.exe を改ざんしてセキュリティ機構を無効化します。Linux を対象とする Bootkitty も、フックする関数名等が違うだけで、やっていることは基本的に同じです。

OS と Linux のブートに関わる主要コンポーネント

ESP 感染型の場合は bootmgfw.efi からフックチェーンが始まります。SPI 感染型の場合はそれよりもっと前の任意の DXE モジュールから、ExitBootServices ブートサービスをフックしてチェーンが始まります。 セキュリティ機構の無効化後は、そのまま継続してカーネル関数をフックしてシェルコードを入れたり、winlogon.exe 等のプロセスにコードを挿入したりと、一般的なマルウェアと同じです。

UEFI ブートキットの感染手法に関してですが、実は上述のブートキットの内、Lojax と BlackLotus 以外の初期感染方法は判明していません。SPI 感染型の LoJax では、ユーザーランド上のマルウェアやカーネルドライバーから感染しています。具体的には、SPI フラッシュ書き込み保護機能をバイパスしたり、書き込み保護が適切に行われていない端末を狙って SPI フラッシュを書き換えたりすることで感染しています。ESP 感染型の BlackLotus では、管理者権限で実行されたインストーラーが単純に ESP の bootmgfw.efi 等を置き換える事で感染しています。

この 2 種類の手法以外の感染方法としては、以下のものが想定されます。

セキュアブートに弾かれないのかという点ですが、こちらに関してもほとんどのブートキットがこれをどう対処しているのかは判明していません。セキュアブートが有効でない環境を対象にしている、あるいはセキュアブートをなんらかの方法で無効にしていると予想されている程度です。ただし、BlackLotus に限ってはセキュアブートのバイパスを行っていることがわかっています。具体的には、Baton Drop と呼ばれる脆弱性を用いてバイパスしています。この脆弱性のあるブートローダーは互換性のためセキュアブートで弾かれないようになっていました。そのため、攻撃者は Bring Your Own Vulnerable Driver (BYOVD) のようにこの脆弱なブートローダーを持ってきてセキュアブートをバイパスしています。セキュアブートは、第三者のモジュールの追加を署名で防ぐという厳しめの制限ではありますが、その運用 (署名管理等) 面では未だ課題が残っていると言えます。

UEFI ブートキットは誰がどれくらい気にするべきか

ここまでで BIOS に感染するメリットや感染方法等を紹介しましたが、実際ここまでやる必要はあるのでしょうか?誰がこの脅威に注目すべきなのでしょうか? この章では、BIOS のセキュリティがどういう文脈において重要となるのかを説明します。

まず、BIOS は安全保障の文脈、すなわち国家が支援しているあるいは背後に存在すると思われる攻撃で使用されるバックドアという場合には重要度を増します。 先ほどのブートキットのリストにはあげていませんが、米国の諜報機関等の政府機関からリークしたとされるドキュメント等を見ると、以下のように BIOS レベルまで感染するハッキングツールを持っていると考えられる記述があります (UEFI BIOS ではなく、レガシー BIOS 対象の物も含まれています)。 民間企業を狙う場合、機密情報を盗んだ後、その旨を伝えてさらに金銭を要求すると言ったように金銭が主な目的で、攻撃の永続性はあまり重視されない傾向があります。しかし、国家が関与する攻撃で使用されるバックドアの場合は、いかにそれが明るみにならないようにするか、また取り除けないようにするかが重要になってきます。 実際にこのようなハッキングツールを作っているかは不明ですが、いずれにせよブートキットは安全保障において重大な脅威と言えます。

リーク年 バックドア名 処理概要
2014 DEITYBOUNCE OSパッチ等を行えるステルスな関数を提供する SMM バックドア
2014 IronChef 情報窃取して Global System for Mobile Communications (GSM) で C2 に送る WAGONBED (ハードウェアインプラント) を SMM から制御/再インストールする
2015 vector-edk NtfsDxerkloader を含む、ブートキットの作成に使えるビルドキット
2016 BANANABALLOT, JETPLOW ファイアウォールの OS を改ざんする
2017 DerStarke (Dark Matter) Mac に SPI フラッシュロックをバイパスして感染し、アップデートがかかっても再インストールするバックドア

また、製造工程のサプライチェーン上で PC にバックドアを入れる事を考える場合、BIOS はサプライチェーン上で関与する会社が多いため入れやすいという点もあります。ユーザーランド上のアプリとしてバックドアを入れる場合は、PC の製造中では OS がインストールされていないフェーズも多いですし、いずれにせよユーザーへ渡される前に初期化されます。カーネルレベルのバックドアを入れる場合でも、OS は Windows であれば Microsoft 一社しか主に関わっていないため、サプライチェーンの範囲が狭くバックドアを入れる隙は少ないです。しかし、BIOS は以下のように多くの企業が開発に関わっています。つまり、サプライチェーンが長いので、その分バックドアを入れる隙も多い事になります (関わる国も多い)。Binarly 社による Attacking (pre)EFI Ecosystem のブログ記事の画像に BIOS のサプライチェーンに関わる企業がよくまとまっていますが、この図以上に色々な企業が関わっていると考えられます。

続いて、クラウドや TEE の文脈においても BIOS の脅威は重要性を増します。 クラウド環境では、クラウドベンダーが用意したハイパーバイザーの上で複数の企業の仮想マシンが動いています。クラウドベンダーにとっての主要な脅威のひとつは、1 つの仮想マシンが侵害されたのちに、その下のハイパーバイザーを攻撃して他の仮想マシンが侵害される事です。1 つの仮想マシンへの攻撃であれば、その利用企業のセキュリティ管理の問題です。しかし、さらにその下のハイパーバイザー等をも攻撃された場合はそのクラウドベンダーの責任になり、被害も桁違いに大きくなります。

ハイパーバイザーが仮想マシン (OS + ユーザーランド) を起動しますが、ハイパーバイザーを実行するのは BIOS です。つまり、ブートキットはハイパーバイザーを任意に改ざんできる権限を持っています。 例えば、この Hyper-V バックドアの PoC では、DXE モジュールから上述のブートキットの仕組みで紹介したフックチェーンを用いて、Hyper-V の実体である hvix64.exe を改ざん (VM exit ハンドラーをフック) しています。

VBS 有効化での Windows

また、近年ハイパーバイザーベースのセキュリティや TEE (Trusted Execution Environment) が普及してきています。ブートキットの仕組みで少し話しましたが、Windows 11 からは VBS (Virtualization Based Security) というセキュリティ機構がデフォルトで有効になっています。これにより、皆さんが普段作業している環境は Hyper-V 上の仮想マシン (VTL 0) になっています (厳密には、Win 10 から 11 にした場合は有効になっていない場合が多いです)。Hyper-V 上ではもう 1 つの仮想マシン (VTL 1) が動いており、Windows のログイン情報等の重要な情報は VTL 1 の方で保管されています (Credential Guard)。この構造により、例え VTL 0 でカーネルレベルまで侵害されても、Credential Guard で隔離された機密情報は守られます。さらに、HVCI によりページのアクセス権限を変更したりできないので悪性処理を自由に実行させないようできています。このように、信頼できる領域 (VTL 1) と信頼できない領域 (VTL 0) を分けるセキュリティ機構を一般に TEE と言います。先ほどの Hyper-V のバックドアはこの TEE をバイパスするものでもあるため、BIOS の侵害は TEE にとって大きな脅威となります。

特に、SMM (ring -2) はハイパーバイザーベースのセキュリティにおいてとても重要視されています。SMM のコードは OS 起動後もメモリに置かれており、かつ任意の物理アドレスにアクセスできます。したがって、SMM バックドアを入れておけば、リアルタイムで VTL 1 のメモリデータを自由に読み書きできます (VBS x SMM の 研究1, 研究2)。

最近では、この BIOS をも脅威モデルに入れたハードウェアサポートのある TEE がクラウド業界で流行しています (一般的に我々が利用するパソコンにはまだ普及していません)。例えば、AMD-SEVIntel TDX などがあります。これらは、信頼できる領域のメモリ空間を暗号化し、CPU 内部でのみ復号して扱う事により、BIOS や SMM からでもこの内容を読めないようにしています。しかし、BIOS とハードウェアサポートのある TEE は未だ互いに競っています。去年の BlackHat Europe 2024 の発表でも、システムファームウェアから TEE をバイパスするような攻撃が発表されていました。

ハードウェアサポートのある TEE

補足: フック

フックの例

フックとは、ある関数や命令列の実行直前/直後に処理を挿入する手法です。例えばあるプログラム A が関数 Fa を呼び出す場合を考えます。Fa が実行される直前に、関数 Fb を呼び出したい場合、関数 Fa の最初の命令を jmp <Fbのアドレス> と書き換えます。そして、Fb で何か処理を実行した後に jmp <Faのアドレス> をして制御を戻せば、Fb の処理を挿入できます。これのユースケースとしては、Fa の関数が A によりどのような引数で呼ばれているかを確認したり、単純に A が関数 Fa を呼び出すタイミングでコードを実行したい時などに使えます。ブートキットでは、OS がロードされているがまだ実行されていないタイミングで OS を改ざんしたいので、このタイミングでコードを実行するためにフックを使用しています。

おわりに

今回は、実際に世に出回ったブートキットの全体的な特徴や分類、その仕組みについて紹介しました。また、このような BIOS レベルの脅威がどういうシナリオにおいて特に重要となるのかについても紹介しました。安全保障/クラウド/TEE は近年特に注目されている分野であり、BIOS の脅威は今後ますます重要になってくると予想できます。

*1: 具体的な関数としては、C 言語における malloc のようなメモリ確保用の関数 AllocatePool / AllocatePages や、イベント処理用の関数 CreateEvent などがあります。