btparser/cparser/tests/exp_lex/MFTRecord.bt

310 lines
9.0 KiB
Plaintext
Raw Normal View History

2016-06-05 21:47:15 +08:00
1:
2:
3:
4:
5:
6:
7:
8:
9:
10: string getMFTNameFromRecurdNumber ( UINT32 record_number ) {
11:
12: switch ( record_number ) {
13: case 0 :
14: return "$MFT" ;
15: case 1 :
16: return "$MFTMirr" ;
17: case 2 :
18: return "$LogFile" ;
19: case 3 :
20: return "$Volume" ;
21: case 4 :
22: return "$AttrDef" ;
23: case 5 :
24: return "$. (root dir)" ;
25: case 6 :
26: return "$Bitmap" ;
27: case 7 :
28: return "$Boot" ;
29: case 8 :
30: return "$BadClus" ;
31: case 9 :
32: return "$Secure" ;
33: case 10 :
34: return "$UpCase" ;
35: case 11 :
36: return "$Extend" ;
37: default :
38: return "" ;
39: }
40: }
41:
42: string GetMFTRecordComment ( struct MFTRecord & record ) {
43: string ret ;
44:
45: SPrintf ( ret , "Record # %u %s (%s)" ,
46: record . mftheader . mft_rec_number ,
47: getMFTNameFromRecurdNumber ( record . mftheader . mft_rec_number ) ,
48: HeaderFlagsToString ( record . mftheader . flags )
49: ) ;
50: return ret ;
51: }
52:
53:
54: wstring GetMFTNameFromAttribute ( struct Attributes & attrs ) {
55:
56: switch ( attrs . attribute . fixed_header . type ) {
57: case STANDARD_INFORMATION :
58: return "$STANDARD_INFORMATION" ;
59: case ATTRIBUTE_LIST :
60: return "$ATTRIBUTE_LIST" ;
61: case FILE_NAME :
62: string ret ;
63: SPrintf ( ret , "$FILE_NAME (%s)" ,
64: attrs . attribute . resident_attribute_content . file_name ) ;
65: return ret ;
66: case OBJECT_ID :
67: return "$OBJECT_ID" ;
68: case SECURITY_DESCRIPTOR :
69: return "$SECURITY_DESCRIPTOR" ;
70: case VOLUME_NAME :
71: return "$VOLUME_NAME" ;
72: case VOLUME_INFORMATION :
73: return "$VOLUME_INFORMATION" ;
74: case DATA :
75: string ret ;
76: if ( attrs . attribute . fixed_header . non_res_flag )
77: return "$DATA (Non resident)" ;
78: else
79: return "$DATA (Resident)" ;
80: case INDEX_ROOT :
81: return "$INDEX_ROOT" ;
82: case INDEX_ALLOCATION :
83: return "$INDEX_ALLOCATION" ;
84: case BITMAP :
85: string ret ;
86: SPrintf ( ret ,
87: "$BITMAP (map of bits telling for each record if they are in use or not)" ) ;
88: return ret ;
89: case REPARSE_POINT :
90: return "$REPARSE_POINT" ;
91: case EA_INFORMATION :
92: return "$EA_INFORMATION" ;
93: case EA :
94: return "$EA" ;
95: case LOGGED_UTILITY_STREAM :
96: return "$LOGGED_UTILITY_STREAM" ;
97: default :
98: return "" ;
99: }
100: }
101:
102:
103: string HeaderFlagsToString ( UINT16 flags ) {
104: string ret ;
105:
106: if ( flags & 0x2 )
107: Strcat ( ret , "Directory, " ) ;
108: else
109: Strcat ( ret , "File, " ) ;
110: if ( flags & 0x1 )
111: Strcat ( ret , "In use" ) ;
112: else
113: Strcat ( ret , "Not in use" ) ;
114: return ret ;
115: }
116:
117:
118: string AttributeFlagsToString ( UINT16 flags ) {
119: string ret ;
120:
121: if ( flags & 0x1 )
122: Strcat ( ret , "Compressed, " ) ;
123: else
124: Strcat ( ret , "Not Compressed, " ) ;
125: if ( flags & 0x4000 )
126: Strcat ( ret , "Encrypted, " ) ;
127: else
128: Strcat ( ret , "Not Encrypted, " ) ;
129: if ( flags & 0x8000 )
130: Strcat ( ret , "Sparse" ) ;
131: else
132: Strcat ( ret , "Not Sparse" ) ;
133: return ret ;
134: }
135:
136:
137: string GetParentDirComment ( uint64 ref_to_parent_dir ) {
138: string ret ,
139: details ;
140:
141:
142:
143: UINT16 seq_num = ref_to_parent_dir >> 24 ;
144: UQUAD mft_entry = ref_to_parent_dir & 0xFFFFFFFFFFFF ;
145: if ( mft_entry == 0x5 ) {
146:
147: Strcat ( ret , "Root dir, " ) ;
148: }
149: SPrintf ( details , "Seq num = %04xh [!!] , MFT entry = %012xh" , seq_num , mft_entry ) ;
150: Strcat ( ret , details ) ;
151: return ret ;
152: }
153:
154:
155: string GetAllocSize ( UQUAD alloc_size ) {
156:
157: string ret ;
158: UQUAD num_clusters = alloc_size / 4096 + ( alloc_size % 4096 ? 1 : 0 ) ;
159: SPrintf ( ret , "%lu clusters (each cluster 4096 bytes)" , num_clusters ) ;
160: return ret ;
161: }
162:
163:
164: string GetDataRunStart ( UINT16 data_run_info ) {
165: string ret ;
166: SPrintf ( ret , "Starting at 0x%x (assuming cluster size = 4096)" , data_run_info * 4096 ) ;
167: return ret ;
168: }
169:
170: typedef struct MFTAttribute {
171: local int64 mftattribute_start = FTell ( ) ;
172: struct FixedHeader {
173: enum < UINT32 > {
174: STANDARD_INFORMATION = 0x10 ,
175: ATTRIBUTE_LIST = 0x20 ,
176: FILE_NAME = 0x30 ,
177: OBJECT_ID = 0x40 ,
178: SECURITY_DESCRIPTOR = 0x50 ,
179: VOLUME_NAME = 0x60 ,
180: VOLUME_INFORMATION = 0x70 ,
181: DATA = 0x80 ,
182: INDEX_ROOT = 0x90 ,
183: INDEX_ALLOCATION = 0xA0 ,
184: BITMAP = 0xB0 ,
185: REPARSE_POINT = 0xC0 ,
186: EA_INFORMATION = 0xD0 ,
187: EA = 0xE0 ,
188: LOGGED_UTILITY_STREAM = 0x100
189: } type ;
190: UINT32 attr_length ;
191: enum < UBYTE > {
192: RESIDENT = 0 ,
193: NON_RESIDENT = 1
194: } non_res_flag < comment = "Resident: stored in the record. Non-resident: stored in the data runs" > ;
195: UBYTE name_length ;
196: UINT16 name_offset ;
197: UINT16 flags < comment = AttributeFlagsToString > ;
198: UINT16 attribute_id ;
199: } fixed_header ;
200: if ( fixed_header . non_res_flag ) {
201: struct NonResidentAttributeHeader {
202: UQUAD start_vcn ;
203: UQUAD end_vcn ;
204: UINT16 datarun_offset ;
205: UINT16 compression_size < comment = "If 0, not compressed" > ;
206: UINT32 padding ;
207: UQUAD alloc_size < comment = GetAllocSize > ;
208: UQUAD real_size < comment = "File size in bytes" > ;
209: UQUAD stream_size < comment = "Equal to real_size unless resized" > ;
210: } non_resident_attribute_header ;
211: if ( fixed_header . type == DATA ) {
212: struct AttributeContentNonResidentData {
213: UBYTE unknown ;
214: UBYTE num_of_clusters ;
215: UINT16 data_run_start < format = hex , comment = GetDataRunStart > ;
216: char padding [ 3 ] ;
217: } attribute_content_non_resident_data ;
218: } else if ( fixed_header . type == BITMAP ) {
219: struct AttributeContentNonResidentBitmap {
220: char bitmap [ fixed_header . attr_length - non_resident_attribute_header . datarun_offset ] ;
221: } attribute_content_non_resident_bitmap ;
222: } else {
223:
224: }
225: } else {
226: struct ResidentAttributeHeader {
227: UINT32 content_size ;
228: UINT16 content_offset ;
229: UINT16 indexed_tag ;
230: } resident_attribute_header ;
231: struct ResidentAttributeContent {
232: if ( fixed_header . type == STANDARD_INFORMATION ) {
233: struct AttributeContentStandardInformation {
234: FILETIME creation_time ;
235: FILETIME alteration_time ;
236: FILETIME mft_changed_time ;
237: FILETIME read_time ;
238: UINT32 dos_permissions ;
239: UINT32 max_num_of_versions ;
240: UINT32 version_number ;
241: UINT32 class_id ;
242: } attribute_content_standard_information ;
243: if ( resident_attribute_header . content_size != 48 ) {
244: UINT32 owner_id ;
245: UINT32 security_id ;
246: UQUAD quota_charged ;
247: UQUAD update_sequence_number ;
248: }
249: } else if ( fixed_header . type == FILE_NAME ) {
250: struct AttributeContentFileName {
251: UQUAD file_ref_to_parent_dir < format = hex , comment = GetParentDirComment > ;
252: FILETIME file_creation_time ;
253: FILETIME file_modification_time ;
254: FILETIME mft_modification_time ;
255: FILETIME file_access_time ;
256: UQUAD allocated_size ;
257: UQUAD real_size ;
258: UINT32 flags ;
259: UINT32 used_by_eas_and_reparse ;
260: UBYTE filename_length_unicode ;
261: UBYTE filename_namespace ;
262: } attribute_content_file_name ;
263:
264: wchar_t file_name [ attribute_content_file_name . filename_length_unicode ] ;
265: } else {
266: UCHAR data [ resident_attribute_header . content_size ] ;
267:
268: }
269: } resident_attribute_content ;
270: }
271: UCHAR padding [ fixed_header . attr_length - ( FTell ( ) - mftattribute_start ) ] ;
272: } mftattribute ;
273:
274: struct MFTRecord {
275: struct MFTHeader {
276: char file_signature [ 4 ] < comment = "Must be FILE" > ;
277: UINT16 fixup_offset ;
278: UINT16 fixup_size ;
279: UQUAD log_seq_number ;
280: UINT16 sequence ;
281: UINT16 hard_links < comment = "Number of hard links" > ;
282: UINT16 attrib_offset ;
283: UINT16 flags < comment = HeaderFlagsToString > ;
284: UINT32 rec_length < comment = "Length of the bytes used for this record. Must be <= 1024" > ;
285: UINT32 all_length < comment = "Length of the whole record. Must be 1024" > ;
286: UQUAD base_mft_rec ;
287: UINT16 next_attr_id ;
288: UINT16 fixup_pattern ;
289: UINT32 mft_rec_number < comment = getMFTNameFromRecurdNumber > ;
290: } mftheader ;
291: UQUAD fixup ;
292: local int i ;
293: local int64 pos ;
294: local UINT32 terminator ;
295: for ( i = 0 ; i == i ; i ++ ) {
296: pos = FTell ( ) ;
297: terminator = ReadUInt ( ) ;
298: if ( terminator == 0xFFFFFFFF ) {
299: struct Terminator {
300: UINT32 terminator < format = hex , comment = "Must be FF FF FF FF" > ;
301: } terminator < comment = "Attribute list terminator" > ;
302: break ;
303: } else {
304: struct Attributes {
305: mftattribute attribute ;
306: } attributes < comment = GetMFTNameFromAttribute > ;
307: }
308: }
309: } mftrecord < comment = GetMFTRecordComment > ;
310: tok_eof