Tip: Registry Byte String to Date - Windows Defender SignaturesLastUpdated

Question came up today - how to read Windows Defender signature update time from the registry?

We can read the value from the Registry, but it’s a REG_BINARY value and its meaning is not clear:

q: (it as string) of values "SignaturesLastUpdated" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Signature Updates" of native registry
A: ff9cdd7c6727d901
T: 2.649 ms
I: plural string

We have to understand a bit about how the bytes are stored. 2 hexadecimal characters make a byte, BUT these bytes are stored in reverse order.
Where the bytes are stored as
ff 9c dd 7c 67 27 d9 01
we actually need to read these bytes in reverse to obtain
01 d9 27 67 7c dd 9c ff

The “real” install time is
0x 01 d9 27 67 7c dd 9c ff, which has integer value 133180989414153471, which represents an ANSI timestamp – the number of 100-nanosecond increments passed since midnight of Jan 01, 1601

So, how to read it in Relevance?

First we can split it up into the pairs of characters representing each bytes (‘firsts 2 of’),
and read these bytes in reverse order by starting two characters before the end of the string (length of it - 2), and step backwards in steps of -2 until we reach position 0 - i.e. [integers in (length of it - 2, 0, -2 ]

q: (firsts 2 of following texts of it) of  positions (integers in (length of it - 2, 0, -2)) of (it as string) of values "SignaturesLastUpdated" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Signature Updates" of native registry
A: 01
A: d9
A: 27
A: 67
A: 7c
A: dd
A: 9c
A: ff
T: 2.434 ms
I: plural substring

Now that we have the bytes in the correct order, we can concatenate them back together to make a 16-character / 8-byte hexadecimal string again, this time with the bytes in the correct high-order:

q: concatenation of (firsts 2 of following texts of it) of  positions (integers in (length of it - 2, 0, -2)) of (it as string) of values "SignaturesLastUpdated" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Signature Updates" of native registry
A: 01d927677cdd9cff
T: 1.975 ms
I: singular string

Next we can convert the hexadecimal into an integer…

q: (hexadecimal integer (it)) of concatenation of (firsts 2 of following texts of it) of  positions (integers in (length of it - 2, 0, -2)) of (it as string) of values "SignaturesLastUpdated" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Signature Updates" of native registry
A: 133180989414153471
T: 1.498 ms
I: singular integer

Then, we divide the 100-nanosecond increments by 10,000,000 to get the number of seconds; then, multiply that by ‘second’ and add it to Jan 1, 1601 (the start of ANSI time):

Side note - we have to divide it by 10,000,000 before we multiply it by “second”, otherwise we overflow the storage size of uint16 and throw an error…

q: ("1 Jan 1601 00:00:00 -0000" as time + (it / 10000000 * second ) ) of (hexadecimal integer (it)) of concatenation of (firsts 2 of following texts of it) of  positions (integers in (length of it - 2, 0, -2)) of (it as string) of values "SignaturesLastUpdated" of keys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Signature Updates" of native registry
A: Fri, 13 Jan 2023 09:55:41 -0600
T: 0.989 ms
I: singular time
8 Likes

absolutely brilliant Jason