之前就看過有人提到此類 driver 的存在。最近在查資料時,又找了一下,記錄下來以備不時之需。
https://efi.akeo.ie/
上述是一個 open source 專案,裡面有很多 file system 的 EFI driver。以讀取 NTFS partition 來說,這個專案比較方便,直接使用 load 方式載入即可。不像另外一個 rufus 專案,還需要動到 dd command 才行。
唯一要注意的是 NTFS 只能 read,不支援 write。想想也很合理,畢竟微軟並沒有提供正式的 Spec,大部份的解決方式都是靠 open source 社群摸索出來的。
pretty code
2019年11月28日 星期四
2016年10月21日 星期五
NTFS B+Tree parsing
假設我們想要從 B+Tree 找到 g:\123\456.txt 這個檔案,其步驟如下
1. 從 Partition G 的第 1 個 sector 找到 NTFS BootSector,並找到 MFT 的起點
2. 找到 index 為 0x05 的 Entry dot file
從 $INDEX_ROOT Attribute (0x90)可以看出
這個 Attritube 是 resident named,其名字為 $I30
裡面儲存的 INDEX Record 其 type 為 $FILE_NAME (0x30),大小為 1K
因為大小不夠存放,故需從 $INDEX_ALLOCATION (0xA0) 找到 DataRun
也就是 LCN 為 0x2C 的位置
3. 找到 INDEX Record 的位置,並 parse 一筆一筆的 Index Entry
找到 123 這個名字的 Entry,並得知其在 MFT 的 index 為 0x2C ,此筆的大小為 0x58,
此目錄的建立時間為 2016-10-19 15:25:51 +0800 CST (1D229DA060F6283)
4. 回到 MFT index 為 0x2C 的 Entry,由於該目錄只有 1 個檔案也就是 456.txt
故沒有 $INDEX_ALLOCATION Attribute,所有的資訊都存放在 $INDEX_ROOT,
該檔案在 MFT 的 index 為 0x2D,其最後修改時間為 2016-10-21 14:48:40 +0800 CST
5. 回到 MFT index 為 0x2D 的 Entry,由於檔案過大,
故其 $DATA是另外存放在 MFT 以外的區域,其 LCN 為 0x7F 的位置
6. 最後來到 LCN 為 0x7F 的位置,其內容就是 456.txt 的內容,至此所有的 parsing 告一段落
1. 從 Partition G 的第 1 個 sector 找到 NTFS BootSector,並找到 MFT 的起點
2. 找到 index 為 0x05 的 Entry dot file
從 $INDEX_ROOT Attribute (0x90)可以看出
這個 Attritube 是 resident named,其名字為 $I30
裡面儲存的 INDEX Record 其 type 為 $FILE_NAME (0x30),大小為 1K
因為大小不夠存放,故需從 $INDEX_ALLOCATION (0xA0) 找到 DataRun
也就是 LCN 為 0x2C 的位置
3. 找到 INDEX Record 的位置,並 parse 一筆一筆的 Index Entry
找到 123 這個名字的 Entry,並得知其在 MFT 的 index 為 0x2C ,此筆的大小為 0x58,
此目錄的建立時間為 2016-10-19 15:25:51 +0800 CST (1D229DA060F6283)
4. 回到 MFT index 為 0x2C 的 Entry,由於該目錄只有 1 個檔案也就是 456.txt
故沒有 $INDEX_ALLOCATION Attribute,所有的資訊都存放在 $INDEX_ROOT,
該檔案在 MFT 的 index 為 0x2D,其最後修改時間為 2016-10-21 14:48:40 +0800 CST
5. 回到 MFT index 為 0x2D 的 Entry,由於檔案過大,
故其 $DATA是另外存放在 MFT 以外的區域,其 LCN 為 0x7F 的位置
6. 最後來到 LCN 為 0x7F 的位置,其內容就是 456.txt 的內容,至此所有的 parsing 告一段落
2016年10月5日 星期三
NTFS $MFT parsing
$MFT 是 MFT 裡的第一筆 Entry,作用是描述 MFT 本身,總共有 4 個 attributes。
藍色代表 MFT Entry Header
綠色代表 Attribute Header
粉紅色則是 Attribute 內容
底下是人工 parsing 的結果
[Entry Header]
Length 0x0198
The Entry End is 0xFFFFFF (為了 8 的倍數,後面補了 0x00000000,故長度是 0x0198)
The next attribute id is 0x0007
0x10 -- 0x0000
0x30 -- 0x0003
0x80 -- 0x0006
0xB0 -- 0x0005
[0x10] -- $STANDARD_INFORMATION
The file creation time is "1601-01-01, 00:00 UTC" + (0x01D21B378809B277 / pow(10,7)) (seconds)
[0x30] -- $FILE_NAME
The name of this entry is $MFT, it has 4 characters, it's lenth is 2 x 4 = 8.
[0x80] -- $DATA, non-resident, no name
Note: not every 0x80 attribute is non-resident, we need to check non-resident flag.
starting VCN 0x00
last VCN 0x3F
offset to the Data Runs 0x40
Data Runs
21 40 BD 04 00 00 00 00
21 40 BD 04 - 00 00 00 00 (group)
first one is header, it means one byte length, two byte offset.
length 0x40
offset 0x04BD
Because $MFT is the description of MFT. this 0x80 attribute tells us that
MFT is at 0x4BD000 (0x04BD x 4096) and the length is 262144 bytes (0x40 * 4096).
We can use starting VCN and last VCN to check this length (0x00 - 0x3F, length 0x40) too.
Move to next group
21 40 BD 04 00 00 00 -> 21 40 BD 04 - 00 00 00 00
Because header is 0x00, it only has one data run.
[0xB0] -- $BITMAP, non-resident, no name
starting VCN 0x00
last VCN 0x01
offset to the Data Runs 0x40
Data Runs
21 01 BC 04 11 01 FF 00
21 01 BC 04 - 11 01 FF - 00 (group)
Run1 21 01 BC 04
length 0x01
offset 0x04BC
Run2 11 01 FF
length 0x01
offset 0x05BB (0x04BC + 0xFF)
從 Run1 得知,data 位於 0x4BC000 (0x04BC x 4096)
每 1 個 bit 代表 1 個 Entry,1 代表使用中,0 則是未使用
Dump 出來的資料如下
01 9F FF 00 FF FF
前 16 筆 Entry 是 metafile
第 25 筆 Entry 開始是 File System 的檔案或目錄
連續的17筆資料中,有 2 筆是未使用的
如果跳到該筆 Entry,可以從 Entry Header Flag 確認,其值應該為 0x00
至於 Run2,dump 出來的值都是 0x00
故只有在 MFT 前 41筆 Entry 是有資料的 (包含保留及空的未使用)
訂閱:
文章 (Atom)








