I am trying to learn the raw binary format of every type of NTFS record and I am making great progress. Related question
I have found Active Disk Editor and it tells me all about the offsets and field names and such for NTFS Master File Table File Records, and there is one thing I don't understand.
In attribute 0x10 $STANDARD_INFORMATION how are the timestamps encoded?
Like, this 8 byte sequence: b'\xb0\x37\x86\x69\x36\x1e\xd7\x01'
, why does it represent 2021-03-21 09:41?
How is it encoded?
I know most numbers in NTFS records are little endian. However, trying to convert it directly to integer will of course yield a very high number, with big endian byte order the number is even higher:
In [133]: int.from_bytes(b'\xb0\x37\x86\x69\x36\x1e\xd7\x01', 'little')
Out[133]: 132607933078190000
In [134]: int.from_bytes(b'\xb0\x37\x86\x69\x36\x1e\xd7\x01', 'big')
Out[134]: 12697765460832081665
Trying to use these numbers as datetime.fromtimestamp
arguments will raise OSError
:
In [135]: from datetime import datetime
In [136]: datetime.fromtimestamp(132607933078190000)
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
Cell In[136], line 1
----> 1 datetime.fromtimestamp(132607933078190000)
OSError: [Errno 22] Invalid argument
Using the first 10 digits will give a date that is too early:
In [137]: datetime.fromtimestamp(int('132607933078190000'[:11]))
Out[137]: datetime.datetime(2390, 3, 21, 17, 41, 47)
In [138]: datetime.fromtimestamp(int('12697765460832081665'[:11]))
Out[138]: datetime.datetime(2372, 5, 18, 5, 4, 20)
In [139]: datetime.fromtimestamp(int('12697765460832081665'[:10]))
Out[139]: datetime.datetime(2010, 3, 28, 19, 42, 26)
In [140]: datetime.fromtimestamp(int('132607933078190000'[:10]))
Out[140]: datetime.datetime(2012, 1, 9, 11, 22, 10)
So how is this timestamp encoded?
This is not a duplicate as the suggested duplicate question doesn't mention converting the 8-byte little endian sequence to integer and none of the answers included this conversion.
There's a comment to the question that gives the source.
Here's the Python code to do the conversion:
ns100 = int.from_bytes(b'\xb0\x37\x86\x69\x36\x1e\xd7\x01', 'little')
timestamp = datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds=ns100 // 10)