exFAT Timestamps: exFAT Primer and My Methodology

Following my quick and dirty post on exFAT timestamp behavior I wanted to follow up with a fuller post (or posts) detailing my methodology and observations. I started looking into the workings and different implementations of exFAT because it had been raised David Cowen in one of his recent ‘Sunday Funday' challenges but everywhere I looked there was something interesting requiring further analysis. To that end I will be following up with a few posts detailing how different operating systems handle exFAT and how different tools (forensic and non-forensic) interpret the filesystem.

The original question posed by David was:
ExFAT is documented to have a timezone field to document which timezone a timestamp was populated with. However most tools just see it as FAT and ignore it. For this challenge document for the following operating systems how they populate ExFAT timestamps and which utility will properly show the correct values.
Operating systems:
  • Windows 7
  • Windows 10
  • OSX High Sierra
  • Ubuntu Linux 16.04
At first this seemed like a pretty basic challenge, but it wasn't until I started poking around that I realised the myriad of different issues and inconsistencies in how alternative operating systems implement exFAT. 

This post will serve as a brief introduction to exFAT, focusing principally on how it handles the recording of MAC times. I will also detail my testing methodology for those who are interested before I expand on results in some follow up posts.

exFAT Primer

I won’t go into full detail of the history, functionality and workings of exFAT. Principally because I would all too quickly expose my ignorance, and more importantly, a much better job than I could hope to match up to has already been done by Robert Shullich and Jeff Hamm with various resourced which I came to rely upon when researching exFAT. 

Key resources/ references were:
Robert Shullich’s GCFA Gold Paper ‘Reverse Engineering the Microsoft Extended FAT File System (exFAT)’ (2009)
Jeff Hamm’s paper ‘Extended FAT File System’ (2009)
Jeff Hamm’s post on the SANS Digital Forensics and Incident Response Blog entitled ‘exFAT File System Time Zone Concerns’ (2010)
Jeff and Robert presentation/ talk entitled ‘exFAT (Extended FAT) File System  - Revealed and Dissected' (2010)

I highly recommend the above resources if you need a crash course in exFAT.

As this research focused on time zone field used in exFAT directory records and how exFAT timestamps are populated by different operating systems I have ignored significant other portions of the filesystem in this primer. 

Within exFAT file metadata is stored with Directory Entries. The Directory Entry associated with any particular file will comprise at least three records, a Directory Entry Record, Stream Extension and Filename Extension. Records are 32 bytes long with the first byte being a Type Code which identifies the type of record. Type Codes are addressed in more detail later. 

Due to the details of the testing performed later, the overwhelming majority of Directory Entries reviewed in this post will contain only three records however it should be noted that it is common for a Directory Entry to contain more than three records. This is caused when a filename exceeds a certain length. The maximum filename length which a single Filename Extension Record can support is 15 characters with longer filenames requiring additional Filename Extension Records. Examples of both are seen in the screenshot below:

This screenshot is associated with an exFAT volume named ‘WinFormat’, at the root of the volume there is one directory ‘System Volume Information’ (highlighted in red) and four files, ‘16_04_txt’, ‘18_04.txt’, ‘Win10.txt’ and ‘Win7.txt’, the last of which is highlighted in green. 

Focussing first on the root entry, we have Directory Entry Records, a 'Volume Label Directory Entry' (Starting 0x83), an 'Allocation Bitmap Directory' Entry (Starting 0x81) and an 'UP-Case Table Directory Entry' (Starting 0x82). These are covered in more detail in the recommended reading, however it is the Directory Entries associated with files and containing our file metatada which we are most interested in. Incidentally, 0x83 is the Type Code associated with a named Volume Label Directory Entry, if the volume were unnamed, the Type Code would be 0x03.

This screenshot shows the two entries associated with a directory (Red) and file (Green) respectively, the latter serves as an example of the above detailed use of additional records when a filename is too long. We can see that there are three records associated with the red Directory Entry, a Directory Entry Record (0x51), Stream Extension (0xC0) and Filename Extension (0xC1) while our Directory Entry highlighted in green is the same but contains 2 Filename Extensions (Two concurrent records with the 0xC1 Type Code).

In the following screenshot we dive into the Directory Entry associated with the same file. I couldn’t find any good worked examples for manual decoding so made this one and hope it is useful. 

A brief description of the components is as follows:

Type Code – Details the Record Type. When dealing with active (not deleted) Directory Entry Records, we are interested in 0x85, 0xC0 and 0xC1. We will only deal with these three as we explore Timestamp and Timezone behaviour.

Notable Type Codes you are likely to encounter are:

Type Code  Definition
0x85  Directory Entry Record
0x83  Volume Name Record, Master Entry (Named Volume)
0x03  Volume Name Record. Master Entry (Unnamed Volume)
0x82  Up-Case Table Logical Location and Size
0x81  Bitmap Logical Location and Size
0xC0  Directory Entry Record, Stream Extension
0xC1  Directory Entry Record, Filename Extension
0x05  Deleted File Name Record
0x40  Deleted File Name Record, Stream Extension
0x41  Deleted File Name Record, Filename Extension

Number of Secondary Entries – The number of secondary records associated with the entry. Mentioned previously, my test files generally have short filenames and so their Directory Entries comprise a Directory Entry Record, Stream Extension and Filename Extension, as such they have a value of 2 for the Number of Secondary Entries.

Checksum – Checksum of Record Entry, beyond the scope of this analysis.

Flags – Metadata Flags (Read Only, Hidden, System File and Archive)

Created/ Last Modified / Last Accessed – Now we are talking… These are 32-bit MSDOS timestamps with the associated limitation of having a granularity of 2 seconds. This limitation is accounted for by the use of additional fields to permit greater granularity as detailed later.
A detailed explanation of the 32-Bit Windows Time/Date Format can found here, but to be honest most analysis tools or hex editors are perfectly capable of parsing it. 

Creation/ Last Modified centisecond offset – Additional fields associated with the Creation and Last Modified timestamps allow an operating system to record a value between 0 and 199 to denote the number of centiseconds which should be added to the recorded MSDOS timestamp. Note, no such field exists for the ‘Last Accessed’ value.

Created Time Zone Code / Modified Time Zone Code / Accessed Time Zone Code – 
The Time Zone Code is a one byte value, the most significant bit denotes whether the application/OS which last updated the timestamp supported and made use of the Time Zone Code and therefore whether the time zone offset should be applied during subsequent interpretation. The required offset is then stored as a 7-bit signed integer. The integer itself represents 15-minute increments from UTC, allowing for the accommodation of timezones which do not fall on the hour. In case your were wondering, examples include Eucla, Western Australia (UTC +8:45), Chatham Islands, New Zealand (UTC +12:45) and Nepal (UTC +5:45)

For ease of reference I have transcribed some common (read: “not Eucla, WA”) timezones and their corresponding Time Zone code.

Hex TimeZone Hex TimeZone
0xB8 UTC+14 0x80 UTC
0xB4 UTC+13 0xFC UTC-1
0xB0 UTC+12 0xF8 UTC-2
0xAC UTC+11 0xF4 UTC-3
0xA8 UTC+10 0xF0 UTC-4
0xA4 UTC+9 0xEC UTC-5
0xA0 UTC+8 0xE8 UTC-6
0x9C UTC+7 0xE4 UTC-7
0x98 UTC+6 0xE0 UTC-8
0x94 UTC+5 0xDC UTC-9
0x90 UTC+4 0xD8 UTC-10
0x8C UTC+3 0xD4 UTC-11
0x88 UTC+2 0xD0 UTC-12
0x84 UTC+1

Length – Filename Length (Unicode Characters)

Filename Hash – a hash of the filename, used for expediting searches.

Valid Data Length – Logical File Size (Bytes)

First Cluster Address – Address of the first cluster...

Data Length – Logical File Size (Bytes)

Filename – Unicode string of filename

On the basis of the above it is clear that if we concerned with having a correct understanding of the time/date artefacts associated analysed evidence then there are 8 fields we are interested in, the Created, Modified, and Accessed TimeStamps, each of their corresponding Time Zone Codes and the 0-199 'Centisecond Offset’ fields associated with the Created and Modified Timestamps.

OS Population of Time Stamp and Time Zone fields

The first half of the puzzle is understanding how different operating systems employ the different fields. David posed the question in relation to Windows 7, Windows 10, OSX High Sierra and Ubuntu Linux 16.04, however as I am a glutton for punishment I have chosen to extend the scope to Windows 8.1 and Ubuntu 18.04. I will note here that I strongly considered playing with XP with added exFAT support and Vista as I know that they throw a further spanner in the works with partial implementation of Microsoft’s own filesystem’s functionality… but maybe another day.

Before I detail the testing performed I want to highlight some limitations (deliberate and otherwise):
  1. I am only considering removable media, which is to say, I am considering the impact on an analyst who receives a piece of removable media with no indication as to the configuration of system(s) which have interacted with it. 
  2. I have had to employ virtual machines for some of the OS testing. My assumption is that USB passthrough within VM Worksation works at the physical layer and that a mass storage device used in this way will operate in the same manner as a directly connected device. But it IS an assumption.
  3. I’m a human being. Much of the operations were deliberately performed manually as opposed to using scripts. As such time/date values which I recorded in notes are expected to be off by a few seconds. This could cause errors in my interpretation of the results of any testing, but it was considered throughout the process.
Test Environment
The following systems were used for testing:
  • Windows 10 – Custom Build PC (Windows 10.0.17134.112)
  • Windows 8.1 – VMWare Workstation 14 hosted VM using USB passthough (Version 6.3.9600)
  • Windows 7 – VMWare Workstation 14 hosted VM using USB passthough (Version 6.1.7601)
  • Ubuntu 18.04 – VMWare Workstation 14 hosted VM using USB passthough (Fresh install required addition of exfat-fuse driver)
  • Ubuntu 16.04 – VMWare Workstation 14 hosted VM using USB passthough (SIFT Workstation)
  • OSX High Sierra – MacBook Pro installed with OSX 10.13.3
Tests Performed
Broadly, my testing procedure was as follows:

Volume creation tests
Connect a physical USB device to each of the operating systems and format the drive as exFAT, capturing an image of the drive after each format. This was to facilitate examination of differences (if any) in how the tested operating systems generated the exFAT volume.
File Write Tests (A)
  1. Format a USB device using Windows 10 to employ the latest ‘official’ implementation of exFAT.
  2. Create directories associated with each tested OS on the USB flash drive
  3. Present the flash drive to each test system and then manually perform the following steps:
    1. Create file on USB device (noting time)
    2. Create file on desktop of test system (noting time)
    3. Copy file from desktop to USB device (noting time)
    4. Change Timezone (noting change details)
    5. Create file on USB device (noting time)
    6. Copy file from desktop to USB device (noting time)
    7. Revert timezone - London (UTC+1)
    8. Cut/Paste (Move) file to USB device (noting time)
The aim of this test was to establish how the different operating systems employed and modified (or didn’t) the different timestamps during these operations.

During this testing phase all actions were performed manually where possible. E.g. Using right click “new file” etc to simulate user behaviour and copy/paste within the GUI to move files. Ubuntu does not support this method of creating a file (to my knowledge) and I didn't want to rely upon any other significant applications lest they have an impact on how the OS operates. In those instances the ‘touch’ command was used on the command line to generate the test files.

File Write Tests (B)
1. Format a USB device using Windows 10 to employ the latest ‘official’ implementation of exFAT.
2. Present the flash drive to each test system and then employ scripting methods to create a textfile on the root of the drive named per the tested OS and containing a string representation of the date/time at which the action was performed.
a. E.g. for Ubuntu: date > 16_04.txt

File Write Tests (C)
Replicated File Write Tests (A) in a fully automated fashion where unexplained anomalies had been observed. Only performed for a limited number of Operating Systems and specific tests. 

The results of all test were then written to a spreadsheet where the date/time as recorded in notes could be compared to the relevant fields as they appear on disk. I then furnished the same spreadsheet with details as to how each tool I analysed displayed the timestamps, and as I am sure any reader will agree this made things immediately clear:

While the spreadsheet of doom is fairly daunting it does allow for the easy identification of patterns and anomalies, the core conclusion at this point is that there were more anomalies than consistencies and that there was a lot more work to do.

I will be exploring the different operating systems one by one in follow up posts and will go into how the relevant fields are (or are not) populated.


  1. Adam. This comment is in case you have not seen the reply that I left to your tweet on the HECFBlog twitter page regarding "FC" as a time zone offset. I pointed out that it does not equate to UTC-1. Rather it is a time zone offset of -1. Given that your computer probably is set to British Summer Time (UTC +1), if you add the TZoffset of -1 ("0xFC) to your local time, you will get UTC. The same would apply to Oleg's +3/-3. Hope this helps.

    Paul Bryant

    1. Hi Paul, I am afforded a little more space to reply here than Twitter's 240 character limit so hopefully I can be more clear.

      Within Windows 7, 8.1 and 10 the time as recorded in the timestamp field is as it appears to the user (i.e. the local system time with with the timezone offset applied). Creating a file at 1500hrs in a timezone of UTC+0 causes the MSDOS 32-bit timestamp representation of 1500hrs to be written to disk and doing the same with the timezone set to UTC+3 causes the timestamp to be written as 1800hrs. The TimeZone field is, as you suggest, the offset which should be applied to convert the timestamp to UTC however to all intents and purposes saying that you need to apply a timezone offset of -1 hour to get UTC and stating that the timezone field indicates that the the timestamp is the equivilent of UTC+1 is the same thing.

      What I considered notable is that OSX, at 1600hrs (UTC) on a system configured with a timezone of UTC+1 (displaying 1700hrs as the current time) the time written to the timestamp was 1500hrs which is equivalent to UTC-1. So the recorded time as written in the MSDOX 32bit timestamp was neither UTC, nor local time but rather in UTC-1 and an appropriate offset of 0xFC was then recorded. Further, when the timezone was amended on the system, this did not appear to have an immediate effect. In my testing the offset remained 0xFC and the time continued to be written in an accurate UTC-1 value even when the system timezone was amended to UTC+3. I imagine this behavior would not survive a reboot but I plan to test this.