1 /*
2 ** The Sleuth Kit
3 **
4 ** Copyright (c) 2013 Basis Technology Corp.  All rights reserved
5 ** Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
6 **
7 ** This software is distributed under the Common Public License 1.0
8 **
9 */
10 
11 /*
12  * This code makes use of research presented in the following paper:
13  * "Reverse Engineering the exFAT File System" by Robert Shullich
14  * Retrieved May 2013 from:
15  * http://www.sans.org/reading_room/whitepapers/forensics/reverse-engineering-microsoft-exfat-file-system_33274
16  *
17  * Some additional details concerning TexFAT were obtained in May 2013
18  * from:
19  * http://msdn.microsoft.com/en-us/library/ee490643(v=winembedded.60).aspx
20 */
21 
22 /**
23  * \file tsk_exfatfs.h
24  * Contains declarations of structures and functions specific to TSK exFAT
25  * file system support.
26  */
27 
28 #ifndef _TSK_EXFATFS_H
29 #define _TSK_EXFATFS_H
30 
31 #include "tsk_fs_i.h"
32 #include "tsk_fatfs.h"
33 
34 /**
35  * \internal
36  * The first cluster of an exFAT cluster heap (data area) is cluster #2.
37  */
38 #define EXFATFS_FIRST_CLUSTER 2
39 
40 /**
41  * \internal
42  * An exFAT volume label should have 11 UTF-16 characters, but in practice
43  * the name can extend into the reserved bytes and have a length up to 15
44  * characters.
45  */
46 #define EXFATFS_MAX_VOLUME_LABEL_LEN_CHAR 15
47 #define EXFATFS_MAX_VOLUME_LABEL_LEN_BYTE 30
48 
49 /**
50  * \internal
51  * AnS exFAT file entry set consists of a file directory entry followed by a
52  * file stream directory entry and at least one file name directory entry.
53  * The file stream and file name entries are the secondary entries.
54  */
55 #define EXFATFS_MIN_FILE_SECONDARY_DENTRIES_COUNT 2
56 
57 /**
58  * \internal
59  * An exFAT file entry set consists of a file directory entry followed by a
60  * file stream directory entry and up to seventeen file name directory entries.
61  * The file stream and file name entries are the secondary entries.
62  */
63 #define EXFATFS_MAX_FILE_SECONDARY_DENTRIES_COUNT 18
64 
65 /**
66  * \internal
67  * An exFAT file name directory entry includes from 1 to 15 UTF-16 characters.
68  * Each character is stored in UTF-16, so the buffer is actually 30-bytes.
69  */
70 #define EXFATFS_MAX_FILE_NAME_SEGMENT_LENGTH_UTF16_CHARS 15
71 #define EXFATFS_MAX_FILE_NAME_SEGMENT_LENGTH_UTF16_BYTES 30
72 
73 /**
74  * \internal
75  * An exFAT file name can be a maximum of 255 UTF-16 characters.
76  */
77 #define EXFATFS_MAX_FILE_NAME_LENGTH_UTF16_CHARS 255
78 
79 /**
80  * \internal
81  * In an exFAT file stream directory entry, the second bit of the general
82  * secondary flags byte is set if there is no FAT chain for a file, i.e., the
83  * file is not fragmented.
84  */
85 #define EXFATFS_INVALID_FAT_CHAIN_MASK 0x02
86 
87 /**
88  * Name for an exFAT volume label directory entry that has an empty label, with
89  * the "$" prefix that is used to indicate "special file" directory entries and
90  * non-file directory entries.
91  */
92 #define EXFATFS_EMPTY_VOLUME_LABEL_DENTRY_NAME "$EMPTY_VOLUME_LABEL"
93 
94 /**
95  * Name for an exFAT volume GUID directory entry, with the "$" prefix that is
96  * used to indicate "special file" directory entries and non-file directory
97  * entries.
98  */
99 #define EXFATFS_VOLUME_GUID_DENTRY_NAME "$VOLUME_GUID"
100 
101 /**
102  * Name for an exFAT allocation bitmap directory entry, with the "$" prefix
103  * that is used to indicate "special file" directory entries and non-file
104  * directory entries.
105  */
106 #define EXFATFS_ALLOC_BITMAP_DENTRY_NAME "$ALLOC_BITMAP"
107 
108 /**
109  * Name for an exFAT upcase table directory entry, with the "$" prefix that is
110  * used to indicate "special file" directory entries and non-file directory
111  * entries.
112  */
113 #define EXFATFS_UPCASE_TABLE_DENTRY_NAME "$UPCASE_TABLE"
114 
115 /**
116  * Name for an exFAT TexFAT directory entry, with the "$" prefix that is used
117  * to indicate "special file" directory entries and non-file directory entries.
118  */
119 #define EXFATFS_TEX_FAT_DENTRY_NAME "$TEX_FAT"
120 
121 /**
122  * Name for an exFAT access control table directory entry, with the "$" prefix
123  * that is used to indicate "special file" directory entries and non-file
124  * directory entries.
125  */
126 #define EXFATFS_ACT_DENTRY_NAME "$ACCESS_CONTROL_TABLE"
127 
128 #ifdef __cplusplus
129 extern "C" {
130 #endif
131 
132     /**
133      * \internal
134      * Master boot record (MBR) structure for exFAT file systems. The MBR will
135      * be at least 512 bytes in length, but may be padded for larger sector
136      * sizes. It is part of a larger structure called the volume boot record
137      * (VBR) that includes OEM parameters, reserved space, and a hash value.
138      * There  should be both a primary and a backup VBR, so there is a primary
139      * MBR and a backup MBR.
140      */
141     typedef struct {
142         uint8_t jump_to_boot_code[3]; ///< 0xEB7690
143         uint8_t fs_name[8];           ///< "EXFAT "
144         uint8_t must_be_zeros[53];    ///< @brief Must be 0x00
145         uint8_t partition_offset[8];  ///< @brief Sector address
146         uint8_t vol_len_in_sectors[8];  ///< @brief Size of total volume in sectors
147         uint8_t fat_offset[4];          ///< Sector address of first FAT
148         uint8_t fat_len_in_sectors[4];  ///< Size of FAT in sectors
149         uint8_t cluster_heap_offset[4]; ///< Sector address of the data region
150         uint8_t cluster_cnt[4];         ///< Number of clusters in the cluster heap
151         uint8_t root_dir_cluster[4];    ///< Cluster address of the root directory
152         uint8_t vol_serial_no[4];     ///< Volume serial number
153         uint8_t fs_revision[2];       ///< VV.MM
154         uint8_t vol_flags[2];         ///< Flags: ActiveFAT, Volume Dirty, Media Failure, Clear to Zero, and Reserved
155         uint8_t bytes_per_sector;     ///< Power of 2. Minimum 2^9 = 512 bytes, maximum 2^12 = 4096 bytes
156         uint8_t sectors_per_cluster;  ///< Power of 2. Minimum 2^1 = 2. Maximum is dependant on the fact that the max cluster size is 32 MiB
157         uint8_t num_fats;             ///< 1 or 2 (only 2 if TexFAT is in use)
158         uint8_t drive_select;         ///< Used by INT 13
159         uint8_t percent_of_cluster_heap_in_use;  ///< Percentage of the heap in use
160         uint8_t reserved[7];      ///< Reserved
161         uint8_t boot_code[390];   ///< Boot program
162         uint8_t signature[2];     ///< 0xAA55
163     } EXFATFS_MASTER_BOOT_REC;
164 
165      /**
166      * exFAT directory entry type byte, containing both the type and
167      * the allocation status
168      */
169     typedef uint8_t EXFATFS_DIR_ENTRY_TYPE;
170 
171     /**
172      * exFAT directory entry types, the first byte of a directory entry minus the
173      * high order bit (which gives allocation status)
174      */
175     enum EXFATFS_DIR_ENTRY_TYPE_ENUM {
176         EXFATFS_DIR_ENTRY_TYPE_NONE = 0x00,         ///< 0x00
177         EXFATFS_DIR_ENTRY_TYPE_VOLUME_LABEL = 0x03, ///< 0x03
178         EXFATFS_DIR_ENTRY_TYPE_VOLUME_GUID = 0x20,  ///< 0x20
179         EXFATFS_DIR_ENTRY_TYPE_ALLOC_BITMAP = 0x01, ///< 0x01
180         EXFATFS_DIR_ENTRY_TYPE_UPCASE_TABLE = 0x02, ///< 0x02
181         EXFATFS_DIR_ENTRY_TYPE_TEXFAT = 0x21,       ///< 0x21
182         EXFATFS_DIR_ENTRY_TYPE_ACT = 0x62,          ///< 0x62
183         EXFATFS_DIR_ENTRY_TYPE_FILE = 0x05,         ///< 0x05
184         EXFATFS_DIR_ENTRY_TYPE_FILE_STREAM = 0x40,  ///< 0x40
185         EXFATFS_DIR_ENTRY_TYPE_FILE_NAME = 0x41     ///< 0x41
186     };
187     typedef enum EXFATFS_DIR_ENTRY_TYPE_ENUM EXFATFS_DIR_ENTRY_TYPE_ENUM;
188 
189     /**
190      * Volume label directory entry structure for exFAT file systems. This
191      * type of entry should be found only in the root directory.
192      */
193     typedef struct {
194         uint8_t entry_type;        ///< 0x83 normally, 0x03 if the media was formatted without a volume label
195         uint8_t volume_label_length_chars;  ///< Number of characters in the volume label
196         uint8_t volume_label[EXFATFS_MAX_VOLUME_LABEL_LEN_BYTE];  ///< Volume label in UTF16
197     } EXFATFS_VOL_LABEL_DIR_ENTRY;
198 
199     /**
200      * Volume GUID directory entry structure for exFAT file systems. This type
201      * of entry should be found only in the root directory.
202      */
203     typedef struct {
204         uint8_t entry_type;    ///< 0xA0
205         uint8_t secondary_entries_count;  ///< Always zero
206         uint8_t check_sum[2];     ///< Set checksum
207         uint8_t flags[2];         ///< Flags: Allocation possible, no FAT chain, custom
208         uint8_t volume_guid[16];  ///< Volume GUID
209         uint8_t reserved[10];     ///< Reserved
210     } EXFATFS_VOL_GUID_DIR_ENTRY;
211 
212     /**
213      * Allocation bitmap directory entry structure for exFAT file systems.
214      * There will be one allocation bitmap for exFAT and two for TexFAT
215      * (transactional exFAT). Bit zero of the flags byte is 0 in the directory
216      * entry for the first bitmap and 1 in the directory entry for the second
217      * bitmap. This type of entry should be found only in the root directory.
218      */
219     typedef struct {
220         uint8_t entry_type;   ///< 0x81
221         uint8_t flags;        ///< 0x00 for first bitmap, 0x01 for the second
222         uint8_t reserved[18]; ///< Reserved
223         uint8_t first_cluster_of_bitmap[4];  ///< Cluster address of first data block
224         uint8_t length_of_alloc_bitmap_in_bytes[8];  ///< Length of the data
225     } EXFATFS_ALLOC_BITMAP_DIR_ENTRY;
226 
227     /**
228      * UP-Case table directory entry structure for exFAT file systems.
229      * The UP-Case table is used to convert file names to upper case when
230      * required. This type of entry should be found only in the root directory.
231      */
232     typedef struct {
233         uint8_t entry_type;   ///< 0x82
234         uint8_t reserved1[3]; ///< Reserved
235         uint8_t table_check_sum[4];  ///< UP-Case table checksum
236         uint8_t reserved2[12];       ///< Reserved
237         uint8_t first_cluster_of_table[4]; ///< Cluster address of first data block
238         uint8_t table_length_in_bytes[8];  ///< Length of the data
239     } EXFATFS_UPCASE_TABLE_DIR_ENTRY;
240 
241     /**
242      * TexFAT (transactional exFAT) directory entry structure for exFAT file
243      * systems. This type of entry should be found only in the root directory.
244      */
245     typedef struct {
246         uint8_t entry_type;    ///< 0xA1
247         uint8_t reserved[31];  ///< Reserved
248     } EXFATFS_TEXFAT_DIR_ENTRY;
249 
250     /**
251      * Access control table directory entry structure for exFAT file systems.
252      * This type of entry should be found only in the root directory.
253      */
254     typedef struct {
255         uint8_t entry_type;   ///< 0xE2
256         uint8_t reserved[31]; ///< Reserved
257     } EXFATFS_ACCESS_CTRL_TABLE_DIR_ENTRY;
258 
259     /**
260      * \internal
261      * It will be followed by a stream directory entry and 1-17 file name
262      * entries. The stream and file name entries are secondary entries. A file
263      * entry and its stream and file name entries constitute a file directory
264      * entry set.
265      */
266     typedef struct {
267         uint8_t entry_type;   ///< 0x85 if allocated, 0x05 if deleted
268         uint8_t secondary_entries_count; ///< Number of entries following the primary directory entry (Range: 2 to 18)
269         uint8_t check_sum[2];     ///< Set checksum
270         uint8_t attrs[2];         ///< File attributes
271         uint8_t reserved1[2];     ///< Reserved
272         uint8_t created_time[2];  ///< Time part of DOS time stamp
273         uint8_t created_date[2];  ///< Date part of DOS time stamp
274         uint8_t modified_time[2]; ///< Time part of DOS time stamp
275         uint8_t modified_date[2]; ///< Date part of DOS time stamp
276         uint8_t accessed_time[2]; ///< Time part of DOS time stamp
277         uint8_t accessed_date[2]; ///< Date part of DOS time stamp
278         uint8_t created_time_tenths_of_sec;   ///< Tenths of seconds part of a DOS time stamp, range is 0-199
279         uint8_t modified_time_tenths_of_sec;  ///< Tenths of seconds part of a DOS time stamp, range is 0-199
280         uint8_t created_time_time_zone_offset;  ///< Time zone difference to UTC in 15 minute increments
281         uint8_t modified_time_time_zone_offset; ///< Time zone difference to UTC in 15 minute increments
282         uint8_t accessed_time_time_zone_offset; ///< Time zone difference to UTC in 15 minute increments
283         uint8_t reserved2[7];  ///< Reserved
284     } EXFATFS_FILE_DIR_ENTRY;
285 
286     /**
287      * Stream extension directory entry structure for exFAT file systems.
288      * It will be preceded by a file directory entry and followed by 1-17
289      * file name directory entries. The stream and file name entries are
290      * secondary entries. A file entry and its stream and file name entries
291      * constitute a file directory entry set.
292      */
293     typedef struct {
294         uint8_t entry_type; ///< 0xC0 if allocated, 0x40 if deleted
295         uint8_t flags;      ///< Flags: Allocation possible, no FAT chain, custom
296         uint8_t reserved1;  ///< Reserved
297         uint8_t file_name_length_UTF16_chars;   ///< Number of characters in UTF16 name contained in following file name directory entries
298         uint8_t file_name_hash[2];  ///< Hash of up-cased file name
299         uint8_t reserved2[2];       ///< Reserved
300         uint8_t valid_data_length[8];  ///< How much actual data has been written to the file. Must be less than data_length
301         uint8_t reserved3[4];          ///< Reserved
302         uint8_t first_cluster_addr[4]; ///< Cluster address of first data block
303         uint8_t data_length[8];        ///< Length of the data. Max 256M for directories
304     } EXFATFS_FILE_STREAM_DIR_ENTRY;
305 
306     /**
307      * File name directory entry structure for exFAT file systems.
308      * It will be preceded by 0-16 file name entries, a stream entry, and
309      * a file entry. A file entry and its stream and file name entries
310      * constitute a file directory entry set. Note that file names are not
311      * null-terminated. The length of a file name is stored in the file stream
312      * entry of the file directory entry set.
313      */
314     typedef struct {
315         uint8_t entry_type;  ///< 0xC1 if allocated, 0x41 if deleted
316         uint8_t flags;       ///< Flags: Allocation possible, no FAT chain, custom
317         uint8_t utf16_name_chars[30];  ///< UTF16 part of file name, max 15 characters
318     } EXFATFS_FILE_NAME_DIR_ENTRY;
319 
320     extern uint8_t
321     exfatfs_open(FATFS_INFO *a_fatfs);
322 
323     extern int8_t
324     exfatfs_is_cluster_alloc(FATFS_INFO *a_fatfs, TSK_DADDR_T a_cluster_addr);
325 
326     extern uint8_t
327     exfatfs_fsstat(TSK_FS_INFO *a_fs, FILE *a_hFile);
328 
329     extern uint8_t
330     exfatfs_is_dentry(FATFS_INFO *a_fatfs, FATFS_DENTRY *a_dentry,
331         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_cluster_is_alloc,
332         uint8_t a_do_basic_tests_only);
333 
334     extern uint8_t
335     exfatfs_is_vol_label_dentry(FATFS_DENTRY *a_dentry,
336         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_cluster_is_alloc);
337 
338     extern uint8_t
339     exfatfs_is_vol_guid_dentry(FATFS_DENTRY *a_dentry,
340         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_alloc_status);
341 
342     extern uint8_t
343     exfatfs_is_alloc_bitmap_dentry(FATFS_DENTRY *a_dentry,
344         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_alloc_status, FATFS_INFO *a_fatfs);
345 
346     extern uint8_t
347     exfatfs_is_upcase_table_dentry(FATFS_DENTRY *a_dentry,
348         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_alloc_status, FATFS_INFO *a_fatfs);
349 
350     extern uint8_t
351     exfatfs_is_texfat_dentry(FATFS_DENTRY *a_dentry,
352         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_alloc_status);
353 
354     extern uint8_t
355     exfatfs_is_access_ctrl_table_dentry(FATFS_DENTRY *a_dentry,
356         FATFS_DATA_UNIT_ALLOC_STATUS_ENUM a_alloc_status);
357 
358     extern uint8_t
359     exfatfs_is_file_dentry(FATFS_DENTRY *a_dentry, FATFS_INFO *a_fatfs);
360 
361     extern uint8_t
362     exfatfs_is_file_dentry_standalone(FATFS_DENTRY *a_dentry, TSK_ENDIAN_ENUM a_endian);
363 
364     extern uint8_t
365     exfatfs_is_file_stream_dentry(FATFS_DENTRY *a_dentry, FATFS_INFO *a_fatfs);
366 
367     extern uint8_t
368     exfatfs_is_file_stream_dentry_standalone(FATFS_DENTRY *a_dentry, TSK_ENDIAN_ENUM a_endian,
369         uint64_t a_cluster_heap_size, TSK_DADDR_T a_last_cluster);
370 
371     extern uint8_t
372     exfatfs_find_file_stream_dentry(FATFS_INFO *a_fatfs, TSK_INUM_T a_file_entry_inum,
373         TSK_DADDR_T a_sector, uint8_t a_sector_is_alloc,
374         EXFATFS_DIR_ENTRY_TYPE a_file_dentry_type,
375         FATFS_DENTRY *a_stream_dentry);
376 
377     extern uint8_t
378     exfatfs_is_file_name_dentry(FATFS_DENTRY *a_dentry);
379 
380     extern TSK_RETVAL_ENUM
381     exfatfs_dinode_copy(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum,
382         FATFS_DENTRY *a_dentry, uint8_t a_is_alloc, TSK_FS_FILE *a_fs_file);
383 
384     extern uint8_t
385     exfatfs_inode_lookup(FATFS_INFO *a_fatfs, TSK_FS_FILE *a_fs_file,
386         TSK_INUM_T a_inum);
387 
388     extern uint8_t
389     exfatfs_istat_attr_flags(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum, FILE *a_hFile);
390 
391     extern uint8_t
392     exfatfs_inode_walk_should_skip_dentry(FATFS_INFO *a_fatfs, TSK_INUM_T a_inum,
393         FATFS_DENTRY *a_dentry, unsigned int a_selection_flags,
394         int a_cluster_is_alloc);
395 
396     extern uint8_t
397     exfatfs_get_alloc_status_from_type(EXFATFS_DIR_ENTRY_TYPE a_dir_entry_type);
398 
399     extern EXFATFS_DIR_ENTRY_TYPE_ENUM
400     exfatfs_get_enum_from_type(EXFATFS_DIR_ENTRY_TYPE a_dir_entry_type);
401 
402     extern TSK_RETVAL_ENUM
403     exfatfs_dent_parse_buf(FATFS_INFO *a_fatfs, TSK_FS_DIR *a_fs_dir, char *a_buf,
404         TSK_OFF_T a_buf_len, TSK_DADDR_T *a_sector_addrs);
405 
406 #ifdef __cplusplus
407 }
408 #endif
409 
410 #endif
411