Thứ Ba, 17 tháng 6, 2014

[FileSystem Forensics]NTFS Data Structures

Basic Concepts
Trong phần này, chúng ta phân tích các NTFS data structure concepts cơ bản. Trong tiểu mục đầu tiên, chúng ta phân tích một đặc tính thiết kế của các data structures lớn mà khiến cho chúng trở nên đáng tin hơn. Tiếp theo, chúng ta thảo luận cấu trúc dữ lieu của một MFT entry và một attribute header.

Fixup Values
Trước khi nhìn vào bất cứ cấu trúc dữ liệu NTFS cụ thể nào, chúng ta cần thảo luận một kĩ thuật lưu trữ được sử dụng cho việc gia tăng tính tin cậy. NTFS kết hợp các fixup values trong các cấu trúc dữ liệu mà có chiều dài vượt quá 1 sector. Với các fixup values, 2 bytes cuối của mỗi sector trong các cấu trúc dữ liệu lớn được thay thế bởi một signature value khi cấu trúc dữ liệu được ghi tới đĩa. Signature sau đó được sử dụng để xác minh tính toàn vẹn của dữ liệu thông qua việc xác minh tất cả các sectors có cùng signature. Chú ý rằng các fixups chỉ được sử dụng trong các cấu trúc dữ liệu và không được sử dụng trong các sectors mà chứa file content.
Các cấu trúc dữ liệu mà sử dụng các fixups có các header fields mà nhận dạng giá trị 16-bit signature hiện hành và một mảng chứa các giá trị ban đầu. Khi cấu trúc dữ liệu được ghi lên đĩa, signature value được tăng lên 1 , 2 bytes cuối của mỗi sector được sao chép vào mảng, và signature value được ghi tới 2 bytes cuối cùng của mỗi sector. Khi đọc ctdl, hệ điều hành sẽ xác minh 2 bytes cuối của mỗi sector xem có bằng signature value hay không, các giá trị ban đầu được thay thế ra khỏi mảng. Hình 13.1 hiển thị một ctdl với các giá trị thực sự và sau đó là phiên bản được ghi lên đĩa. Trong ctdl thứ 2, 2 bytes cuối của mỗi sector được thay thế với 0x0001.

Các fixups có thể được sử dụng để phát hiện các sectors bị đe dọa (damaged sectors) và các ctdl bị lỗi. Nếu chỉ một sector của một ctdl nhiều sector (multi-sector data structure) được ghi, fixup này sẽ khác với signature, và OS sẽ biết data bị lỗi. Khi chúng ta dissect file system, chúng ta đầu tiên sẽ cần thay thế các signature values.

MFT Entries (File Records)
Như ta đã biết , Master File Table (MFT) là trái tim của NTFS và có một entry cho mọi file và directory. Các MFT entries có một kích thước được gán cứng và chỉ chứa một vài fields. Cho tới thời điểm này, các entries có kích thước 1024 bytes, nhưng kích thước này được định nghĩa trong boot sector. Mỗi MFT entry sẽ dụng các giá trị fixup, vì vậy phiên bản trên đĩa của ctdl có 2 bytes cuối cùng của mỗi sector được thay thế bởi một giá trị fixup. Các fields của ctdl được hiển thị trong Bảng 13.1
Giá trị signature chuẩn là "FILE", nhưng thỉnh thoảng sẽ vẫn có "BAAD" nếu chkdsk tìm thấy một lỗi trong nó. Hai fields tiếp theo là cho các fixup values, và mảng thông thường được lưu sau byte 42. Các giá trị offset là tương đối so với bắt đầu của  entry.

LSN được sử dụng cho file system log (hoặc journal). Các log records khi metadata update được tạo tới file system vì vậy một corrupt file system có thể nhanh chóng được sửa chữa.

Sequence value được tăng lên khi entry hoặc được cấp phát hoặc không cấp phát, được xác định bởi OS. Nếu các hard links được tạo cho file, số này được tăng lên 1 cho mỗi link.

Chúng ta tìm được attribute đầu tiên cho file sử dụng offset value, giá trị này tương đối với bắt đầu của entry. Tất cả các attributes khác theo sau attribute đầu tiên, và chúng ta tìm chúng thông qua việc tiến về phía trước sử dụng size field trong attribute header. Marker đánh dấu kết thúc file 0xffffffff tồn tại sau attribute cuối cùng. Nếu một file cần nhiều hơn một MFT entry, các MFT entry bổ sung sẽ có file reference của base entry trong MFT entry của chúng.

Flags field chỉ có 2 giá trị. 0x01 bit được set khi entry là đang sử dụng, và 0x02 được set khi entry là cho directory. 

Nào hãy cùng nhìn vào một raw MFT entry. Để nhìn thấy table, chúng ta sử dụng icat từ The Sleuth Kit (TSK) và view $DATA attribute cho $MFT file, là MFT entry 0. Nhớ rằng bạn có thể chỉ định bất cứ attribute nào trong TSK thông qua việc thêm vào attribute type ID theo sau MFT entry address. Trong trường hợp này, $DATA attribute có type là 128.

# icat –f ntfs ntfs1.dd 0-128 | xxd
0000000: 4649 4c45 3000 0300 4ba7 6401 0000 0000 FILE0...K.d.....
0000016: 0100 0100 3800 0100 b801 0000 0004 0000 ....8...........
0000032: 0000 0000 0000 0000 0600 0000 0000 0000 ................
0000048: 5800 0000 0000 0000 1000 0000 6000 0000 X...........`...
[REMOVED]
0000496: 3101 b43a 0500 0000 ffff ffff 0000 5800 1..:..........X.
0000512: 0000 0000 0000 0000 0000 0000 0000 0000 ................
[REMOVED]
0001008: 0000 0000 0000 0000 0000 0000 0000 5800 ..............X.

Output được hiển thị theo thứ tự little-endian, vì vậy chúng ta cần đảo ngược thứ tự của các số. Chúng ta thấy "FILE" signature, và các bytes 4 và 5 cho ta thấy rằng fixup array được xác định vị trí 48 bytes (0x0030) bên trong MFT entry. Các bytes 6 và 7 cho chúng ta thấy mảng này có 3 giá trị bên trong nó. Các bytes 16 và 17 cho chúng ta thấy sequence value cho MFT entry này là 1, có nghĩa là đây là lần đầu tiên entry này được sử dụng. Các bytes 18 và 19 cho ta thấy giá trị link count bằng 1, vì vậy chúng ta biết được chúng chỉ có 1 name. Các bytes 20 tới 21 cho chúng ta thấy attribute đầu tiên được đặt tại offset 56 (0x0038)

Các flags trong các bytes 22 tới 23 cho chúng ta thấy entry này là in use (0x0001). Các base entry values trong các bytes từ 32 tới 39 là 0, điều này cho chúng ta thấy đó là một base entry, và các bytes 40 tới 41 cho ta thấy next attribute ID được gán là 6. Do đó, chúng ta nên mong đợi là có các attributes với ID từ 1 đến 5.

Fixup array bắt đầu từ byte 48. Hai bytes đầu tiên hiển thị signature value, giá trị là 0x0058. 2 bytes tiếp theo là các giá trị ban đầu mà nên được sử dụng để thay thế signature value. Bạn nhìn vào 2 bytes cuối của mỗi sector, các bytes 510 tới 511 và 1022 tới 1023, bạn nhìn thấy giá trị là 0x0058. Để process entry này, chúng ta thay thế các giá trị này với 0x0000, là những giá trị trong fixup array. Theo sau fixup array, attribute đầu tiên bắt đầu ở byte 56. Các file attributes kết thúc tại byte 504 với kết thúc của file marker 0xffff ffff. Phần còn lại của attribute entry là các số 0.

Nếu bạn muốn view bất cứ MFT entry nào với TSK, bạn có thể sử dụng dd cùng với icat để bỏ qua phần đầu tới vị trí chính xác cần tới. Bạn có thể làm điều đó thông qua việc thiết lập block size bằng 1024, là kích thước của MFT entry. Ví dụ, để nhìn entry 1234 bạn có thể sử dụng
# icat -f ntfs ntfs1.dd 0 | dd bs = 1024 skip 1234 count = 1 | xxd

Attribute Header
Một MFT entry được fill với các attributes, và mỗi attribute có cùng một cấu trúc dữ liệu header, chúng ta sẽ phân tích ngay sau đây. Ta cần nhắc lại một chút ở đây, Hình 13.2 hiển thị một diagram của một file thông thường và các vị trí header. Cấu trúc dữ liệu là khác nhau rõ ràng giữa resident và non-resident attributes bởi vì các non-resident attributes cần lưu run information.
16 bytes đầu tiên là như nhau trong cả resident và non-resident và chứa các fields được đưa ra trong Bảng 13.2.
Các gía trị này cho ta những thông tin cơ bản về attribute, bao gồm kiểu của nó, kích cỡ, và vị trí name. Kích cỡ được sử dụng để tìm attribute tiếp theo trong MFT entry, và nếu nó là attribute cuối cùng, 0xffff ffff sẽ tồn tại sau nó. Non-resident flag được set tới 1 khi attribute là non-resident. Giá trị flag nhận dạng nếu attribute bị nén (0x0001), hoặc bị mã hóa (0x4000), hoặc sparse (0x8000). Attribute identifier là một số mà duy nhất đối với thuộc tính đó trong MFT entry. Offset to the name là tương đối với bắt đầu của attribute. Một resident attribute có các fields được hiển thị trong Bảng 13.3
Các giá trị này đơn giản đưa ra kích cỡ và vị trí (tương đối so với bắt đầu của attribute) của attribute content, còn được gọi là một stream. Nào hãy cùng nhìn vào một ví dụ. Khi chúng ta dissect MFT entry ở phía trước, chúng ta đã thấy rằng các attributes bắt đầu ở byte 56. Chúng ta lấy attribute từ đó và reset các số offset bên output  vì vậy các attribute header offsets có thể dễ dàng được xác định.

0000000: 1000 0000 6000 0000 0000 1800 0000 0000  ....`...........
0000016: 4800 0000 1800 0000 305a 7a1f f63b c301  H.......0Zz..;..

Output cho ta thấy rằng attribute type trong 4 bytes đầu tiên là là 16 (0x10), đây là giá trị dành cho $STANDARD_INFORMATION. Các bytes 4 tới 7 cho ta thấy nó có một kích thước là 96 bytes (0x60). Byte 8 cho ta thấy đây là một resident attribute (0x00) và byte 9 cho ta thấy rằng nó không có một name (0x00). Các flags và id values được set tới 0 trong các bytes 12 tới 13 và 14 tới 15 . Các bytes từ 16 tới 19 cho ta thấy rằng attribute này có kích thước là 72 bytes (0x48), và các bytes 20 và 21 cho ta thấy rằng nó bắt đầu 24 bytes (0x18) từ bắt đầu của attribute. Kiểm tra lại ta thấy rằng 24 byte offset và chiều dài 72 bytes của attribute bằng tổng cộng 96 bytes, đây là con số đã được báo cáo trong header.

Non-resident attributes có một cấu trúc dữ liệu khác bởi vì chúng cần có thể mô tả một số tùy ý của các cluster runs. Thuộc tính có các fields có thể thấy trong Bảng 13.4
Nhắc lại rằng VCN là một tên khác của các logical file addresses. Các số VCN bắt đầu và kết thúc được sử dụng khi nhiều MFT entries được cần tới để mô tả một single attribute. Ví dụ, nếu một $DATA attribute bị phân mảnh quá nặng và các runs của nó không thể fit bên trong một single MFT entry, nó có thể cấp phát một MFT entry thứ 2. Entry thứ 2 này có thể chứa một $DATA attribute với một starting VCN bằng với VCN sau ending VCN trên entry đầu tiên. Bạn sẽ nhìn thấy một ví dụ của điều này trong "$ATTRIBUTE_LIST" section.
Offset to the data runlist được đưa ra tương đối so với bắt đầu của attribute. Định dạng của một runlist là rất hiệu quả và khá dễ gây nhầm lẫn. Nó có một chiều dài thay đổi, nhưng nó phải có ít nhất một byte. Byte đầu tiên của cấu trúc dữ liệu được tổ chức thành 4 bits cao và 4 bits thấp (còn được biết đến như là các nibbles). Các bits ít quan trọng nhất chứa số bytes trong run length field, mà theo sau header byte. 4 bits quan trọng nhất chứa số bytes trong run offset field. Bạn có thể thấy một ví dụ trong Hình 13.3. Byte đầu tiên cho ta thấy rằng run length field là 1 byte và run offset là 2 bytes.

Các giá trị này là trong các cluster-sized units, và offset field là một giá trị có dấu (signed value) mà tương đối offset trước đó. Ví dụ, offset của run đầu tiên trong attribute sẽ tương đối với bắt đầu của file system, và run offset thứ 2 sẽ tương đối với offset trước đó. Một số âm sẽ có bit quan trọng nhất được set tới 1, và nếu bạn dự định plug giá trị này vào trong một calculator để convert giá trị , bạn phải add nhiều giá trị 1như cần thiết để tạo ra số 32 hay là 64 bit đầy đủ. Ví dụ, nếu giá trị là 0xf1, bạn cần enter 0xfffffff1 trong một converter.

Nhìn vào một non-resident attribute, chúng ta quay trở lại entry chúng ta phân tích trước đó và tiến tới để nhìn vào $DATA attribute. Attribute content được hiển thị ở đây, và các giá trị offset là tương đối so với bắt đầu của attribute:

0000000: 8000 0000 6000 0000 0100 4000 0000  0100 ....`.....@.....
0000016: 0000 0000 0000 0000 ef20 0000 0000 0000  ......... ......
0000032: 4000 0000 0000 0000 00c0 8300 0000 0000  @...............
0000048: 00c0 8300 0000 0000 00c0 8300 0000 0000  ................
0000064: 32c0 1eb5 3a05 2170 1b1f 2290 015f 7e31  2...:.!p..".._~1
0000080: 2076 ed00 2110 8700 00b0 6e82 4844 7e82  v..!.....n.HD~.

4 bytes đầu tiên cho ta thấy rằng attribute có kiểu 128 (0x80), và tập hợp 4 bytes thứ 2 cho ta thấy tổng kích cỡ của nó là 96 bytes (0x60). Byte 8 là 1, điều này cho ta thấy đó là một non-resident attribute, và byte 9 là 0, điều này cho ta thấy độ dài của attribute name là 0, và do đó đó là $DATA attribute mặc định và không phải là một ADS. Các flags trong các bytes 12 và 13 là 0, điều này có nghĩa là attribute không bị nén hoặc bị mã hóa.

Non-resident information bắt đầu ở byte 16, và các bytes từ 16 tới 23 cho ta thấy starting VCN cho tập hợp các runs là 0. Ending VCN cho tập hợp các runs này là trong các bytes 24 tới 31, và chúng được set tới 8431(0x20ef). Các bytes 22 tới 23 cho ta thấy offset của runlist tính là 64 bytes (0x0040) từ bắt đầu. Các bytes từ 40 tới 47, từ 48 đến 55, và 56 đến 64 là cho lượng không gian được cấp phát, lượng không gian thực sự, và lượng không gian được khởi tạo, và tất cả chúng được set tới cùng một giá trị là 8,634,368 (0x0083c000) bytes.

Tại byte 64, chúng ta cuối cùng cũng đã có được runlist. Tôi sẽ sao chép output một lần nữa:
 0000064: 32c0 1eb5 3a05 2170 1b1f

Nhắc lại rằng byte đầu tiên trong run được tổ chức thành các nibbles, điều này cho ta thấy độ lớn của các trường khác là bao nhiêu. 4 bits thấp của byte 64 cho ta thấy có 2 bytes trong field dành cho run length và 4 bits cao cho ta thấy có 3 bytes trong offset field. Để xác định độ dài của run, chúng ta phân tích các bytes 65 tới 66, cho ta giá trị 7,872 clusters (0x1ec0). 3 bytes tiếp theo, các bytes từ 67 tới 69, được sử dụng cho offset, cho ta giá trị là cluster 342,709 (0x053ab5). Do đó run đầu tiên bắt đầu tại cluster 342,709 và mở rộng cho 7,872 clusters.

Data structure cho run tiếp theo bắt đầu sau run phía trước, đó là byte 70. Ở đó bạn có thể thấy length field là 1 byte và offset field là 2 bytes. Length value là ở trong byte 71, đó là 112(0x70). Offset value là ở trong các bytes 72 tới 73, đó là 7,963 (0x1f1b). Offset được đánh dấu và tương đối so với offset trước đó, vì vậy chúng ta cộng 7,963 với 342,709 và có được 350,672. Do đó, run thứ 2 bắt đầu tại cluster 350,672 và mở rộng ra 112 clusters.

Standard File Attributes
Trong phần trước chúng ta đã nêu ra cách chúng ta đã nêu ra cách process một MFT entry và các attribute headers. Mỗi attribute header trỏ tới một vị trí resident hoặc non-resident ở đó attribute content có thể được tìm thấy. Phần này mô tả cách chúng ta process mỗi kiểu attribute content khác nhau.

$STANDARD_INFORMATION attribute
$STANDARD_INFORMATION attribute, có type identifier là 16, luôn luôn là resident và chứa các metadata cơ bản cho một file hoặc directory. Nó tồn tại trong mọi file và directory và nó thường là attribute đầu tiên bởi vì nó có type identifier nhỏ nhất. Nó có các (non-essential) fields được đưa ra trong Bảng 13.5
4 giá trị thời gian được lưu như số một trăm nano giây từ ngày 1, 1, 1601 UTC. Các trường thời gian giống như vậy còn tồn tại trong $FILE_NAME attribute, nhưng những giá trị thời gian trong $STANDARD_INFORMATION được Windows hiển thị khi view các properties của file, và những fields này được cập nhật. Các giá trị ID được sử dụng hoặc cho các features mức ứng dụng hoặc security. Security ID value là index tới $Secure file, không phải là Windows SID value. Các flag values được đưa ra trong Bảng 13.6
Nhiều flags giống như ta đã thấy trong FAT, và một description cảu chúng có thể đươc tìm thấy ở đó. Các flags cho các attributes được mã hóa và sparse cũng được đưa ra trong các attribute headers, vì vậy chúng ta có thể xem xét nó là không essential trong vị trí này. Điều đó có thể đáng tranh cãi, bởi vì một người khác có thể claim rằng flag này là essential và các MFT entry header không essential.

Nào chúng ta hãy cùng nhìn vào một $STANDARD_INFORMATION attribute. Chúng ta có thể view attribute này sử dụng icat và chỉ định attribute type. Điều này loại bỏ loại bỏ standard header cho chúng ta một cách tự động và đưa cho chúng ta chỉ content. Các contents của attribute cho $MFT file là

# icat -f ntfs ntfs1.dd 0-16 | xxd
0000000: 305a 7a1f f63b c301 305a 7a1f f63b c301 0Zz..;..0Zz..;..
0000016: 305a 7a1f f63b c301 305a 7a1f f63b c301 0Zz..;..0Zz..;..
0000032: 0600 0000 0000 0000 0000 0000 0000 0000 ................
0000048: 0000 0000 0001 0000 0000 0000 0000 0000 ................
0000064: 0000 0000 0000 0000                     ........

8 bytes đầu tiên cho ta thấy creation time, và giá trị này là giống nhau cho cả 4 fields thời gian. Các bytes 32 tới 35 cho ta flag value, những gì là 0x00000060, và bao gồm các bits cho hidden và system, những gì được mong đợi cho một file system metadata file. Các bytes từ 36 tới 39 và từ 40 tới 43 cho ta biết rằng các file versions không được sử dụng, và từ 44 tới 47 cho chúng ta thấy rằng class ID là 0. Owner ID trong các bytes từ 48 tới 51 là 0, và security ID trong các bytes từ 52 tới 55 là 1. Phần còn lại của các giá trị là 0, điều này không có gì là ngạc nhiên cho $MFT bởi vì nó không thường được áp dụng tới bất cứ user quota nào, và hầu hết các hệ thong không có change journaling, vì vậy USN có thể không được gán.

$FILE_NAME Attribute
$FILE_NAME attribute, có một type identifier là 48, và được sử dụng cho 2 mục đích. Và nó được đặt trong một MFT entry để lưu tên của file và thông tin của thư mục cha, và nó được sử dụng trong một directory index. Khi nó được sử dụng trong một MFT entry, nó không chứa bất cứ essential information nào, nhưng nó có chứa khi nó được sử dụng trong một directory index.

Đối với standard file hoặc directory, nó sẽ là attribute thứ 2 và thường xuyên là resident. Nếu một file yêu cầu nhiều MFT entries, $ATTRIBUTE_LIST attribute sẽ xuất hiện giữa $STANDARD_INFORMATION và attribute này. $FILE_NAME attribute có các fields được đưa ra trong Bảng 13.7
3 name fields cuối cùng là essential khi attribute này được sử dụng trong directory index, nhưng không essential khi nó được sử dụng trong MFT entry cho một file. Flag field sử dụng cùng các giá trị như $STANDARD_INFORMATION, và chúng được liệt kê phía trước.

Namespace byte nhận dạng những rules gì mà name phải tuân theo. Các giá trị của nó được đưa ra trong Bảng 13.8




Để view một $FILE_NAME attribute, chúng ta nhìn vào $MFT một lần nữa và chỉ định type 48:

# icat -f ntfs ntfs1.dd 0-48 | xxd
0000000: 0500 0000 0000 0500 305a 7a1f f63b c301 ........0Zz..;..
0000016: 305a 7a1f f63b c301 305a 7a1f f63b c301 0Zz..;..0Zz..;..
0000032: 305a 7a1f f63b c301 0040 0000 0000 0000 0Zz..;...@......
0000048: 0040 0000 0000 0000 0600 0000 0000 0000 .@..............
0000064: 0403 2400 4d00 4600 5400                ..$.M.F.T.

8 bytes đầu là dành cho mồ file reference, vì vậy 2 bytes cao là sequence number và 6 bytes thấp là MFT entry. Do đó, parent directory là MFT entry 5, và sequence number là 5, là entry cho root directory. 8 bytes tiếp theo là dành cho creation time và cùng một giá trị cho 3 giá trị times còn lại trong attribute.

Các bytes 40 tới 47 và 48 tới 55 cho ta thấy kích thước được cấp phát và kích cỡ thực sự của file. Cả 2 giá trị này đều được set tới 16,384 bytes (0x4000). Trong thực tế, $DATA attribute cho file này là 8,634,368 bytes, vì vậy nó rõ rang là không chính xác. Nhiều files có các kích thước được set tới 0, nhưng nó lại chính xác khi attribute này được sử dụng trong một directory index.

Các flag values tại các bytes 56 và 57 được set tới 0x0006, những gì là hidden và system flags. Các flags này là giống như các flags ta đã thấy trong $STANDARD_INFORMATION. Byte 64 cho ta thấy name có độ dài 4 từ, và byte 65 cho ta thấy được nó nằm trong name space 3, những gì tuân thủ cho cả DOS và Win32. Name là trong UTF-16 Unicode và có thể nhìn thấy bắt đầu trong byte 66. Name là $MFT.

Như một ví dụ cuối cùng, xét một file với 2 $FILE_NAME attributes bởi vì Windows yêu cầu rằng một DOS name tồn tại. File này có các attributes cho cả DOS name space và Win32 name space. Chúng tôi sẽ không dissect chi tiết, nhưng output được show ở đây:

# icat -f ntfs ntfs1.dd 5009-48-2 | xxd
0000000: 3920 0000 0000 0300 00b6 89a9 086a c401  9 ...........j..
0000016: 00b6 89a9 086a c401 00b6 89a9 086a c401  .....j.......j..
0000032: 00b6 89a9 086a c401 0000 0000 0000 0000  .....j..........
0000048: 0000 0000 0000 0000 2020 0000 0000 0000  ........ ......
0000064: 0b01 3500 3700 3300 3900 3800 3400 3000  ..5.7.3.9.8.4.0.
0000080: 3800 6400 3000 3100                      8.d.0.1.

Chú ý rằng byte 65 hiển thị name space như 1, là Win32. Name trong entry này là "57398408d01." Bây giờ, chúng ta nhìn vào $FILE_NAME attribute tiếp theo, attribute có type identifier giống như vậy 48, nhưng attribute identifier là 3

# icat -f ntfs ntfs1.dd 5009-48-3 | xxd
0000000: 3920 0000 0000 0300 00b6 89a9 086a c401  9 ...........j..
0000016: 00b6 89a9 086a c401 00b6 89a9 086a c401  .....j.......j..
0000032: 00b6 89a9 086a c401 0000 0000 0000 0000  .....j..........
0000048: 0000 0000 0000 0000 2020 0000 0000 0000  ........ ......
0000064: 0802 3500 3700 3300 3900 3800 3400 7e00  ..5.7.3.9.8.4.~.
0000080: 3100      

Attribute này có một name space trong byte 65 là 2, là giá trị cho DOS. Name trong entry này là "573984~1.".

$DATA Attribute
$DATA attribute là đơn giản để hiểu bởi vì nó không có native structure. Sau header, chỉ có raw content mà tương ứng với các contents của một file. Nó có một type identifier là 128 và không có các kích cỡ nhỏ nhất hay lớn nhất. Nếu content vượt qua 700 bytes, nó sẽ có thể là một non-resident attribute. Đối với hầu hết các files, đó là attribute cuối cùng trong MFT entry. Chú ý rằng các directories có thể có các $DATA attributes ngoài các index attributes của chúng.

$ATTRIBUTE_LIST Attribute
Một $ATTRIBUTE_LIST attribute tồn tại trong một MFT entry để hiển thị nơi các attributes khác có thể được locate. Nó được sử dung cho các files mà có các attribute headers mà sẽ không fit trong một MFT entry và chứa một list với một entry cho mọi attribute trong file hay thư mục này. Attribute này một type identifier 32 và mỗi list entry có các fields trong Bảng 13.9.
Starting VCN value được sử dung khi nhiều MFT entries được cần tới để mô tả một single attribute. Khi điều đó xảy ra, các entries sẽ có non-zero starting VCN values. Attribute header này còn nên hiểu thị nó là một non-zero starting VCN.

Nào chúng ta cùng nhìn vào một file với một $ATTRIBUTE_LIST attribute.
4 bytes đầu tiên cho ta thấy kiểu của entry đầu tiên, giá trị là 16 (0x10) và do đó là $STANDARD_INFORMATION attribute. Các bytes từ 4 tới 5 cho ta thấy độ dài của entry list này là 32 bytes (0x0020) và các bytes từ 16 tới 21 cho ta thấy rằng attribute này được located trong MFT entry 5,009 (0x1391), là attribute mà chúng ta hiện đang xét.

2 bytes tiếp theo tại các bytes 32 và 64 là dành cho các $FILE_NAME attributes, attribute mà có một type identifier là 48 (0x30). Cả 2 attributes này đều được đặt trong MFT entry hiện hành.

Byte 96 là nơi mà entry đầu tiên cho $DATA attribute bắt đầu. Các bytes từ 104 đến 111 cho ta thấy $DATA attribute này có VCN bằng 0, và các bytes từ 112 tới 117 cho ta thấy rằng attribute này được đặt trong MFT entry 4,919 (0x1337). Entry thứ 2 cho $DATA attribute bắt đầu tại byte 128. Chúng ta có thể nói rằng chúng là bộ phận của cùng $DATA attribute bởi vì ID value trong cả 2 cấu trúc dữ liệu đều bằng 0. Các bytes từ 136 tới 143 cho chúng ta thấy rằng entry thứ 2 có một starting VCN là 5,152 (0x1420). Hay nói cách khác, $DATA attribute trong entry đầu tiên để không gian trong MFT entry để mô tả 5,152 entry đầu tiên. Phần còn lại của các cluster runs được lưu trong một $DATA attribute trong MFT entry 5,037 (0x13ad), như ta có thể thấy trong các bytes từ 144 tới 149.

Hình 13.4 cho chúng ta một tổng kết của file này. Nó có một $STANDARD_INFORMATION và 2 $FILE_NAME attributes trong base MFT entry 5,009, và các headers cho $DATA attributed được đặt tại các entries 4,919 và 5,037.
Các non-base MFT entries sẽ không có standard $FILE_NAME và $STANDARD_INFORMATION attributes. Chúng ta có thể xác minh điều này thông qua việc nhìn vào một trong các entries trong ví dụ này. Output khi running istat đối với non-base entry 4919 là như sau:

# istat –f ntfs ntfs1.dd 4919
MFT Entry Header Values:
Entry: 4919        Sequence: 18
Base File Record: 5009
$LogFile Sequence Number: 66117460
Allocated File
Links: 0
[REMOVED]
Attributes:
Type: $DATA (128-0)   Name: $Data Non-Resident size: 5787792
929409 929410 929411 929412 929413 929414 929415 929416
[REMOVED]

MFT entry này chỉ có một $DATA attribute, và chúng ta có thể thấy rằng header hiển thị base record là entry 5,009. Link count là 0 bởi vì không có names nào trỏ tới nó.

$OBJECT_ID Attribute
$OBJECT_ID Attribute có một type identifier là 64 và lưu một 128-bit global object identifier của file mà có thể được sử dụng để address file thay vì name của nó. Nó cho phép một file được tìm thấy thậm chí khi name của nó được thay đổi. \$Extend\$Object index được sắp xếp bởi các object IDs của cac files và chứa file reference address nơi mỗi file có thể được tìm thấy. Attribute này chỉ có 4 fields, và thông thường chỉ field đầu tiên được định nghĩa. Các fields có thể được tìm thấy trong Bảng 13.10.

Nhiều files mà có một object ID được gán có chỉ giá trị đầu tiên, kích cỡ attribute là 16 bytes. $Volume file thường xuyên chứa $OBJECT_ID attribute, và nó được biết tới ở đây:

# icat -f ntfs img.dd 3-64 | xxd
0000000: fe24 b024 e292 fe47 95ac e507 4bf5 6782  .$.$...G....K.g.

$REPARSE_POINT Attribute
$REPARSE_POINT attribute có một attribute identifier là 192, và nó được sử dụng cho các files mà là các reparse points. Microsoft định nghĩa một vài $REPARSE_POINT attribute contents, nhưng các ứng dụng chỉ định cũng có thể phát triển các contents này. Con contents của một junction và mount point có cấu trúc như trong Bảng 13.11

Table 13.11. Data structure for the junction and mount point $REPARSE_POINT attributes.
Byte Range  Description  Essential
0–3  Reparse type flags  Yes
4–5  Size of reparse data  Yes
6–7  Unused No
8–9  Offset to target name (relative to byte 16)  Yes
10–11  Length of target name  Yes
12–13  Offset to print name of target (relative to byte 16)  Yes
14–15  Length of print name  Yes

Các type flags cho một junction hoặc mount point sẽ có 0xa0000000 flat được set. Ở đây bạn thấy một reparse point mà liên kết tới c:\windows:

# icat -f ntfs ntfs2.dd 167-192 | xxd
0000000: 0300 00a0 2800 0000 0000 1c00 1e00 0000  ....(...........
0000016: 5c00 3f00 3f00 5c00 6300 3a00 5c00 7700  \.?.?.\.c.:.\.w.
0000032: 6900 6e00 6400 6f00 7700 7300 0000 1200  i.n.d.o.w.s.....

Các byte 8 tới 9 cho ta thấy rằng offset tới target name là 0 bytes, vì vậy nó bắt đầu tại byte 16. Độ dài của nó được đưa ra trong các bytes 10 tới 11, và chúng ta có thể thấy rằng nó có chiều dài là 28 bytes. Trong Unicode name của target như là "\??\c:\windows."


Index Attributes and Data Structures
Trong những phần trước chúng ta đã đề cập tới các attributes và concepts áp dụng tới tất cả các files. Phần này tập trung vào các cấu trúc dữ liệu và các attributes mà chỉ định cho các indexes. Nhắc lại những cocept cơ bản đằng sau các indexes là đó là một cấu trúc dữ liệu mà ở trong một tree được sắp xếp. Tree có một hay nhiều nodes, và mỗi node có một hay nhiều index entries. Root của tree được locate trong $INDEX_ROOT attribute, và các nodes khác được locate trong các index records trong $INDEX_ALLOCATION attribute. $BITMAP attribute được sử dụng để quản lý allocation status của các index records.

Trong phần này, chúng ta đi từ phía bên ngoài vào. Chúng ta sẽ bắt đầu với các attributes và sau đó mô tả các cấu trúc dữ liệu mà phổ biến tới chúng.

$INDEX_ROOT Attribute
$INDEX_ROOT attribute luôn luôn resident và có một type identifier là 144. Nó thường xuyên là root của index tree và có thể lưu một danh sách nhỏ các index entries. $INDEX_ROOT attribute có một 16-byte header, theo sau đó là node header và một danh sách của các index entries. Bạn có thể thấy trong Hình 13.5
$INDEX_ROOT header có các giá trị được đưa ra trong Bảng 13.12 và bắt đầu tại byte 0 của attribute content.
Cấu trúc dữ liệu này nhận dạng kiểu của attribute mà các index entries sẽ chứa , cách chúng được sắp xếp, và kích cỡ của mỗi index record trong $INDEX_ALLOCATION attribute. Các giá trị trong các bytes từ 8 tới 11 có đơn vị là bytes, và giá trị trong byte 12 hoặc là số lượng clusters hoặc là logarit của kích thước. Trong phần "$Boot File" mô tả phương thức encoding chi tiết hơn. Chú ý rằng kích thước của index record cũng được đưa ra trong boot sector.

Để nhìn vào các contents của một $INDEX_ROOT attribute, chúng ta sử dụng icat và cung cấp 144 type.

# icat -f ntfs ntfs1.dd 7774-144 | xxd
0000000: 3000 0000 0100 0000 0010 0000 0400 0000 0...............
0000016: 1000 0000 a000 0000 a000 0000 0100 0000 ................
[REMOVED]

Các bytes từ 0 tới 3 cho chúng ta thấy rằng attribute trong index là cho attribute type 48 (0x30), đây là giá trị cho $FILE_NAME attribute, và các bytes từ 8 tới 11 cho ta thấy được mỗi index record là 4,096 bytes.

$INDEX_ALLOCATION Attribute
Các directories lớn không thể fit tất cả các index entries của chúng trong resident $INDEX_ROOT attribute, vì vậy chúng cần một non-resident $INDEX_ALLOCATION attribute. $INDEX_ALLOCATION attribute được fill với các index records. Một index record có một kích thước tĩnh và chứa một node trong sorted tree. Index record size được định nghĩa trong $INDEX-ROOT attribute header và trong cả boot sector nữa, nhưng kích thước thông thường của nó là 4,096 bytes. $INDEX_ALLOCATION attribute có type identifier là 160 và không nên tồn tại mà không có $INDEX_ROOT attribute.

Mỗi index record bắt đầu với một cấu trúc dữ liệu header đặc biệt và một danh sách các index entries. Node header và các index entries thì có cùng các cấu trúc dữ liệu và được sử dụng trong $INDEX_ROOT attribute. Index record đầu tiên bắt đầu tại byte 0 của attribute. Bạn có thể thấy trong Hình 13.6, có 2 index records trong $INDEX_ALLOCATION attribute.

Index record header có các giá trị được đưa ra trong Bảng 13.13

4 trường đầu gần như giống nhau đối với tất cả các fields cho một MFT entry, nhưng signature là khác biệt.

VCN value trong các bytes từ 16 tới 23 nhận diện nơi record này fit trong tree. $INDEX_ALLOCATION attribute được fill với các index records, những records này có thể không đúng như thứ tự.

VCN value trong header nhận dạng nơi index record này fit vào trong buffer lớn hơn. Khi một index entry trỏ tới child node của nó, nó sử dụng VCN address trong index record header của nó.

Nào hãy cùng nhìn vào các contents của $INDEX_ALLOCATION attribute từ cùng một directory sở hữu $INDEX_ROOT attribute được phân tích:

# icat –f ntfs ntfs1.dd 7774-160 | xxd
0000000: 494e 4458 2800 0900 4760 2103 0000 0000  INDX(...G`!.....
0000016: 0000 0000 0000 0000 2800 0000 f808 0000  ........(.......
[REMOVED]

Bạn có thể thấy signature value "INDX" ở dòng đầu tiên, và các bytes 4 và 5 và 6 tới 7 hiển thị các giá trị fixup record. Các bytes từ 16 tới 23 cho ta thấy index record này là VCN 0 buffer. Node header bắt đầu tại byte 24. $INDEX_ALLOCATION attribute có kích cỡ 8,192 bytes, vì vậy có room cho index record khác. Nó bắt đầu tại byte 4096:

[REMOVED]
0004096: 494e 4458 2800 0900 ed5d 2103 0000 0000  INDX(....]!.....
0004112: 0400 0000 0000 0000 2800 0000 6807 0000  ........(...h...
0004128: e80f 0000 0000 0000 3b00 0500 6900 c401  ........;...i...
[REMOVED]

Bạn nhìn thấy "INDX" signature và các bytes 4,112 tới 4,119 cho ta thấy đó là VCN 4 (mỗi cluster trong file system này có kích cỡ 1024 bytes ). Chúng tôi sẽ quay trở lại ví dụ này sau khi thảo luận về node header và các index entries.

$BITMAP Attribute
Trong phần trước, chúng ta đã thấy một $INDEX_ALLOCATION attribute với 2 index records độ dài 4096 byte. Có thể là một vài index records là không in use. $BITMAP attribute được sử dụng để keep track những index records nào trong $INDEX_ALLOCATION attribute được cấp phát tới một index record. Thông thường, Windows cấp phát các index records chỉ khi cần thiết, nhưng một directory có thể chứa các records không được cần tới sau khi xóa đi nhiều files hoặc bởi vì mỗi cluster là lớn hơn một index record. Chú ý rằng thuộc tính này đã được sử dụng bởi $MFT để keep track những MFT entries nào được cấp phát.

$BITMAP attribute có một type identifier là 176 và được tổ chức bởi các bytes, và mỗi bit tương ứng tới một index record. Chúng ta có thê view $BITMAP attribute từ directory trước đó thong qua sử dụng icat:

# icat -f ntfs ntfs1.dd 7774-176 | xxd
0000000: 0300 0000 0000 0000   

Chúng ta có thể nhìn thấy 0x03 ở byte 0, ở dạng binary thì là 0000 0011. Do đó, các index records 0 và 1 được cấp phát.

Index Node Header Data Structure
Chúng ta đã nhìn thấy các $INDEX_ROOT và $INDEX_ALLOCATION attributes, và chúng có một vài header data được theo sau bởi node header và một danh sách các index entries. Trong phần này, chúng ta mô tả cấu trúc dữ liệu node header. Header này xuất hiện trong $INDEX_ROOT và trong mỗi cấu trúc dữ liệu index record và được sử dụng để hiển thị nơi danh sách index entries bắt đầu và kết thúc. Header này có các fields được đưa ra trong Bảng 13.14
Các index entries cho một $INDEX_ROOT node sẽ bắt đầu ngay lập tức sau node header, nhưng các index entries trong một index buffer có thể không bởi vì các fixup values. Khi chúng ta đang nhìn vào các dữ liệu còn sót lại từ các index entries bị xóa, chúng ta sẽ phân tích dữ liệu cuối phần được sử dụng của buffer và cuối của buffer được cấp phát.

Trường Flags chỉ có một flag, và 0x01 flag được set khi có các children nodes mà được trỏ tới bởi các entries trong list này. Cùng flag này tồn tại trong mỗi index entry.

Nào hãy cùng nhìn vào các attributes phía trước chúng ta đã dissect. $INDEX_ROOT attribute có các dữ liệu sau:

# icat -f ntfs ntfs1.dd 7774-144 | xxd
0000000: 3000 0000 0100 0000 0010 0000 0400 0000  0...............
0000016: 1000 0000 a000 0000 a000 0000 0100 0000  ................
[REMOVED]

Node header bắt đầu tại byte 16, và các bytes từ 16 tới 19 cho chúng ta thấy rằng list bắt đầu cách node header 16 bytes, tức là byte thứ 32, và kết thúc cách node header 160 bytes (0xa0), tức là byte 176. Trong trường hợp này, không gian được cấp phát và không gian được sử dụng là giống nhau bởi vì chúng là từ một $INDEX_ROOT attribute, mà attribute này là resident và phải là nhỏ nhất có thể. Byte 28 có một 0x01 flag set, vì vậy có những children nodes tới node này (những node này được đặt trong $INDEX_ALLOCATION ).

Nào hãy cùng nhìn vào $INDEX_ALLOCATION attribute một lần nữa:

# icat –f ntfs ntfs1.dd 7774-160 | xxd
0000000: 494e 4458 2800 0900 4760 2103 0000 0000  INDX(...G`!.....
0000016: 0000 0000 0000 0000 2800 0000 f808 0000  ........(.......
0000032: e80f 0000 0000 0000 2100 0000 0600 0000  ........!.......
[REMOVED]

24 bytes đầu tiên là cho index record header, và node header bắt đầu sau đó. Các bytes từ 24 tới 27 cho ta thấy rằng index entry list bắt đầu tại byte offset 40 (0x28). Chú ý rằng đó là tương đối so với bắt đầu của node header, và chúng ta cần cộng them 24 tới nó, giá trị ta thu được là 64. Đó là trường hợp mà ở đó index entry list không ngay theo ngay sau index entry list header bởi vì fixup record array nằm giữa index entry list header và list thực sự. Nhắc lại rằng các bytes từ 4 tới 5 của index record header cho ta thấy rằng fixup array phải được đặt tại offset 40 (0x28).

Các bytes từ 28 tới 31 cho ta thấy rằng offset tới cuối của list entry cuối cùng (0x08f8), và các bytes từ 32 tới 35 cho ta thấy rằng offset tới cuối của list buffer được cấp phát là 4,072 bytes. Do đó, có 1,776 bytes là của unused space trong buffer mà chứa dữ liệu từ các files với các names được lưu trong những node entries này. Các bytes từ 36 tới 39 cho ta thấy flag value là 0, vì vậy không có các children nodes tới node này.

Generic Index Entry Data Structure

Chúng ta đã thảo luận các khái niệm chung chung của các NTFS indexes, vì chỉ một điều còn thiếu đó là thảo luận và các index entries. Từ thời điểm này, các cấu trúc dữ liệu sẽ là cụ thể tới kiểu của index, nhưng có một cấu trúc chung áp dụng tới tất cả cấu trúc dữ liệu index entry, những gì chúng ta sẽ thảo luận trong phần này.

Các standard fields cho một index entry được đưa ra trong Bảng 13.15.

8 bytes đầu được sử dụng để lưu dữ liệu mà cụ thể tới index entry. Các bytes từ 8 tới 9 định nghĩa kích thước của index entry lớn như thế nào, và 10 tới 11 cho chúng ta kích thước của index entry content, những gì bắt đầu từ byte 16. Content có thể là bất cứ dữ liệu nào. Trường flag có các giá trị được đưa ra trong Bảng 13.16
Khi một index entry có một child node, 0x01 flag sẽ được set, và VCN address của child node này sẽ được tìm thấy trong index entry này. Nhắc lại rằng mỗi index record có một VCN. 0x02 flag được set khi đó là entry cuối cùng trong list.

Directory Index Entry Data Structure
Một directory index, những gì được sử dụng cho các file names, có một cấu trúc dữ liệu index entry riêng biệt. Nó sử dụng một basic template, như đã được nêu ra trong phần trước, và bao gồm một file reference address và một $FILE_NAME attribute. Mỗi index entry có các fields được đưa ra trong Bảng 13.17
File reference value trỏ tới MFT entry tới những index entry tương ứng. 2 flag values áp dụng tới entry này, 0x01 nếu có một child node và 0x02 nếu đó là entry cuối cùng trong list.

Nào chúng ta hãy cùng nhìn vào phần còn lại của $INDEX_ROOT và $INDEX_ALLOCATION attributes mà chúng ta đã thảo luận một phần trước đó. Các contents của $INDEX_ROOT attribute được hiển thị ở đây:

# icat -f ntfs ntfs1.dd 7774-144 | xxd
0000000: 3000 0000 0100 0000 0010 0000 0400 0000 0...............
0000016: 1000 0000 a000 0000 a000 0000 0100 0000  ................
0000032: c51e 0000 0000 0500 7800 5a00 0100 0000  ........x.Z.....
0000048: 5e1e 0000 0000 0300 e03d ca37 5029 c401  ^........=.7P)..
0000064: 004c c506 0202 c401 e09a 2a36 5029 c401  .L........*6P)..
0000080: d0e4 22b5 096a c401 0004 0000 0000 0000  .."..j..........
0000096: 7003 0000 0000 0000 2120 0000 0000 0000  p.......! ......
0000112: 0c02 4d00 4100 5300 5400 4500 5200 7e00  ..M.A.S.T.E.R.~.
0000128: 3100 2e00 5400 5800 5400 0000 0000 0300  1...T.X.T.......
0000144: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000160: 1800 0000 0300 0000 0400 0000 0000 0000  ................
[REMOVED]

Chúng ta đã process 32 bytes đầu tiên bởi vì 16 bytes đầu là $INDEX_ROOT header, và 16 bytes thứ hai là node header. Các bytes từ 32 từ 37 entry này là cho MFT entry 7,877 (0x1ec5). Các bytes từ 40 tới 45 cho ta thấy kích thước của index entry là 120 bytes (0x78), và nó sẽ kết thúc tại byte 152 trong output của chúng ta. Các bytes 26 tới 27 cho ta thấy kích cỡ của attribute này là 90 bytes (0x5a). Flag tại byte 28 cho ta thấy có một child node sở hữu địa chỉ được đưa ra trong 8 bytes cuối cùng entry, những gì chúng ta mong đợi bởi vì flag trong node header cho ta thấy có một child.

$FILE_NAME attribute được đặt tại các bytes 48 tới 137 và các bytes từ 144 tới 151 là các bytes cuối cùng trong index entry và chứa VCN của child node, những gì là cluster 0. Chúng ta có thể nhìn thấy name "MASTER~1.TXT" như là name của file này. Các bytes 152 tới 175 chứa một empty index entry và flag tại byte 164 là 3, giá trị này cho thấy đó là cuối của list và nó chứa một child. Các bytes từ 168 đến 175 chứa địa chỉ của child node, giá trị VCN 4. Có 2 index records chúng ta thấy trong $INDEX_ALLOCATION attribute.


File System Metadata Files
Bây giờ chúng ta sẽ xem xét các file system metadata files. Hầu hết trong số các files này sử dụng các file attributes bình thường, nhưng cũng có những files có các attributes của riêng chúng. Các attributes này được mô tả trong các phần sau đây.

$MFT File
$MFT file được located trong MFT entry 0, file này rất quan trọng đối với mọi file trong file system. Nó có các standard attributes, và $DATA attribute là MFT.

Một unique attribute của MFT là một $BITMAP attribute, attribute này được sử dụng để quản lý allocation status của các MFT entries. Nó được tổ chức bởi các bytes, và khi một bit được set tới 1 entry này được cấp phát. Nếu không, khi bit có giá trị là 0 entry này không được cấp phát. Chúng ta có thể view $BITMAP attribute sử dụng icat và chỉ định attribute type là 176

# icat -f ntfs ntfs1.dd 0-176 | xxd
0000000: ffff 00ff ffff ffff ffff ffff ffff ffff ................
0000016: ffff ffff ffff ffff ffff ffff ffff ffff ................
[REMOVED]

Bạn có thể nhìn thấy ở đây hầu hết các bits được set tới 1 ngoại trừ trong byte 2. Byte này tương ứng với các MFT entries từ 16 tới 23.

$Boot File
$Boot file được located trong MFT entry 7 và chứa boot sector và boot code trong $DATA attribute của nó. Attribute này thường xuyên bắt đầu trong sector 0, và cấu trúc dữ liệu boot sector được located ở đó. Các sectors khác được sử dụng cho boot code. Boot sector có các fields được hiển thị trong Table 13.18.

Các fields mà không được sử dụng tương ứng với BIOS Parameter Block (BPB) fields trong FAT boot sector. Microsoft document nhận dạng một vài trong số chúng phải là 0 cho file system được mount, nhưng vẫn được xem xét như là các nonessential values bởi vì chúng là không cần thiết cho file system để function, Microsoft có thể quyết định không kiểm tra các giá trị. Tôi xác minh rằng Windows XP không mount disk này nếu các giá trị của nó là non-zero.

Các giá trị quan trọng khác trong boot sector là kích thước của mỗi sector và cluster. Nếu không có các giá trị này, chúng ta sẽ không thể nhận dạng được vị trí của bất cứ thứ gì. Giá trị quan trọng khác là vị trí bắt đầu của MFT và kích thước của mỗi MFT. Đến thời điểm này, các MFT entries thường xuyên có kích thước là 1,024 bytes, nhưng trường này tồn tại như vậy kích thước này có thể dễ dàng thay đổi trong tương lai. Một chú ý nữa là địa chỉ của $DATA attribute của $MFTMirr được đưa ra. Nó cho phép một recover tool xác định backup copy của MFT entry này nằm ở đâu vì vậy vị trí của MFT có thể được xác định.

Các fields mà hiển thị các kích thước của MFT entry và index record có một format đặc biêt. Nếu giá trị này lớn hơn 0, nếu biểu diễn số lượng clusters được sử dụng cho mỗi cấu trúc dữ liệu. Nếu giá trị này nhỏ hơn 0, nó biểu diễn logarit cơ số 2 của số lượng bytes trong mỗi cấu trúc dữ liệu. Để tính toán số lượng bytes, lấy giá trị tuyệt đối của số âm và lấy gía trị cơ số 2 vơí số mũ là giá trị vừa tính được. Ví dụ, nếu giá trị là -10, kích thước của cấu trúc dữ liệu là 2^10 = 1024 bytes. Điều này xảy ra khi kích thước của một cluster là lớn hơn một single MFT entry hay index record.

Nào hãy cùng dissect một boot sector. Chúng ta nhìn thấy istat output cho $Boot file, và chúng ta có thể sử dụng icat để view $DATA attribute (type 128).

# icat –f ntfs ntfs1.dd 7-128 | xxd
0000000: eb52 904e 5446 5320 2020 2000 0202 0000  .R.NTFS    .....
0000016: 0000 0000 00f8 0000 3f00 ff00 3f00 0000  ........?...?...
0000032: 0000 0000 8000 8000 4060 1f00 0000 0000  ........@`......
0000048: b53a 0500 0000 0000 10d8 0700 0000 0000  .:..............
0000064: 0100 0000 0400 0000 947c 2250 8422 5004  .........|"P."P.
0000080: 0000 0000 fa33 c08e d0bc 007c fbb8 c007  .....3.....|....
0000096: 8ed8 e816 00b8 000d 8ec0 33db c606 0e00  ..........3.....
[REMOVED]
0000448: 6d70 7265 7373 6564 000d 0a50 7265 7373  mpressed...Press
0000464: 2043 7472 6c2b 416c 742b 4465 6c20 746f   Ctrl+Alt+Del to
0000480: 2072 6573 7461 7274 0d0a 0000 0000 0000   restart........
0000496: 0000 0000 0000 0000 83a0 b3c9 0000 55aa  ..............U.
[REMOVED]

Trên dòng đầu tiên chúng ta thấy OEM name, là "NTFS,", theo sau bởi một vài ASCII spaces (0x20). Đó là standard name mà Windows gán cho. Các bytes 11 và 12 cho chúng ta số lượng bytes trong mỗi sector, đó là 512 (0x2000). Byte 13 cho chúng ta biết có 2 sectors trên cluster, vì vậy mỗi cluster là 1,024 bytes. Các bytes từ 40 tới 47 hiển thị tổng số lượng sectors trong file system 2,056,256 (0x001f6040), có nghĩa file system có kích thước là 1GB. Các bytes từ 48 tới 55 cho ta thấy cluster bắt đầu của $DATA attribute của MFT mirror là 514,064 (0x0007d810).

Byte 64 cho ta kích thước của mỗi MFT entry. Nhắc lại rằng encoding của giá trị này phụ thuộc vào nó là số âm hay số dương. Trong trường hợp này, nó là 1, vì vậy nó biểu diễn số lượng các clusters trong MFT entry, đó là 1024 bytes. Byte 68 là kích thước của mỗi index record, được sử dụng cho các directories. Giá trị này là 4, vì vậy có 4 clusters trên index record.

Các bytes từ 72 tới 79 cho ta serial number, giá trị đó là 0x04502284  50227C94. Phần còn lại của các bytes chứa boot code và các bytes 510 và 511 có 0xAA55 signature, giống như trong FAT.

$AttrDef File
$AttrDef file system metadata file là MFT entry number 4 và định nghĩa các file system attribute names và các identifiers. $DATA attribute cho file này chứa một danh sách các entries, mà có những fields được hiển thị trong Bảng 13.19

Table 13.19. Data structure for the $AttrDef entries.
Byte Range  Description  Essential
0–127  Name of attribute  Yes
128–131  Type identifier  Yes
132–135  Display rule  No
136–139  Collation rule  No
140–143  Flags (see Table 13.20)  Yes
144–151  Minimum size  No
152–159  Maximum size  No

Nếu attribute này không có bất kì các giới hạn kích thước nào, minimum size sẽ là 0, và maximum value sẽ là 0xffffffffffffffff. Flag field có các giá trị được hiển thị trong Hình 13.20

Table 13.20. Flag values for the $AttrDef entry flag field.
Value  Description
0x02  Attribute can be used in an index
0x04  Attribute is always resident
0x08  Attribute can be non-resident

Luật đối chiếu được sử dụng khi attribute là trong một index. Nó xác định cách nó nên được sắp xếp. $DATA attribute của $AttrDef file trong ví dụ của chúng ta có các contents sau:

# icat -f ntfs ntfs1.dd 4-128 | xxd
0000000: 2400 5300 5400 4100 4e00 4400 4100 5200  $.S.T.A.N.D.A.R.
0000016: 4400 5f00 4900 4e00 4600 4f00 5200 4d00  D._.I.N.F.O.R.M.
0000032: 4100 5400 4900 4f00 4e00 0000 0000 0000  A.T.I.O.N.......
0000048: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000064: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000096: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000112: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000128: 1000 0000 0000 0000 0000 0000 4000 0000  ............@...
0000144: 3000 0000 0000 0000 4800 0000 0000 0000  0.......H.......
[REMOVED]

Bạn có thể nhìn thấy định nghĩa attribute đầu tiên là dành cho $STANDARD_INFORMATION attribute. Tại các bytes từ 128 tới 131 chúng ta có thể thấy kiểu của identifier này là 16 (0x10). Các flags trong các bytes từ 140 tới 143 cho chúng ta thấy rằng entry này thường xuyên là resident. Các bytes từ 144 tới 151 cho ta biết rằng minimum size của attribute này là 48 bytes (0x30), và maximum size là 72 bytes (0x48).

$Bitmap File
$Bitmap file, file được located trong MFT entry 6, có một $DATA attribute mà được sử dụng để quản lý allocation status của các clusters. Bitmap data được tổ chức bên trong các giá trị 1-byte, bit ít quan trọng nhất của mỗi byte tương ứng với cluster mà theo sau cluster mà bit quan trọng nhất của byte phía trước tương ứng với.

Ví dụ, xét 2 bytes với các giá trị nhị phân 00000001 và 00000011. Byte đầu tiên có 1 là bit kém quan trọng nhất tương ứng với cluster 0. 7 bit tiếp theo (đi ngược từ phải sang trái) tất cả đều là 0, vì vậy chúng ta biết rằng các clusters từ 1 tới 7 không được cấp phát. Byte thứ 2 có 2 bit quan trọng nhất được set tới 1, những gì tương ứng với các clusters 8 và 9. Như bạn có thể thấy, bạn đọc nó thông qua việc nhìn vào bit kém quan trọng nhất, di chuyển ngược từ phải sang trái, và sau đó đi tới byte tiếp theo tới phía bên phải.

Để xác định allocation status của một cluster cho trước, chúng ta cần xác định bitmap được located tại byte nào. Điều này được thực hiện thông qua việc chia cluster address cho 8 và lờ đi phần dư. Ví dụ, cluster 5 có thể là trong byte 0 của bitmap, và cluster 18 có thể là trong byte 2 của bitmap này. Để tìm bit trong byte mà tương ứng với cluster, chúng ta phân tích phần dư. Ví dụ, chúng ta chi 5 cho 8, chúng ta có phần dư là 5, và khi chúng ta chia 18 cho 8 chúng ta có phần dư là 2. Nhìn Hình 13.9 minh họa cho ví dụ tính toán vị trí của cluster 5 và 74 trong bitmap.

Với kiến thức về cách các bits được tổ chức trong bitmap, nào hãy cùng quay trở lại file system ví dụ của chúng ta. Chúng ta có thể phân tích các contents của $DATA attribute sử dụng icat:

# icat –f ntfs ntfs1.dd 6-128 | xxd
0000000: ffff ffff ffff ffff ffff ff3f 0000 0000  ...........?....
0000016: 0000 f0ff ffff ffff ffff ffff ffff ffff  ................
0000032: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000048: ffff ffff ffff ffff 0300 0000 ffff ffff  ................
0000064: ffff ffff ffff ffff ffff ffff ffff ffff  ................
0000080: ffff ffff ffff ffff ffff ffff ffff ffff  ................
[REMOVED]

Bạn có thể thấy ở đây các bits khởi đầu tất cả đều là 1bởi vì boot sector được located trong 8KB đầu tiên của file system, vì vậy ta mong đợi rằng chúng được cấp phát. Trong byte 11 của output, chúng ta nhìn thấy giá trị 0x3f, ở dạng binary thì nó là 00111111. Byte này tương ứng với các cluster 88 tới 95 của file sytem, 6 bits quan trọng nhất được set tới 1, có nghĩa là chúng được cấp phát. Các bits thứ 7 và 8 được set tới 0, tương ứng với các clusters 94 và 95. Chúng ta cũng có thể thấy các 6 bytes tiếp theo  tất cả đều là zero, vì vậy tất cả các clusters tương ứng với các bits đó đều là unallocated. Trong byte 18 chúng ta có thể thấy giá trị 0xf0, trong binary là 1111 0000.

$Volume File
$Volume file là trong MFT entry 3, và nó có 2 unique attributes. Chúng được mô tả trong phần này.

$VOLUME_NAME Attribute
$VOLUME_NAME attribute có một type identifier là 96 và nghĩa vụ của nó được cấp phát chỉ tới $Volume file. Nó chứa tên của volume trong UTF-16 Unicode và ngoài ra không còn có gì khác. Các contents của nó từ image ví dụ của chúng ta được hiển thị ở đây:

# icat -f ntfs ntfs1.dd 3-96 | xxd
0000000: 4e00 5400 4600 5300 2000 4400 6900 7300 N.T.F.S. .D.i.s.
0000016: 6b00 2000 3200                          k. .2.

Bạn có thể thấy volume name cho file system này là "NTFS Disk 2."

$VOLUME_INFORMATION Attribute
attribute thứ 2 là unique đối với $Volume file là $VOLUME_INFORMATION attribute, attribute này có một type identifier là 112. Attribute này chứa version của file system. Nó có các fields trong Bảng 13.21.

Table 13.21. Data structure for the $VOLUME_INFORMATION attribute.
Byte Range  Description  Essential
0–7  Unused  No
8–8  Major version  Yes
9–9  Minor version  Yes
10–11  Flags (see Table 13.22)  No

Windows NT sử dụng một major version là 1 và một minor version là 2. Windows 2000 sử dụng một major version là 3 và một minor version là 0. Windows XP sử dụng một major version là 3 và một minor version là 1. Các flags được hiển thị trong Bảng 13.22 được áp dụng tới cấu trúc dữ liệu này.

Table 13.22. Flag values for the $VOLUME_INFORMATION flags field.
Flag  Description
0x0001  Dirty
0x0002  Resize $LogFile (file system journal)
0x0004  Upgrade volume next time
0x0008  Mounted in NT
0x0010  Deleting change journal
0x0020  Repair object IDs
0x8000  Modified by chkdsk

$VOLUME_INFORMATION attribute trong file system ví dụ của chúng ta có các contents sau:

# icat -f ntfs ntfs1.dd 3-112 | xxd
0000000: 0000 0000 0000 0000 0301 0000        ............

Byte 8 và 9 cho chúng ta thấy file system này là version 3.1, là XP. Các flags được set tới 0.

$Objld file
Một file có thể được addressed sử dụng object ID của nó thay cho name của nó. Nó cho phép một file được renamed nhưng vẫn tìm thấy được. \$Extend\$ObjId file có một index được đặt tên $O mà kết hợp với object ID của file tới MFT entry của nó. $ObjId file thường không được located trong một reserved MFT entry.

Index này sẽ có các $INDEX_ROOT và $INDEX_ALLOCATION attributes, và các index entries của nó sẽ có các fields được đưa ra trong Bảng 13.23

Table 13.23. Data structure for the $ObjId index entries.
Byte Range  Description  Essential
0–1  Offset to file information  Yes
2–3  Size of file information  Yes
4–7  Unused  No
8–9  Size of index entry  Yes
10–11  Size of object ID (16-bytes)  Yes
12–15  Flags (see Table 13.16)  Yes
16–31  Object ID  Yes
32–39  File reference  Yes
40–55  Birth volume ID  No
56–71  Birth object ID  No
72–87  Birth domain ID  No

Field flags có các standard values 0x01 khi các child nodes tồn tại và 0x02 khi nó là entry cuối cùng trong index entry list. Đây là một vài index entries từ một $INDEX_ROOT attribute, với node header được loại bỏ đi:

0000000: 2000 3800 0000 0000 5800 1000 0000 0000  .8.....X........
0000016: fe24 b024 e292 fe47 95ac e507 4bf5 6782  .$.$...G....K.g.
0000032: 0300 0000 0000 0300 0000 0000 0000 0000  ................
0000048: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000064: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000080: 0000 0000 0000 0000 2000 3800 0000 0000  ........ .8.....
0000096: 5800 1000 0000 0000 a162 3d5e cdda d811  X........b=^....
0000112: 883c 00b0 d01d e93f a400 0000 0000 0100  .<.....?........
0000128: fe24 b024 e292 fe47 95ac e507 4bf5 6782  .$.$...G....K.g.
0000144: a162 3d5e cdda d811 883c 00b0 d01d e93f  .b=^.....<.....?
0000160: 0000 0000 0000 0000 0000 0000 0000 0000  ................

Chúng ta có thể thấy byte 8 mà entry là dài 88 bytes (0x58), và các bytes từ 16 tới 31 cho ta thấy 16-byte object id. Các bytes từ 32 tới 37 hiển thị MFT entry address của object ID này, đó là 3. Đó là index entry cho $OBJECT_ID attribute mà chúng ta đã dissect trong "$OBJECT_ID Attribute". Phần còn lại của các ID fields là 0 cho entry này, entry tiếp theo bắt đầu tại byte 88.

$Quota File
\$Extend\$Quota file được sử dụng bởi user quota feature. Nó không được located trong reserved MFT entry. Nó chứa 2 indexes mà sử dụng cả standard $INDEX_ROOT và $INDEX_ALLOCATION attributes để lưu các index entries của nó. $O index kết hợp với SID tơi một owner ID, và $Q index kết hợp một owner ID tới quota information. Index entry này cho $O index có các fields được đưa ra trong Bảng 13.24.

Table 13.24. Data structure for the $O index entries in $Quota.
Byte Range  Description  Essential
0–1  Offset to owner ID (OFF)  Yes
2–3  Length of owner ID  Yes
4–7  Unused  No
8–9  Size of index entry  Yes
10–11  Size of SID (L)  Yes
12–15  Flags (see Table 13.16)  Yes
16–(16+L-1)  SID  Yes
OFF+  Owner ID  Yes

Các giá trị flag cho index entry này là giống nhau như chúng ta đã thấy cho các file names. 0x01 được set khi có một child node, và 0x02 được set khi nó là entry cuối cùng trong list. Nếu một child tồn tại, 8 bytes cuối cùng sẽ được sử dụng cho VCN của child này.

Ở đây là index entry đầu tiên trong $O index:

0000000: 1c00 0400 0000 0000 2000 0c00 0000 0000  ........ .......
0000016: 0101 0000 0000 0005 1200 0000 0401 0000  ................
0000032: 1c00 0400 0000 0000 2000 0c00 0000 0000  ........ .......
0000048: 0101 0000 0000 0005 1300 0000 0301 0000  ................
[REMOVED]

Các bytes 0 và 1 cho chúng ta biết owner ID được located tại offset 28 (0x1c) từ bắt đầu của entry, và các bytes 2 tới 3 cho chúng ta biết owner ID có độ dài 4 bytes. Các bytes từ 8 tới 9 cho chúng ta biết index entry dài 32 bytes, và các bytes từ 10 tới 11 hiên thị SID là 12 bytes (0x0c). Các bytes từ 16 tới 27 chứa SID, và các bytes từ 28 tới 31 chứa owner ID, giá trị là 260 (0x0104). Entry thứ 2 trong list bắt đầu tại byte 32, và owner ID được tìm thấy trong các byte từ 60 tơí 63, giá trị là 259(0x0103).

$Q index ánh xạ (map) một owner ID tới quota information của user. Index entry của nó có các giá trị được hiển thị trong Bảng 13.25.

Table 13.25. Data structure for the $Q index entries in $Quota.
Byte Range  Description  Essential
0–1  Offset to quota information  Yes
2–3  Size of quota information  Yes
4–7  Unused  No
8–9  Size of index entry  Yes
10–11  Size of owner ID (4 bytes)  Yes
12–15  Flags (see Table 13.16)  Yes
16–19  Owner ID  Yes
20–23  Version  No
24–27  Quota flags (see Table 13.26)  Yes
28–35  Bytes charged to user  Yes
36–43  Time of last charge  No
44–51  Threshold value (a soft limit)  Yes
52–59  Hard limit value  Yes
60–67  Exceeded time  Yes
68–79  SID  Yes

Các index entry flags là các standard flag chuẩn, nếu có một child node thì là 0x01, 0x02 thì là entry cuối cùng trong list. Quota flags có các giá trị được hiển thị trong Bảng 13.26

Table 13.26. Flag values for the $Q index entry flags field.
Flag  Description
0x00000001  Default limits being used
0x00000002  Limit reached
0x00000004  ID deleted
0x00000010  Tracking data usage
0x00000020  Enforcing data usage
0x00000040  Usage tracking requested
0x00000080  Create log when threshold is met
0x00000100  Create log when limit is met
0x00000200  Out of date
0x00000400  Corrupt
0x00000800  Pending deletes

Ở đây một index entry là từ image giống như chúng ta đã sử dụng trong $O index. Điều này đến từ $INDEX_ALLOCATION attribute, và header data được loại bỏ. Nó thực sự đến từ bên trong entry list và tương ứng tới các owner IDs đã được thấy trong ví dụ trước

0000000: 1400 3c00 0000 0000 5000 0400 0000 0000  ..<.....P.......
0000016: 0301 0000 0200 0000 0100 0000 0028 0500  .............(..
0000032: 0000 0000 401b 7c3c 7751 c401 ffff ffff  ....@.|<wQ......
0000048: ffff ffff ffff ffff ffff ffff 0000 0000  ................
0000064: 0000 0000 0101 0000 0000 0005 1300 0000  ................
0000080: 1400 3c00 0000 0000 5000 0400 0000 0000  ..<.....P.......
0000096: 0401 0000 0200 0000 0100 0000 0094 6602  ..............f.
0000112: 0000 0000 90fe 8bdf d769 c401 ffff ffff  .........i......
0000128: ffff ffff ffff ffff ffff ffff 0000 0000  ................
0000144: 0000 0000 0101 0000 0000 0005 1200 0000  ................

Các bytes 0 tới 1 cho chúng ta thấy offset tới quota information là 20 bytes (0x14) , và các bytes từ 2 tới 3 cho ta thấy rằng có 60 bytes quota information. Các bytes từ 16 tới 19 cho ta thấy đó là owner ID 259 (0x0103), những gì là entry thứ 2 chúng ta nhìn thấy trong $O index. Các bytes từ 24 tới 27 có các quota flags, và chúng ta thấy đó là user có các giới hạn mặc định. Các bytes từ 28 tới 35 cho chúng ta thấy rằng user này chỉ có 337,920 bytes (0x052800) được nạp tới account của cô ta.

$LogFile File
$LogFile ở trong MFT entry 2 và được sử dung như NTFS journal. Nó có các standard file attributes và lưu log data trong $DATA attribute. Không may mắn thay, các chi tiết chính xác về cấu trúc dữ liệu không được biết tới.

Log được tổ chức trong các 4,096 byte pages. 2 pages đầu là dành cho vùng bắt đầu, và chúng có signature "RSTR" trong mỗi page trong 4 pages đầu:

# icat -f ntfs ntfs1.dd 2 | xxd | grep RSTR
0000000: 5253 5452 1e00 0900 0000 0000 0000 0000  RSTR............
0004096: 5253 5452 1e00 0900 0000 0000 0000 0000  RSTR............

Nhiều giá trị khác trong cấu trúc dữ liệu này là zero, và chỉ là "NTFS" trong Unicode.








Thứ Hai, 16 tháng 6, 2014

[FileSystem Forensics]Object Identifiers

NTFS version 3.0+ cho phép một phương thức thứ 2 cho việc addressing các files và directories thay cho việc sử dung directory và file name thong thường hoặc MFT entry address. Một ứng dung hoặc OS có thể assign một unique 128-bit object identifier tới file, và nó có thể được sử dung để refer file mặc cho name của nó thay đổi hoặc nó được di chuyển tới volume khác. Microsoft products sử dung object IDs khi chúng nhúng các files bên trong các file khác. File được nhúm sẽ được refer bởi object ID của nó vì vậy nó có thể được tìm thấy thậm chí khi nó bị di chuyển.

Một file hoặc directory mà có một object ID được gán tới nó có một $OBJECT_ID attribute mà chứa object ID và có thể chứa thông tin về original domain và volume mà chúng được tạo. Nếu bạn muốn tìm một file dựa trên object ID của nó, bạn có thể refer tớ \$Extend\$ObjId index. Index này chứa một entry cho mọi assigned object ID trong file system và đưa ra file reference address cho nó.

Phương thức addressing này có thể ảnh hưởng tới người điều tra bởi vì anh ta cần phải locate một file dựa trên object ID của nó.

Allocation Algorithms
NTFS indexes sử dụng B-trees, có nghĩa là không phải là first hay là next available strategories cho việc cấp phát các data structures. Mặc dù, có những biến thể trong cách một B-tree có thể được implement khi nó cần add và remove các entries. Ý tưởng cơ bản là xác định vị trí trong tree mà files thuộc về và add nó vào. Nếu node có quá nhiều entries, nó được phân chia và một level mới được tạo. Quá trình lặp lại cho đến khi tree này còn nằm trong trạng thái valid. Khi delete một file, entry của nó được remove khỏi tree, và các entries còn lại trong node đó lại được di chuyển. Nếu một node có quá ít entries, nó cố gắng mượn các entries từ các node khác vì vậy tree vẫn cân bằng.

Một directory nhỏ sẽ có một node, và nó sẽ được cấp phát tới $INDEX_ROOT attribute. Khi các entries không fit đủ ở đó, OS sẽ move các entries tới một index record trong một $INDEX_ALLOCATION attribute. Tại điểm này, vẫn chỉ có một node trong B-tree, và $INDEX_ROOT không có các entries bên cạnh một empty entry trỏ tới child node. Khi một index record đầy lên, một record thứ 2 được cấp phát, và $INDEX_ROOT attribute sẽ được sử dụng như là một root nod. Children của nó sẽ là 2 index records. Khi những index records này đầy lên, record thứ 3 được cấp phát, và root sẽ có 3 children.

Trong hệ thống mà tôi thấy, các giá trị thời gian và kích thước trong $FILE_NAME attribute được updated tại cùng một tốc độ như các giá trị trong $STANDARD_INFORMATION attribute trong MFT entry của file.

Analysis Techniques
File name category analysis được tiến thành để locate các files và directories dựa trên các names của chúng. Quá trình này yêu cầu việc locate các directories, xử lý các contents, và locate metadata liên kết với một file.

Phân tích NTFS file names và indexes là một quá trình phức tạp. Bước đầu là locate root directory, directory này nằm ở MFT entry 5. Để process một directory, chúng ta phân tích các contents của $INDEX_ROOT và $INDEX_ALLOCATION attributes và process các index entries. Các attributes này chứa một danh sách được gọi là index records mà tường ứng với các nodes trong một tree. Mỗi index record bao gồm một hay nhiều index entries. Một index record còn có thể chứa các unallocated index entries, và record header nhận diện allocated entry cuối cùng được đặt ở đâu. Allocation status của các index records có thể đươc định nghĩa sử dụng $BITMAP attribute của directory. Các allocated files có thể có các unallocated index entries ngoài các allocated entries của chúng bởi vì các directories được lưu trong B-trees và phải được re-sorted khi các files được thêm vào hay xóa đi.

Một file name có thể tương ứng tới một reparse point, những gì là một pointer hay là một mount point. Mục tiêu của reparse point được định nghĩa trong $REPARSE_POINT attribute của MFT entry. Microsoft định nghĩa một vài kiểu reparse points, nhưng các reparse points khác có thể là đặc trưng ứng dụng. Với Microsoft reparse points, vị trí mục tiêu có thể dễ dàng được đọc bởi vì nó là Unicode.

Analysis Considerations
Unallocated file names có thể gây hiểu lầm trong NTFS. Khi các files được thêm vào và xóa đi khỏi một thư mục, tree được re-sorted, và các entries được moved tới các nodes khác và các vị trí khác bên trong một node. Nó làm cho data từ các file bị xóa tồn tại trong allocated space của một tree node và data từ các deleted files có thể bị ghi đè. Unallocated space của một vài indexes có thể chứa nhiều bản sao của data cho cùng một file. Để xác định xem file đó đã thực sự bị xóa, phần còn lại của các indexes phải được searched để xem coi có một bản sao của file name trong allocated space.

Khi tên của một file bị xóa được tìm thấy, có một vài lợi ích so với các file systems khác. Sequence number trong file reference có thể cho ta thấy rằng MFT entry có được tái cấp phát từ khi file bị xóa đi. Nếu MFT entry được cấp phát, MFT entry data có thể không phải là của file name này. Với các file systems khác, bạn phải đoán xem nó có vẫn đang đồng bộ hay không. Một lợi ích khác đó là $FILE_NAME attribute tồn tại trong index này và chứa một tập hợp đầy đủ các giá trị thời gian và các cờ. Do đó, thậm chí nều một MFT entry được tái cấp phát và dữ liệu từ file này bị ghi đè, chúng ta vẫn có những thông tin cơ bản.

Khi cố gắng xác định những deleted files nào tồn tại trong thư mục, một công cụ phân tích nên kiểm tra 2 vị trí. Vị trí thứ nhất là các vùng không được cấp phát (unallocated areas) của mỗi node trong directory index tree. Vị trí thứ 2 là trong các các MFT entries không được cấp phát (unallocated MFT entries). Nếu một file name bị xoá đi khỏi index nhưng MFT entry của nó vẫn còn tồn tại, chúng ta có thể nhận diện ra rằng nó là bộ phận của directory thông qua việc nhìn vào parent directory MFT address của nó. Đảm bảo rằng công cụ phân tích của bạn sử dụng cả 2 thủ tục trên khi nó hiển thị các deleted file names trong một directory.

Analysis Scenario
Trong suốt quá trình điều tra, ta sử dụng Digital Investigator 4000 (DI4K) và một công cụ khác để xác minh kết quả đó là FSAnalyzer (FSA1K). Computer được phân tích có một NTFS File system, và bạn tìm thấy một directory với nhiều mảnh vật chứng. Bạn quyết định so sánh các directory contents giữa 2 tools và tìm thấy một vài sự khác biệt, đó là
1. deleted file aaa.txt không được hiển thị trong DI4K output, nhưng nó xuất hiện trong FSA1K.
2. Các date và time stamps của mmm.txt file là khác nhau trong 2 outputs. Các times của DI4K thì sớm hơn so với các times của FSA1K.
3. Deleted file www.txt được hiển thị trong DI4K output, nhưng ta không thể thấy nó trong FSA1K.

Không có sự khác biệt trong các outputs khi hiển thị các allocated files. Để hiểu sâu thêm, bạn mở một hex editor và bắt đầu parsing directory index. Sau khi processing $INDEX_ROOT và $INDEX_ALLOCATION attributes bằng tay, bạn tìm thấy rằng index có cấu trúc được hiển thị trong hình 12.10(A). Bạn thấy index entry trong root của index và metadata của nó là trong MFT entry 31, như bạn có thể thấy trong Hình 12.10 (B). Bạn process $STANDARD_INFORMATION attribute cho MFT entry 31 và tìm thấy các times mà FSA1K hiển thị. Bạn cũng có thể process các times trong $FILE_NAME attribute trong index entry và tìm thấy các times mà DI4K hiển thị. Để tìm ra xem output nào chính xác hơn, bạn so sánh các sequence numbers trong index entry và trong MFT entry. Bạn thấy rằng index entry có một sequence number là 3 và MFT entry có sequence number là 4. Do đó, MFT entry được tái cấp phát sau khi mmm.txt bị xóa, và DI4K tool nhìn thấy điều đó và hiển thị dates từ $FILE_NAME index entry.

Vấn đề thứ 3 liên quan tới một file www.txt mới, nhưng bạn không nhìn thấy nó trong index. Nhắc lại về các deleted orphan NTFS files, những gì xảy ra bởi vì một deleted name bị ghi đè trong index. Bạn search qua các MFT entries để tìm một entry có name www.txt thông qua việc thực hiện một lo

Sử dụng layout này, bạn có thể thấy tại sao vấn đề thứ nhất xảy ra. FSA1K in aaa.txt file như là một file bị xóa mặc dù file này được cấp phát. Unallocated entry giống như đã được tạo sau khi một file khác bị xóa, và aaa.txt entry được di chuyển trong node. DI4K mới hơn đã tìm kiếm allocated aaa.txt và không in unallocated entry.

Application Category
NTFS là một file system duy nhất mà ở đó nó cung cấp support cho nhiều features mức ứng dung. Có các features không cần phải included vào trong một file system nhưng mà cho phép hệ điều hành hoặc các ứng dụng có thể run hiệu quả hơn. Nó còn có nghĩa là không một trong các features này là quan trọng với mục đích của file system như là lưu (saving) và lấy (retrieving) các files. Thực tế, một user hoặc ứng dụng có thể disable một vài trong số chúng. Trong phần này chúng ta sẽ thảo luận về các hạn mức đĩa (disk quotas), logging (hoặc file system journaling), và change journaling.

Disk Quotas
NTFS bao gồm việc hỗ trợ các hạn mức không gian đĩa (disk space quotas). Các quotas có thể được setup bởi một administrator để giới hạn lượng không gian đĩa mà mỗi user cấp phát. Bộ phận của quota information được lưu như file system data và data khác được lưu trong các files mức ứng dụng, ví dụ như Windows registry. Trong các versions trước 3.0, có tồn tại một \$Quota file system metadata file trong MFT entry 9, nhưng trong các version 3.0+ một file giống như vậy tồn tại trong \$Extend directory và có thể ở trong bất cứ MFT entry nào.

$Quota file sử dụng 2 indexes để quản lý quota information. Một index được đặt tên $O, và nó phối hợp với một SID với một owner ID (chú ý rằng đó là Windows SID thông thường và không phải là ID chúng ta đã thấy trong security descriptors). Index thứ 2 được đặt tên là $Q và nó phối hợp với một owner ID với các chi tiết bao nhiêu bytes mà được nạp (charged) tới quota của user và bao nhiêu bytes anh ấy được phép.

Analysis Considerations
Quota được tính như là non-essential bởi vì một hệ điều hành không cần sử dụng quota information khi nó sử dụng file system. Ví dụ, một OS khác có thể mount một NTFS file system và không update quota khi một user tạo một file. Quota có thể hữu dụng cho forensic analysis khi cố gắng xác định các users nào lưu một số lượng lớn dữ liệu. Ví dụ, nếu bạn tìm một system với nhiều accounts và một số lượng lớn phim lậu , bạn có thể sử dụng quota files để xác định user nào tạo ra chúng. Bạn có thể có được thông tin giống như vậy khi nhìn vào $STANDARD_INFORMATION attribute của mỗi file. Quota system không được bật lên bởi mặc định, vì vậy dữ liệu này không tồn tại cho hầu hết các hệ thống.

Logging - File System Journaling
Để cải thiện tính đáng tin cậy của một file system, Mirosoft thêm vào journaling tới NTFS. Họ gọi nó là feature logging, nhưng thông thường trong các hệ thống khác gọi là journaling. Một file system journal cho phép một hệ điều hành nhanh chóng mang một file system về một trạng thái clean. File system thường trở nên bị corrupt nếu hệ thống crash trong ghi dữ liệu đang được ghi tới file system. Journal record thông tin về các metadata updates trước khi chúng xảy ra và sau đó record khi các updates được thực hiện. Nếu hệ thống crash trước khi journal record mà update vẫn được thực hiện, hệ điều hành nhanh chóng thay đổi hệ thống ngược về known state.

NTFS log journal file được đặt trong MFT entry 2, được đặt tên là $LogFile. MFT entry này không có bất kỳ attributes đặc biệt nào, và log data được lưu trong $DATA attribute. Tôi phát hiện ra rằng log file có kích thước nằm trong khoảng từ 1 đến 2 phần trăm tổng kích thước của file system.

Log file có 2 sections chính: vùng bắt đầu (starting area) và logging area. Như ta có thể thấy trong Hình 12.11, restarting area chứa 2 bản sao của một cấu trúc dữ liệu mà giúp OS xác định các transactions nào cần được phân tích khi một cleanup được thực hiện. Nó chứa một con trỏ trong logging area cho transaction cuối cùng.
Logging area chứa một series các records. Mỗi record có một logical sequence number (LSN) , là một gía trị 64-bit. Các LSNs được cấp phát theo một thứ tự tăng dần. Logging area có một kích thước hữu hạn, và khi không có nhiều không gian ở cuối mỗi file cho một record mới, record được đặt tại đầu của file. Trong tình huống này, record nằm ở đầu của log file sẽ có một LSN lớn hơn record đặt ở cuối file. Nói cách khác, LSN được gán tới một record dựa trên thời điểm record được tạo, không phải dựa trên vị trí mà record được đặt. Các records này không cần thiết bị ghi đè khi log quay vòng.

Có rất nhiều kiểu records, nhưng Microsoft mô tả chỉ 2 trong số chúng. Update record là phổ biến nhất và được sử dụng để mô tả một file system transaction trước khi nó xảy ra. Nó còn được sử dụng khi file system transaction được thực hiện. Nhiều transactions yêu cầu nhiều hơn một record bởi vì chúng được chia ra nhiều hoạt động nhỏ hơn, và mỗi hoạt động có một update record. Ví dụ của file system transactions bao gồm
  • Tạo một file mới hoặc directory
  • Thay đổi nội dung của một file hoặc directory
  • Renaming một file hoặc directory
  • Thay đổi bất cứ dữ liệu được lưu trong MFT entry của một file hoặc directory (user ID, security settings, và tương tự).

[FileSystem Forensics]Links to Files and Directories

NTFS cho phép một file có nhiều hơn một name, điều này xảy ra khi một hard link được tạo. Một hard link trông không có  bất cứ khác biệt gì từ file ban đầu và được cấp phát một entry trong parent directory entry của nó. Link count trong MFT entry header được tăng lên 1 khi một hard link được tạo, và entry này sẽ không được unallocated cho đến khi link count trở thành 0. Nói cách khác, nếu file name ban đầu bị xoá nhưng hard link vẫn còn tồn tại, file sẽ không bị xóa đi. Một MFT entry sẽ có một $FILE_NAME attribute cho mỗi hard link names của nó. Các hard links có thể được tạo bên trong cùng một volume.

NTFS v3.0+ có một feature được gọi là reparse points mà có thể được sử dụng để link các files, directories, và volumes. Một reparse point là một file đặc biệt hoặc directory mà chứa thông tin về những gì link tới nó. Reparse points có thể link tới các files và directories trên cùng một volume, trên các volumes khác, hoặc trên remote servers. Reparse point còn có thể được sử dụng để mount một volume trên một thư mục thay vì mount nó tại các drive letter ví dụ như 'E:\' . Một symbolic link là một reparse point mà link 2 files với nhau, một junction là một reparse point mà link 2 directories lại với nhau, và một mount point là một reparse point mà link một directory với một volume. Windows Remote Storage Server feature sử dụng các reparse points để mô tả server location của file hoặc directory.

Reparse point là các file đặc biệt, và chúng có một flag set trong $STANDARD_INFORMATION và $FILE_NAME attributes của chúng. Chúng còn có một $REPARSE_POINT attribute mà chứa thông tin về vị trí của target file hoặc directory.

NTFS keep tracks các vị trí reparse point sử dụng một index trong \$Extend\$Reparse file system metadata file. Index được sort bởi file reference của reparse point, nhưng nó không chứa vị trí của target.

Ngoài $Reparse file, NTFS keeps track của mount points trong một $DATA trong root directory, MFT entry 5. $DATA attribute, đặt tên là $MountMgrRemoteDatabase, chứa một danh sách của các target volumes mà được trỏ đến bởi các mount points. $DATA attribute này chỉ được tạo khi một mount point tồn tại trong file system.

Chủ Nhật, 15 tháng 6, 2014

[FileSystem Forensics] Indexes

NTFS sử các cấu trúc dữ liệu index trong nhiều hoàn cảnh, và phần này mô tả chúng. Một index trong NTFS là một tập hợp các attributes mà được sắp xếp theo một thứ tự. Ứng dụng phổ biến nhất của một index là trong một directory bởi vì các directories chứa các $FILE_NAME attributes.

Trước phiên bản 3.0 của NTFS (trong Windows 2000), chỉ $FILE_NAME attribute nằm trong một index, nhưng bây giờ có một vài phiên bản  khác sử dụng các indexes và chúng chứa các attributes khác nhau. Ví dụ như security information được lưu trong một index, như là một quota information. Phần này cho ta thấy một index trông như thế nào và cách nó được implement.

B-Trees
Một NTFS sắp xếp các attributes theo một cây, nhất là một B-tree. Một cây là một nhóm các cấu trúc dữ liệu được gọi là các nodes mà được liên kết cùng với nhau như vậy có một head node và nó được rẽ nhánh ra các nodes khác. Xét hình 11.13(A) , ở đó ta thấy node A nằm trên đỉnh và nó liên kết tới các nodes B và C. Node B liên kết tới Node D và E. Một parent node là một node liên kết tới các nodes khác, một child node là một node được liên kết tới. Ví dụ, A là parent node của B và C, những nodes là child node của node A. Một leaf node là một node mà không có các links từ nó. các nodes C, D, và E là các leaves.
Các trees hữu dụng bởi vì chúng có thể được sử dụng dễ dàng để sắp xếp và tìm dữ liệu. Hình 11.13 (B) hiển thị cùng một tree như là tree phía bên tay trái, nhưng bây giờ là với các giá trị được gán cho mỗi node. Nếu bạn đang cố gắng từ kiếm một giá trị, bạn nên so sánh nó với root node. Nếu root node lớn hơn, chúng ta nên tìm kiếm child node phía bên tay trái. Nếu root node nhỏ hơn, chúng ta tìm kiếm child node phía bên tay phải. Ví dụ, nếu muốn tìm giá trị 6 , chúng ta so sánh nó với root node, có giá trị là 7. Node này lớn hơn, vì vậy chúng ta đi tới các child phía bên trái và so sánh với giá trị của nó, là 5. Node này nhỏ hơn nên ta đi tới child phía bên tay phải và ta đã tìm được giá trị cần tìm. Chúng ta đã tìm được giá trị với chỉ 3 phép so sánh. Chúng ta có thể tìm được giá trị 9 chỉ trong 2 phép so sánh thay vì 5 nếu giá trị được lưu trong một list.

NTFS sử dụng B-trees, tương tự với binary tree mà chúng ta mới thấy, nhưng có thể nhiều 2 children trên một node. Thông thường, số lượng children mà một node có dựa trên bao nhiêu giá trị mỗi node có thể lưu. Ví dụ, trong binary tree chúng ta lưu một giá trị trong mỗi node và có 2 children. Nếu chúng ta có thể lưu 5 giá trị trong mỗi node, chúng ta có thể có 6 children.

có nhiều biến thể của B-trees, và có các rules mà tôi sẽ mô tả ở đây bởi vì mục đích của phần này là để mô tả các concepts của chúng, không nhắm tới việc mô tả cách bạn có thể tạo một B-tree.

Trong Hình 11.14 hiển trị một B-tree với các names thay cho các số. Node A chứa 3 giá trị và 4 children. Nếu bạn đang muốn tìm kiếm file ggg.txt, bạn có thể nhìn vào các giá trị trong root node và xác định name theo alphabe nằm trong khoảng giữa eee.txt và lll.txt. Do đó, chúng ta xử lý node C và nhìn vào các giá trị của nó. Chúng tìm thấy file name trong node này.
Nào hãy phức tạp hóa vấn đề lên bằng cách nhìn vào cách các giá trị được thêm vào và xóa đi. Đó là một khái niệm quan trọng bởi vì nó giải thích tại sao các file names bị xóa rất khó để tìm thấy trong NTFS. Chúng tôi giả sử chúng ta chỉ có thể fit 3 file names trên node, và file jjj.txt được thêm vào. Thoạt nghe có vẻ dễ, nhưng bạn sẽ nhìn thấy kết quả là việc 2 nodes bị xóa đi và 5 nodes mới được tạo ra. Khi chúng ta locate nơi jjj.txt nên fit, chúng ta nhận diện được nó nên nằm tại cuối node C, theo sau iii.txt name. Hình 11.15 phía trên đỉnh cho ta thấy tình huống này, nhưng không may mắn thay, có 4 names trong node này, và nó chỉ có thể fit được 3. Do đó chúng ta chia đôi node C, di chuyển ggg.txt lên một cấp độ , và tạo các nodes F và G với các resulting names từ node C. Bạn có thể thấy hình 11.15 phía dưới.
Không may mắn thay, node A có 4 giá trị trong nó. Vì vậy chúng ta chia đôi nó và di chuyển ggg.txt tới node trên đỉnh. Kết quả cuối cùng có thể thấy trong Hình 11.16. Thêm một node làm cho di chuyển các nodes A và C và thêm vào các nodes F, G, H, I và J. Bất cứ dữ liệu còn lại nào trong các nodes A và C từ các files bị xóa phía trước đều đi mất.
Bây giờ xóa đi zzz.txt file. Hành động này remove name từ node E và không yêu cầu bất cứ thay đổi nào khác. Phụ thuộc vào việc triển khai, các chi tiết của zzz.txt vẫn có thể tồn tại trong node và có thể được phục hồi.

Để làm cho sự việc càng khó khăn hơn, xét xem nếu fff.txt bị xóa đi. Node F trở thành trống rỗng, và chúng ta cần fill vào nó. Chúng ta move eee.txt từ node I tới node F và move bbb.txt từ node B tới node I. Điều này tạo một tree mà vẫn cân bằng nơi tất cả các leaves vẫn có cùng một khoảng cách từ node H. Kết quả các bạn có thể thấy trong Figure 11.17.
Node B sẽ chứa bbb.txt trong không gian không được cấp phát (unallocated space) của nó bởi vì bbb.txt được move tới node I. Công cụ phân tích của chúng ta có thể hiển thị bbb.txt bị xóa, nhưng thực sự không phải như vậy. Nó đơn giản là bị moved bởi vì fff.txt bị xóa.

Quá trình thêm và xóa các giá trị từ tree cho ta thấy sự phức tạp của nó.




Thứ Năm, 5 tháng 6, 2014

[File System Forensics] NTFS concepts

Everthing is a File
Một trong các khái niệm quan trọng cần biết để hiểu về thiết kế của NTFS đó là dữ liệu quan trọng được cấp phát cho các files. Dữ liệu này bao gồm dữ liệu quản trị file system cơ bản (basic file system administrative data) mà thường được ẩn trong các file systems khác. Thực tế, các files mà chứa administrative data có thể được đặt ở bất cứ đâu trong volume, giống như bất cứ file bình thường nào. Do đó, một NTFS file system không có một layout cụ thể giống như các file systems khác. Toàn bộ file system được xét như là một data area, và bất cứ sector nào cũng có thể được cấp phát tới một file. Chỉ có một layout nhất quán là các sectors đầu tiên chứa boot sector và boot code.

MFT Concepts
Master File Table (MFT) là trái tim của NTFS bởi vì nó chứa thông tin của tất cả các files và các thư mục. Mọi file và thư mục có ít nhất một entry trong bảng này, và chính các entries cũng thực sự đơn giản. Chúng có kích thước 1KB, nhưng chỉ 42 bytes đầu tiên có một mục đích được định nghĩa sẵn. Các bytes còn lại lưu các thuộc tính (attributes), đây là những cấu trúc dữ liệu nhỏ mà có một mục đích rất cụ thể. Ví dụ, một thuộc tính được sử dụng để lưu tên file, và một thuộc tính khác được sử dụng để lưu nội dung của file. Hình 11.1 biểu diễn layout cơ bản của một MFT entry ở đó có một vài thông tin header và 3 thuộc tính.
Microsoft gọi mỗi entry trong bảng là một file record, nhưng trong bài viết chúng ta gọi mỗi entry là MFT entry. Mỗi entry được gán cho một địa chỉ dựa trên vị trí của nó trong bảng, bắt đầu từ 0. Đến nay, tất cả các entries có kích thước là 1024 bytes, nhưng kích thước chính xác được định nghĩa trong boot sector.

Giống như mọi thứ trong NTFS, MFT là một file. Vậy thì MFT cũng có một entry cho chính nó. Entry đầu tiên trong bảng được đặt tên là $MFT, và nó mô tả vị trí trên đĩa của MFT. Thực tế, đó là nơi duy nhất mà ở đó vị trí của MFT được mô tả. Vị trí bắt đầu của MFT được xác định trong boot sector mà thường xuyên được đặt trong sector đầu tiên của file system. Bạn có thể nhìn thấy trong Hình 11.2 ở đó boot sector được sử dụng để tìm MFT entry đầu tiên, entry này cho ta thấy MFT được phân mảnh và đi từ clusters 32 tới 34 và 56 tới 58. Giống như FAT, NTFS sử dụng clusters để nhóm các sectors liên tiếp lại với nhau.
Theo Microsoft, MFT khởi đầu nhỏ nhất có thể và mở rộng khi nhiều entries được cần tới. Theo lý thuyết, một OS có thể tạo một lượng "cứng" các entries khi file system được tạo, nhưng Microsoft cho phép dễ dàng tạo file system lớn hơn khi nhiều không gian được thêm vào từ việc mở rộng volume (volume spanning). Microsoft không xóa đi các MFT entries mà chúng đã tạo.

MFT Entry Contents
Kích thước của mỗi MFT được định nghĩa trong boot sector, nhưng tất cả các versions của Windows sử dụng kích thước là 1024 bytes. 42 bytes đầu tiên của cấu trúc dữ liệu chứa 12 fields, và 982 bytes còn lại là không được cấu trúc và có thể được fill với các attributes. Bạn có thể nghĩ MFT entry như là một cái hộp lớn được sử dụng để lưu tài sản của bạn. Phía bên ngoài hộp là thông tin cơ bản, ví dụ như là tên của bạn và địa chỉ. Thông tin cơ bản tương đương với các trường được gán cứng của MFT entry. Phía bên trong hộp ban đầu thì trống rỗng, nhưng nó có thể được sử dụng để lưu bất cứ thứ gì miễn là nó ở trong một container nhỏ hơn hộp. Điều này tương tự như cách một MFT entry có một kiến trúc bên trong và nó chứa một vài attributes mà chứa thông tin xác định.

Trường đầu tiên trong MFT entry là signature, và một standard entry sẽ có một chuỗi ASCII "FILE.". Nếu một lỗi được tìm ra trong entry này, nó có thể có một chuỗi là "BAAD." Cũng có một trường flag để nhận diện xem entry đang được sử dụng và entry là cho một thư mục. Trạng thái cấp phát của MFT entry có thể được xác đinhj từ $BITMAP attribute trong $MFT file.

Nếu một file không thể fit các attributes của nó trong một entry, nó có thể sử dụng nhiều entries. Khi điều này xảy ra, entry đầu tiên được gọi là base file record, hay là base MFT entry, và mỗi entries phía sau chứa địa chỉ của base entry trong một trong các trường gán cứng của nó.

MFT Entry Addresses
Mỗi MFT entry được đánh địa chỉ tuần tự sử dụng một giá trị 48-bit, và entry đầu tiên có địa chỉ là 0. Địa chỉ MFT cực đại thay đổi theo sự lớn lên của MFT và được xác định bang cách chia kích thước của mỗi entry cho $MFT. Microsoft gọi địa chỉ tuần tự này là file number.

Mỗi MFT entry còn có một số tuần tự (sequence number) 16-bit và được tăng lên khi entry này được cấp phát. Ví dụ, xét MFT entry 313 với một sequence number là 1. File mà cấp phát entry 313 bị xóa, và entry này được tái cấp phát tới một file mới. Khi entry này được tái cấp phát, nó có một sequence number mới là 2. MFT entry và sequence number được kết hợp, với sequence number là 16 bits cao , để tạo nên một file reference address có độ dài 64-bit, như trong Hình 11.3
NTFS sử dụng file reference address để refer tơis các MFT entries bởi vì sequence number là cho việc xác định xác định khi một file system trong trạng thái lỗi (corrupt state) dễ dàng hơn. Ví dụ, nếu hệ thống crash tại một vài điểm trong khi các cấu trúc dữ liệu khác nhau cho một file đang được cấp phát, sequence number có thể xác định một cấu trúc dữ liệu có chứa một MFT entry address hay không bởi vì file trước đó đã sử dụng nó hoặc nó là một phần của file mới. Chúng ta cũng có thể sử dụng nó để khôi phục nội dung bị xóa. Ví dụ, nếu chúng ta có một cấu trúc dữ liệu chưa được cấp phát với một file reference number trong nó, chúng ta có thể xác định MFT entry được tái cấp phát từ khi cấu trúc dữ liệu này sử dụng nó. Sequence number có thể hữu dụng trong suốt quá trình điều tra.

File System Metadata Files
Bởi vì mọi byte trong volume đều được cấp phát tới một file, có sự tồn tại của các files lưu dữ liệu quản trị file system (filesystem's administrative data). Microsoft gọi những files này là metadata files, nhưng điều này có thể gây ra nhầm lẫn bởi vì chúng ta có refer tới file metadata. Chúng ta sẽ tạm gọi những files mang dữ liệu quản trị này là file system metadata files.

Microsoft dành riêng 16 MFT entries đầu tiên cho các file system metadata files. Các entries được dự trữ mà không được sử dụng ở trong một trạng thái được cấp phát (allocated state) và chỉ có những thông tin tổng quát. Mọi file system metadata file được liệt kê trong root directory, mặc dù chúng thường ẩn đi với hầu hết users. Tên của mỗi file system metadata file bắt đầu với "$", và kí tự đầu tiên được viết hoa. Table 11.1 liệt kê các file system metadata cùng với description của chúng để tiện cho việc tham khảo.
 

MFT Entry Attribute Concepts
Một MFT entry có một kiến trúc nhỏ bên trong và hầu hết được sử dụng để lưu các attributes , đầy là các cấu trúc dữ liệu mà lưu một kiểu dữ liệu chỉ định. Có nhiều kiểu attributes, và mỗi attribute có kiến trúc bên trong của riêng nó. Ví dụ, có các attribute cho tên file, thời gian, ngày tháng và thậm chí là nội dung của nó. Đó là một trong những điểm khác biệt của NTFS so với các file system khác. Hầu hết các file systems tồn tại để đọc và ghi nội dung file, nhưng NTFS tồn tại để đọc và ghi các attributes, một trong các attribute đó là nội dung file.
Xét một điều tương tự trước đây một MFT entry như là một hộp lớn mà ban đầu trống rỗng bên trong. Các attributes tương tự như những hộp nhỏ bên trong hộp lớn mà ở đó các hộp nhỏ có thể là bất cứ hình thù nào để lưu đối tượng. Ví dụ, một chiếc mũ có thể được lưu trong một hộp ngắn, và một poster có thể được lưu trong một hộp dài.
Trong khi mỗi kiểu của attribute lưu một kiểu dữ liệu khác nhau, tất cả các attributes có 2 phần: header và content. Hình 11.4 thể hiện một MFT entry với 4 cặp header và content. Header là chung và chuẩn đối với tất cả các attributes. Content là cụ thể đối với kiểu attribute và có thể có bất cứ kích thước nào. Nếu bạn nghĩ về một điều tương tự như những cái hộp, luôn luôn có những thông tin cơ bản giống nhau phía ngoài mỗi hộp nhỏ, nhưng hình dáng của mỗi hộp có thể khác nhau.

 
Attribute Headers
Attribute header nhận diện kiểu của attribute, kích thước của nó, và tên của nó. Nó cũng có các flags để nhận dạng nếu giá trị này được nén hoặc được mã hóa. Attribute type là một số nhận dạng dựa trên kiểu dữ liệu. Một MFT entry có thể có nhiều attributes của cùng một kiểu.
Một vài attributes có thể được một name và nó được lưu với định dạng UTF-16 Unicode trong attribute header. Một attribute còn có một giá trị định dạng được gán cho nó mà là duy nhất đối với MFT entry đó. Nếu một entry có nhiều hơn một attribute của cùng một kiểu, identifier này có thể được sử dụng để phân biệt giữa chúng.
 
Attribute Content
Content của attribute có thể có bất cứ định dạng và kích thước nào. Ví dụ, một trong số các attributes được sử dụng để lưu content của một file, vì vậy nó có thể có kích thước là một vài MB hoặc một vài GB. Vấn đề là không thực tế khi lưu lượng dữ liệu như thế này trong một MFT entry, những gì chỉ có kích cỡ là 1024 bytes.
 
Để giải quyết vấn đề này, NTFS cung cấp 2 vị trí mà attribute content có thể được lưu. Một resident attribute lưu content của nó trong MFT entry với attribute header. Điều này thực hiện được đối với chỉ các attributes nhỏ. Một non-resident attribute lưu content của nó tron một external cluster trong file system. Header của attribute nhận diện rằng attribute là resident hay non-resident. Nếu một attribute là resident, content sẽ lập tức theo sau header. Nếu attribute là non-resident, header sẽ đưa cho các cluster addresses. Trong Hình 11.5 chúng ta thấy ví dụ MFT entry mà chúng ta thấy trước đây, nhưng attribute thứ 3 là quá lớn đê fit trong MFT, và nó cấp phát cluster 829.
Non-resident attributes được lưu trong các cluster runs, đây là các clusters liên tiếp và run được document sử dụng địa chỉ cluster băt đầu (starting cluster address) và chiều dài run (run length). Ví dụ, nếu một attribute cấp phát tới các clusters 48, 49, 50, 51 và 52, nó phải có một run bắt đầu ở cluster 48 với length là 5. Nếu attribute này cũng cấp phát tới các clusters 80 và 81, nó có một run thứ 2 mà bắt đầu ở cluster 80 với length là 2. Run thứ 3 bắt đầu tại cluster 56 và có length là 4. Bạn có thể thấy trong Hình 11.6
NTFS sử dụng các thuật ngữ Logical Cluster Number (LCN) (giống như logical file system address) và Virtual Cluster Number (VCN) (giống như logical file address) để biểu diễn các địa chỉ.

Standard Attribute Types
Chúng ta đã nói về các thuật ngữ chung cho các kiểu attribute. Bây giờ chúng tôi sẽ nói về những thứ cơ bản của một vài standard attributes.

Như đã được đề cập trước đây, một số (number) được định nghĩa cho mỗi kiểu của attribute, và Microsoft sắp xếp các attributes trong một entry sử dụng số này. Các standard attributes có một giá trị kiểu (type value) mặc định được gán cho chúng, nhưng chúng ta sẽ thấy sau này là nó có thể được định nghĩa lại trong $AttrDef file system metadata file. Ngoài số này ra, mỗi attribute type có một name, và name này là in hoa bắt đầu với "$". Một vài kiểu attribute mặc định và identifiers của chúng có trong Table 11.2. Không phải mọi attribute types và identifiers sẽ tồn tại cho mọi file.
Gần như mọi allocated MFT entry có một $FILE_NAME và một $STANDARD_INFORMATION type attribute. Một ngoại lệ là các non-base MFT entries. Attribute $FILE_NAME chứa tên file, kích thước, và thông tin thời gian. $STANDARD_INFORMATION attribute chứa thông tin về thời gian, quyền sở hữu (ownership), và security. Attribute sau tồn tại đối với mọi file và directory bởi vì nó chứa dữ lieu cần để thực thi data security và các hạn mức (quotas). Trong một nghĩa trừu tượng, không có dữ liệu quan trọng trong attribute này, nhưng các application-level features của file system yêu cầu phải có nó ở đó. Cả 2 attributes này luôn luôn là resident.

Mọi file có một $DATA attribute, trong đó có file content. Nếu content có kích thước vượt quá 700 bytes, nó trở thành non-resident và được lưu trong các external clusters. Khi một file có nhiều hơn một $DATA attribute, các attributes bổ sung thỉnh thoảng được đề cập tới như là alternate data streams (ADS). $DATA attribute mặc định được tạo khi một file được tạo không có một name liên kết với nó, nhưng các $DATA attributes bổ sung phải có một name. Chú ý rằng attribute name là khác với type name. Ví dụ, $DATA là attribute type, và attribute's name có thể là "fred". Một vài tools, bao gồm The Sleuth Kit (TSK) , sẽ gán tên "$Data" cho $DATA attribute mặc định.

Mọi directory có một $INDEX_ROOT attribute mà chứa thông tin về các files và các subdirectories mà được đặt trong nó. Nếu directory quá lớn, $INDEX_ALLOCATION và $BITMAP attributes còn được sử dụng để lưu thông tin. Rối rắm hơn nữa là khi một directory có một $DATA attribute ngoài $INDEX_ROOT attribute. Hay nói cách khác, một directory có thể chứa cả file content và một danh sách các files của nó và các subdirectories. $DATA attribute có thể lưu bất cứ content nào mà một ứng dụng hay một user muốn lưu ở đó. $INDEX_ROOT và $INDEX_ALLOCATION attributes cho một directory thường có name "$I30."

Figure 11.7. cho ta thấy ví dụ MFT entry mà chúng ta đã sử dụng trước đó, và các attributes của nó có những names và types. Nó có 3 standard file attributes. Trong ví dụ này, tất cả các attributes là resident.

Other Attribute Concepts
Trong những phần trước chúng ta đã nhắc đến các khái niệm cơ bản mà được áp dụng cho tất cả các NTFS attributes. Mặc dù không phải mọi attribute đều là cơ bản, và phần này chúng ta sẽ đề cập tới các khái niệm nâng cao hơn. Cụ thể là, chúng ta xem coi điều gì sẽ xảy ra khi một file có quá nhiều attributes và xem các cách thức mà các contents của một attribute được nén (compressed) và được mã hóa (encrypted).

Base MFT entries
Một file có có tới 65,536 attributes (bởi vì indentifier có 16 bit), vì vậy có thể cần nhiều hơn một MFT entry để lưu tất cả attribute headers (thậm chí non-resident attributes cần các header của chúng ở trong MFT entry). Khi các MFT entries bổ sung được cấp phát cho một file, MFT entry ban đầu trở thành base MFT entry . Các non-base entries sẽ có base entry's address trong một trong những trường của MFT entry.

Base MFT entry sẽ có một $ATTRIBUTE_LIST type attribute mà chứa một danh sách với mỗi file's attributes và MFT address có thể được tìm thấy ở đây. Các non-base MFT entries không có $FILE_NAME và $STANDARD_INFORMATION attributes trong chúng.

Sparse Attributes
NTFS có thể giảm lượng không gian được cần bởi một file thông qua việc lưu một vài non-resident $DATA attribute như là sparse. Một sparse attribute là một attribute mà trong đó các clusters mà chứa toàn zero không được ghi lên đĩa. Thay vào đó, một run đặc biệt được tạo ra cho các zero clusters. Thông thường, một run chứa vị trí bắt đầu cluster (starting cluster location) và kích thước, nhưng một sparse run chỉ chứa kích thước và không có starting location. Cũng có một flag mà ám chỉ rằng một attribute là sparse.

Ví dụ, xét một file mà nên chiếm 12 clusters. 5 clusters đầu tiên là non-zero, 3 clusters tiếp theo chứa zero, và 4 clusters cuối cùng là non-zero. Khi lưu như một attribute thông thường , một run có độ dài 12 được tạo cho file, như trong Figure 11.8(A). Khi lưu như một sparse attribute, 3 runs được tạo và chỉ 9 clusters được cấp phát, như ta có thể thấy trong Figure 11.8(B)