Obsah

NTFS (New Technology File System)

  1. MFT
  2. Update Sequence
  3. Atributy
  4. Data Run
  5. Soubor
  6. Adresář
Documentation

MFT (Master File Table)

Je to soubor, kerej obsahuje hlavičky všech souború včetně sebe. Obvykle zabírá 1/8 disku.

Boot sektor (první sektor disku nebo partyšnu)

OfsetVelikostVýznam
131Velikost klastru v sektorech (sektor = 512 B)
488Číslo klastru MFT
568Číslo klastru MFTMirr (záloha prvních 4 souború)
641Velikost MFT záznamu v bajtech (-N = 2N) (0F6h = 1024)

Speciální soubory

ČísloNázev
0$MFT
1$MFTMirr
2$LogFile
3$Volume
4$AttrDef
5. (Root Directory)
6$BitMap
7$Boot
8$BadClus
9$Secure
10$UpCase
11$Extend
12-23$ObjId
12-23$Quota
12-23$Reparse
12-23$UsnJrnl

MFT záznam

FileDescriptorAtribut1Atribut2Atribut3...0xFFFFFFFF...
1024

struct FileDescriptor{
 uns4 signature // ="FILE"
 uns2 offset_update_seq // =30h
 uns2 size_update_seq // =3
 uns8 log_file_seq_n
 uns2 del_count
 uns2 hard_links
 uns2 first_atr_ofs // =38h: ofset prvního atributu od začátku MFT záznamu
 uns2 flags // 0 volno/smazanej soubor, 1 soubor, 2 smazanej adresář, 3 adresář
 uns4 real_size
 uns4 allocated
 uns8 base_file
 uns2 next_atr_id
 uns1 padding[6] // zarovnání na 8 B
 uns2 update_seq_n
 uns2 update_seq_array[2]
 uns1 padding2[2] // zarovnání na 8 B
}

Update Sequence

Každej sektor v MFT končí dvoubajtovym číslem update sequence. V 1024 bajtovym záznamu to sou 2 položky. Data, kerý byly na těhle pozicích púvodně, se ukládají do update_seq_array.

Atributy

Atributy se dělej na rezidentní a nerezidentní. Rezidentní sou celý v MFT záznamu, nerezidentní obsahujou takzvanej DataRun, kerej odkazuje do datový části disku. Rezidentní atributy začínaj strukturou StandardHeader.

struct StandardHeader{
 uns4 atr_type // 0xFFFFFFFF = konec
 uns4 atr_size // včetně atr_type, doplněno na násobek 8 B.
 bool non_resident // 0 rezidentní, 1 nerezidentní
 uns1 name_len // dýlka názvu atributu
 uns2 name_ofs // ofset názvu atributu
 uns2 flags // 1 compressed, 4000h encrypted, 8000h sparse
 uns2 atr_id // identifikační číslo atributu
 uns4 atr_len // dýlka obsahu atributu
 uns2 atr_ofs // ofset obsahu atributu
 uns1 idx_flag
 uns1 padding
}

Typy atributú (atr_type)

ČísloVýznam
10hSTANDARD INFORMATION
20hATTRIBUTE LIST
30hFILE NAME
40hOBJECT ID
50hSECURITY DESCRIPTOR
60hVOLUME NAME
70hVOLUME INFORMATION
80hDATA
90hINDEX ROOT
0A0hINDEX ALLOCATION
0B0hINDEX BITMAP
0C0hREPARSE POINT
0D0hEA INFORMATION
0E0hEA
0F0hPROPERTY SET
100hLOGGED UTILITY STREAM

Data Run

U nerezidentních atributú.
VCN (Virtual Cluster Number) = číslo klastru v souboru.
LCN (Logical Cluster Number) = číslo klastru na disku.

struct DataAtr{
 uns4 atr_type
 uns4 atr_size
 bool non_resident
 uns1 name_len
 uns2 name_ofs
 uns2 flags // 1 compressed, 4000h encrypted, 8000h sparse
 uns2 atr_id
 uns8 init_vcn
 uns8 final_vcn
 uns2 data_runs_ofs // ofset DataRunu od začátku atributu
 uns2 compression_unit_len
 uns4 padding
 uns8 atr_alloc_size
 uns8 atr_real_size
 uns8 init_data_len
 // +name
 // +data run
}

Položka v DataRunu

OfsetVelikostVýznam
01sizes (& 0Fh = počet bajtú count, >> 4 = počet bajtú base, 00 = konec)
1sizes & 0Fhcount (počet klastrú)
1 + sizes & 0Fhsizes >> 4base (klastr začátku, se znamínkem, relativní k předchozímu)

Příklad (hex): 31 02 56 34 12 11 04 24 11 06 F0 00
1. datarun: count = 2, base = 0 + 123456h
2. datarun: count = 4, base = 123456h + 24h = 12347Ah
3. datarun: count = 6, base = 12347Ah + 0F0h = 12347Ah - 10h = 12346Ah

Soubor

Obsahuje tyhle atributy:
10h - STANDARD INFORMATION
30h - FILE NAME (pro každej hardlink)
50h - SECURITY DESCRIPTOR (přístupový práva)
80h - DATA (obsah souboru - rezidentní nebo nerezidentní)

struct StandardInformation{
 // +StandardHeader
 DateTime created
 DateTime modified
 DateTime mft_modified
 DateTime accessed
 uns4 permissions
 uns4 max_versions // 0 - not limited
 uns4 version
}

struct FileNameAtr{
 // +StandardHeader
 uns8 parent_dir
 DateTime created
 DateTime modified
 DateTime mft_modified
 DateTime accessed
 uns8 allocated
 uns8 size
 uns4 flags // 1 read only, 2 hidden, 4 system, 20h arch, 40h dev, 100h tmp, 200h sparse, 400h reparse, 10000000h dir
 uns4 ea_reparse
 uns1 name_len
 uns1 namespace
 uns2 name[256]
}

Méno souboru je v UTF-16 LE.
Namespace: 0 posix, 1 win, 2 dos, 3 dos & win

Adresář

Obsahuje tyhle atributy:
10h - STANDARD INFORMATION
30h - FILE NAME
50h - SECURITY DESCRIPTOR
90h - INDEX ROOT

Pokud je nastaven flag large:
0A0h - INDEX ALLOCATION - nerezidentní
0B0h - INDEX BITMAP

Ména atributú (ne souboru) sou "$I30" (UTF-16 LE)

struct IndexRoot{
 // +StandardHeader
 // Index Root
 uns4 atr_type, collation, alloc_index_entry_size
 uns1 clusters_per_index_record, padding[3]
 // Index Header
 uns4 ofs_first_index_entry // from index header - 0x10
 uns4 index_entries_total_len // from index header - 0x28
 uns4 index_entries_alloc // from index header - 0x28
 uns1 flags // 0 small index, 1 large index
 uns1 padding[3]
 // +IndexEntry[]
}

struct IndexEntry{
 uns8 file_ref // pokud není poslední
 uns2 index_entry_size // od IndexEntry
 uns2 stream_len
 uns2 index_flags // 1:má subnode, 2:poslední
 uns2 padding
 uns8 parent_ref
 uns8 created, modified, mftmodified, accessed
 uns8 allocated, real_size, file_flags
 uns1 filename_len, namespace
 // +file_name
 // +[index_entry_size - 8] VCN subnode, pokud má subnode, zarovnáno na 8 B
}

Pokud se IndexEntry nevejdou do MFT záznamu, nastaví se flag large a IndexRoot obsahuje pouze jeden IndexEntry, jehož subnode odkazuje na VCN kořenovýho uzlu (root node).

Uzel (node)

StandardIndexHeader (18h) NodeHeader (10h) Fixup (18h) IndexEntry1 IndexEntry2 IndexEntry3 ...
4096

Číslo subnode je VCN do INDEX ALLOCATION. Subnode obsahuje ty uzly, kerý sou menší než aktuální uzel, kromě posledního.
Fixup je to samý jako update_sequence. Velikost uzlu je 4096 (8 sektorú) a 1 číslo update sequence, takže potřebujeme 9 * 2 B, zbytek je zarovnání na 8 B.

struct StandardIndexHeader{
 uns4 signature // ="INDX"
 uns2 ofs_fixup_array // 28h
 uns2 entries_in_fixup_array // 9
 uns8 log_file
 uns8 vcn_of_this_record
}

struct NodeHeader{
 uns4 ofs_start_index_entry_list // od node header - 28h
 uns4 ofs_end_index_entry_list // od node header
 uns4 ofs_end_allocated // od node header - 0FE8h
 uns4 flags // 1:any children
}

Pravidlo pro přidání (add rule)

Najdi první klíč, kerej je věčí než novej. Přidej novej před něj.
1: Pokud je uzel plnej: rozděl ho na dva, najdi medián(prostřední klíč), ten přidej do rodiče. goto 1
Add a node (en)

Pravidlo pro smazání (delete rule)

Smaž klíč
Pokud měl potomka: Najdi nejvěčího potomka a přesuň ho sem. To samý pro uzel nejvěčího potomka.
2: Pokud uzel není dostatečně zaplněnej:
Pokud sourozenec má dostatek klíčú, ukradni jeden, jinak spoj se sourozencem.
goto 2