Writeupについて
ミニキャンプ2021の修了試験で出題されたファイルシステムに関する問題のWriteUpです。
(途中までしか解けませんでしたが...)
解説
基本方針
基本方針としてはひたすらSDカードのダンプを解読するのみです(自分は未解凍のダンプをそのまま読もうとして終了しました())。SDカードはFAT32でフォーマットされているためそれを前提に解読を進めます。
第2クラスタの位置
ファイルシステムの構造を以下に示す。この中のルートディレクトリに手がかりとなるファイルのメタデータ(ディレクトリエントリという)があると考えて、まずはその位置を探す。
FAT32ファイルシステムの先頭部分はあらかじめ予約された領域となっており、この中にはブートセクタやファイルシステムのメタ情報などが含まれている。その中で今回使用する情報を以下に示す。
項目名 | オフセット | サイズ(B) | 概要 |
---|---|---|---|
BPB_BytesPerSec | 0xB | 2 | 1セクタの大きさ(Byte)512, 1024, 2048, 4096のいずれか |
BPB_SecPerClus | 0xD | 1 | 1クラスタあたりのセクタ数 |
BPB_ResvdSecCnt | 0xE | 2 | 予約領域のセクタ数 |
BPB_NumFATs | 0x10 | 1 | FATテーブルの個数 |
BPB_FATSz32 | 0x24 | 4 | FATテーブルのセクタ数 |
FATの構成の通り先頭から 予約領域の大きさ + FATテーブルの大きさ だけ読み進めたところが第2クラスタの先頭の位置となる。
予約領域の大きさは **BPB_BytesPerSec(セクタ1つの大きさ) * BPB_ResvdSecCnt(セクタ数)**で求めることができる。
またFATテーブルの大きさは **BPB_BytesPerSec(セクタ1つの大きさ) * BPB_FATSz32(テーブルあたりのセクタ数) * BPB_NumFATs(テーブル数)**で求めることができる。
それぞれの値をリトルエンディアンで確認する。
BPB_BytesPerSecはオフセット0xBで、その値は0x0200、10真数で512となる。つまりセクタ1つ分の大きさは512バイトとなる。
BPB_ResvdSecCntはオフセット0xEで、その値は0x20、10真数で32となる。予約領域のセクタ数は32であることが分かる。
BPB_FATSz32はオフセット0x24で、その値は0x1ff8、10真数で8184となる。テーブル1つあたりのセクタ数は8184であることが分かる。
BPB_NumFATsはオフセット0x10で、その値は0x02、10真数で2となる。FATテーブルの数は2つとなる。
以上のことから
予約領域の大きさは 512 * 32 = 16384(byte)
FATテーブルの合計サイズは 512 * 8184 * 2 = 8380416(byte)
16834 + 8380416 = 8396800
よって第2クラスタの位置は先頭から8396800バイト目であることが分かる。
第2クラスタ内のファイルのメタデータ
実際に8296800バイト分飛ばして確認すると、気になる部分としてSECRET.ZIP、.ASSWORDTXTの2つが見つかる(ファイルのメタデータが保存されている)。.ASSWORDTXTについては先頭バイトがE5になっているため削除されていることが分かる(おそらく元の名前はPASSWORDTXT)。データ本体は別の場所に格納されているはずであり、ファイル先頭からオフセット0x14の値は0x0、0x1Aの値は0x18E8であるから、ファイルのデータ本体は0x18E8番目のクラスタから始まっている。ディレクトリエントリの見方についてはこちらを参照。
0x18E8は10進数で6376であり、該当するデータは6376番目のクラスタから始まっている。1番目のクラスタは予約領域とFATテーブルで占められているから該当する場所は第1クラスタの大きさ + (クラスタ番号 - 2)*クラスタ1つあたりの大きさで求められる。
SECRET.ZIP
第1クラスタの大きさは 16384 + 8380416 = 8396800(byte)
第2から第6376クラスタまでの大きさは 6374 * 4096(セクタ数*セクタの大きさ) = 26107904(byte)
求める位置は 8396800 + 2610794 = 34505704(byte) となる。
別のツールではデコードしたときのデータの中身が日本語で読める状態になっており、CLUSTER_()_LOCKの()の中身にSECRET.ZIPのパスワードは、SECRET.ZIPのデータ部分の始まりのクラスタ番号(10進数)であることが書かれている。
SECRET.ZIPのメタデータ部分のオフセット0x14の上位ビットの値は0x0、0x1Aの下位ビットの値は0x131Eとなっているためパスワードは10進数で4894となる。
SECRET.ZIPをパスワードを用いて開くことでフラグが手に入る。