I work in a larger company and I was tasked with managing several thousand endpoints and a daunting list of exclusions that hadn't been updated in years. Managing SEP had been passed from admin to admin like a hot potato, and by the time I received it, the exception list was a mess of over 3,000 exceptions of dubious relevance and serious negative effects on our security.
So the first part to fixing the problem was reporting on it, and in spite of years and years of forum posts by quite a few users, I really hadn't seen a good solution. PowerShell has been my tool of choice for managing our systems, so I wanted to build something that fit into our mangement module.
Step 1: Find the right table
I really can't take credt for this - our Symantec support rep (thank you Tony) was able to point me to the right table, BASIC_METADATA. I would never have found this on my own.
Step 2: Query the table and convert it to something I can actually read
The table BASIC_METADATA stores binary data. It's not hard to convert with basic TSQL, but you have to know the data is there in the first place (thanks again Tony). Once you've converted it from binary, you're left with an XML you can actually read.
Step 3: Parse the XML file
I'm a fan of PowerShell, but use your XML reader of choice. If I were able, I would do this within the TSQL query itself. Each excption type has different properties, and you may prefer to group or view them in a different format than I have provided. If you've gotten this far enough to get the XML file, you'll almost definitely be able to find a way to parse it that presents the data in a way that's meaningful to you.
The script:
Hopefully this works for you. You'll need to provide credentials that both have access to the server via WinRM (for Invoke-Command) and which have access to the database. You may find it easier to query the database directly rather than with WinRM, or you may wan to modify it to take two sets of credentials. If you have a unique connection situation, feel free to respond and I'll try to update it to work for you.
Function Get-SEPMExclusions {
param (
[Parameter(Mandatory=$true)]
[Alias('Name','ComputerName')]
[string]$ServerName,
[Parameter(Mandatory=$true)]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
begin{
$Parm += @{ComputerName = $ServerName;Credential = $Credential}
$query = @"
SELECT e.NAME
,CONVERT(varchar(max),CONVERT(varbinary(max),e.CONTENT)) as XML
,e.DESCRIPTION
,s.NAME as DOMAIN
FROM BASIC_METADATA e WITH(NOLOCK)
INNER JOIN IDENTITY_MAP s
ON s.DOMAIN_ID=e.DOMAIN_ID
WHERE e.TYPE = 'PolicyOverride' AND E.DELETED = 1 AND s.TYPE = 'SemDomain'"@
$connectionString = "Server=LocalHost;Database=sem5;Trusted_Connection=True;"
}
Process{}
End{
$table = Invoke-Command -HideComputerName @Parm -ArgumentList $Query,$connectionString{
param($query,$connectionString)
if (!($connection)){
$connection = New-Object System.Data.SqlClient.SqlConnection
}
$connection.ConnectionString = $connectionString
$connection.Open()
$command = $connection.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteReader()
$table = New-Object “System.Data.DataTable”
$table.Load($result)
$connection.Close()
$table
}
foreach ($item in $table){
([xml]($item.XML)).PolicyOverride.OverrideItem.SecurityRiskOverride | ForEach-Object {
if ($PSItem.InnerXML -eq $null) { return }
New-Object PSObject -Property @{
Domain = $item.DOMAIN
Name = $item.Name
ExclusionType = ($PSItem.innerxml -split "" -replace "<")[0]
XML = $PSItem.InnerXML
Path = $PSItem.DirectoryOverride.DirectoryPath,$PSItem.FileOverride.FilePath -join $null
ExcludeSubDirectories = $PSItem.DirectoryOverride.ExcludeSubDirectories,$PSItem.FilePath -join $null
Prefix = $PSItem.DirectoryOverride.PrefixVariable
ScanType = ( $PSItem.FileOverride.ProtectionTechnology.ScanType,$PSItem.DirectoryOverride.ScanType,$PSItem.Extension.ScanType | Where-Object {$_ -ne $null} ) -join ","
Extension = $PSItem.InnerText
} | %{ $PSItem.PSObject.TypeNames.Insert(0,"SEP.Exclusion");$PSItem }
}
}
}
<#
.SYNOPSIS
Queries a Symantec Endpoint Protection Manager for exceptions.
.DESCRIPTION
Queries a Symantec Endpoint Protection Manager for exceptions. To format output, you can update formatdata for "SEP.Exclusion"
.PARAMETER ServerName
The name of the SEPM you want to query.
.PARAMETER filePath
A credential object with credentials with both remote access to the server and read access to the SEP database
.EXAMPLE
Get-SEPMExclusions <your sepm hostname> -Credential <credential object>
Connect with a credential object.
.EXAMPLE
Get-SEPMExclusions <your sepm hostname>
Connect with prompt for credentials.
#>
}
Just the SQL query:
SELECT e.NAME
,CONVERT(varchar(max),CONVERT(varbinary(max),e.CONTENT)) as XML
,e.DESCRIPTION
,s.NAME as DOMAIN
FROM BASIC_METADATA e WITH(NOLOCK)
INNER JOIN IDENTITY_MAP s
ON s.DOMAIN_ID=e.DOMAIN_ID
WHERE e.TYPE = 'PolicyOverride' AND E.DELETED = 1 AND s.TYPE = 'SemDomain'