Overview

While Forefront Endpoint Protection 2010 (FEP) is integrating with System Center Configuration Manager 2007 R2 (ConfigMan) for management and monitoring, out of the box there is no preferred method for pushing updates using SSCM’s Advertisements.

Out of the box, FEP supports 5 methods of getting updates:

  1. WSUS or SUP (Software Update Point in ConfigMan)
  2. UNC shares
  3. Windows Update
  4. Microsoft Security Portal (http://www.microsoft.com/security/encyclopedia/adlpackages.aspx)
  5. Manual method (such as ConfigMan, scheduled scripts or similar solution)

While we have a lot of options, some customers really want to use the Distribution Points and Advertisement in ConfigMan, as they have an existing investment in this and want the most control of the network bandwidth.

In the next version of ConfigMan, Microsoft hopes to include options for automatically approving updates, something that WSUS has and ConfigMan does not. Until then, this article addresses one approach by leveraging the existing SSCM’sdeployment methods.

Architecture

To accomplish this with ConfigMan 2007 R2, we will follow this architecture below:

 Step 1 and 2: We execute a scheduled script that:

  1. Determines the current engine version.
  2. Determines the current signature version.
  3. Downloads either a delta update (if engine and signature have not passed the rebase period) or a full update.
  4. Copies the downloaded file to a location for ConfigMan.

Step 3: On a scheduled basis, we update the remote distribution points with the new update.

Step 4: On a scheduled basis, the client (re)run the update Forefront advertisement.

Setup

While this entire setup could be scripted, part of this article try’s to fully explain what and how things are setup. Please note that this approach only performs delta updates (to optimize network bandwidth) and will not update a new install with the full client. Your FEP policy should include the ability for a client to get the full engine package by using other methods.

Step 1. Create the directoriesC:\FEPUpdates,C:\FEPUpdates\script and C:\FEPUpdates\defs on the Primary Site Server.

 Step 2. In the C:\FEPUpdates\script directory, create the VBS Script in appendix A.

 Step 3. Schedule the script to run every 6 hours by using the Windows Task Scheduler as shown below:

Note: Because this will be a scheduled task, you will need a service account with a non-expiring password.

Step 4. Manually run the scheduled task, so that your directory structure and files will be populated before you setup the program and advertisement in ConfigMan.

Step 5. Create a package in ConfigMan to where the package updates from the source every7 hours as shown below:

Step 6. Create a program in the above package that runs the command cmd.exe /c "%PROCESSOR_ARCHITECTURE%\mpam-d.exe"as shown below:

Step 7. Schedule a reoccurring advertisement  in ConfigMan that runs every 8 hours, as shown below:

  

Appendix A – Download Script

' FEP Download delta definitions

'Customer needs to modify these for local environment

'================================================================================================

strRootLocation =  "C:\FEPUpdates\Defs"  ' this need to be modified to local path for root of the folder structures for updates

strLogFile =  "C:\FEPUpdates\script\DefDownloadv5.log"  ' set this to where you want to save the log file at if not placing in strRootLocation then will need to insure that folder structure exists and specify full path

strLogData =  ""

'================================================================================================

'Constants to not modify value in this area

'================================================================================================

Const ForReading = 1, ForWriting = 2, ForAppending = 8, WindowsFolder = 0

Const TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0

'================================================================================================

LogToEventLog = True

strSigNameDelta =  "mpam-d.exe"

AVDelta =  reduceByOne(ReadReg("HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates\AVSignatureVersion"))

ASDelta =  reduceByOne(ReadReg("HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates\ASSignatureVersion"))

Engine =  ReadReg("HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates\EngineVersion")

strMSEx86URLDelta = "http://go.microsoft.com/fwlink/?LinkID=121721&clcid=0x409&arch=x86&eng=" & Engine & "&avdelta=" & AVDelta & "&asdelta=" & ASDelta

strMSEx64URLDelta = "http://go.microsoft.com/fwlink/?LinkID=121721&clcid=0x409&arch=x64&eng=" & Engine & "&avdelta=" & AVDelta & "&asdelta=" & ASDelta

'=============== Logging Function =======================================

Set objFSO = Createobject("Scripting.FileSystemObject")

if (not objFSO.FileExists(strLogFile)) then

objFSO.CreateTextfile strLogFile

set fileObj = objFSO.GetFile(strLogFile)

set logStream = FileObj.OpenAsTextStream(ForAppending, TristateUseDefault)

logstream.writeline now & " " & "Log file created and opened"

else

set fileObj = objFSO.GetFile(strLogFile)

set logStream = FileObj.OpenAsTextStream(ForAppending, TristateUseDefault)

end if

'=============== Logging Function =======================================

'======================================================

'= Sub to download and save the files

'= __in objConnection winhttprequest object

'= __in strURL the url of the fiel to download

'= __in strPAth the path to save the file to

'= __ FileName name of the file to be saved

sub DownloadDefs(objConnection, strURL, Path, FileName, logfile)

'turn on error handling

on error resume next

'copy PAth to temp variable to manipulate

strPath = Path

'check to see if the URL for x86 or x64 was passed

set regEx = new RegExp

regEx.Pattern = "x86"

regEx.IgnoreCase = True

regEx.Global = False

if (regEx.Test(strUrl)) then

strPath = strPath + "\" + "x86"

Else

strPath = strPath + "\" + "x64"

end if

LogData " > Download of " & strURL & " started at: " & now

objConnection.open "GET", strURL, false

if (err.Number <> 0) then

LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

Err.Clear

exit sub

end if

objConnection.send()

if (err.Number <> 0) then

LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

Err.Clear

exit sub

end if

'check to see if download was successful before moving on

If objConnection.Status = 200 Then

Set objADOStream = CreateObject("ADODB.Stream")

objADOStream.Open

objADOStream.Type = 1 'adTypeBinary

objADOStream.Write objConnection.ResponseBody

objADOStream.Position = 0 'Set the stream position to the start

Set m_objFSO = Createobject("Scripting.FileSystemObject")

'check if folder structure exists

if (m_objFSO.FolderExists(strPath)) then

'create complete path

strCompletePath = strPath + "\" + FileName

'check if file exists if so delete

If m_objFSO.FileExists(strCompletePath) Then m_objFSO.DeleteFile(strCompletePath) end if

if (err.Number <> 0) then

LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

Err.Clear

exit sub

end if

else

m_objFSO.CreateFolder(strPath)

strCompletePath = strPath + "\" + FileName

If m_objFSO.FileExists(strCompletePath) Then m_objFSO.DeleteFile(strCompletePath) end if

if (err.Number <> 0) then

LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

Err.Clear

exit sub

end if

end if

objADOStream.SaveToFile(strCompletePath)

if (err.Number <> 0) then

LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

Err.Clear

end if

objADOStream.Close

LogData " >> " & strCompletePath & " Successfully downloaded at: " & now

end if

'Cleanup

strCompletePath = ""

strPath = ""

Set objADOStream = Nothing

Set m_objFSO = Nothing

 end sub

 function reduceByOne(versionnumber)

versionnumberSplit= Split(versionnumber,".")

reduceByOne = versionnumberSplit(0) & "." & versionnumberSplit(1) & "." & versionnumberSplit(2)-1 & "." & versionnumberSplit(3)

 end function

 sub LogData(mydata)

logStream.writeline mydata

if LogToEventLog then strLogData = strLogData & vbcrlf & mydata

 end sub

 sub WriteToEventLog()

Set WshShell = WScript.CreateObject("WScript.Shell")

WshShell.LogEvent 0, strLogData

 end sub

 Function ReadReg(RegPath)

Dim objRegistry, Key

Set objRegistry = CreateObject("Wscript.shell")

Key = objRegistry.RegRead(RegPath)

ReadReg = Key

 End Function

 '=======================================================================================

 '=== Main program body

 '=======================================================================================

 'Turn on error handling for Main program body

 on error resume next

 

 ' create WINHTTP object used to retrieve the file

 Set objWINHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")

 LogData " "

 LogData "==================== " & now & " Download Session started ===================="

 DownloadDefs objWinHTTP, strMSEx86URLDelta, strRootLocation, strSigNameDelta, logstream

 DownloadDefs objWinHTTP, strMSEx64URLDelta, strRootLocation, strSigNameDelta, logstream

 LogData "===================== " & now & " Download Session ended ====================="

 if LogToEventLog then WriteToEventLog()

'Clean UP

set objFSO = nothing

Set objWINHTTP = Nothing

 

Author

Kevin Saye, Security Technical Specialist – Microsoft

Reviewers

  • Daniel Taylor, Security Technical Specialist – Microsoft
  • Kenneth Bess, Consultant – Microsoft Consulting Services
  • Chris Norman, Escalation Engineer – Microsoft
  • Andrew Plue, Anti-Malware Practice Lead – Certified Security Solutions
  • Adam Rafels, Senior Lead Consultant – Catapult Systems