--------------- <> -----------------
--- KHOA HỌC - CÔNG NGHỆ - GIÁO DỤC - VIỆC LÀM ---
--- Học để đi cùng bà con trên thế giới ---

Tìm kiếm trong Blog

Hiển thị các bài đăng có nhãn compressed attribute. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn compressed attribute. Hiển thị tất cả bài đăng

He thong quan ly tap tin NTFS - 9 - Attribute $FILE_NAME & $DATA



(tiếp theo của He thong quan ly tap tin NTFS - 8 - Attribute $STANDARD_INFORMATION)


Attribute $FILE_NAME


Mỗi tập tin hoặc thư mục (từ đây gọi tắt là tập tin) luôn có ít nhất một attribute $FILE_NAME trong MFT entry của nó. Một bản sao của attribute $FILE_NAME cũng được lưu trong index của thư mục cha (chứa nó), hai phiên bản này không nhất thiết phải giống nhau hoàn toàn về nội dung. Nội dung của attribute $FILE_NAME trong index của thư mục cha sẽ được đề cập sau, phần này chỉ xem xét attribute $FILE_NAME trong MFT entry.

Mã loại của attribute này là 48. Kích thước của attribute này không cố định, tùy thuộc vào chiều dài của tên tập tin. Cụ thể, kích thước của attribute là: 66 + chiều dài của tên tập tin.

Tên của tập tin là một chuỗi kí tự kiểu UTF-16 Unicode, được định dạng theo kiểu DOS 8.3, Win32 hoặc POSIX. Windows thường yêu cầu một tập tin ít nhất phải có định dạng tên kiểu DOS 8.3, do đó trong attribute $FILE_NAME sẽ có cả hai loại định dạng là: DOS và dạng tên đầy đủ. Tùy thuộc vào kiểu định dạng tên, sẽ có quy định những kí tự nào gọi là hợp lệ khi đặt tên cho tập tin.

Attribute $FILE_NAME có chứa địa chỉ (file reference) MFT entry của thư mục cha chứa nó.
Attribute $FILE_NAME cũng chứa bốn thông tin về thời gian, tương tự như trong attribute $STANDARD_INFORMATION. Tuy nhiên, hệ thống Windows không cập nhật thông tin về thời gian thường xuyên như trong attribute $STANDARD_INFORMATION, thông thường nó chỉ được cập nhật khi tập tin được tạo ra, được di chuyển hoặc khi đổi tên.

Trong attribute $FILE_NAME có trường cho biết kích thước của tập tin, tuy nhiên, giá trị trường này thường là 0.

Cuối cùng, attribute $FILE_NAME có chứa “cờ báo” cho biết một số thông tin liên quan đến tập tin này, ví dụ như: là thư mục, là tập tin chỉ đọc, là tập tin hệ thống, được nén, được mã hóa…v.v.

Nói chung, attribute $FILE_NAME chứa rất nhiều các thông tin tương tự như trong attribute $STANDARD_INFORMATION. Trong đó có hai thông tin quan trọng là tên của tập tin, tên này cũng được sử dụng để tạo chỉ mục trong thư mục và địa chỉ của thư mục cha, địa chỉ này giúp xác định đường dẫn.

Trong MFT entry, thông thường attribute $FILE_NAME nằm ở vị trí thứ hai và là attribute kiểu resident. Tuy nhiên, nếu một tập tin cần nhiều hơn một MFT entry thì sẽ có attribute $ATTRIBUTE_LIST nằm giữa attribute $STANDARD_INFORMATION và attribute $FILE_NAME.

Cũng như tất cả các attribute khác, cấu trúc của attribute $FILE_NAME gồm các phần sau.

Byte thứ
Mô tả
0 – 15
Cấu trúc header chuẩn của attribute $FILE_NAME.
16 – 19
Kích thước phần nội dung của attribute $FILE_NAME.
20 – 21
Nơi bắt đầu (offset) của phần nội dung attribute $FILE_NAME.

Để đọc được nội dung của attribute $FILE_NAME, trước hết cần tính byte bắt đầu của attribute này.
Attribute $FILE_NAME nằm ngay sau attribute $STANDARD_INFORMATION. Attribute $STANDARD_INFORMATION bắt đầu tại offset 56, kích thước của $STANDARD_INFORMATION là 96 byte, vậy attribute $FILE_NAME sẽ bắt đầu tại vị trí (byte): 56 + 96 = 152.

Từ offset 152, đọc 16 byte sẽ là nội dung header của attribute $FILE_NAME, xem Hình 28.



Bảng sau là nội dung header của attribute $FILE_NAME.

Byte thứ
Giá trị (Hệ 16 – Hệ 10)
Mô tả
0 – 3
0x00000030 – 48
Mã loại là 48.
4 – 7
0x00000070 – 112
Kích thước của attribute $FILE_NAME là 112 byte.
8 – 8
0x00 – 0
Attribute thuộc kiểu resident.
9 – 9
0x00 – 0
Attribute này không được đặt tên, nên không có giá trị chiều dài của tên.
10 – 11
0x0000 – 0
Attribute này không được đặt tên, nên không có thông tin về vị trí của tên.
12 – 13
0x0000 – 0
Giá trị cờ báo.
14 – 15
0x0002 – 2
Định danh của attribute (attribute ID) $FILE_NAME là 2.


Đọc tiếp byte thứ 16 -> 19 để biết kích thước phần nội dung, 0x00000052 = 82 byte.

Đọc byte thứ 20 -> 21 để biết vị trí bắt đầu của phần nội dung, 0x0018 = 24, vậy phần nội dung sẽ được lưu bắt đầu từ byte thứ 24 tính từ đầu attribute.


Cấu trúc các trường của phần nội dung attribute $FILE_NAME được mô tả trong bảng sau.

Byte thứ
Giá trị hệ 16 – hệ 10
Mô tả
0 – 7
“05 00 00 00 00 00 05 00”
Địa chỉ MFT entry của thư mục cha (file reference).
8 – 15
0x01CF352F00BB73E4 – 130381390209053668
Thời gian tạo tập tin: Saturday, March 1, 2014 4:17:01AM UTC.
16 – 23
0x01CF352F00BB73E4 – 130381390209053668
Thời gian tập tin có thay đổi: Saturday, March 1, 2014 4:17:01AM UTC.
24 – 31
0x01CF352F00BB73E4 – 130381390209053668
Thời gian MFT entry có thay đổi: Saturday, March 1, 2014 4:17:01AM UTC.
32 – 39
0x01CF352F00BB73E4 – 130381390209053668
Thời gian truy cập tập tin mới nhất: Saturday, March 1, 2014 4:17:01AM UTC.
40 - 47
0x0000000000000000
Kích thước cấp phát cho tập tin. NTFS không sử dụng đến trường này, giá trị luôn là 0.
48 – 55
0x0000000000000000
Kích thước thật của tập tin. NTFS không sử dụng đến trường này, giá trị luôn là 0. Giá trị thật được lưu trong attribute $DATA.
56 – 59
0x00000020
Giá trị cờ báo, tập tin được đánh dấu là archive. (Xem thêm về giá trị và ý nghĩa của cờ đã đề cập trong phần attribute $STANDARD_INFORMATION).
60 – 63
“00 00 00 00”
Giá trị Reparse
64 – 64
0x08 – 8
Chiều dài của tên tập tin: 8 kí tự.
65 – 65
0x03 – 3
Giá trị cho biết định dạng tên tập tin (Namespace). Xem thêm bên dưới.
66+ (8)
“54 00 65 00 73 00 74 00”
Tên của tập tin: Test.txt

Bảng sau mô tả một số kiểu định dạng tên tập tin. 

Giá trị
Kiểu định dạng tên
Mô tả
0
POSIX
Tên có phân biệt chữ hoa, chữ thường. Cho phép sử dụng tất cả các kí tự Unicode ngoại trừ ‘/’ và NULL.
1
Win32
Tên có phân biệt chữ hoa, chữ thường. Cho phép sử dụng tất cả các kí tự Unicode ngoại trừ ‘/’, ‘\’, ‘ :’, ‘ >’, ‘<’ và ‘?’.
2
DOS
Tên không phân biệt chữ hoa, chữ thường, tất cả đều được chuyển sang dạng chữ hoa. Số kí tự của phần tên phải ít hơn hoặc bằng tám kí tự, phần mở rộng phải ít hơn hoặc bằng ba kí tự.
3
Win32 & DOS
Định dạng kép Win32 và DOS. Khi định dạng DOS có thể lưu đầy đủ tên tập tin rồi, thì mặc định hiểu là nó cũng được lưu ở định dạng Win32 mà không cần lưu ở hai định dạng riêng biệt.

 

Attribute $DATA


Attribute $DATA được sử dụng để lưu trữ tất cả các loại dữ liệu. Mã loại của attribute này là 128. Attribute $DATA không có kích thước cố định. Mỗi tập tin có thể gồm một hoặc nhiều attribute $DATA. Attribute $DATA đầu tiên không có tên, các attribute $DATA tiếp sau phải được đặt tên cụ thể.

Trong hệ thống Windows, attribute $DATA cũng được tạo thêm khi người dùng nhập thông tin vào mục “Summary” (chuột phải vào tập tin\ chọn properties\ Summary), được tạo thêm do trình anti-virus, hoặc được tạo thêm do chương trình sao lưu dự phòng…v.v.

Attribute $DATA có thể được mã hóa để đảm bảo an toàn thông tin. Khi được mã hóa, “cờ báo” trong header của attribute sẽ được thiết lập, “khóa” của quá trình mã hóa được lưu trong attribute $LOGGED_UTILITY_STREAM.

Hình 29 minh họa một tập tin với hai attribute $DATA đã được mã hóa.



Cấu trúc của attribute $DATA khá đơn giản. Sau phần header của attribute là phần nội dung, đây là dữ liệu ở dạng thô của một tập tin. Attribute $DATA không có kích thước tối thiểu và tối đa. Nếu kích thước phần nội dung vượt quá 700 byte, attribute sẽ được chuyển từ loại resident sang loại non-resident. Trong hầu hết các tập tin, attribute $DATA luôn nằm ở vị trí sau cùng trong MFT entry.

Phần sau đây trình bày quá trình đọc attribute $DATA, xem Hình 30.

Đọc header của attribute nằm kế sau attribute $FILE_NAME, gồm 16 byte. Xét mã loại,  byte 0 -> 3 có giá trị là  0x00000040 = 64, kết luận: đây là attribute $OBJECT_ID. Tính kích thước của attribute $OBJECT_ID để nhảy qua attribute kế tiếp, byte 4 –> 7 có giá trị là 0x00000028 =  40 byte.

Vậy ta sẽ bỏ qua 40 byte của attribute $OBJECT_ID, để đọc header của attribute kế tiếp.



Xét mã loại, byte 0 -> 3 có giá trị 0x00000080 = 128, kết luận: đây là attribute $DATA.

Bảng sau là nội dung header của attribute $DATA.

Byte thứ
Giá trị (Hệ 16 – Hệ 10)
Mô tả
0 – 3
0x00000080 – 128
Mã loại là 128
4 – 7
0x00000030 – 48
Kích thước của attribute $DATA là 48 byte
8 – 8
0x00 – 0
Attribute thuộc kiểu resident
9 – 9
0x00 – 0
Attribute này không được đặt tên, nên không có giá trị chiều dài của tên.
10 – 11
0x0018 – 24
Attribute này không được đặt tên, nhưng vẫn có thông tin về vị trí của tên?
12 – 13
0x0000 – 0
Giá trị cờ báo.
14 – 15
0x0001 – 1
Định danh của attribute (attribute ID) $DATA là 1.

Đọc tiếp byte thứ 16 -> 19 để biết kích thước phần nội dung, 0x00000015 = 21 byte.

Đọc byte thứ 20 -> 21 để biết vị trí bắt đầu của phần nội dung, 0x0018 = 24, tức là bắt đầu từ byte thứ 24 tính từ đầu attribute.

Nội dung của tập tin văn bản là “Du lieu dang van ban!”.

Cuối cùng, do chưa sử dụng hết 1024 byte của MTF entry, hệ thống sử dụng giá trị 0xFFFFFFFF để đánh dấu kết thúc phần nội dung của MFT entry.
-----------------------------
Tài liệu đã tham khảo:
Brian Carrie, File System Forensic Analysis, Addison Wesley Professional, 2005
-------------------
Cập nhật 2014/5/29
 ------------------
Đọc thêm
He thong quan ly tap tin NTFS - 1 - MBR
-----
Bạn muốn tự học HTML bài bản? Xem thêm

Dia cung - 14 - NTFS - sparse - compressed attribute

(tiếp theo của Dia cung - 13)



Thêm một số khái niệm về attribute

Ở phần trên đã đề cập đến các khái niệm tổng quan về attribute. Phần tiếp theo sẽ trình bày thêm một số khái niệm liên quan đến attribute trong một số tình huống sử dụng cụ thể: ví dụ, hệ thống sẽ xử lý như thế nào khi tập tin có quá nhiều attribute, việc nén và mã hóa nội dung của attribute được thực hiện như thế nào.
Base MFT entry
Một tập tin có thể có tới 65 536 attribute (vì mã định danh attribute là một số 16 bit), giả sử, tất cả các MFT entry đều thuộc kiểu non-resident, tức là MFT entry chỉ cần lưu header của các attribute, thì kích thước cần dùng tới là 65 536 * 42 = 2 752 512 byte. Trong khi kích thước của một MFT entry chỉ có 1024 byte
Như vậy, trong nhiều trường hợp, một tập tin cần nhiều hơn một MFT entry để lưu trữ các attribute của nó.
Khi có hơn một MFT entry được cấp cho một tập tin, MFT entry đầu tiên của tập tin sẽ được chuyển thành base MFT entry. Các MFT entry còn lại thuộc về tập tin này được gọi là non-base MFT entry (gọi tắt là non-base entry). Khi đó, các non-base entry sẽ có một trường để lưu địa chỉ tham chiếu tới base entry của nó.
Base MFT entry sử dụng attribute $ATTRIBUTE_LIST để chứa: tất cả các attribute thuộc về một tập tin, địa chỉ của attribute trong MFT. Các non-base entry không có chứa hai attribute: $FILE_NAME và $STANDARD_INFORMATION.
Sparse Attribute (attribute “thưa”)
NTFS có thể giảm không gian đĩa thực tế cần thiết để lưu một tập tin bằng cách lưu attribute $DATA dạng non-resident theo kiểu sparse attribute.
Sparse attribute là attribute có chứa các cluster mang giá trị 0 (tại sao lại có các cluster chứa giá trị 0?), các cluster này sẽ không được ghi vào đĩa. Trong trường hợp có sparse attribute, một run (đường chạy) đặc biệt sẽ được tạo cho các cluster mang giá trị 0.
Một run thông thường sẽ có hai thông tin: cluster bắt đầu và kích thước của run (số cluster thuộc về run). Với sparse run, sẽ chỉ có một thông tin là kích thước của run mà không có thông tin về cluster bắt đầu. NTFS sử dụng “cờ” để báo một attribute là sparse hay không sparse.
Ví dụ, xét một tập tin cần sử dụng 12 cluster để lưu trữ, trong đó 5 cluster đầu có giá trị khác 0, 3 cluster tiếp theo chứa giá trị 0, và 4 cluster cuối cùng có giá trị khác 0. Để lưu tập tin này lên trên đĩa, nếu sử dụng attribute thông thường, sẽ cần một run có chiều dài là 12, nghĩa là cần ghi 12 cluster lên đĩa. Tuy nhiên, nếu sử dụng sparse attribute sẽ cần 3 run, nhưng tổng số cluster cần ghi lên đĩa là 9. Xem hình minh họa bên dưới.

Compressed attribute (tạm dịch “thuộc tính nén”)
NTFS cho phép ghi các attribute lên đĩa dưới dạng nén, tuy nhiên, thuật toán nén không được công bố. Chú ý, đây là nén tập tin ở mức hệ thống (system-level compression) chứ không phải nén tập tin bằng các ứng dụng (application-level compression) như zip, gzip.
Microsoft chỉ thực hiện nén các attribute kiểu $DATA dạng non-resident.
NTFS sử dụng cả sparse run và nén dữ liệu để giảm không gian lưu trữ trên đĩa. Trong header của attribute $DATA có “cờ báo” cho biết attribute có được nén hay không, các “cờ báo” trong attribute $STANDARD_INFORMATION và $FILE_NAME cũng cho biết tập tin có chứa attribute được nén hay không.
Trước khi thực hiện nén, dữ liệu được chia nhỏ thành các khối có kích thước bằng nhau, gọi là các đơn vị nén (compression unit). Kích thước của đơn vị nén được lưu trong header của attribute. Có ba trường hợp xảy ra với mỗi đơn vị nén:
  1. Nếu đơn vị nén chỉ chứa giá trị 0, một run kiểu sparse sẽ được tạo ra, và không cấp phát đĩa cho đơn vị nén này.
  2. Nếu kích thước của dữ liệu sau khi nén cũng bằng kích thước của dữ liệu gốc thì sẽ không thực hiện nén dữ liệu và run sẽ được tạo dựa trên dữ liệu gốc.
  3. Nếu kích thước của dữ liệu sau khi nén nhỏ hơn kích thước của dữ liệu gốc, một run sẽ được tạo ra để lưu dữ liệu đã được nén, đồng thời một sparse run cũng sẽ được tạo, để đảm bảo tổng số cluster của run và sparse run bằng với số cluster của đơn vị nén ban đầu.
Ví dụ, quan sát tình huống sau. Giả sử, đơn vị nén có kích thước 16 cluster, chúng ta có một attribute kiểu $DATA kích thước 64 cluster. Như vậy, sẽ chia dữ liệu ra thành 4 đơn vị nén.
    • Đơn vị nén đầu tiên và thứ tư không được nén, vì sau khi thực hiện nén, kích thước vẫn là 16 cluster. Tạo hai run tương ứng cho hai đơn vị nén.
    • Đơn vị nén thứ hai chỉ chứa giá trị 0, do vậy sẽ tạo một sparse run và không cấp phát không gian đĩa.
    • Đơn vị nén thứ ba, sau khi thực hiện nén xong, còn lại kích thước 10 cluster, vì vậy, sẽ thực hiện nén đơn vị này, tạo run có kích thước 10 cluster để lưu trữ, đồng thời tạo một sparse run kích thước 6 cluster.
Xem hình minh họa dưới đây.

Khi hệ điều hành đọc các attribute $DATA đã được nén, nó thấy “cờ báo” nén được thiết lập, đồng thời thấy kích thước của các run được thiết lập dựa trên kích thước của đơn vị nén. Run đầu tiên có kích thước bằng đơn vị nén, vì vậy, nó biết run này không bị nén. Run thứ hai, có kích thước bằng đơn vị nén, và nó là một sparse, vì vậy, đây sẽ là 16 cluster mang giá trị 0; Kết hợp run thứ ba và run thứ tư sẽ tạo thành một đơn vị nén, trong đó chỉ có 10 cluster cần giải nén; run cuối cùng có kích thước bằng đơn vị nén, nên hệ điều hành cũng biết run này không bị nén.
Với các attribute $DATA đã được nén, nhưng các run lại bị phân mảnh, dẫn tới kích thước của các run không bằng nhau, không dựa trên kích thước của đơn vị nén. Trong trường hợp này, việc giải nén sẽ phức tạp hơn. Để giải nén, hệ điều hành cần thực hiện các việc sau: trộn các run lại thành một khối, chia lại khối dữ liệu thành các khối nhỏ hơn có kích thước bằng kích thước của đơn vị nén, thực hiện giải nén. Quan sát ví dụ ở hình dưới đây.

Ở hình trên, sau khi trộn run sẽ tạo thành bốn run: bắt đầu là run dữ liệu bình thường, theo sau là một sparse run, tiếp theo là một run dữ liệu bình thường, cuối cùng là một sparse run.
Thực hiện chia lại bốn run thành các run mới, với kích thước của run mới là kích thước của đơn vị nén. Kích thước của các run ban đầu: 20 + 14 + 2 + 28 + 4 + 12 = 80. Kích thước của đơn vị nén là 16. Vậy số run mới là: 80/16 = 5 run.
Thực hiện giải nén: hai run đầu tiên không có sparse run, không cần giải nén. Run thứ ba và thứ năm có sparse run, thực hiện giải nén. Run thứ tư là sparse run, tất cả mang giá trị 0.
----------------------

Tham khảo
[1] Brian Carrie, File System Forensic Analysis, Addison Wesley Professional, 2005
----------------------
Cập nhật: 2013/9/30