はじめに
このブログ・シリーズの最初のパートでは、保護 MBR と、最新の GPT パーティション・ディスクとレガシー・システムとの互換性を保護する役割について説明しました。保護 MBR が、古いシステムが GPT ディスクを誤って解釈するのを防ぐバリアとしてどのように機能し、それによってディスク全体が GPT によって使用中であるとマークされることを保証するのかについて掘り下げました。この基本的な理解は、GUIDパーティションテーブル(GPT)そのものの核心であるGPTヘッダーをより深く掘り下げるための舞台となる。
この第 2 部では、ディスクの構造に関する重要な情報を提供する GPT スキーマの重要なコン ポーネントである GPT ヘッダーを解き明かします。GPT ヘッダー内の各フィールドを調べ、その重要性と、ディスクの全体的な機能と整合性にどのように寄与するかを説明します。この投稿が終わる頃には、GPTヘッダーの包括的な理解が得られ、フォレンジック調査やデータ復旧のシナリオでGPTパーティションのディスクを自信を持って分析・操作できるようになります。
GPTヘッダーの概要
GPT(GUID パーティションテーブル)ヘッダーは、ディスクのパーティションシステ ムの重要なコンポーネントです。ディスクを別々のセクションに分割し、それぞれにオペレーティングシステム、個人ファイル、アプリケーションデータ、ゲームなど、さまざまな種類のデータを保存できます。これらのセクションは、異なるドライブ(C:ドライブ、D:ドライブ、E:ドライブなど)にすることができます。
GPTヘッダーには、ディスクの末尾にバックアップ・コピーが含まれており、これはメイン・キーが紛失したり破損したりした場合に備えて、ライブラリ・カタログのスペア・キーを持つようなものだ。これにより、何か問題が発生した場合でも、確実にデータを見つけ、アクセスすることができる。
GPTヘッダーは、そのバックアップの場所と、GUIDパーティションテーブルエントリーアレイの場所を提供します。これは、ディスク上のセクション(パーティション)がどこにあるかを示すGPTパーティションエントリーのリストです。

図1:1つのボリュームを持つ仮想的なWindows 10インストールのレイアウト(n = ドライブの最後のセクタ)
GPTヘッダーはEFI PARTという署名で始まります。残りの値の内訳は下表のとおりです:
GPTヘッダーの構造
GPTヘッダーは「EFI PART」というシグネチャーで始まります:


ソース https://uefi.org/specs/UEFI/2.10/05_GUID_Partition_Table_Format.html

これまでのところ、GPTヘッダーの最初の16バイトは、異なるGPTディスク間で一定です。
GPTヘッダーCRC

以下はGPTヘッダーのCRC32の計算方法の例です:

Pythonスクリプトを使って、孤立バイトCRCを計算することができる:

Pythonスクリプトは以下にある: https://github.com/eichbaumj/Python

Pythonスクリプトは結果のCRC32値を受け取り、GPTヘッダーに必要なフォーマットに変換します。この場合、計算された値は0x1B2C37BCです。しかし、GPTヘッダー内のフィールドに格納するために、値はリトルエンディアンで読み込まれます:0xBC372C1Bです。

ディスクGUID

下のスクリーンショットは、GPTヘッダーのGUIDをハイライトしたものです:

GUIDは16バイトの16進数値だが、値をコピーしてハイフンで適当に区切り、中括弧で囲めばいいと思ったら大間違いだ。間違った値になってしまう。
右側のデータ・インスペクタで、HxDがGUID変換を提供しているのがわかる。しかし、これはどのように行われるのでしょうか?どのように
55 ba 55 51 2b d8 59 41 bc 1f c4 17 80 0f d7 63
なる:
{5155BA55-D82B-4159-BC1F-C417800FD763}
GUIDフォーマット
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
55 ba 55 51 | 2b d8 | 59 41 | bc 1f | c4 17 80 0f d7 63
最初の4バイトのセットはリトルエンディアンの16進数に変換される: 51 55 BA 55
2バイト目のセットはリトルエンディアンの16進数に変換される:D8 2B
2バイトの3番目のセットはリトルエンディアンの16進数に変換される: 59 41
残りの2組の16進値はそのままビッグエンディアンとする:bc 1f | c4 17 80 0f d7 63
すべての変換が完了したら、ハイフンを必要なところに入れ、中括弧で囲んで、すべてをまとめることができる:
{5155BA55-D82B-4159-BC1F-C417800FD763}
コマンドラインからdiskpartを起動し、ディスクのuniqueidをチェックすることで、これが正しいGUIDのエンコーディングであることを確認できる:


GPTパーティションテーブルチェックサムCRC

同じPythonスクリプトを使いますが、16進数の値をパーティション・エントリーの配列にある値に置き換えることができます。



そして、その値がGPTヘッダーにあるものと一致していることがわかる。
GPTヘッダーの修復
さて、GPTヘッダーがどのような構造になっているのか、そしてディスクの最後のセクタにバックアップがあることはわかった。
GPTヘッダーを修復するには、ディスクの末尾から最後の512バイトをコピーし、LBA 1(セクタ#2)に貼り付けます。いくつかの修正が必要であることに注意してください。
以下は、バックアップGPTヘッダーがディスクの最後にどのように見えるかの例です:

オリジナルのGPTヘッダーと比較して、いくつかの値が一定のままであることがわかります。これらの定数は以下で赤くハイライトされています:

変更すべき値は4つある。
最初はGPTヘッダーのCRCです。今のところ、これらの値はゼロにしてもかまいません。他の値を修正した後に計算されたCRCを使用して、再び正しい値を取得する必要があるからです。

次に、オフセット24の4バイトにあるMyLBA値です。この値はGPTヘッダーの位置(現在ある場所)を指し、現在の位置はLBA 1または0x0100000000000です。

オフセット32の8バイト値は、バックアップGPTヘッダーの場所を示す値です。バックアップは現在オリジナルを指していますが、ディスクの最後のセクタを表すようにこの値を変更する必要があります。これは前のステップで変更した16進数値で起こりました。この例では、値を0xAFD23B7700000000に変更する必要があります。

オフセット72にある8バイトの値は、GPTパーティションエントリアレイの位置と開始を反映する必要があります。現在、バックアップGPTヘッダーはそのアレイのバックアップを指しています。この値は0x02000000000000に変更する必要があります。

これら3つの値が変更されたので、次はCRC32値を計算する番だ。
チェックサムは次のようになる:

これで、オフセット16の0x00000000の値を0xBC372C1Bに置き換えることができる:

HxDにはCRC32チェックサム計算機能が「解析」→「チェックサム」に組み込まれています。結果の値はリトルエンディアンの値として追加するだけでよい。
好奇心のために、復元したオリジナルとバックアップの512バイトを分離してみると、ハッシュ値は確かに一致し、バックアップを使ってオリジナルのGPTヘッダーをうまく再現できたことがわかります。

結論
GPTヘッダーの複雑さを理解することは、デジタルフォレンジック、データ復旧、システム管理に携わる人にとって不可欠です。GPT ヘッダーは、ディスクのレイアウトと構造を定義するだけでなく、CRC32 チェックサムやバックアップヘッダーなどのメカニズムを通じてデータの整合性を保証します。GPTヘッダーの詳細をマスターすることで、ディスクの問題をトラブルシューティングし、修復する能力が向上し、重要なデータの信頼性とアクセス性が保証されます。
このシリーズを続けるにあたり、次はGPTパーティションテーブルエントリアレイに焦点を当てます。パーティションエントリがどのような構造になっているのか、またGPTヘッダとどのように連動してディスクパーティションの構成と整合性を維持するのかを探ります。GPT パーティションテーブルエントリーアレイの解析と修復に関する包括的なガイドにご期待ください。
パート1を見逃した?
最初から始めようGPTパーティション・ディスクの保護MBRを理解する(前編) - ここでは、GPTがどのようにレガシーシステムとの下位互換性を確保するかを取り上げます。
次のステップの準備はできているか?
つづく Part 3: GPTパーティションエントリアレイのナビゲーション - パーティション・エントリーがどのように構造化され、GPTヘッダーをどのように補完するのかを探ります。
2件のフィードバック
素晴らしいページだ(そのページとパート1)。
ありがとう!