A long time have I searched for the answer to this question: How old are the antivirus & antispyware signatures in Microsoft's Forefront / Security Essentials products? All of the other web sites out there give you the same bit of code that provides the same answers: Version Number and Applied Date.
Here's a screenshot of the registry settings this code pulls from:
Through experimentation, I've discovered that 'Applied Date' does not necessarily mean 'Definition Signature Date'. It is possible that five minutes ago your PC applied the latest definition file it could find which just happened to be three weeks old. Of course if this happens, you've got bigger issues to deal with; but it is still a possibility.
I looked through WMI and scoured the registry for additional information. I couldn't find any. Yet somehow the Microsoft Security Essentials console window is pulling the Definition Signature Date from somewhere.
Eventually I turned to the actual files that hold the AV and AS definitions. The 'Date created' and 'Date modified' NTFS file properties are unusable for our purposes.
The Antivirus and Antivirus definitions are built from two files (each); a base and a delta. You can see them in the screenshot above. If you were to use a hex editor to open each of the vdm files show above, you could find a timestamp embedded within them. Scroll to the end and look for "Microsoft Timestamping PCA". Then go 92 characters beyond the beginning character of "Microsoft Timestamping PCA". Then grab and parse the next 12 characters into a timestamp. I feel that using this timestamp that is embedded within the file is a safe date to use because a timestamp for a file cannot be applied to a file that does not yet exist. Furthermore, it's got to be timestamped
before it gets handed out to the public.
In this case, the file was signed by Microsoft on 7/7/2010 9:34:59 AM Pacific Standard Time. According to my calculations this timestamp is in Pacific Standard Time and is not affected by Daylight Savings Time.
I wrote some code (and pieced together code from others) to automate this task for me. Here is the output:
The one thing I can't figure out is why the 'AS Signature Applied' date is
before the 'Born on Date' for the AS signature definition delta file. Either there is a flaw in my code or Microsoft's log keeping is a little wonky. Remember, the 'Born on Date' is coming straight out of the file and the 'AS Signature Applied' date is coming out of the registry.
So here's the code. I'm asking for comments and suggestions.
Option Explicit
'Define Constants
Const strKeyPath = "SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates"
Const KEY_QUERY_VALUE = &H0001
Const HKEY_LOCAL_MACHINE = &H80000002
'Define Variants
Dim strValueName
Dim objWMIService
Dim oReg
Dim bHasAccessRight
Dim parameter_value
Dim strSignatureLocation
'Populate Variants
strValueName = "AVSignatureVersion"
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set oReg = objWMIService.Get("StdRegProv")
bHasAccessRight = False
'Check to make sure this user has access to this registry path
oReg.CheckAccess HKEY_LOCAL_MACHINE, strKeyPath, KEY_QUERY_VALUE, bHasAccessRight
If bHasAccessRight = True Then
Wscript.echo " Microsoft Forefront / Security Essentials Antivirus & Antispyware Details:"
Wscript.echo "============================================================================"
' Microsoft AV / Antimalware / Security
strValueName = "AVSignatureVersion"
oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,parameter_value
wscript.echo "Current Version - AV: " & parameter_value
' Microsoft AV / Antimalware / Security
strValueName = "ASSignatureVersion"
oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,parameter_value
wscript.echo "Current Version - AS: " & parameter_value
' Microsoft AV / Antimalware / Security
strValueName = "ASSignatureApplied"
oReg.GetBinaryValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,parameter_value
parameter_value = BinaryToDate(parameter_value)
wscript.echo "When AS Signature Applied: " & parameter_value
' Microsoft AV / Antimalware / Security
strValueName = "AVSignatureApplied"
oReg.GetBinaryValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,parameter_value
parameter_value = BinaryToDate(parameter_value)
wscript.echo "When AV Signature Applied: " & parameter_value
' Get Current Microsoft AV/AS Definition folder
strValueName = "SignatureLocation"
oReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strSignatureLocation
' Get Current AS Definition Base "Born On Date"
parameter_value = GetBornOnDate(strSignatureLocation, "mpasbase.vdm")
wscript.echo "'Born On Date' for AS Base: " & parameter_value
' Get Current AS Definition Base "Born On Date"
parameter_value = GetBornOnDate(strSignatureLocation, "mpasdlta.vdm")
wscript.echo "'Born On Date' for AS Delta: " & parameter_value
' Get Current AV Definition Base "Born On Date"
parameter_value = GetBornOnDate(strSignatureLocation, "mpavbase.vdm")
wscript.echo "'Born On Date' for AV Base: " & parameter_value
' Get Current AV Definition Delta "Born On Date"
parameter_value = GetBornOnDate(strSignatureLocation, "mpavdlta.vdm")
wscript.echo "'Born On Date' for AV Delta: " & parameter_value
End If
WScript.quit
Function GetBornOnDate(strPath, strFile)
' This is a simple example of managing binary files in
' vbscript using the ADODB object
'Define Constants
Const adTypeText = 2
Const adTypeBinary = 1
Const strLookFor = "Microsoft Timestamping PCA"
Const intChars = 300
'Define Variants
Dim inStream
Dim outStream
Dim i
Dim buff
Dim strConverted
Dim strDate
'NOTE: Portions of this code taken from:
' http://nerds-central.blogspot.com/2007/01/ok-you-win-vbscript-read-binary-file.html
' We can create the scream object directly, it does not
' need to be built from a record set or anything like that
set inStream=WScript.CreateObject("ADODB.Stream")
' We call open on the stream with no arguments. This makes
' the stream become an empty container which can be then
' used for what operations we want
inStream.Open
inStream.type=adTypeBinary
inStream.LoadFromFile(strPath & "\" & strFile)
buff=inStream.Read()
inStream.Close()
Set inStream = Nothing
i = 1
'Grab the last 300 characters of the file
strConverted = BinaryToString(Mid(buff,Len(buff) - intChars,intChars))
'Search for "Microsoft Timestamping PCA" in the file and go 92 characters beyond it
strDate = Mid(strConverted, Instr(strConverted, "Microsoft Timestamping PCA") + 92,12)
'Process the date into something readable
strDate = Mid(strDate,3,2) & "/" & Mid(strDate,5,2) & "/" & Mid(strDate,1,2) & " " & _
Mid(strDate,7,2) & ":" & Mid(strDate,9,2) & ":" & Mid(strDate,11,2)
'The Microsoft Forefront / MSE definition files are signed using PST time offset
' The machine that automatically kicks them out does not appear to be
' aware of Daylight Savings Time
' This resets the time back to GMT
strDate = DateAdd("h", -8, strDate)
'Now take into consideration our local Time Offset
strDate = DateAdd("n", GetTimeBias(), strDate)
'Wscript.echo strDate & " Eastern Standard Time"
GetBornOnDate = strDate
End Function
Function BinaryToString(Binary)
'Define Variants
Dim I
Dim S
Dim Temp
S = ""
For I = 1 To LenB(Binary)
'Take one byte at a time ...and chew thoroughly...
Temp = AscB(MidB(Binary, I, 1))
'If the character held within Temp is not an
' ASCII printable character, turn it into a space
Select Case True
Case (Temp < 32)
Temp = 32
Case (Temp > 126)
Temp = 32
End Select
'Add this new character to the string
S = S & Chr(Temp)
Next
'Return the whole string
BinaryToString = S
End Function
Function BinaryToDate(Binary)
Err.Clear
'Define Variants
Dim lngHigh
Dim lngLow
Dim dtmDate
Dim i
'Populate Variants
lngHigh = 0
lngLow = 0
'NOTE: Portions of this code taken from:
' http://www.visualbasicscript.com/m30907.aspx
for i=7 to 4 step -1
lngHigh = lngHigh * 256 + Binary(i)
next
for i=3 to 0 step -1
lngLow = lngLow * 256 + Binary(i)
next
if err.number<>0 then
dtmDate = #1/1/1601#
Err.Clear
else
If lngLow < 0 Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0 ) Then
dtmDate = #1/1/1601#
Else
dtmDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow)/600000000 - GetTimeBias())/1440
End If
End If
BinaryToDate = dtmDate
End Function
Function GetTimeBias
'Define Variants
Dim lngBiasKey
Dim lngBias
' Obtain local Time Zone bias from machine registry.
oReg.GetDWORDValue HKEY_Local_Machine, "System\CurrentControlSet\Control\TimeZoneInformation", "ActiveTimeBias", lngBiasKey
If UCase(TypeName(lngBiasKey)) = "LONG" Then
lngBias = lngBiasKey
ElseIf UCase(TypeName(lngBiasKey)) = "VARIANT()" Then
lngBias = 0
For k = 0 To UBound(lngBiasKey)
lngBias = lngBias + (lngBiasKey(k) * 256^k)
Next
End If
'wscript.echo "lngBias = " & lngBias
GetTimeBias = lngBias
End Function PS. It's been a very long time since I last posted here. It's good to be back.