AntiMalware log events

CollectAntiMalwareInformation (Rule)

This rule collects antimalware information and sends it to the cloud

Element properties:

TargetMicrosoft.Windows.Computer
CategoryCustom
EnabledFalse
Alert GenerateFalse
RemotableFalse

Member Modules:

ID Module Type TypeId RunAs 
DS DataSource TimedPowershellPropertyBagProvider Default
WA2 WriteAction Microsoft.SystemCenter.AntiMalwareInformationDataWriteAction Default

Source Code:

<Rule ID="CollectAntiMalwareInformation" Enabled="false" Target="Windows!Microsoft.Windows.Computer" ConfirmDelivery="false" Remotable="false">
<Category>Custom</Category>
<DataSources>
<DataSource ID="DS" TypeID="TimedPowershellPropertyBagProvider">
<IntervalSeconds>3600</IntervalSeconds>
<SyncTime/>
<ScriptName>CollectLastUpdateTime</ScriptName>
<ScriptBody><Script>

Param(
[parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$logfile = "$env:windir\debug\mrt.log",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$showCount = "false",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$retryTimeInSeconds = 10
)

&lt;#
Defines Protection and Threat Status Codes. Implement general Add-MalwareScan function for all modules.
#&gt;

$global:malwareScans = @();

#region Protection Status Codes and Rankings
$ThreatDetectedProtectionCode = @( 550, "Threat Detected" )
$UnknownProtectionCode = @( 470, "Unknown" )
$NotReportingProtectionCode = @( 450, "Not Reporting" )
$ActionRequiredProtectionCode = @( 350, "Action Required" )
$NoRealTimeProtectionProtectionCode = @( 270, "No real time protection" )
$SignaturesOutOfDateProtectionCode = @( 250, "Signatures out of date" )
$RealTimeProtectionCode = @( 150, "Real time protection" )
#endregion

#region Threat Status Codes and Rankings
$ActiveThreatCode = @( 550, "Active" )
$UnknownThreatCode = @( 470, "Unknown" )
$RemediatedThreatThreatCode = @( 370, "Remediated" )
$QuarantinedThreatCode = @( 350, "Quarantined" )
$BlockedThreatCode = @( 330, "Blocked" )
$AllowedThreatCode = @( 250, "Allowed" )
$NoThreatsDetectedThreatCode = @( 150, "No threats detected" )
#endregion

function Add-MalwareScan {
param(
$ProtectionRank,
$ProtectionStatus,
$ProtectionStatusDetails,
$DetectionId,
$Threat,
$ThreatStatusRank,
$ThreatStatus,
$ThreatStatusDetails,
$Signature,
$ScanDate,
$DateCollected,
$ToolName
)
try {
$scanDateInt = $ScanDate.ToUniversalTime().ToString("G", [System.Globalization.CultureInfo]::InvariantCulture);
} catch {
$scanDateInt = $ScanDate;
}

try {
$dateCollectedInt = $DateCollected.ToUniversalTime().ToString("G", [System.Globalization.CultureInfo]::InvariantCulture);
} catch {
$dateCollectedInt = $DateCollected;
}

$malware_scan = @{};
$malware_scan.ProtectionStatusRank = $ProtectionRank;
$malware_scan.ProtectionStatus = $ProtectionStatus;
$malware_scan.ProtectionStatusDetails = $ProtectionStatusDetails;
$malware_scan.DetectionId = $DetectionId;
$malware_scan.Threat = $Threat;
$malware_scan.ThreatStatusRank = $ThreatStatusRank;
$malware_scan.ThreatStatus = $ThreatStatus;
$malware_scan.ThreatStatusDetails = $ThreatStatusDetails;
$malware_scan.Signature = $Signature;
$malware_scan.Tool = $ToolName;
$malware_scan.ScanDate = $scanDateInt
$malware_scan.DateCollected = $dateCollectedInt
$global:malwareScans += $malware_scan;
} # Contains general definision and
&lt;#
Extracts Anti-Malware information via Microsoft AM Engine PowerShell commands.
Two sets of commands are supported: Defender &amp; SCEP.
#&gt;

$global:msRetryTimeoutInSeconds = 10;
$global:msTimeWindowInHours = 24;
$global:msMpModuleCommands = $null

Function Scan-ComputerStatus
{
Param(
[parameter(Mandatory=$true, ValueFromPipeline=$false)]
[PSObject]$mpModuleCommands,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$retryTimeoutInSeconds = 10,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24
)

$global:msRetryTimeoutInSeconds = $retryTimeoutInSeconds;
$global:msTimeWindowInHours = $timeWindowInHours;
$global:msMpModuleCommands = $mpModuleCommands;

$ThreatStatusFromStatusCode = @{
"0" = $UnknownThreatCode, "Unknown";
"1" = $ActiveThreatCode, "Detected";
"2" = $RemediatedThreatThreatCode, "Cleaned";
"3" = $QuarantinedThreatCode, "Quarantined";
"4" = $RemediatedThreatThreatCode, "Removed";
"5" = $AllowedThreatCode, "Allowed";
"6" = $BlockedThreatCode, "Blocked";
"Blocked" = $BlockedThreatCode, "CleanFailed";
"102" = $ActiveThreatCode, "QuarantineFailed";
"103" = $ActiveThreatCode, "RemoveFailed";
"104" = $QuarantinedThreatCode, "AllowFailed";
"105" = $UnknownThreatCode, "Abandoned";
"107" = $RemediatedThreatThreatCode, "BlockedFailed";
}

Set-StrictMode -Version 2

$currentTime = (Get-Date);
$computerStatus = $null;
$threatDetections = $null;

$protectionStatusCode = $UnknownProtectionCode;
($protectionRank, $protectionStatus) = $UnknownProtectionCode;
$protectionStatusDetails = "Unable to determine status";

($threatStatusRank, $threatStatus) = $UnknownThreatCode;
$threatStatusDetails = "Unable to determine status";

$signature = "";


# Get Computer Status information
try {
$computerStatus = Collect-ComputerStatus

if ($computerStatus -ne $null) {
$protectionStatusDetails = "";

# See if any of the protection aspects are disabled

$protectionStatusDetailsEnableArray = @();

if ($computerStatus.AMServiceEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "Antimalware disabled";
}
if ($computerStatus.OnAccessProtectionEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "On access protection disabled";
}
if ($computerStatus.IoavProtectionEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "Ioav protection disabled";
}
if ($computerStatus.BehaviorMonitorEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "Behavior monitor disabled";
}
if ($computerStatus.AntivirusEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "Antivirus disabled";
}
if ($computerStatus.AntispywareEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "Antispyware disabled";
}
if ($computerStatus.RealTimeProtectionEnabled -eq $false) {
$protectionStatusDetailsEnableArray += "Real-time protection disabled";
}

# Check currency of signatures and quick scan

$protectionStatusDetailsAgeArray = @();

if ($computerStatus.AntispywareSignatureAge -gt 7) {
$protectionStatusDetailsAgeArray += "Antispyware";
}
if ($computerStatus.AntivirusSignatureAge -gt 7) {
$protectionStatusDetailsAgeArray += "Antivirus";
}

if ($protectionStatusDetailsEnableArray.length -gt 0) {
$protectionStatusCode = $NoRealTimeProtectionProtectionCode;
$protectionStatusDetails += [string]::join('; ', $protectionStatusDetailsAgeArray);
$protectionStatusDetails += ";";
}
elseif ($protectionStatusDetailsAgeArray.length -gt 0) {
$protectionStatusCode = $SignaturesOutOfDateProtectionCode;
$protectionStatusDetails += "Signatures older than 7 days:";
$protectionStatusDetails += [string]::join('; ', $protectionStatusDetailsAgeArray);
$protectionStatusDetails += ";";
} else {
$protectionStatusCode = $RealTimeProtectionCode
$protectionStatusDetails = "AntivirusSignatureLastUpdated:" + $ComputerStatus.AntivirusSignatureLastUpdated;
}

($protectionRank, $protectionStatus) = $protectionStatusCode;

$signature = $ComputerStatus.AntivirusSignatureVersion;
}
} catch {
#
# Something bad happened - Everything goes to not reporting status
#
($protectionRank, $protectionStatus) = $NotReportingProtectionCode;
$protectionStatusDetails = "Failed to collect computer status";
$ErrorMessage = $protectionStatusDetails + "; ErrorMessage:" + $_.Exception.Message;
Write-Warning $ErrorMessage
}

#
# Report about Protection Status State
#

($threatStatusRank, $threatStatus) = $NoThreatsDetectedThreatCode;
$threatStatusDetails = "";
$detectionId = [System.Guid]::NewGuid().ToString();

Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails $detectionId "" $threatStatusRank $threatStatus $threatStatusDetails `
$signature $currentTime $currentTime $global:msMpModuleCommands.ToolName;

#
# Get Threads Detection information
#

try {

$threatDetections = Collect-DetectionStatus

if ($threatDetections -ne $null) {

$pastDateTime = (Get-Date).AddHours(-$global:msTimeWindowInHours);

($protectionRank, $protectionStatus) = $ThreatDetectedProtectionCode;
$protectionStatusDetails = "At least one threat detected";

foreach ($threatDetection in $threatDetections) {
# Determine the threat categories based on ThreatStatusID
(($threatStatusRank, $threatStatus), $threatStatusDetails) = ThreatStatusFromStatusCode $threatDetection.ThreatStatusID.ToString();
$scanDate = $threatDetection.LastThreatStatusChangeTime;

if ($threatStatus -eq $ActiveThreatCode[1] &lt;#Active Threat#&gt; -or
$scanDate -ge $pastDateTime &lt;#Filter threads by Time Window#&gt;)
{
$threatStatusDetails += "; ThreatID:" + $threatDetection.ThreatID + "; Resources:" + $threatDetection.Resources;
$threatName = Get-ThreatNameById $threatDetection.ThreatID;
$detectionId = $threatDetection.DetectionID.Substring(1, $threatDetection.DetectionID.Length-2);

Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails $detectionId `
$threatName $threatStatusRank $threatStatus $threatStatusDetails $signature `
$scanDate $currentTime $global:msMpModuleCommands.ToolName
}
}
}

} catch {
#
# Something bad happened - Failed to collect threat detections
#
($threatStatusRank, $threatStatus) = $UnknownThreatCode;
$threatStatusDetails = "Failed to collect threat detections";
$ErrorMessage = $threatStatusDetails + "; ErrorMessage:" + $_.Exception.Message;
Write-Warning $ErrorMessage

Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails "" "" $threatStatusRank $threatStatus $threatStatusDetails `
$signature $currentTime $currentTime $global:msMpModuleCommands.ToolName;
}
}

function Get-ThreatStatusFromStatusCode {
param(
$ThreatStatusID
)

(($threatStatusRank, $threatStatus), $threatStatusDetails) = $ThreatStatusFromStatusCode[$ThreatStatusID];

if ($threatStatusRank) {
return $ThreatStatusFromStatusCode[$ThreatStatusID];
}
else {
(($threatStatusRank, $threatStatus), $threatStatusDetails) = $ThreatStatusFromStatusCode["0"];
$threatStatusDetails += " (ThreatStatusID:" + $ThreatStatusID + ")";
return (($threatStatusRank, $threatStatus), $threatStatusDetails);
}
}

function Get-ThreatNameById {
param(
$ThreatID
)
# get the threat associated with detection
$threatName = "Unknown"; # defaults to unknown threat name
try {
$threats = Collect-Threats
$threat = $threats | Where-Object { $_.ThreatID -eq $ThreatID } | Select-Object -First 1
if ($threat -ne $null) {
$threatName = $threat.ThreatName;
}
}
catch {
Write-Warning "Failed to collect threat information"
}
$threatName
}

function Collect-ComputerStatus {
foreach ($attempt in 1..5) {
try {
$status = &amp;$global:msMpModuleCommands.GetMpComputerStatusCmdName #Get-MProtComputerStatus
return $status;
}
catch {
if ($attempt -ne 5) {
Start-Sleep -s $global:msRetryTimeoutInSeconds
} else {
throw
}
}
}
}

function Collect-Threats {
foreach ($attempt in 1..5) {
try {
$threats = &amp;$global:msMpModuleCommands.GetMpThreatCmdName #Get-MProtThreat
return $threats;
}
catch {
if ($attempt -ne 5) {
Start-Sleep -s $global:msRetryTimeoutInSeconds
} else {
throw
}
}
}
}

function Collect-DetectionStatus {
foreach ($attempt in 1..5) {
try {
$threatsDetections = @()
$threatsDetectionInfo = &amp;$global:msMpModuleCommands.GetMpThreatDetectionCmdName #Get-MProtThreatDetection
foreach ($tdi in $threatsDetectionInfo)
{
$threatsDetections += $tdi
}
if($threatsDetections.Count -eq 1)
{
return ,$threatsDetections
}
return $threatsDetections
}
catch {
$ErrorMessage = "Failed to call " + $global:msMpModuleCommands.GetMpThreatDetectionCmdName;
Write-Warning $ErrorMessage;
if ($attempt -ne 5) {
Start-Sleep -s $global:msRetryTimeoutInSeconds
} else {
throw
}
}
}
}
# Extracts Anti-Malware information via Microsoft AM Engine PowerShell commands.
&lt;#
Detects Windows Defender AM Engine and returns set of PowerShell commands for MsEngineLib module.
#&gt;

Function Detect-Defender
{
try {
$mpComputerStatus = Get-MpComputerStatus;
return ($mpComputerStatus -ne $null);
}
catch {
return $false;
}
}

Function Get-DefenderCommands
{
return New-Object PSObject -Property @{
GetMpComputerStatusCmdName="Get-MpComputerStatus";
GetMpThreatCmdName="Get-MpThreat";
GetMpThreatDetectionCmdName="Get-MpThreatDetection";
ToolName="Windows Defender";
}
}

# Detects Windows Defender AM Engine and returns set of PowerShell commands for MsEngineLib module.
&lt;#
Detects System Center Endpoint Protection (SCEP) AM Engine and returns set of PowerShell commands for MsEngineLib module.
#&gt;

Function Detect-SCEP
{
try {
$module = Import-SCEPMpModule;
return ($module -ne $null);
}
catch {
return $false;
}
}

Function Get-SCEPCommands
{
return New-Object PSObject -Property @{
GetMpComputerStatusCmdName="Get-MProtComputerStatus";
GetMpThreatCmdName="Get-MProtThreat";
GetMpThreatDetectionCmdName="Get-MProtThreatDetection";
ToolName="System Center Endpoint Protection";
}
}

Function Import-SCEPMpModule
{
$mpModulePaths = @(
"$env:ProgramFiles\Microsoft Security Client\MpProvider\MpProvider.psd1"
);

foreach ($mpModulePath in $mpModulePaths)
{
$path = [System.Environment]::ExpandEnvironmentVariables($mpModulePath)
if (Test-Path $path)
{
$mpModule = Import-Module $path -PassThru
if ($mpModule -ne $null)
{
return $mpModule;
}
}
}

return $null;
} # Detects System Center Endpoint Protection (SCEP) AM Engine and returns set of PowerShell commands for MsEngineLib module.
&lt;#
.SYNOPSIS

Parses the Malicious Software Removal Tool logfile

.DESCRIPTION

Outputs a summary from each run of the Malicious Software Removal Tool, showing:
* return code
* signature version or build number
* scan date
* protection status
* threat status
* malware found
* action taken

.PARAMETER logfile

Path to the logfile to be read.
Default is %windir%\debug\mrt.log

.PARAMETER timeWindowInHours

Controls how many hours in the past to look for scans. (Always returns latest scan)

Default is 24

.PARAMETER showCount

Controls whether the count of total records parsed is output

#&gt;


Function Detect-MsrtLog
{
try {
return (Test-Path $logfile);
}
catch {
return $false;
}
}

Function Scan-MsrtLog
{
Param(
[parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$logfile = "$env:windir\debug\mrt.log",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$showCount = "false"
)

Set-StrictMode -Version 2

#region ProtectionCodes
$ProtectionStatusFromStatusCode = @{
"-1" = $NotReportingProtectionCode;
"0" = $NoRealTimeProtectionProtectionCode;
"1" = $NotReportingProtectionCode;
"2" = $NotReportingProtectionCode;
"3" = $NotReportingProtectionCode;
"4" = $NotReportingProtectionCode;
"5" = $UnknownProtectionCode;
"6" = $ThreatDetectedProtectionCode;
"7" = $ThreatDetectedProtectionCode;
"8" = $ActionRequiredProtectionCode;
"9" = $ActionRequiredProtectionCode;
"10" = $ActionRequiredProtectionCode;
"11" = $ActionRequiredProtectionCode;
"12" = $ActionRequiredProtectionCode;
"13" = $ActionRequiredProtectionCode;
}
#endregion

#region MSRTCodes
# MSRT protection status return code taken from http://support.microsoft.com/kb/891716
$DescriptionFromStatusCode = @{
"-1" = "Not reporting - Unable to collect data";
"0" = "No infection found";
"1" = "Not reporting - OS Environment Error";
"2" = "Not reporting - Not running as an Administrator";
"3" = "Not reporting - Not a supported OS";
"4" = "Not reporting - Error Initializing the scanner. (Download a new copy of the tool)";
"5" = "Unknown";
"6" = "At least one infection detected.";
"7" = "At least one infection was detected, but errors were encountered.";
"8" = "Manual steps are required for a complete removal.";
"9" = "Manual steps are required for complete removal and errors were encountered.";
"10" = "Restart is required for complete removal";
"11" = "Restart is required for complete removal and errors were encountered";
"12" = "Manual steps and a restart is required for complete removal.";
"13" = "Restart is required.";
}
#endregion

$build = ""
$returnCode = ""
$signatureVersion = ""
$scanDate = ""
$malware = @()
$malware_found = ""
$malware_details_found = ""
$currentTime = (Get-Date);
$countRecords = 0

foreach ($line in (Get-Content $logfile) )
{
Write-Debug "&gt;$line"
switch -regex ($line)
{
"^-{87}$" # record separator is 87 -, reset values
{
Write-Debug "New record"
$build = ""
$returnCode = ""
$signatureVersion = ""
$scanDate = ""
$malware = @()
$malware_found = ""
$malware_details_found = ""
}

"build ([\d.]+)"
{
$build = $Matches[1]
Write-Debug "Build = $build"
}

"^Started On (.+)"
{
$scanDate = $Matches[1]
Write-Debug "ScanDate = $scanDate"
}

"^Signatures: ([\d.]+)"
{
$signatureVersion = $Matches[1]
Write-Debug "Signature Version = $signatureVersion"
}

"^Threat Detected: (\S+?)(, | and )(.*)$"
{
$malware_found = $Matches[1]
$malware_details_found = $Matches[3]
Write-Debug "Malware: $malware_found, Details: $malware_details_found"
}

" Action: (\w+), Result: ([\d\w]+)"
{
$action = $Matches[1]
$actionCode = $Matches[2]
if (($action -eq "Remove" -or $action -eq "Clean") -and $actionCode -eq "0x00000000")
{
$threat_status = $RemediatedThreatThreatCode
}
else
{
$threat_status = $ActiveThreatThreatCode
}

$item = @{};
$item.Threat = $malware_found;
($item.ThreatStatusRank, $item.ThreatStatus) = $threat_status;
$item.ThreatStatusDetails = $malware_details_found;

$malware += $item
Write-Debug "$malware_found : $item"
}

"^Return code: (\d+)"
{
$returnCode = $Matches[1]
Write-Debug "Return code = $returnCode"

$countRecords += Add-Line $returnCode $build $signatureVersion $scanDate $malware $currentTime;
}
}
}

if ($countRecords -eq 0)
{
$countRecords += Add-Line "" "" "" "" @() $currentTime;
}

if ($showCount -eq "true")
{
Write-Host "$countRecords processed"
}
}

function Add-Line
{
param(
$returnCode,
$build,
$signatureVersion,
$scanDate,
$malware,
$collectedDateTime)

Write-Debug "$returnCode, $build, $signatureVersion, $scanDate, $malware"

$scanDateTime = (Get-Date).ToUniversalTime().Date.ToLocalTime() # scanDateTime will default to 12:00:00AM of the current date if log file doesn't exist or if it cannot parse the format of the MSRT log file
$threatStatus = ""
$returnProtectionStatus = ""
$returnProtectionRank = ""
$returnScanDate = ""
$toolName = "Malicious Software Removal Tool";
$countRecords = 0;

if ($scanDate -ne "")
{
try
{
$scanDateTime = ([datetime]::ParseExact($scandate, 'ddd MMM dd HH:mm:ss yyyy', [System.Globalization.CultureInfo]::InvariantCulture)) # MSRT Date format is not a standard format
}
catch
{
Write-Verbose "Scan date not valid: $scanDate"
}
}

$nowMinusTimeWindow = (Get-Date).AddHours(-$timeWindowInHours)
if ($scanDateTime -gt $nowMinusTimeWindow)
{
if ($returnCode -eq "")
{
$returnCode = "-1";
}

($returnProtectionRank, $returnProtectionStatus) = $ProtectionStatusFromStatusCode[$returnCode];

if ($signatureVersion -eq "")
{
if ($build -ne "")
{
$signatureVersion = $build
}
else
{
$signatureVersion = "Unknown"
}
}

if ($malware.Count -gt 0 )
{
foreach ($item in $malware)
{
$detectionId = [System.Guid]::NewGuid().ToString();
Add-MalwareScan $returnProtectionRank $returnProtectionStatus $DescriptionFromStatusCode[$returnCode] $detectionId `
$item.Threat $item.ThreatStatusRank $item.ThreatStatus $item.ThreatStatusDetails `
$signatureVersion $scanDateTime $collectedDateTime $toolName;

$countRecords++;
}
}
else
{
if ($returnCode -eq -1) {
($threatStatusRank, $threatStatus) = $UnknownThreatCode;
} else {
($threatStatusRank, $threatStatus) = $NoThreatsDetectedThreatCode;
}

$detectionId = [System.Guid]::NewGuid().ToString();

Add-MalwareScan $returnProtectionRank $returnProtectionStatus $DescriptionFromStatusCode[$returnCode] `
$detectionId "" $threatStatusRank $threatStatus "" $signatureVersion $scanDateTime $collectedDateTime $toolName;

$countRecords++;
}
}

return $countRecords;
}
# Parses the Malicious Software Removal Tool logfile.
&lt;#
Detects Windows Security Center and Extract Protection information via WSC API.

enum _WSC_SECURITY_PRODUCT_STATE {
WSC_SECURITY_PRODUCT_STATE_ON = 0,
WSC_SECURITY_PRODUCT_STATE_OFF = 1,
WSC_SECURITY_PRODUCT_STATE_SNOOZED = 2,
WSC_SECURITY_PRODUCT_STATE_EXPIRED = 3
}

enum _WSC_SECURITY_SIGNATURE_STATUS {
WSC_SECURITY_PRODUCT_OUT_OF_DATE = 0,
WSC_SECURITY_PRODUCT_UP_TO_DATE = 1
}
#&gt;

$global:wscRetryTimeoutInSeconds = 10;
$global:wscTimeWindowInHours = 24;

Function Detect-WSC
{
try {
$productsList = New-Object -ComObject wscAPI.WSCProductList;
return ($productsList -ne $null);
}
catch {
return $false;
}
}

Function Scan-WSCStatus
{
Param(
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$retryTimeoutInSeconds = 10,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24
)

$global:wscRetryTimeoutInSeconds = $retryTimeoutInSeconds;
$global:wscTimeWindowInHours = $timeWindowInHours;

Set-StrictMode -Version 2

$currentTime = (Get-Date);

$protectionStatusCode = @(0, "");
$protectionStatusDetails = "";
$computerStatus = $null;
$threatDetections = $null;
($threatStatusRank, $threatStatus) = $UnknownThreatCode;

$productsList = New-Object -ComObject wscAPI.WSCProductList;
$provider = 4; #WSC_SECURITY_PROVIDER_ANTIVIRUS
$productsList.Initialize($provider);

#Find Product in ON state
$productInOnStateInx = -1;
for ($i=0; $i -lt $productsList.Count; $i++){
if ($productsList.Item($i).ProductState -eq 0) {
$productInOnStateInx = $i;
}
}

for ($i=0; $i -lt $productsList.Count; $i++){

# Report only one record in case of On Product was found
if (($productInOnStateInx -ne -1) -and ($i -ne $productInOnStateInx )) {
continue;
}

switch ($productsList.Item($i).ProductState) {
"0" &lt;# WSC_SECURITY_PRODUCT_STATE_ON #&gt; {
if ($productsList.Item($productInOnStateInx).SignatureStatus -eq 1) &lt;# WSC_SECURITY_PRODUCT_UP_TO_DATE #&gt; {
($protectionRank, $protectionStatus) = $RealTimeProtectionCode;
} else {
($protectionRank, $protectionStatus) = $SignaturesOutOfDateProtectionCode;
}
}
"1" &lt;# WSC_SECURITY_PRODUCT_STATE_OFF #&gt; {
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}
"2" &lt;# WSC_SECURITY_PRODUCT_STATE_SNOOZED #&gt; {
($protectionRank, $protectionStatus) = $ActionRequiredProtectionCode;
}
"3" &lt;# WSC_SECURITY_PRODUCT_STATE_EXPIRED #&gt; {
($protectionRank, $protectionStatus) = $ActionRequiredProtectionCode;
}
}

$detectionId = [System.Guid]::NewGuid().ToString();
$toolName = "WSC:" + $productsList.Item($i).ProductName;
Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails `
$detectionId "" $threatStatusRank $threatStatus "" `
"" $productsList.Item($i).ProductStateTimestamp $currentTime $toolName;
}
} # Detects Windows Security Center and Extract Protection information via WSC API.
#
# Implements Main logic for OMS Anti-Malware solution:
# Run different AM Engines in predefined order, collect &amp; format results and pass its to ODS.
# Create ETW event for debug purpose
#

Function LogScriptEvent
{
Param(
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
$oAPI=$null,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$ScriptName = "",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$EventID = 9999,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$Severity = 0,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$Description = "")

if ($oAPI -ne $null)
{
$oAPI.LogScriptEvent($ScriptName, $EventID, $Severity, $Description);
}
}

Function Run-DetectionInt
{
Param(
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
$oAPI = $null,
[parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$logfile = "$env:windir\debug\mrt.log",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$showCount = "false",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$retryTimeInSeconds = 10,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$deviceName = ""
)

LogScriptEvent $oAPI "AntiMalware Collection Script Started" 9991 0 "";
$SymantecCommands = Get-SymantecCommands;
$trendMicroCommands = Get-TrendMicroCommands;

if (Detect-Symantec $SymantecCommands) {
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine" 9992 0 "Symentec Endpoint Protection";
Scan-SymantecStatus $SymantecCommands
} elseif (Detect-TrendMicro $trendMicroCommands) {
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine " 9992 0 "Trend Micro Deep Security";
Scan-TrendMicroStatus $trendMicroCommands $timeWindowInHours $deviceName
} elseif (Detect-SCEP) {
$SCEPCommands = Get-SCEPCommands
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine" 9992 0 $SCEPCommands.ToolName;
Scan-ComputerStatus $SCEPCommands $retryTimeInSeconds $timeWindowInHours;
} elseif (Detect-Defender) {
$DefenderCommands = Get-DefenderCommands
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine" 9992 0 $DefenderCommands.ToolName;
Scan-ComputerStatus $DefenderCommands $retryTimeInSeconds $timeWindowInHours ;
} elseif (Detect-WSC) {
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine", 9992 0 "Windows Security Center";
Scan-WSCStatus $retryTimeInSeconds $timeWindowInHours
} elseif (Detect-MsrtLog) {
$decription = "MSRT, Logfile Path:" + $logfile;
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine " 9992 0 $decription;
Scan-MsrtLog $logfile $timeWindowInHours $showCount
} else { # No AM Engine was detected
LogScriptEvent $oAPI "AntiMalware Collection Script Detected Engine " 9992 0 "No Anti-Malware Tool was detected";
($threatStatusRank, $threatStatus) = $UnknownThreatCode;
($protectionRank, $protectionStatus) = $UnknownProtectionCode;

$detectionId = [System.Guid]::NewGuid().ToString();
$toolName = "No Anti-Malware Tool was detected";
$currentTime = (Get-Date);

Add-MalwareScan $protectionRank $protectionStatus "" $detectionId `
"" $threatStatusRank $threatStatus "" `
"" $currentTime $currentTime $toolName;
}
}

Function Run-Detection
{
Param(
[parameter(Mandatory=$false, ValueFromPipeline=$true)]
[string]$logfile = "$env:windir\debug\mrt.log",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$showCount = "false",
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$retryTimeInSeconds = 10,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$deviceName = ""
)

$oAPI = new-object -comObject "MOM.ScriptAPI";

Run-DetectionInt $oAPI $logfile $timeWindowInHours $showCount $retryTimeInSeconds $deviceName;

foreach ($scan in $global:malwareScans) {
$oPropertyBag = $oAPI.CreatePropertyBag();

$oPropertyBag.AddValue("DeviceName", $deviceName);
$oPropertyBag.AddValue("Tool", $scan.Tool);
$oPropertyBag.AddValue("Signature", $scan.Signature);
$oPropertyBag.AddValue("ScanDate", $scan.ScanDate);
$oPropertyBag.AddValue("DateCollected", $scan.DateCollected);
$oPropertyBag.AddValue("DetectionId", $scan.DetectionId);

$oPropertyBag.AddValue("ProtectionStatusRank", $scan.ProtectionStatusRank);
$oPropertyBag.AddValue("ProtectionStatus", $scan.ProtectionStatus);
$oPropertyBag.AddValue("ProtectionStatusDetails", $scan.ProtectionStatusDetails);

$oPropertyBag.AddValue("Threat", $scan.Threat);
$oPropertyBag.AddValue("ThreatStatusRank", $scan.ThreatStatusRank);
$oPropertyBag.AddValue("ThreatStatus", $scan.ThreatStatus);
$oPropertyBag.AddValue("ThreatStatusDetails", $scan.ThreatStatusDetails);

$eventData = "DeviceName:" + $deviceName + ", " +
"Tool:" + $scan.Tool + ", " +
"Signature:" + $scan.Signature + ", " +
"ScanDate:" + $scan.ScanDate + ", " +
"DateCollected:" + $scan.DateCollected + ", " +
"ProtectionStatusRank:" + $scan.ProtectionStatusRank + ", " +
"ProtectionStatus:" + $scan.ProtectionStatus + ", " +
"ProtectionStatusDetails:" + $scan.ProtectionStatusDetails + ", " +
"ThreatStatusRank:" + $scan.ThreatStatusRank + ", " +
"ThreatStatus:" + $scan.ThreatStatus + ", " +
"ThreatStatusDetails:" + $scan.ThreatStatusDetails + ", " +
"Threat:" + $scan.Threat + ", " +
"DetectionId:" + $scan.DetectionId;

LogScriptEvent $oAPI "AntiMalware Collection Script scan" 9993 0 $eventData;
$eventData
$oPropertyBag
}

LogScriptEvent $oAPI "AntiMalware Collection Script Finished" 9994 0 "AntiMalware Collection Script Returned";
}



# Implements Main detection logic for OMS Anti-Malware solution
&lt;#
Detecs Trend Micro AM Engine and extracts protection information via TM agent CLI
#&gt;

Function Detect-TrendMicro
{
Param(
[parameter(Mandatory=$true, ValueFromPipeline=$false)]
[PSObject]$trendMicroModuleCommands
)
$global:tmModuleCommands = $trendMicroModuleCommands;

# Trend micro will be detected if this registry location exists and dsq_query.cmd file is found
$tmRegistryPath = "HKLM:\SOFTWARE\TrendMicro\Deep Security Agent";
$tmInstallationFolderRegValueName = "InstallationFolder";
$tmInstalledVersionRegValueName = "InstalledVersion";
$tmDsaQueryCommandName = "dsa_query.cmd";

try {

if ((&amp;$global:tmModuleCommands.GetTestPathCommand $tmRegistryPath) -eq $false) {
return $false;
}

$global:tmDsaQueryPath = (&amp;$global:tmModuleCommands.GetItemProperty -Path $tmRegistryPath).$tmInstallationFolderRegValueName;

if ($global:tmDsaQueryPath -eq $null)
{
return $false;
}

$global:tmDsaQueryPath += $tmDsaQueryCommandName;

if ((&amp;$global:tmModuleCommands.GetTestPathCommand $global:tmDsaQueryPath) -eq $false) {
return $false;
}
}
catch {
return $false;
}

# Attempt to detect trend micro version, to be included with scan failures
try {
$global:tmVersion = (&amp;$global:tmModuleCommands.GetItemProperty -Path $tmRegistryPath).$tmInstalledVersionRegValueName;
if ($global:tmVersion -eq $null)
{
$global:tmVersion = "Unknown";
}
}
catch {
$global:tmVersion = "Unknown";
}

return $true;
}

Function Get-TrendMicroCommands
{
return New-Object PSObject -Property @{
GetTestPathCommand = "Test-Path";
GetItemProperty = "Get-ItemProperty";
GetDsaQueryResultCommand = "Get-DsaQueryResult";
GetEventLogCommand = "Get-EventLog";
}
}

Function Get-DsaQueryResult
{
return &amp;$global:tmDsaQueryPath -c GetComponentInfo;
}

Function Convert-UnixTimeToDateTimeUtc([int]$UnixTime)
{
(New-Object DateTime(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc)).AddSeconds($UnixTime)
}

function Get-ThreatStatusFromScanResultAndAction {
param(
$scanResult,
$scanAction
)

$ThreatStatusFromScanAction = @{
"Delete" = $RemediatedThreatThreatCode, "Removed";
"Unknown"= $UnknownThreatCode, "Unknown";
}

(($threatStatusRank, $threatStatus), $threatStatusDetails) = $ThreatStatusFromScanAction[$scanAction];

if ($threatStatusRank -and ($scanResult -eq "SUCCESS")) {
return $ThreatStatusFromScanAction[$scanAction];
}
else {
return $ThreatStatusFromScanAction["Unknown"];
}
}

function GetGuidFromMd5HashOfString {
param(
$someString
)

$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider;
$utf8 = new-object -TypeName System.Text.UTF8Encoding;
$guidFromHash = New-Object -TypeName System.Guid -ArgumentList @(,$md5.ComputeHash($utf8.GetBytes($someString)));
return $guidFromHash.Guid.ToString();
}

Function Scan-TrendMicroStatus
{
Param(
[parameter(Mandatory=$true, ValueFromPipeline=$false)]
[PSObject]$trendMicroModuleCommands,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[int]$timeWindowInHours = 24,
[parameter(Mandatory=$false, ValueFromPipeline=$false)]
[string]$deviceName = ""
)
$global:tmModuleCommands = $trendMicroModuleCommands;
$toolName = "Trend Micro Deep Security";
$currentTime = (Get-Date);

# First find all alerts in the last $timeWindowInHours for HSC scenarios, in which the trend micro extension is generating event 9501 to the event log.
# Needed for parity with ASC trend micro alerts, until the alerts are moved to the new tier2 service to service model.
$timeWindow = $currentTime.AddHours(-$timeWindowInHours);
$tmAlerts = &amp;$global:tmModuleCommands.GetEventLogCommand -After $timeWindow -LogName application -Source "Deep Security Agent" | ?{$_.EventId -eq "9501"}
foreach ($tmAlert in $tmAlerts) {
# The 9501 event message contains a json such as
#{"data":{"scanResult":"SUCCESS","scanAction":"Delete","infected_resource":"C:\\Users\\dvir\\AppData\\Local\\Microsoft\\Windows\\INetCache\\IE\\TRD29GMC\\eicar[1].com","time":1483620885,"malware":"Eicar_test_file"},"type":"AntiMalware"}
($protectionRank, $protectionStatus) = $ThreatDetectedProtectionCode;
$protectionStatusDetails = "At least one threat detected";
$eventJson = ConvertFrom-Json $tmAlert.Message;
$scanDateTime = Convert-UnixTimeToDateTimeUtc(($eventJson | select -expand data).time);
$threatName = ($eventJson | select -expand data).malware;
$scanAction = ($eventJson | select -expand data).scanAction;
$infectedResource = ($eventJson | select -expand data).infected_resource;
$scanResult = ($eventJson | select -expand data).scanResult;
(($threatStatusRank, $threatStatus), $threatStatusDetails) = Get-ThreatStatusFromScanResultAndAction $scanResult $scanAction;
$threatStatusDetails += "; Resources:infected_resource:" + $infectedResource;
$detectionId = GetGuidFromMd5HashOfString ($deviceName + $tmAlert.Message);

Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails $detectionId `
$threatName $threatStatusRank $threatStatus $threatStatusDetails `
"" $scanDateTime $currentTime $toolName;
}

# Now collect one record for the current protection status of the machine
# Threat status and rank are always unknown for Trend Micro
($threatStatusRank, $threatStatus) = $UnknownThreatCode;
($protectionRank, $protectionStatus) = $UnknownProtectionCode;
$detectionId = [System.Guid]::NewGuid().ToString();
$protectionStatusDetails = "";

$dsaQueryResult = &amp;$global:tmModuleCommands.GetDsaQueryResultCommand;
# Searching for AM mode synatx value, for example - "Component.AM.mode: on", -1 to get the last array value which is the actual property value
$amMode = $dsaQueryResult.Split("`n") | Select-String -Pattern "Component.AM.mode" -SimpleMatch;

if ($amMode -eq $null)
{
Write-Warning "Could not retrieve Component.AM.mode from dsa_query.cmd";
$amMode = "Unknown";
}
else
{
$amMode = $amMode.ToString().Split(" ")[-1];
}

# map Component.AM.mode possible values to OMS values
switch ($amMode.ToString().Trim().ToLower())
{
"on"
{
($protectionRank, $protectionStatus) = $RealTimeProtectionCode;
break;
}

"off"
{
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
$protectionStatusDetails = "Trend Micro Deep Security Agent is off";
break;
}

"not-capable"
{
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
$protectionStatusDetails = "Trend Micro Deep Security Agent is not activated";
break;
}
default
{
($protectionRank, $protectionStatus) = $UnknownProtectionCode;
$protectionStatusDetails = "Wrong Trend Micro Deep Security format. Version: $global:tmVersion";
Write-Warning "Could not identify dsa_query state: $amMode, Version: $global:tmVersion";
break;
}
}

Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails $detectionId `
"" $threatStatusRank $threatStatus "" `
"" $currentTime $currentTime $toolName;
} # Detects Trend Micro AM Engine and extracts protection information via TM agent CLI
Function Detect-Symantec
{
Param(
[parameter(Mandatory=$true, ValueFromPipeline=$false)]
[PSObject]$symantecModuleCommands
)

$global:msSymantecModuleCommands = $symantecModuleCommands;

$SymantecData = "";
$SymantecData = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion" -Value "PRODUCTNAME";
if ($SymantecData -ne $null) {
return ($SymantecData -eq 'Symantec Endpoint Protection');
}
return $false ;
}

Function Get-SymantecCommands
{
return New-Object PSObject -Property @{
GetTestRegistryValueComamnd = "Test-RegistryValue";
}
}

Function Scan-SymantecStatus
{
Param(
[parameter(Mandatory=$true, ValueFromPipeline=$false)]
[PSObject]$symantecModuleCommands
)

$global:msSymantecModuleCommands = $symantecModuleCommands;

# Init parameters
$DateCollected = (Get-Date).ToShortDateString();
$ToolName = "Symantec Endpoint Protection";

$DetectionId = [System.Guid]::NewGuid().ToString();

($protectionRank, $protectionStatus) = $UnknownProtectionCode;
$protectionStatusDetails = "Unable to determine protection status";

($threatStatusRank, $threatStatus) = $UnknownThreatCode;
$threatStatusDetails = "Unable to determine threat status";

$Signature = "Not Found";
$ASRunningStatus = "";

# Find version
$SymantecVersion = -1;

$SymantecData = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion" -Value "PRODUCTVERSION";
if ($SymantecData -ne $null) {
$SymantecVersion = ($SymantecData.Split('.'))[0];
}

# Check version, stop check other status if version &lt; 12
if ($SymantecData -eq $null) {
($protectionRank, $protectionStatus) = $NotReportingProtectionCode;
$protectionStatusDetails = "Symantec Version not Found";
}elseif ([bool]($SymantecVersion -as [int]) -eq $false) {
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
$protectionStatusDetails = "Wrong Symantec Version Format: $SymantecData";
}elseif ($SymantecVersion -le 11) {
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
$protectionStatusDetails = "Unsupported Symantec Version: $SymantecData";

}else {
# Find AM Engine running status
$ASRunningStatus = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion\public-opstate" -Value "ASRunningStatus";

# Find latest scan date
$ScanDate = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion\public-opstate" -Value "LastSuccessfulScanDateTime";

# Find latest signature date
$SignatureDate = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion\public-opstate" -Value "LatestVirusDefsDate";

# Find RTP status
$RTPOnOff = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "AV\Storages\Filesystem\RealTimeScan" -Value "OnOff";

# Find signature version number
# Path to signature version for Symantec 12
$SymantecSRTSP12 = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion\SharedDefs" -Value "SRTSP";
# Path to signature version for Symantec 14
$SymantecSRTSP14 = &amp;$global:msSymantecModuleCommands.GetTestRegistryValueComamnd -Path "CurrentVersion\SharedDefs\SDSDefs" -Value "SRTSP";
if ($SymantecSRTSP14 -ne $null) {
$SymantecSRTSP = $SymantecSRTSP14;
}else {
$SymantecSRTSP = $SymantecSRTSP12;
}
if ($SymantecSRTSP -ne $null) {
$SignatureData = $SymantecSRTSP.Split('\');
if ($SignatureData.Length -gt 0) {
$Signature = $SignatureData[$SignatureData.Length-1];
}
}

# Update protectionRank, $protectionStatus and protectionStatusDetails
try {
$protectionStatusDetailsArray = @();

# Signature Date
if ($SignatureDate -eq $null) {
$protectionStatusDetailsArray += "Signature date not found";
}else{
if ($SignatureDate -ne "") {
$SignatureDate = dateTimeValidate -DateTimeValue $SignatureDate;
}else{
$SignatureDate = "Wrong Format"
}
if ($SignatureDate -eq "Wrong Format") {
$protectionStatusDetailsArray += "Signature date in wrong format";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}elseif($SignatureDate.AddDays(7) -lt (Get-Date)) {
($protectionRank, $protectionStatus) = $SignaturesOutOfDateProtectionCode;
$protectionStatusDetailsArray += "Signature older than 7 days";
}
}

# RPT Off
if($RTPOnOff -eq $null) {
$protectionStatusDetailsArray += "Real time protection status not found";
}elseif ($RTPOnOff -eq 0) {
$protectionStatusDetailsArray += "Real time protection disabled";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}elseif ($RTPOnOff -ne 1) {
$protectionStatusDetailsArray += "Real time protection status in wrong format: $RTPOnOff";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}

# AM Engine not detect
if ($ASRunningStatus -eq $null) {
$protectionStatusDetailsArray += "Antimalware engine status not found";
}elseif ($ASRunningStatus -eq 0) {
$protectionStatusDetailsArray += "Antimalware disabled";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}elseif ($ASRunningStatus -ne 1) {
$protectionStatusDetailsArray += "Antimalware engine status in wrong format: $ASRunningStatus";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}

# Scan date
if ($ScanDate -eq $null) {
$protectionStatusDetailsArray += "Latest scan date not found";
}else {
if ($ScanDate -ne "") {
$ScanDate = dateTimeValidate -DateTimeValue $ScanDate;
}else{
$ScanDate = "Wrong Format"
}
if ($ScanDate -eq "Wrong Format") {
$protectionStatusDetailsArray += "Latest scan date in wrong format";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}elseif ($ScanDate.AddDays(7) -lt (Get-Date)) {
$protectionStatusDetailsArray += "Latest scan older than 7 days";
($protectionRank, $protectionStatus) = $NoRealTimeProtectionProtectionCode;
}
}

# Check if any value not found, update protection code
if(($RTPOnOff -eq $null) -or ($SignatureDate -eq $null) -or ($ASRunningStatus -eq $null) -or ($ScanDate -eq $null)) {
($protectionRank, $protectionStatus) = $NotReportingProtectionCode;
}

# Change status details array to String
if ($protectionStatusDetailsArray.length -gt 0) {
$protectionStatusDetails = "";
$protectionStatusDetails += [string]::join("; ", $protectionStatusDetailsArray);
$protectionStatusDetails += "."
}else {
#RTP On
$protectionStatusDetails= "Real time protection enabled";
($protectionRank, $protectionStatus) = $RealTimeProtectionCode;
}

} catch {
#
# Something bad happened - Everything goes to not reporting status
#
($protectionRank, $protectionStatus) = $UnknownThreatCode;
$protectionStatusDetails = "Failed to collect computer status";
$ErrorMessage = $protectionStatusDetails + "; ErrorMessage:" + $_.Exception.Message;
Write-Warning $ErrorMessage;
}
}

Add-MalwareScan $protectionRank $protectionStatus $protectionStatusDetails `
$DetectionId "" $threatStatusRank $threatStatus $threatStatusDetails `
$Signature $ScanDate $DateCollected $ToolName;
}


#
# Helper function that take registry paths and registry property to be found,
# return false if paths not exists or property not exists;
# return property value if the property is found.
# The paths not found and property not found errors/exceptions are logged in warning message.
#
Function Test-RegistryValue {
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$Path,

[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$Value
)

$Path32 = "HKLM:\Software\Symantec\Symantec Endpoint Protection\" + $Path;
$Path64 = "HKLM:\Software\Wow6432Node\Symantec\Symantec Endpoint Protection\" + $Path;

try {
if (Test-Path $Path32) {
Get-ItemProperty -Path $Path32 | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null;
$propFound = Get-ItemProperty -Path $Path32;
return $propFound.$Value;
}elseif (Test-Path $Path64) {
Get-ItemProperty -Path $Path64 | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null;
$propFound = Get-ItemProperty -Path $Path64;
return $propFound.$Value;
}
Write-Warning "Path to $Value : $Path32 and $Path64 not found";
return $null;
}
catch {
Write-Warning "Path to $Value : $_.Exception.Message";
return $null;
}
}

Function dateTimeValidate() {
param (
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]$DateTimeValue
)

try {
return [datetime]$dateTimeValue
}catch {
Write-Warning "$_.Exception.Message";
return "Wrong Format";
}
} # Detects Symantec Endpoint Protection information via PowerShell commands.

$deviceName = "$Target/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$";

Start-Sleep -Seconds 180 # Sleep a little to allow vendor services to catch up on state after restart
Run-Detection $logfile $timeWindowInHours $showCount $retryTimeInSeconds $deviceName


</Script></ScriptBody>
<TimeoutSeconds>600</TimeoutSeconds>
</DataSource>
</DataSources>
<WriteActions>
<WriteAction ID="WA2" TypeID="Types!Microsoft.SystemCenter.AntiMalwareInformationDataWriteAction"/>
</WriteActions>
</Rule>