Repository: darkoperator/Posh-Sysmon
Branch: master
Commit: f89a27fd1897
Files: 65
Total size: 822.3 KB
Directory structure:
gitextract_jqcvzr7i/
├── .gitattributes
├── Config.ps1
├── Filters.ps1
├── Format/
│ ├── Sysmon.ConfigOption.ps1xml
│ ├── Sysmon.Rule.Filter.ps1xml
│ └── Sysmon.Rule.ps1xml
├── Functions/
│ ├── ConvertFrom-SysmonBinaryConfiguration.ps1
│ ├── ConvertTo-SysmonXMLConfiguration.ps1
│ ├── Get-SysmonConfiguration.ps1
│ ├── Get-SysmonEventData.ps1
│ ├── Get-SysmonHashingAlgorithm.ps1
│ ├── Get-SysmonRule.ps1
│ ├── Get-SysmonRuleFilter.ps1
│ ├── New-SysmonConfiguration.ps1
│ ├── New-SysmonCreateRemoteThreadFilter.ps1
│ ├── New-SysmonDriverLoadFilter.ps1
│ ├── New-SysmonFileCreateFilter.ps1
│ ├── New-SysmonFileCreateStreamHashFilter.ps1
│ ├── New-SysmonImageLoadFilter.ps1
│ ├── New-SysmonNetworkConnectFilter.ps1
│ ├── New-SysmonPipeFilter.ps1
│ ├── New-SysmonProcessAccessFilter.ps1
│ ├── New-SysmonProcessCreateFilter.ps1
│ ├── New-SysmonProcessTerminateFilter.ps1
│ ├── New-SysmonRawAccessReadFilter.ps1
│ ├── New-SysmonRegistryFilter.ps1
│ ├── New-SysmonWmiFilter.ps1
│ ├── Remove-SysmonRule.ps1
│ ├── Remove-SysmonRuleFilter.ps1
│ ├── Schemas/
│ │ ├── SysmonConfigurationSchema_3_40.xsd
│ │ └── SysmonConfigurationSchema_4_00.xsd
│ ├── Set-SysmonHashingAlgorithm.ps1
│ └── Set-SysmonRule.ps1
├── LICENSE
├── Posh-SysMon.psm1
├── Posh-Sysmon.psd1
├── README.md
├── build.ps1
├── docs/
│ ├── Get-SysmonEventData.md
│ ├── Get-SysmonHashingAlgorithm.md
│ ├── Get-SysmonRule.md
│ ├── Get-SysmonRuleFilter.md
│ ├── New-SysmonConfiguration.md
│ ├── New-SysmonDriverLoadFilter.md
│ ├── New-SysmonFileCreateFilter.md
│ ├── New-SysmonFileCreateStreamHash.md
│ ├── New-SysmonFileCreateStreamHashFilter.md
│ ├── New-SysmonImageLoadFilter.md
│ ├── New-SysmonNetworkConnectFilter.md
│ ├── New-SysmonPipeEvent.md
│ ├── New-SysmonPipeFilter.md
│ ├── New-SysmonProcessAccessFilter.md
│ ├── New-SysmonProcessCreateFilter.md
│ ├── New-SysmonProcessTerminateFilter.md
│ ├── New-SysmonRegistryEvent.md
│ ├── New-SysmonRegistryFilter.md
│ ├── Remove-SysmonRule.md
│ ├── Remove-SysmonRuleFilter.md
│ ├── Set-SysmonHashingAlgorithm.md
│ └── Set-SysmonRule.md
├── en-US/
│ ├── Posh-SysMon-help.xml
│ └── Posh-SysMon.psm1-Help.xml
└── lib/
├── sysmon3_1.dtd
├── sysmon3_2.dtd
└── sysmon3_3.dtd
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
# Custom for PowerShell*.psm1 text
*.psd1 text
*.psm1 text
*.ps1xml text
================================================
FILE: Config.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonConfiguration
{
[CmdletBinding(HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonConfiguration.md')]
Param
(
# Path to write XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[String]
$Path,
# Specify one or more hash algorithms used for image identification
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('ALL', 'MD5', 'SHA1', 'SHA256', 'IMPHASH')]
[string[]]
$HashingAlgorithm,
# Log Network Connections
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[Switch]
$NetworkConnect,
# Log process loading of modules.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[Switch]
$DriverLoad,
# Log process loading of modules.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[Switch]
$ImageLoad,
# Log create remote thread actions.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=5)]
[Switch]
$CreateRemoteThread,
# Log file creation time modifications.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=6)]
[Switch]
$FileCreateTime,
# Log process creation.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=7)]
[Switch]
$ProcessCreate,
# Log process termination.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=8)]
[Switch]
$ProcessTerminate,
# Log when a running process opens another process.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=9)]
[Switch]
$ProcessAccess,
# Log raw access reads of files.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=10)]
[Switch]
$RawAccessRead,
# Check for signature certificate revocation.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=11 )]
[Switch]
$CheckRevocation,
# Log Registry events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=12 )]
[Switch]
$RegistryEvent,
# Log File Creation events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=13 )]
[Switch]
$FileCreate,
# Log File Stream creations events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=14 )]
[Switch]
$FileCreateStreamHash,
# Log NamedPipes connection and creations events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=15 )]
[Switch]
$PipeEvent,
# WMI Permanent Event component events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=16 )]
[Switch]
$WmiEvent,
# Comment for purpose of the configuration file.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true)]
[String]
$Comment,
# Schema Vesion for the configuration file, default is 3.3.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true)]
[ValidateSet('2.0','3.0', '3.1', '3.2','3.3', '3.4')]
[String]
$SchemaVersion = '3.4'
)
Begin{}
Process
{
if ($HashingAlgorithm -contains 'ALL')
{
$Hash = '*'
}
else
{
$Hash = $HashingAlgorithm -join ','
}
$Config = ($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path))
# get an XMLTextWriter to create the XML
$XmlWriter = New-Object System.XMl.XmlTextWriter($Config,$Null)
# choose a pretty formatting:
$xmlWriter.Formatting = 'Indented'
$xmlWriter.Indentation = 1
# write the header
if ($Comment)
{
$xmlWriter.WriteComment($Comment)
}
$xmlWriter.WriteStartElement('Sysmon')
$XmlWriter.WriteAttributeString('schemaversion', $SchemaVersion)
Write-Verbose -Message "Enabling hashing algorithms : $($Hash)"
$xmlWriter.WriteElementString('HashAlgorithms',$Hash)
# Enable checking revocation.
if ($CheckRevocation)
{
if ($SchemaVersion -in @('3.1','3.2','3.3','3.4'))
{
Write-Verbose -message 'Enabling CheckRevocation.'
$xmlWriter.WriteElementString('CheckRevocation','')
}
else
{
Write-Warning -Message 'CheckRevocation was not enabled because it is not supported in this SchemaVersion.'
}
}
# Create empty EventFiltering section.
$xmlWriter.WriteStartElement('EventFiltering')
if ($NetworkConnect)
{
Write-Verbose -Message 'Enabling network connection logging for all connections by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('NetworkConnect')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($DriverLoad)
{
Write-Verbose -Message 'Enabling logging all driver loading by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('DriverLoad ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ImageLoad)
{
Write-Verbose -Message 'Enabling logging all image loading by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ImageLoad ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($CreateRemoteThread)
{
Write-Verbose -Message 'Enabling logging all CreateRemoteThread API actions by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('CreateRemoteThread ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ProcessCreate)
{
Write-Verbose -Message 'Enabling logging all process creation by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ProcessCreate ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ProcessTerminate)
{
Write-Verbose -Message 'Enabling logging all process termination by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ProcessTerminate ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($FileCreateTime)
{
Write-Verbose -Message 'Enabling logging all process creation by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('FileCreateTime ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ProcessAccess)
{
Write-Verbose -Message 'Enabling logging all process access by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ProcessAccess ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($RawAccessRead)
{
Write-Verbose -Message 'Enabling logging all process access by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('RawAccessRead ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# Log registry events.
if ($RegistryEvent)
{
if ($SchemaVersion -gt 3.2)
{
Write-Verbose -message 'Enabling RegistryEvent.'
$xmlWriter.WriteStartElement('RegistryEvent ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
else
{
Write-Warning -Message 'RegistryEvent was not enabled because it is not supported in this SchemaVersion.'
}
}
# Log file create events.
if ($FileCreate)
{
if ($SchemaVersion -gt 3.2)
{
Write-Verbose -message 'Enabling FileCreate.'
$xmlWriter.WriteStartElement('FileCreate ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
else
{
Write-Warning -Message 'FileCreate was not enabled because it is not supported in this SchemaVersion.'
}
}
# Log file create events.
if ($FileCreateStreamHash)
{
if ($SchemaVersion -gt 3.2)
{
Write-Verbose -message 'Enabling FileCreateStreamHash.'
$xmlWriter.WriteStartElement('FileCreateStreamHash ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
else
{
Write-Warning -Message 'FileCreateStreamHash was not enabled because it is not supported in this SchemaVersion.'
}
}
# NamedPipes create and connect events.
if ($PipeEvent)
{
if ($SchemaVersion -gt 3.2)
{
Write-Verbose -message 'Enabling PipeEvent.'
$xmlWriter.WriteStartElement('PipeEvent ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
else
{
Write-Warning -Message 'PipeEvent was not enabled because it is not supported in this SchemaVersion.'
}
}
# NamedPipes create and connect events.
if ($WmiEvent)
{
if ($SchemaVersion -gt 3.4)
{
Write-Verbose -message 'Enabling WmiEvent.'
$xmlWriter.WriteStartElement('WmiEvent ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
els
{
Write-Warning -Message 'WmiEvent was not enabled because it is not supported in this SchemaVersion.'
}
}
# End Element of EventFiltering
$xmlWriter.WriteFullEndElement()
# Sysmon
$xmlWriter.WriteEndElement()
# finalize the document:
#$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()
Write-Verbose -Message "Config file created as $($Config)"
write-verbose -Message "Configuration is for Sysmon $($sysmonVerMap[$SchemaVersion])"
}
End
{
}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Get-SysmonHashingAlgorithm
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonHashingAlgorithm.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[string]$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
[string]$LiteralPath
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path' {[xml]$Config = Get-Content -Path $Path}
'LiteralPath' {[xml]$Config = Get-Content -LiteralPath $LiteralPath}
}
}
catch [System.Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$ObjOptions = @{}
if ($Config.Sysmon.SelectSingleNode('//HashAlgorithms'))
{
$ObjOptions['Hashing'] = $config.Sysmon.HashAlgorithms
}
else
{
$ObjOptions['Hashing'] = ''
}
#$ObjOptions['Comment'] = $Config.'#comment'
$ConfigObj = [pscustomobject]$ObjOptions
$ConfigObj.pstypenames.insert(0,'Sysmon.HashingAlgorithm')
$ConfigObj
}
End{}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Get-SysmonRule
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRule.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[string]$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
[string]$LiteralPath,
# Event type to parse rules for.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('ALL', 'NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad', 'ProcessAccess',
'RawAccessRead','ProcessAccess', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')]
[string[]]
$EventType = @('ALL')
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path' {[xml]$Config = Get-Content -Path $Path}
'LiteralPath' {[xml]$Config = Get-Content -LiteralPath $LiteralPath}
}
}
catch [System.Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
# Collect all individual rules if they exist.
$Rules = $Config.Sysmon.EventFiltering
if ($EventType -contains 'ALL')
{
$TypesToParse = @('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad','CreateRemoteThread',
'ProcessAccess', 'RawAccessRead', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')
}
else
{
$TypesToParse = $EventType
}
foreach($Type in $TypesToParse)
{
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$Type]
$RuleData = $Rules.SelectNodes("//EventFiltering/$($EvtType)")
if($RuleData -ne $null)
{
Write-Verbose -Message "$($EvtType) Rule Found."
Get-RuleWithFilter($RuleData)
}
}
}
End{}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Set-SysmonHashingAlgorithm
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Set-SysmonHashingAlgorithm.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Specify one or more hash algorithms used for image identification
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('ALL', 'MD5', 'SHA1', 'SHA256', 'IMPHASH')]
[string[]]
$HashingAlgorithm
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [System.Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
Write-Verbose -Message 'Updating Hashing option.'
if ($HashingAlgorithm -contains 'ALL')
{
$Hash = '*'
}
else
{
$Hash = $HashingAlgorithm -join ','
}
# Check if Hashing Alorithm node exists.
if($Config.SelectSingleNode('//Sysmon/HashAlgorithms') -ne $null)
{
$Config.Sysmon.HashAlgorithms = $Hash
}
else
{
$HashElement = $Config.CreateElement('HashAlgorithms')
[void]$Config.Sysmon.Configuration.AppendChild($HashElement)
$Config.Sysmon.Configuration.Hashing = $Hash
}
Write-Verbose -Message 'Hashing option has been updated.'
Write-Verbose -Message "Option have been set on $($FileLocation)"
$Config.Save($FileLocation)
}
End{}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Set-SysmonRule
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Set-SysmonRule.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type to update.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad', 'CreateRemoteThread',
'ProcessAccess', 'RawAccessRead', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')]
[string[]]
$EventType,
# Action for event type rule and filters.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Include', 'Exclude')]
[String]
$OnMatch = 'Exclude',
# Action to take for Schema 3.0 files.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[ValidateSet('Modify', 'Add')]
[String]
$Action = 'Modify'
)
Begin{}
Process
{
# if no elemrnt create one either if it is schema 2.0 or 3.0.
# If one is present we modify that one if Schema 2.0 and if Schema 3.0 and action modify.
# If Schema 3.0 and action add we check if only is present and that it is not the same OnMatch
# as being specified if it is we do nothing if not we add.
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$Rules = $config.SelectSingleNode('//Sysmon/EventFiltering')
foreach($Type in $EventType)
{
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$Type]
$RuleData = $Rules.SelectSingleNode("//EventFiltering/$($EvtType)")
$elements = $Rules."$($EvtType)" | Select-Object -property onmatch -Unique
if($RuleData -ne $null)
{
if ($Rules."$($EvtType)".count -eq $null)
{
if (($Config.Sysmon.schemaversion -eq '2.0') -or ($Config.Sysmon.schemaversion -in @('3.0', '3.1', '3.2','3.3', '3.4') -and $Action -eq 'Modify'))
{
Write-Verbose -Message "Setting as default action for $($EvtType) the rule on match of $($OnMatch)."
$RuleData.SetAttribute('onmatch',($OnMatch.ToLower()))
Write-Verbose -Message 'Action has been set.'
}
elseif ($Config.Sysmon.schemaversion -in @('3.0', '3.1', '3.2','3.3', '3.4') -and $Action -eq 'Add')
{
if ($RuleData.onmatch -ne $OnMatch)
{
Write-Verbose -Message "Creating rule for event type with action of $($OnMatch)"
$TypeElement = $config.CreateElement($EvtType)
$TypeElement.SetAttribute('onmatch',($OnMatch.ToLower()))
$RuleData = $Rules.AppendChild($TypeElement)
Write-Verbose -Message 'Action has been set.'
}
else
{
Write-Verbose -Message 'A rule with the specified onmatch action already exists.'
}
}
}
elseif ($Config.Sysmon.schemaversion -in ('3.0', '3.1', '3.2','3.3', '3.4') -and $elements.count -eq 2)
{
Write-Verbose -Message 'A rule with the specified onmatch action already exists.'
}
else
{
Write-Error -Message 'This XML file does not conform to the schema.'
return
}
}
else
{
Write-Verbose -Message "No rule for $($EvtType) was found."
Write-Verbose -Message "Creating rule for event type with action of $($OnMatch)"
$TypeElement = $config.CreateElement($EvtType)
$TypeElement.SetAttribute('onmatch',($OnMatch.ToLower()))
$RuleData = $Rules.AppendChild($TypeElement)
Write-Verbose -Message 'Action has been set.'
}
Get-RuleWithFilter($RuleData)
}
$config.Save($FileLocation)
}
End{}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Remove-SysmonRule
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Remove-SysmonRule.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type to remove. It is case sensitive.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad', 'CreateRemoteThread',
'ProcessAccess', 'RawAccessRead', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')]
[string[]]
$EventType,
# Action for event type rule and filters.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Include', 'Exclude')]
[String]
$OnMatch = 'Exclude'
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$Rules = $config.SelectSingleNode('//Sysmon/EventFiltering')
foreach ($rule in $rules.ChildNodes)
{
if ($rule.name -in $EventType -and $rule.onmatch -eq $OnMatch)
{
[void]$rule.ParentNode.RemoveChild($rule)
Write-Verbose -Message "Removed rule for $($EventType)."
}
}
$config.Save($FileLocation)
}
End{}
}
================================================
FILE: Filters.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonImageLoadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonImageLoadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'ImageLoaded', 'Hashes', 'Signed',
'Signature')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process
{
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ImageLoad'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch($psCmdlet.ParameterSetName)
{
'Path'
{
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath'
{
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End { }
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonDriverLoadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonDriverLoadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ImageLoaded',
'Hashes', 'Signed', 'Signature')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'DriverLoad'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonNetworkConnectFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonNetworkConnectFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'User', 'Protocol', 'Initiated', 'SourceIsIpv6',
'SourceIp', 'SourceHostname', 'SourcePort',
'SourcePortName', 'DestinationIsIpv6',
'DestinationIp', 'DestinationHostname',
'DestinationPort', 'DestinationPortName')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'NetworkConnect'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonFileCreateFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonFileCreateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'TargetFilename', 'CreationUtcTime',
'PreviousCreationUtcTime')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
switch($psCmdlet.ParameterSetName) {
'Path' {
New-RuleFilter -Path $Path -EventType FileCreateTime -Condition $Condition -EventField $FieldString -Value $Value -OnMatch $OnMatch
}
'LiteralPath' {
New-RuleFilter -LiteralPath $LiteralPath -EventType FileCreateTime -Condition $Condition -EventField $FieldString -Value $Value -OnMatch $OnMatch
}
}
}
End {}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonProcessCreateFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonProcessCreateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'CommandLine', 'User', 'LogonGuid', 'LogonId',
'TerminalSessionId', 'IntegrityLevel',
'Hashes', 'ParentProcessGuid', 'ParentProcessId',
'ParentImage', 'ParentCommandLine')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ProcessCreate'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End { }
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonProcessTerminateFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonProcessTerminateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process
{
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ProcessTerminate'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch($psCmdlet.ParameterSetName)
{
'Path'
{
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath'
{
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonCreateRemoteThreadFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonCreateRemoteThreadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('SourceImage', 'TargetImage')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin { }
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'CreateRemoteThread'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for the logging of when a running process opens another.
.DESCRIPTION
Create a new filter for the logging of when a running process opens another.
.EXAMPLE
C:\PS> New-SysmonProcessAccessFilter -Path .\testver31.xml -OnMatch include -Condition Contains -EventField TargetImage lsass.exe
Log any process trying to open lsass.exe.
#>
function New-SysmonProcessAccessFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonProcessAccessFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'SourceProcessGUID',
'SourceProcessId', 'SourceThreadId', 'SourceImage',
'TargetProcessGUID', 'TargetProcessId', 'TargetImage',
'GrantedAccess','CallTrace')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ProcessAccess'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for the logging of file raw access read actions.
.DESCRIPTION
Create a new filter for the logging of file raw access read actions.
.EXAMPLE
C:\PS> New-SysmonRawAccessReadFilter -Path .\testver31.xml -OnMatch include -Condition Contains -EventField Image NTDS.dit
Log any raw access read of the file NTDS.dit.
#>
function New-SysmonRawAccessReadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonRawAccessReadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId',
'Image', 'Device')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'RawAccessRead'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for the logging file creation.
.DESCRIPTION
Create a new filter for the logging file creation.
.EXAMPLE
#>
function New-SysmonFileCreateFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonFileCreateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('TargetFilename', 'ProcessGuid', 'ProcessId',
'Image')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'FileCreate'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for the logging of the saving of data on a file stream.
.DESCRIPTION
Create a new filter for the logging of the saving of data on a file stream.
#>
function New-SysmonFileCreateStreamHashFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonFileCreateStreamHashFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('TargetFilename', 'ProcessGuid', 'ProcessId',
'Image')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'FileCreateStreamHash'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for the actions against the registry.
.DESCRIPTION
Create a new filter for actions against the registry. Supports filtering
by aby of the following event types:
* CreateKey
* DeleteKey
* RenameKey
* CreateValue
* DeleteValue
* RenameValue
* SetValue
Hives on Schema 3.2 in TargetObject are referenced as:
* \REGISTRY\MACHINE\HARDWARE
* \REGISTRY\USER\Security ID number
* \REGISTRY\MACHINE\SECURITY
* \REGISTRY\USER\.DEFAULT
* \REGISTRY\MACHINE\SYSTEM
* \REGISTRY\MACHINE\SOFTWARE
* \REGISTRY\MACHINE\SAM
Hives on Schema 3.3 and above in TargetObject are referenced as:
* HKLM
* HKCR
* HKEY_USER
.EXAMPLE
C:\PS> New-SysmonRegistryFilter -Path .\32config.xml -OnMatch include -Condition Contains -EventField TargetObject 'RunOnce'
Capture persistance attemp by creating a registry entry in the RunOnce keys.
#>
function New-SysmonRegistryFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonRegistryFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({ Test-Path -Path $_ })]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('TargetObject', 'ProcessGuid', 'ProcessId',
'Image', 'EventType')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {
# Event types used to validate right type and string case
$EventTypeMap = @{
CreateKey = 'CreateKey'
DeleteKey = 'DeleteKey'
RenameKey = 'RenameKey'
CreateValue = 'CreateValue'
DeleteValue = 'DeleteValue'
RenameValue = 'RenameValue'
SetValue = 'SetValue'
}
$Etypes = $EventTypeMap.Keys
}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
if ($EventField -in 'EventType') {
if ($Value -in $Etypes) {
$Value = $EventTypeMap[$Value]
} else {
Write-Error -Message "Not a supported EventType. Supported Event types $($Etypes -join ', ')"
return
}
}
$cmdoptions = @{
'EventType' = 'RegistryEvent'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for when a Named Pipe is created or connected.
.DESCRIPTION
Create a new filter for when a Named Pipe is created or connected.
Useful for watching malware inter process communication.
#>
function New-SysmonPipeFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonPipeFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Pipe', 'ProcessGuid', 'ProcessId',
'Image')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'PipeEvent'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
<#
.SYNOPSIS
Create a new filter for WMI Permamanent Event Classes.
.DESCRIPTION
Create a new filter for WMI permamanent event classes are created or connected.
Useful for monitoring for persistence actions.
#>
function New-SysmonWmiFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonWmiFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Name', 'EventNamespace', 'Destination',
'Type', 'Query', 'Operation', 'Consumer', 'Filter')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'WmiEvent'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Remove-SysmonRuleFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Remove-SysmonRuleFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type to update.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread', 'RawAccessRead', 'ProcessAccess',
'FileCreateStreamHash', 'RegistryEvent', 'FileCreate',
'PipeEvent', 'WmiEvent')]
[string]
$EventType,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=5)]
[string[]]
$Value
)
Begin{}
Process {
$EvtType = $null
# Check if the file is a valid XML file and if not raise and error.
try {
switch($psCmdlet.ParameterSetName) {
'Path' {
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath' {
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException] {
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null) {
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
$Rules = $Config.SelectSingleNode('//Sysmon/EventFiltering')
# Select the proper condition string.
switch ($Condition) {
'Is' {$ConditionString = 'is'}
'IsNot' {$ConditionString = 'is not'}
'Contains' {$ConditionString = 'contains'}
'Excludes' {$ConditionString = 'excludes'}
'Image' {$ConditionString = 'image'}
'BeginWith' {$ConditionString = 'begin with'}
'EndWith' {$ConditionString = 'end with'}
'LessThan' {$ConditionString = 'less than'}
'MoreThan' {$ConditionString = 'more than'}
Default {$ConditionString = 'is'}
}
# Check if the event type exists if not create it.
if ($Rules -eq '') {
Write-Error -Message 'Rule element does not exist. This appears to not be a valid config file'
return
} else {
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$EventType]
$EventRule = $Rules.SelectNodes("//EventFiltering/$($EvtType)")
}
if($EventRule -eq $null) {
Write-Warning -Message "No rule for $($EvtType) was found."
return
}
if($EventRule -eq $null) {
Write-Error -Message "No rule for $($EvtType) was found."
return
} else {
if ($EventRule.count -eq $null -or $EventRule.Count -eq 1) {
if ($EventRule.onmatch -eq $OnMatch) {
$Filters = $EventRule.SelectNodes('*')
if ($Filters.count -gt 0) {
foreach($val in $Value) {
foreach($Filter in $Filters) {
if ($Filter.Name -eq $EventField) {
if (($Filter.condition -eq $null) -and ($Condition -eq 'is') -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
} elseif (($Filter.condition -eq $Condition) -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
}
}
}
}
Get-RuleWithFilter($EventRule)
}
}
} else {
Write-Verbose -Message 'Mutiple nodes.'
foreach ($rule in $EventRule) {
if ($rule.onmatch -eq $OnMatch) {
$Filters = $rule.SelectNodes('*')
if ($Filters.count -gt 0) {
foreach($val in $Value) {
foreach($Filter in $Filters) {
if ($Filter.Name -eq $EventField) {
if (($Filter.condition -eq $null) -and ($Condition -eq 'is') -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
} elseif (($Filter.condition -eq $Condition) -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
}
}
}
}
Get-RuleWithFilter($rule)
}
}
}
}
}
$config.Save($FileLocation)
}
End{}
}
<#
.SYNOPSIS
Get the configured filters for a specified Event Type Rule in a Sysmon configuration file.
.DESCRIPTION
Get the configured filters for a specified Event Type Rule in a Sysmon configuration file.
.EXAMPLE
C:\PS> Get-SysmonRuleFilter -Path C:\sysmon.xml -EventType ProcessCreate
Get the filter under the ProcessCreate Rule.
#>
function Get-SysmonRuleFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRuleFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type rule to get filter for.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread','RawAccessRead', 'ProcessAccess',
'FileCreateStreamHash', 'RegistryEvent', 'FileCreate',
'PipeEvent', 'WmiEvent')]
[string]
$EventType,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch
)
Begin{}
Process {
$EvtType = $null
# Check if the file is a valid XML file and if not raise and error.
try {
switch($psCmdlet.ParameterSetName){
'Path'{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath' {
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [System.Management.Automation.PSInvalidCastException] {
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null){
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
$Rules = $Config.SelectSingleNode('//Sysmon/EventFiltering')
if ($Rules -eq '') {
Write-Error -Message 'Rule element does not exist. This appears to not be a valid config file'
return
} else {
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$EventType]
$EventRule = $Rules.SelectNodes("//EventFiltering/$($EvtType)")
}
if($EventRule -eq $null) {
Write-Error -Message "No rule for $($EvtType) was found."
return
} else {
if ($EventRule.count -eq $null -or $EventRule.Count -eq 1) {
Write-Verbose -Message 'Single Node'
if ($EventRule.onmatch -eq $OnMatch) {
$Filters = $EventRule.SelectNodes('*')
if ($Filters.ChildNodes.Count -gt 0) {
foreach($Filter in $Filters) {
$FilterObjProps = @{}
$FilterObjProps['EventField'] = $Filter.Name
$FilterObjProps['Condition'] = &{if($Filter.condition -eq $null){'is'}else{$Filter.condition}}
$FilterObjProps['Value'] = $Filter.'#text'
$FilterObjProps['EventType'] = $EvtType
$FilterObjProps['OnMatch'] = $OnMatch
$FilterObj = [pscustomobject]$FilterObjProps
$FilterObj.pstypenames.insert(0,'Sysmon.Rule.Filter')
$FilterObj
}
}
}
}
else
{
Write-Verbose -Message 'Mutiple nodes.'
foreach ($rule in $EventRule)
{
if ($rule.onmatch -eq $OnMatch)
{
$Filters = $rule.SelectNodes('*')
if ($Filters.ChildNodes.Count -gt 0)
{
foreach($Filter in $Filters)
{
$FilterObjProps = @{}
$FilterObjProps['EventField'] = $Filter.Name
$FilterObjProps['Condition'] = &{if($Filter.condition -eq $null){'is'}else{$Filter.condition}}
$FilterObjProps['Value'] = $Filter.'#text'
$FilterObjProps['EventType'] = $EvtType
$FilterObjProps['OnMatch'] = $OnMatch
$FilterObj = [pscustomobject]$FilterObjProps
$FilterObj.pstypenames.insert(0,'Sysmon.Rule.Filter')
$FilterObj
}
}
}
}
}
}
}
End{}
}
<#
.Synopsis
Searches for specified SysMon Events and retunrs the Event Data as a custom object.
.DESCRIPTION
Searches for specified SysMon Events and retunrs the Event Data as a custom object.
.EXAMPLE
Get-SysMonEventData -EventId 1 -MaxEvents 10 -EndTime (Get-Date) -StartTime (Get-Date).AddDays(-1)
All process creation events in the last 24hr
.EXAMPLE
Get-SysMonEventData -EventId 3 -MaxEvents 20 -Path .\export.evtx
last 20 network connection events from a exported SysMon log.
#>
function Get-SysmonEventData {
[CmdletBinding(DefaultParameterSetName='ID',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonEventData.md')]
Param (
# Sysmon Event ID of records to show
[Parameter(Mandatory=$true,
ParameterSetName='ID',
ValueFromPipelineByPropertyName=$true,
Position=0)]
[ValidateSet(1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,255)]
[Int32[]]
$EventId,
# EventType that a Rule can be written against.
[Parameter(Mandatory=$false,
ParameterSetName='Type',
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string[]]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread', 'RawAccessRead', 'ProcessAccess', 'Error',
'FileCreateStreamHash', 'RegistryValueSet', 'RegistryRename',
'RegistryAddOrDelete', 'FileCreate','ConfigChange','PipeCreated',
'PipeConnected', 'WmiFilter', 'WmiConsumer', 'WmiBinding')]
$EventType,
# Specifies the maximum number of events that Get-WinEvent returns. Enter an integer. The default is to return all the events in the logs or files.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[int]
$MaxEvents,
# Specifies a path to one or more exported SysMon events in evtx format.
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
HelpMessage='Path to one or more locations.')]
[Alias('PSPath')]
[ValidateNotNullOrEmpty()]
[string[]]
$Path,
# Start Date to get all event going forward.
[Parameter(Mandatory=$false)]
[datetime]
$StartTime,
# End data for searching events.
[Parameter(Mandatory=$false)]
[datetime]
$EndTime
)
Begin
{
$EventTypeMap = @{
ProcessCreate = 1
FileCreateTime = 2
NetworkConnect = 3
ProcessTerminate = 5
DriverLoad = 6
ImageLoad = 7
CreateRemoteThread = 8
RawAccessRead = 9
ProcessAccess = 10
FileCreate = 11
RegistryAddOrDelete = 12
RegistryValueSet = 13
RegistryRename = 14
FileCreateStreamHash = 15
ConfigChange = 16
PipeCreated = 17
PipeConnected = 18
WmiFilter = 19
WmiConsumer = 20
WmiBinding = 21
Error = 255
}
$EventIdtoType = @{
'1' = 'ProcessCreate'
'2' = 'FileCreateTime'
'3' = 'NetworkConnect'
'5' = 'ProcessTerminate'
'6' = 'DriverLoad'
'7' = 'ImageLoad'
'8' = 'CreateRemoteThread'
'9' = 'RawAccessRead'
'10' = 'ProcessAccess'
'11' = 'FileCreate'
'12' = 'RegistryAddOrDelete'
'13' = 'RegistryValueSet'
'14' = 'RegistryRename'
'15' = 'FileCreateStreamHash'
'16' = 'ConfigChange'
'17' = 'PipeCreated'
'18' = 'PipeConnected'
'19' = 'WmiFilter'
'20' = 'WmiConsumer'
'21' = 'WmiBinding'
'255' = 'Error'
}
}
Process
{
# Hash for filtering
$HashFilter = @{LogName='Microsoft-Windows-Sysmon/Operational'}
# Hash for command paramteters
$ParamHash = @{}
if ($MaxEvents -gt 0)
{
$ParamHash.Add('MaxEvents', $MaxEvents)
}
if ($Path -gt 0)
{
$ParamHash.Add('Path', $Path)
}
switch ($PSCmdlet.ParameterSetName) {
'ID' { $HashFilter.Add('Id', $EventId) }
'Type' {
$EventIds = @()
foreach ($etype in $EventType)
{
$EventIds += $EventTypeMap[$etype]
}
$HashFilter.Add('Id', $EventIds)
}
}
if ($StartTime)
{
$HashFilter.Add('StartTime', $StartTime)
}
if ($EndTime)
{
$HashFilter.Add('EndTime', $EndTime)
}
$ParamHash.Add('FilterHashTable',$HashFilter)
Get-WinEvent @ParamHash | ForEach-Object {
[xml]$evtxml = $_.toxml()
$ProcInfo = [ordered]@{}
$ProcInfo['EventId'] = $evtxml.Event.System.EventID
$ProcInfo['EventType'] = $EventIdtoType[$evtxml.Event.System.EventID]
$ProcInfo['Computer'] = $evtxml.Event.System.Computer
$evtxml.Event.EventData.Data | ForEach-Object {
$ProcInfo[$_.name] = $_.'#text'
}
New-Object psobject -Property $ProcInfo
}
}
End {}
}
================================================
FILE: Format/Sysmon.ConfigOption.ps1xml
================================================
Sysmon.ConfigOptionSysmon.ConfigOptionHashingNetworkImageLoadingComment
================================================
FILE: Format/Sysmon.Rule.Filter.ps1xml
================================================
Sysmon.Rule.FilterSysmon.Rule.Filter121250EventFieldConditionValue
================================================
FILE: Format/Sysmon.Rule.ps1xml
================================================
Sysmon.RuleSysmon.RuleEventTypeScopeDefaultActionFilters
================================================
FILE: Functions/ConvertFrom-SysmonBinaryConfiguration.ps1
================================================
<#
.SYNOPSIS
Parses a binary Sysmon configuration.
.DESCRIPTION
ConvertFrom-SysmonBinaryConfiguration parses a binary Sysmon configuration. The configuration is typically stored in the registry at the following path: HKLM\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters\Rules
ConvertFrom-SysmonBinaryConfiguration currently only supports the following schema versions: 3.30, 3.40 and 4.0
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
.PARAMETER RuleBytes
Specifies the raw bytes of a Sysmon configuration from the registry.
.EXAMPLE
[Byte[]] $RuleBytes = Get-ItemPropertyValue -Path HKLM:\SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters -Name Rules
ConvertFrom-SysmonBinaryConfiguration -RuleBytes $RuleBytes
.OUTPUTS
Sysmon.EventCollection
Output a fully-parsed rule object including the hash of the rules blob.
.NOTES
ConvertFrom-SysmonBinaryConfiguration is designed to serve as a helper function for Get-SysmonConfiguration.
#>
function ConvertFrom-SysmonBinaryConfiguration {
[OutputType('Sysmon.EventCollection')]
[CmdletBinding()]
param (
[Parameter(Mandatory = $True)]
[Byte[]]
[ValidateNotNullOrEmpty()]
$RuleBytes
)
#region Define byte to string mappings. This may change across verions.
$SupportedSchemaVersions = @(
[Version] '3.30.0.0',
[Version] '3.40.0.0',
[Version] '4.00.0.0'
)
$EventConditionMapping = @{
0 = 'Is'
1 = 'IsNot'
2 = 'Contains'
3 = 'Excludes'
4 = 'BeginWith'
5 = 'EndWith'
6 = 'LessThan'
7 = 'MoreThan'
8 = 'Image'
}
# The following value to string mappings were all pulled from
# IDA and will require manual validation with with each new
# Sysmon and schema version. Here's hoping they don't change often!
$ProcessCreateMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'CommandLine'
5 = 'CurrentDirectory'
6 = 'User'
7 = 'LogonGuid'
8 = 'LogonId'
9 = 'TerminalSessionId'
10 = 'IntegrityLevel'
11 = 'Hashes'
12 = 'ParentProcessGuid'
13 = 'ParentProcessId'
14 = 'ParentImage'
15 = 'ParentCommandLine'
}
$ProcessCreateMapping_4_00 = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'FileVersion'
5 = 'Description'
6 = 'Product'
7 = 'Company'
8 = 'CommandLine'
9 = 'CurrentDirectory'
10 = 'User'
11 = 'LogonGuid'
12 = 'LogonId'
13 = 'TerminalSessionId'
14 = 'IntegrityLevel'
15 = 'Hashes'
16 = 'ParentProcessGuid'
17 = 'ParentProcessId'
18 = 'ParentImage'
19 = 'ParentCommandLine'
}
$FileCreateTimeMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'TargetFilename'
5 = 'CreationUtcTime'
6 = 'PreviousCreationUtcTime'
}
$NetworkConnectMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'User'
5 = 'Protocol'
6 = 'Initiated'
7 = 'SourceIsIpv6'
8 = 'SourceIp'
9 = 'SourceHostname'
10 = 'SourcePort'
11 = 'SourcePortName'
12 = 'DestinationIsIpv6'
13 = 'DestinationIp'
14 = 'DestinationHostname'
15 = 'DestinationPort'
16 = 'DestinationPortName'
}
$SysmonServiceStateChangeMapping = @{
0 = 'UtcTime'
1 = 'State'
2 = 'Version'
3 = 'SchemaVersion'
}
$ProcessTerminateMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
}
$DriverLoadMapping = @{
0 = 'UtcTime'
1 = 'ImageLoaded'
2 = 'Hashes'
3 = 'Signed'
4 = 'Signature'
5 = 'SignatureStatus'
}
$ImageLoadMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'ImageLoaded'
5 = 'Hashes'
6 = 'Signed'
7 = 'Signature'
8 = 'SignatureStatus'
}
$ImageLoadMapping_4_00 = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'ImageLoaded'
5 = 'FileVersion'
6 = 'Description'
7 = 'Product'
8 = 'Company'
9 = 'Hashes'
10 = 'Signed'
11 = 'Signature'
12 = 'SignatureStatus'
}
$CreateRemoteThreadMapping = @{
0 = 'UtcTime'
1 = 'SourceProcessGuid'
2 = 'SourceProcessId'
3 = 'SourceImage'
4 = 'TargetProcessGuid'
5 = 'TargetProcessId'
6 = 'TargetImage'
7 = 'NewThreadId'
8 = 'StartAddress'
9 = 'StartModule'
10 = 'StartFunction'
}
$RawAccessReadMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'Device'
}
$ProcessAccessMapping = @{
0 = 'UtcTime'
1 = 'SourceProcessGUID'
2 = 'SourceProcessId'
3 = 'SourceThreadId'
4 = 'SourceImage'
5 = 'TargetProcessGUID'
6 = 'TargetProcessId'
7 = 'TargetImage'
8 = 'GrantedAccess'
9 = 'CallTrace'
}
$FileCreateMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'TargetFilename'
5 = 'CreationUtcTime'
}
$RegistryEventCreateKeyMapping = @{
0 = 'EventType'
1 = 'UtcTime'
2 = 'ProcessGuid'
3 = 'ProcessId'
4 = 'Image'
5 = 'TargetObject'
}
$RegistryEventSetValueMapping = @{
0 = 'EventType'
1 = 'UtcTime'
2 = 'ProcessGuid'
3 = 'ProcessId'
4 = 'Image'
5 = 'TargetObject'
6 = 'Details'
}
$RegistryEventDeleteKeyMapping = @{
0 = 'EventType'
1 = 'UtcTime'
2 = 'ProcessGuid'
3 = 'ProcessId'
4 = 'Image'
5 = 'TargetObject'
6 = 'NewName'
}
$FileCreateStreamHashMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'Image'
4 = 'TargetFilename'
5 = 'CreationUtcTime'
6 = 'Hash'
}
$SysmonConfigurationChangeMapping = @{
0 = 'UtcTime'
1 = 'Configuration'
2 = 'ConfigurationFileHash'
}
$PipeEventCreatedMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'PipeName'
4 = 'Image'
}
$PipeEventConnectedMapping = @{
0 = 'UtcTime'
1 = 'ProcessGuid'
2 = 'ProcessId'
3 = 'PipeName'
4 = 'Image'
}
$WmiEventFilterMapping = @{
0 = 'EventType'
1 = 'UtcTime'
2 = 'Operation'
3 = 'User'
4 = 'EventNamespace'
5 = 'Name'
6 = 'Query'
}
$WmiEventConsumerMapping = @{
0 = 'EventType'
1 = 'UtcTime'
2 = 'Operation'
3 = 'User'
4 = 'Name'
5 = 'Type'
6 = 'Destination'
}
$WmiEventConsumerToFilterMapping = @{
0 = 'EventType'
1 = 'UtcTime'
2 = 'Operation'
3 = 'User'
4 = 'Consumer'
5 = 'Filter'
}
$EventTypeMapping = @{
1 = @('ProcessCreate', $ProcessCreateMapping)
2 = @('FileCreateTime', $FileCreateTimeMapping)
3 = @('NetworkConnect', $NetworkConnectMapping)
# SysmonServiceStateChange is not actually present in the schema. It is here for the sake of completeness.
4 = @('SysmonServiceStateChange', $SysmonServiceStateChangeMapping)
5 = @('ProcessTerminate', $ProcessTerminateMapping)
6 = @('DriverLoad', $DriverLoadMapping)
7 = @('ImageLoad', $ImageLoadMapping)
8 = @('CreateRemoteThread', $CreateRemoteThreadMapping)
9 = @('RawAccessRead', $RawAccessReadMapping)
10 = @('ProcessAccess', $ProcessAccessMapping)
11 = @('FileCreate', $FileCreateMapping)
12 = @('RegistryEventCreateKey', $RegistryEventCreateKeyMapping)
13 = @('RegistryEventSetValue', $RegistryEventSetValueMapping)
14 = @('RegistryEventDeleteKey', $RegistryEventDeleteKeyMapping)
15 = @('FileCreateStreamHash', $FileCreateStreamHashMapping)
# SysmonConfigurationChange is not actually present in the schema. It is here for the sake of completeness.
16 = @('SysmonConfigurationChange', $SysmonConfigurationChangeMapping)
17 = @('PipeEventCreated', $PipeEventCreatedMapping)
18 = @('PipeEventConnected', $PipeEventConnectedMapping)
19 = @('WmiEventFilter', $WmiEventFilterMapping)
20 = @('WmiEventConsumer', $WmiEventConsumerMapping)
21 = @('WmiEventConsumerToFilter', $WmiEventConsumerToFilterMapping)
}
#endregion
$RuleMemoryStream = New-Object -TypeName System.IO.MemoryStream -ArgumentList @(,$RuleBytes)
$RuleReader = New-Object -TypeName System.IO.BinaryReader -ArgumentList $RuleMemoryStream
# I'm noting here for the record that parsing could be slightly more robust to account for malformed
# rule blobs. I'm writing this in my spare time so I likely won't put too much work into increased
# parsing robustness.
if ($RuleBytes.Count -lt 16) {
$RuleReader.Dispose()
$RuleMemoryStream.Dispose()
throw 'Insufficient length to contain a Sysmon rule header.'
}
# This value should be either 0 or 1. 1 should be expected for a current Sysmon config.
# A value of 1 indicates that offset 8 will contain the file offset to the first rule grouping.
# A value of 0 should indicate that offset 8 will be the start of the first rule grouping.
# Currently, I am just going to check that the value is 1 and throw an exception if it's not.
$HeaderValue0 = $RuleReader.ReadUInt16()
if ($HeaderValue0 -ne 1) {
$RuleReader.Dispose()
$RuleMemoryStream.Dispose()
throw "Incorrect header value at offset 0x00. Expected: 1. Actual: $HeaderValue0"
}
# This value is expected to be 1. Any other value will indicate the presence of a "registry rule version"
# that is incompatible with the current Sysmon schema version. A value other than 1 likely indicates the
# presence of an old version of Sysmon. Any value besides 1 will not be supported in this script.
$HeaderValue1 = $RuleReader.ReadUInt16()
if ($HeaderValue1 -ne 1) {
$RuleReader.Dispose()
$RuleMemoryStream.Dispose()
throw "Incorrect header value at offset 0x02. Expected: 1. Actual: $HeaderValue1"
}
$RuleGroupCount = $RuleReader.ReadUInt32()
$RuleGroupBeginOffset = $RuleReader.ReadUInt32()
$SchemaVersionMinor = $RuleReader.ReadUInt16()
$SchemaVersionMajor = $RuleReader.ReadUInt16()
$SchemaVersion = New-Object -TypeName System.Version -ArgumentList $SchemaVersionMajor, $SchemaVersionMinor, 0, 0
Write-Verbose "Obtained the following schema version: $($SchemaVersion.ToString(2))"
if (-not ($SupportedSchemaVersions -contains $SchemaVersion)) {
$RuleReader.Dispose()
$RuleMemoryStream.Dispose()
throw "Unsupported schema version: $($SchemaVersion.ToString(2)). Schema version must be at least $($MinimumSupportedSchemaVersion.ToString(2))"
}
#region Perform offset updates depending upon the schema version here
# This logic should be the first candidate for refactoring should the schema change drastically in the future.
switch ($SchemaVersion.ToString(2)) {
'4.0' {
Write-Verbose 'Using schema version 4.00 updated offsets.'
# ProcessCreate and ImageLoad values changed
$EventTypeMapping[1][1] = $ProcessCreateMapping_4_00
$EventTypeMapping[7][1] = $ImageLoadMapping_4_00
}
}
#endregion
$null = $RuleReader.BaseStream.Seek($RuleGroupBeginOffset, 'Begin')
$EventCollection = for ($i = 0; $i -lt $RuleGroupCount; $i++) {
$EventTypeValue = $RuleReader.ReadInt32()
$EventType = $EventTypeMapping[$EventTypeValue][0]
$EventTypeRuleTypes = $EventTypeMapping[$EventTypeValue][1]
$OnMatchValue = $RuleReader.ReadInt32()
$OnMatch = $null
switch ($OnMatchValue) {
0 { $OnMatch = 'Exclude' }
1 { $OnMatch = 'Include' }
default { $OnMatch = '?' }
}
$NextEventTypeOffset = $RuleReader.ReadInt32()
$RuleCount = $RuleReader.ReadInt32()
[PSObject[]] $Rules = New-Object -TypeName PSObject[]($RuleCount)
# Parse individual rules here
for ($j = 0; $j -lt $RuleCount; $j++) {
$RuleType = $EventTypeRuleTypes[$RuleReader.ReadInt32()]
$Filter = $EventConditionMapping[$RuleReader.ReadInt32()]
$NextRuleOffset = $RuleReader.ReadInt32()
$RuleTextLength = $RuleReader.ReadInt32()
$RuleTextBytes = $RuleReader.ReadBytes($RuleTextLength)
$RuleText = [Text.Encoding]::Unicode.GetString($RuleTextBytes).TrimEnd("`0")
$Rules[$j] = [PSCustomObject] @{
PSTypeName = 'Sysmon.Rule'
RuleType = $RuleType
Filter = $Filter
RuleText = $RuleText
}
$null = $RuleReader.BaseStream.Seek($NextRuleOffset, 'Begin')
}
[PSCustomObject] @{
PSTypeName = 'Sysmon.EventGroup'
EventType = $EventType
OnMatch = $OnMatch
Rules = $Rules
}
$null = $RuleReader.BaseStream.Seek($NextEventTypeOffset, 'Begin')
}
$RuleReader.Dispose()
$RuleMemoryStream.Dispose()
# Calculate the hash of the binary rule blob
$SHA256Hasher = New-Object -TypeName System.Security.Cryptography.SHA256CryptoServiceProvider
$ConfigBlobSHA256Hash = ($SHA256Hasher.ComputeHash($RuleBytes) | ForEach-Object { $_.ToString('X2') }) -join ''
[PSCustomObject] @{
PSTypeName = 'Sysmon.EventCollection'
SchemaVersion = $SchemaVersion
ConfigBlobSHA256Hash = $ConfigBlobSHA256Hash
Events = $EventCollection
}
}
================================================
FILE: Functions/ConvertTo-SysmonXMLConfiguration.ps1
================================================
<#
.SYNOPSIS
Recovers a Sysmon XML configuration from a binary configuration.
.DESCRIPTION
ConvertTo-SysmonXMLConfiguration takes the parsed output from Get-SysmonConfiguration and converts it to an XML configuration. This function is useful for recovering lost Sysmon configurations or for performing reconnaisance.
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: Get-SysmonConfiguration
GeneratedCode.ps1
.PARAMETER Configuration
Specifies the parsed Sysmon configuration output from Get-SysmonConfiguration.
.EXAMPLE
Get-SysmonConfiguration | ConvertTo-SysmonXMLConfiguration
.EXAMPLE
$Configuration = Get-SysmonConfiguration
ConvertTo-SysmonXMLConfiguration -Configuration $Configuration
.INPUTS
Sysmon.Configuration
ConvertTo-SysmonXMLConfiguration accepts a single result from Get-SysmonConfiguration over the pipeline. Note: it will not accept input from Get-SysmonConfiguration when "-MatchExeOutput" is specified.
.OUTPUTS
System.String
Outputs a Sysmon XML configuration document.
#>
function ConvertTo-SysmonXMLConfiguration {
[OutputType([String])]
[CmdletBinding()]
param (
[Parameter(Mandatory = $True, ValueFromPipeline = $True)]
[PSTypeName('Sysmon.Configuration')]
$Configuration
)
$SchemaVersion = $Configuration.SchemaVersion
# Get the parsing code for the respective schema.
# Code injection note: an attacker would be able to influence the schema version used. That would only influence what
# non-injectible source code was supplied to Add-Type, however. $ConfigurationSchemaSource variables should always be
# constant variables with script (i.e. module) scope.
$SchemaSource = Get-Variable -Name "SysmonConfigSchemaSource_$($SchemaVersion.Replace('.', '_'))" -Scope Script -ValueOnly
# Compile the parsing code
Add-Type -TypeDefinition $SchemaSource -ReferencedAssemblies 'System.Xml' -ErrorAction Stop
$NamespaceName = "Sysmon_$($SchemaVersion.Replace('.', '_'))"
# Create a base "Sysmon" object. This serves as the root node that will eventually be serialized to XML.
$Sysmon = New-Object -TypeName "$NamespaceName.Sysmon"
$Sysmon.schemaversion = $Configuration.SchemaVersion
if ($Configuration.CRLCheckingEnabled) { $Sysmon.CheckRevocation = New-Object -TypeName "$NamespaceName.SysmonCheckRevocation" }
# The hashing algorithms need to be lower case in the XML config.
$Sysmon.HashAlgorithms = ($Configuration.HashingAlgorithms | ForEach-Object { $_.ToLower() }) -join ','
$ProcessAccessString = ($Configuration.ProcessAccess | ForEach-Object { "$($_.ProcessName):0x$($_.AccessMask.ToString('x'))" }) -join ','
if ($ProcessAccessString) { $Sysmon.ProcessAccessConfig = $ProcessAccessString }
# Do not consider redundant event types. A well-formed binary Sysmon rule blob will have
# identical RegistryEvent, PipeEvent, and WmiEvent rule entries as of config schema version 3.4[0]
$EventTypesToExclude = @(
'RegistryEventSetValue',
'RegistryEventDeleteKey',
'PipeEventConnected',
'WmiEventConsumer',
'WmiEventConsumerToFilter'
)
# Group rules by their respective event types - a requirement for
# setting properties properly in the SysmonEventFiltering instance.
$EventGrouping = $Configuration.Rules |
Where-Object { -not ($EventTypesToExclude -contains $_.EventType) } |
Group-Object -Property EventType
# A configuration can technically not have any EventFiltering rules.
if ($EventGrouping) {
$Sysmon.EventFiltering = New-Object -TypeName "$NamespaceName.SysmonEventFiltering"
foreach ($Event in $EventGrouping) {
# The name of the event - e.g. ProcessCreate, FileCreate, etc.
$EventName = $Event.Name
# Normalize these event names.
# Have a mentioned that I hate that these aren't unique names in Sysmon?
switch ($EventName) {
'RegistryEventCreateKey' { $EventName = 'RegistryEvent' }
'PipeEventCreated' { $EventName = 'PipeEvent' }
'WmiEventFilter' { $EventName = 'WmiEvent' }
}
if ($Event.Count -gt 2) {
Write-Error "There is more than two $EventName entries. This should not be possible."
return
}
if (($Event.Count -eq 2) -and ($Event.Group[0].OnMatch -eq $Event.Group[1].OnMatch)) {
Write-Error "The `"onmatch`" attribute values for the $EventName rules are not `"include`" and `"exclude`". This should not be possible."
return
}
$Events = foreach ($RuleSet in $Event.Group) {
# The dynamic typing that follows relies upon naming consistency in the schema serialization source code.
$EventInstance = New-Object -TypeName "$NamespaceName.SysmonEventFiltering$EventName" -Property @{
onmatch = $RuleSet.OnMatch.ToLower()
}
$RuleDefs = @{}
foreach ($Rule in $RuleSet.Rules) {
$PropertyName = $Rule.RuleType
# Since each property can be of a unique type, resolve it accordingly.
$PropertyTypeName = ("$NamespaceName.SysmonEventFiltering$EventName" -as [Type]).GetProperty($PropertyName).PropertyType.FullName.TrimEnd('[]')
if (-not $RuleDefs.ContainsKey($PropertyName)) {
$RuleDefs[$PropertyName] = New-Object -TypeName "Collections.ObjectModel.Collection``1[$PropertyTypeName]"
}
$RuleInstance = New-Object -TypeName $PropertyTypeName
# This needs to be lower case in the XML config.
$RuleInstance.condition = $Rule.Filter.ToLower()
# An exception is thrown here if the value has a space and it is being cast to an enum type.
# Currently, "Protected Process" is the only instance. I'll need to refactor this if more instances arise.
if ($Rule.RuleText -eq 'Protected Process') { $RuleInstance.Value = 'ProtectedProcess' } else { $RuleInstance.Value = $Rule.RuleText }
$RuleDefs[$PropertyName].Add($RuleInstance)
}
# Set the collected rule properties accordingly.
foreach ($PropertyName in $RuleDefs.Keys) {
$EventInstance."$PropertyName" = $RuleDefs[$PropertyName]
}
$EventInstance
}
$EventPropertyName = $Events[0].GetType().Name.Substring('SysmonEventFiltering'.Length)
$Sysmon.EventFiltering."$EventPropertyName" = $Events
}
}
$XmlWriter = $null
try {
$XmlWriterSetting = New-Object -TypeName Xml.XmlWriterSettings
# A Sysmon XML config is not expected to have an XML declaration line.
$XmlWriterSetting.OmitXmlDeclaration = $True
$XmlWriterSetting.Indent = $True
# Use two spaces in place of a tab character.
$XmlWriterSetting.IndentChars = ' '
# Normalize newlines to CRLF.
$XmlWriterSetting.NewLineHandling = [Xml.NewLineHandling]::Replace
$XMlStringBuilder = New-Object -TypeName Text.StringBuilder
$XmlWriter = [Xml.XmlWriter]::Create($XMlStringBuilder, $XmlWriterSetting)
$XmlSerializer = New-Object -TypeName Xml.Serialization.XmlSerializer -ArgumentList ("$NamespaceName.Sysmon" -as [Type]), ''
# This will strip any additional "xmlns" attributes from the root Sysmon element.
$EmptyNamespaces = New-Object -TypeName Xml.Serialization.XmlSerializerNamespaces
$EmptyNamespaces.Add('', '')
$XmlSerializer.Serialize($XmlWriter, $Sysmon, $EmptyNamespaces)
} catch {
Write-Error $_
} finally {
if ($XmlWriter) { $XmlWriter.Close() }
}
$XMlStringBuilder.ToString()
}
================================================
FILE: Functions/Get-SysmonConfiguration.ps1
================================================
<#
.SYNOPSIS
Parses a Sysmon driver configuration from the registry. Output is nearly identical to that of "sysmon.exe -c" but without the requirement to run sysmon.exe.
.DESCRIPTION
Get-SysmonConfiguration parses a Sysmon configuration from the registry without the need to run "sysmon.exe -c". This function is designed to enable Sysmon configuration auditing at scale as well as reconnaissance for red teamers.
Get-SysmonConfiguration has been tested with the following Sysmon versions: 6.20
Due to the admin-only ACL set on the Sysmon driver registry key, Get-SysmonConfiguration will typically need to run in an elevated context. Because the user-mode service and driver names can be changed, Get-SysmonConfiguration will locate the service and driver regardless of their names.
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: ConvertFrom-SysmonBinaryConfiguration
.PARAMETER MatchExeOutput
Mirrors the text output of "sysmon.exe -c". This parameter was implemented primarily to enable testing scenarios - i.e. to ensure that the output matches that of the version of Sysmon (or schema) being tested against.
.EXAMPLE
Get-SysmonConfiguration
.EXAMPLE
Get-SysmonConfiguration -MatchExeOutput
.OUTPUTS
Sysmon.Configuration
Outputs a fully parsed Sysmon configuration including the hash of the registry rule blob for auditing purposes.
System.String
Outputs mirrored output from "sysmon.exe -c".
.NOTES
Get-SysmonConfiguration will have to be manually validated for each new Sysmon and configuration schema version. Please report all bugs and indiscrepencies with new versions by supplying the following information:
1) The Sysmon config XML that's generating the error (only schema versions 3.30 and later).
2) The version of Sysmon being used (only 6.20 and later).
#>
function Get-SysmonConfiguration {
[OutputType('Sysmon.Configuration', ParameterSetName = 'PSOutput')]
[OutputType([String], ParameterSetName = 'ExeOutput')]
[CmdletBinding(DefaultParameterSetName = 'PSOutput')]
param (
[Parameter(ParameterSetName = 'ExeOutput')]
[Switch]
$MatchExeOutput
)
# Find the Sysmon driver based solely off the presence of the "Rules" value.
# This is being done because the user can optionally specify a driver name other than the default: SysmonDrv
$ServiceParameters = Get-ChildItem -Path HKLM:\SYSTEM\CurrentControlSet\Services -Recurse -Include 'Parameters' -ErrorAction SilentlyContinue
$DriverParameters = $ServiceParameters | Where-Object { $_.Property -contains 'Rules' }
if (-not $DriverParameters) {
Write-Error 'Unable to locate a Sysmon driver. Either it is not installed or you do not have permissions to read the driver configuration in the registry.'
return
}
$FoundSysmonMatch = $False
$SysmonDriverName = $null
$SysmonServiceName = $null
$SysmonDriverParams = $null
# Just in case there is more than one instance where there is a "Rules" value, correlate it with the user-mode service to confirm.
$DriverParameters | ForEach-Object {
$CandidateDriverName = $_.PSParentPath.Split('\')[-1]
$CandidateDriverParams = $_
$CandidateUserModeServices = $ServiceParameters | Where-Object { $_.Property -contains 'DriverName' }
if (-not $CandidateUserModeServices) {
Write-Error 'Unable to locate a user-mode Sysmon service.'
return
}
$CandidateUserModeServices | ForEach-Object {
$CandidateServiceName = $_.PSParentPath.Split('\')[-1]
$DriverName = ($_ | Get-ItemProperty).DriverName
# We have a matching user-mode Sysmon service and Sysmon driver.
if ($DriverName -eq $CandidateDriverName) {
$FoundSysmonMatch = $True
$SysmonDriverName = $CandidateDriverName
$SysmonServiceName = $CandidateServiceName
$SysmonDriverParams = $CandidateDriverParams | Get-ItemProperty
}
}
}
if ($FoundSysmonMatch) {
# HKLM\SYSTEM\CurrentControlSet\Services\\Parameters
$RuleBytes = $SysmonDriverParams.Rules # REG_BINARY
$Options = $SysmonDriverParams.Options # REG_DWORD
$HashingAlgorithmValue = $SysmonDriverParams.HashingAlgorithm # REG_DWORD
$ProcessAccessMasks = $SysmonDriverParams.ProcessAccessMasks # REG_BINARY - No larger than size: 0x28 (0x28 / 4 == 10: unique masks to interpret alongside ProcessAccessNames)
$ProcessAccessNames = $SysmonDriverParams.ProcessAccessNames # REG_MULTI_SZ - Can have no more than 10 entries
$CheckRevocation = $SysmonDriverParams.CheckRevocation # REG_BINARY of size: 1 byte
# The high-order bit of HashingAlgorithm must be set to 1 (i.e. 0x80000000)
$HashingAlgorithms = if ($HashingAlgorithmValue) {
if ($HashingAlgorithmValue -band 1) { 'SHA1' }
if ($HashingAlgorithmValue -band 2) { 'MD5' }
if ($HashingAlgorithmValue -band 4) { 'SHA256' }
if ($HashingAlgorithmValue -band 8) { 'IMPHASH' }
}
$NetworkConnection = $False
if ($Options -band 1) { $NetworkConnection = $True }
$ImageLoading = $False
if ($Options -band 2) { $ImageLoading = $True }
$CRLChecking = $False
if (($CheckRevocation.Count -gt 0) -and ($CheckRevocation[0] -eq 1)) { $CRLChecking = $True }
# Parse the binary rules blob.
$Rules = ConvertFrom-SysmonBinaryConfiguration -RuleBytes $RuleBytes
$ProcessAccess = $False
if ($Rules.Events.EventType -contains 'ProcessAccess') { $ProcessAccess = $True }
# Process ProcessAccessNames and ProcessAccessMasks.
# The code path to actually use these appears to be a dead one now.
# I'm only parsing this to mirror Sysmon 6.20 supporting parsing.
$ProcessAccessList = New-Object -TypeName PSObject[]($ProcessAccessNames.Count)
for ($i = 0; $i -lt $ProcessAccessNames.Count; $i++) {
$ProcessAccessList[$i] = [PSCustomObject] @{
ProcessName = $ProcessAccessNames[$i]
AccessMask = [BitConverter]::ToInt32($ProcessAccessMasks, $i * 4)
}
}
$Properties = [Ordered] @{
PSTypeName = 'Sysmon.Configuration'
ServiceName = $SysmonServiceName
DriverName = $SysmonDriverName
HashingAlgorithms = $HashingAlgorithms
NetworkConnectionEnabled = $NetworkConnection
ImageLoadingEnabled = $ImageLoading
CRLCheckingEnabled = $CRLChecking
ProcessAccessEnabled = $ProcessAccess
ProcessAccess = $ProcessAccessList
SchemaVersion = $Rules.SchemaVersion.ToString(2)
ConfigBlobSHA256Hash = $Rules.ConfigBlobSHA256Hash
Rules = $Rules.Events
}
# Don't print the ProcessAccess property if it's not populated. With Sysmon 6.20, this
# should never be present anyway unless there's a stale artifact from an older version.
if ($ProcessAccessList.Count -eq 0) { $Properties.Remove('ProcessAccess') }
if ($MatchExeOutput) {
$NetworkConnectionString = if ($NetworkConnection) { 'enabled' } else { 'disabled' }
$ImageLoadingString = if ($ImageLoading) { 'enabled' } else { 'disabled' }
$CRLCheckingString = if ($CRLChecking) { 'enabled' } else { 'disabled' }
$ProcessAccessString = if ($ProcessAccess) { 'enabled' } else { 'disabled' }
if ($ProcessAccessList) {
$ProcessAccessString = ($ProcessAccessList | ForEach-Object { "`"$($_.ProcessName)`":0x$($_.AccessMask.ToString('x'))" }) -join ','
}
$AllRuleText = $Rules.Events | ForEach-Object {
# Dumb hacks to format output to the original "sysmon.exe -c" output
$EventType = $_.EventType
if ($EventType.StartsWith('RegistryEvent')) { $EventType = 'RegistryEvent' }
if ($EventType.StartsWith('WmiEvent')) { $EventType = 'WmiEvent' }
if ($EventType.StartsWith('PipeEvent')) { $EventType = 'PipeEvent' }
$RuleText = $_.Rules | ForEach-Object {
$FilterText = switch ($_.Filter) {
'Is' { 'is' }
'IsNot' { 'is not' }
'Contains' { 'contains' }
'Excludes' { 'excludes' }
'BeginWith' { 'begin with' }
'EndWith' { 'end with' }
'LessThan' { 'less than' }
'MoreThan' { 'more than' }
'Image' { 'image' }
}
"`t{0,-30} filter: {1,-12} value: '{2}'" -f $_.RuleType, $FilterText, $_.RuleText
}
$RuleSet = @"
- {0,-34} onmatch: {1}
{2}
"@ -f $EventType,
$_.OnMatch.ToLower(),
($RuleText | Out-String).TrimEnd("`r`n")
$RuleSet.TrimEnd("`r`n")
}
$ConfigOutput = @"
Current configuration:
{0,-34}{1}
{2,-34}{3}
{4,-34}{5}
{6,-34}{7}
{8,-34}{9}
{10,-34}{11}
{12,-34}{13}
Rule configuration (version {14}):
{15}
"@ -f ' - Service name:',
$SysmonServiceName,
' - Driver name:',
$SysmonDriverName,
' - HashingAlgorithms:',
($HashingAlgorithms -join ','),
' - Network connection:',
$NetworkConnectionString,
' - Image loading:',
$ImageLoadingString,
' - CRL checking:',
$CRLCheckingString,
' - Process Access:',
$ProcessAccessString,
"$($Rules.SchemaVersion.Major).$($Rules.SchemaVersion.Minor.ToString().PadRight(2, '0'))",
($AllRuleText | Out-String).TrimEnd("`r`n")
$ConfigOutput
} else {
[PSCustomObject] $Properties
}
} else {
Write-Error 'Unable to locate a Sysmon driver and user-mode service.'
}
}
================================================
FILE: Functions/Get-SysmonEventData.ps1
================================================
<#
.Synopsis
Searches for specified SysMon Events and retunrs the Event Data as a custom object.
.DESCRIPTION
Searches for specified SysMon Events and retunrs the Event Data as a custom object.
.EXAMPLE
Get-SysMonEventData -EventId 1 -MaxEvents 10 -EndTime (Get-Date) -StartTime (Get-Date).AddDays(-1)
All process creation events in the last 24hr
.EXAMPLE
Get-SysMonEventData -EventId 3 -MaxEvents 20 -Path .\export.evtx
last 20 network connection events from a exported SysMon log.
#>
function Get-SysmonEventData {
[CmdletBinding(DefaultParameterSetName='ID',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonEventData.md')]
Param (
# Sysmon Event ID of records to show
[Parameter(Mandatory=$true,
ParameterSetName='ID',
ValueFromPipelineByPropertyName=$true,
Position=0)]
[ValidateSet(1,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,255)]
[Int32[]]
$EventId,
# EventType that a Rule can be written against.
[Parameter(Mandatory=$false,
ParameterSetName='Type',
ValueFromPipelineByPropertyName=$true,
Position=0)]
[string[]]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread', 'RawAccessRead', 'ProcessAccess', 'Error',
'FileCreateStreamHash', 'RegistryValueSet', 'RegistryRename',
'RegistryAddOrDelete', 'FileCreate','ConfigChange','PipeCreated',
'PipeConnected', 'WmiFilter', 'WmiConsumer', 'WmiBinding',
'DnsEvent', 'FileDelete', 'ClipboardChange', 'ProcessTampering')]
$EventType,
# Specifies the maximum number of events that Get-WinEvent returns. Enter an integer. The default is to return all the events in the logs or files.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[int]
$MaxEvents,
# Specifies a path to one or more exported SysMon events in evtx format.
[Parameter(Mandatory=$false,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
HelpMessage='Path to one or more locations.')]
[Alias('PSPath')]
[ValidateNotNullOrEmpty()]
[string[]]
$Path,
# Start Date to get all event going forward.
[Parameter(Mandatory=$false)]
[datetime]
$StartTime,
# End data for searching events.
[Parameter(Mandatory=$false)]
[datetime]
$EndTime
)
Begin
{
$EventTypeMap = @{
ProcessCreate = 1
FileCreateTime = 2
NetworkConnect = 3
ProcessTerminate = 5
DriverLoad = 6
ImageLoad = 7
CreateRemoteThread = 8
RawAccessRead = 9
ProcessAccess = 10
FileCreate = 11
RegistryAddOrDelete = 12
RegistryValueSet = 13
RegistryRename = 14
FileCreateStreamHash = 15
ConfigChange = 16
PipeCreated = 17
PipeConnected = 18
WmiFilter = 19
WmiConsumer = 20
WmiBinding = 21
DnsEvent = 22
FileDelete = 23
ClipboardChange = 24
ProcessTampering = 25
Error = 255
}
$EventIdtoType = @{
'1' = 'ProcessCreate'
'2' = 'FileCreateTime'
'3' = 'NetworkConnect'
'5' = 'ProcessTerminate'
'6' = 'DriverLoad'
'7' = 'ImageLoad'
'8' = 'CreateRemoteThread'
'9' = 'RawAccessRead'
'10' = 'ProcessAccess'
'11' = 'FileCreate'
'12' = 'RegistryAddOrDelete'
'13' = 'RegistryValueSet'
'14' = 'RegistryRename'
'15' = 'FileCreateStreamHash'
'16' = 'ConfigChange'
'17' = 'PipeCreated'
'18' = 'PipeConnected'
'19' = 'WmiFilter'
'20' = 'WmiConsumer'
'21' = 'WmiBinding'
'22' = 'DnsEvent'
'23' = 'FileDelete'
'24' = 'ClipboardChange'
'25' = 'ProcessTampering'
'255' = 'Error'
}
}
Process
{
# Hash for filtering
$HashFilter = @{LogName='Microsoft-Windows-Sysmon/Operational'}
# Hash for command paramteters
$ParamHash = @{}
if ($MaxEvents -gt 0)
{
$ParamHash.Add('MaxEvents', $MaxEvents)
}
if ($Path -gt 0)
{
$ParamHash.Add('Path', $Path)
}
switch ($PSCmdlet.ParameterSetName) {
'ID' { $HashFilter.Add('Id', $EventId) }
'Type' {
$EventIds = @()
foreach ($etype in $EventType)
{
$EventIds += $EventTypeMap[$etype]
}
$HashFilter.Add('Id', $EventIds)
}
}
if ($StartTime)
{
$HashFilter.Add('StartTime', $StartTime)
}
if ($EndTime)
{
$HashFilter.Add('EndTime', $EndTime)
}
$ParamHash.Add('FilterHashTable',$HashFilter)
Get-WinEvent @ParamHash | ForEach-Object {
[xml]$evtxml = $_.toxml()
$ProcInfo = [ordered]@{}
$ProcInfo['EventId'] = $evtxml.Event.System.EventID
$ProcInfo['EventType'] = $EventIdtoType[$evtxml.Event.System.EventID]
$ProcInfo['Computer'] = $evtxml.Event.System.Computer
$evtxml.Event.EventData.Data | ForEach-Object {
$ProcInfo[$_.name] = $_.'#text'
}
New-Object psobject -Property $ProcInfo
}
}
End {}
}
================================================
FILE: Functions/Get-SysmonHashingAlgorithm.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Get-SysmonHashingAlgorithm
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonHashingAlgorithm.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[string]$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
[string]$LiteralPath
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path' {[xml]$Config = Get-Content -Path $Path}
'LiteralPath' {[xml]$Config = Get-Content -LiteralPath $LiteralPath}
}
}
catch [System.Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$ObjOptions = @{}
if ($Config.Sysmon.SelectSingleNode('//HashAlgorithms'))
{
$ObjOptions['Hashing'] = $config.Sysmon.HashAlgorithms
}
else
{
$ObjOptions['Hashing'] = ''
}
#$ObjOptions['Comment'] = $Config.'#comment'
$ConfigObj = [pscustomobject]$ObjOptions
$ConfigObj.pstypenames.insert(0,'Sysmon.HashingAlgorithm')
$ConfigObj
}
End{}
}
================================================
FILE: Functions/Get-SysmonRule.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Get-SysmonRule
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRule.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[string]$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
[string]$LiteralPath,
# Event type to parse rules for.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('ALL', 'NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad', 'ProcessAccess',
'RawAccessRead','ProcessAccess', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')]
[string[]]
$EventType = @('ALL')
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path' {[xml]$Config = Get-Content -Path $Path}
'LiteralPath' {[xml]$Config = Get-Content -LiteralPath $LiteralPath}
}
}
catch [System.Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
# Collect all individual rules if they exist.
$Rules = $Config.Sysmon.EventFiltering
if ($EventType -contains 'ALL')
{
$TypesToParse = @('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad','CreateRemoteThread',
'ProcessAccess', 'RawAccessRead', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')
}
else
{
$TypesToParse = $EventType
}
foreach($Type in $TypesToParse)
{
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$Type]
$RuleData = $Rules.SelectNodes("//EventFiltering/$($EvtType)")
if($RuleData -ne $null)
{
Write-Verbose -Message "$($EvtType) Rule Found."
Get-RuleWithFilter($RuleData)
}
}
}
End{}
}
================================================
FILE: Functions/Get-SysmonRuleFilter.ps1
================================================
<#
.SYNOPSIS
Get the configured filters for a specified Event Type Rule in a Sysmon configuration file.
.DESCRIPTION
Get the configured filters for a specified Event Type Rule in a Sysmon configuration file.
.EXAMPLE
C:\PS> Get-SysmonRuleFilter -Path C:\sysmon.xml -EventType ProcessCreate
Get the filter under the ProcessCreate Rule.
#>
function Get-SysmonRuleFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRuleFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type rule to get filter for.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread','RawAccessRead', 'ProcessAccess',
'FileCreateStreamHash', 'RegistryEvent', 'FileCreate',
'PipeEvent', 'WmiEvent','RuleName')]
[string]
$EventType,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch
)
Begin{}
Process {
$EvtType = $null
# Check if the file is a valid XML file and if not raise and error.
try {
switch($psCmdlet.ParameterSetName){
'Path'{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath' {
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [System.Management.Automation.PSInvalidCastException] {
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null){
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
$Rules = $Config.SelectSingleNode('//Sysmon/EventFiltering')
if ($Rules -eq '') {
Write-Error -Message 'Rule element does not exist. This appears to not be a valid config file'
return
} else {
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$EventType]
$EventRule = $Rules.SelectNodes("//EventFiltering/$($EvtType)")
}
if($EventRule -eq $null) {
Write-Error -Message "No rule for $($EvtType) was found."
return
} else {
if ($EventRule.count -eq $null -or $EventRule.Count -eq 1) {
Write-Verbose -Message 'Single Node'
if ($EventRule.onmatch -eq $OnMatch) {
$Filters = $EventRule.SelectNodes('*')
if ($Filters.ChildNodes.Count -gt 0) {
foreach($Filter in $Filters) {
$FilterObjProps = @{}
$FilterObjProps['EventField'] = $Filter.Name
$FilterObjProps['Condition'] = &{if($Filter.condition -eq $null){'is'}else{$Filter.condition}}
$FilterObjProps['Value'] = $Filter.'#text'
$FilterObjProps['EventType'] = $EvtType
$FilterObjProps['OnMatch'] = $OnMatch
$FilterObj = [pscustomobject]$FilterObjProps
$FilterObj.pstypenames.insert(0,'Sysmon.Rule.Filter')
$FilterObj
}
}
}
}
else
{
Write-Verbose -Message 'Mutiple nodes.'
foreach ($rule in $EventRule)
{
if ($rule.onmatch -eq $OnMatch)
{
$Filters = $rule.SelectNodes('*')
if ($Filters.ChildNodes.Count -gt 0)
{
foreach($Filter in $Filters)
{
$FilterObjProps = @{}
$FilterObjProps['EventField'] = $Filter.Name
$FilterObjProps['Condition'] = &{if($Filter.condition -eq $null){'is'}else{$Filter.condition}}
$FilterObjProps['Value'] = $Filter.'#text'
$FilterObjProps['EventType'] = $EvtType
$FilterObjProps['OnMatch'] = $OnMatch
$FilterObj = [pscustomobject]$FilterObjProps
$FilterObj.pstypenames.insert(0,'Sysmon.Rule.Filter')
$FilterObj
}
}
}
}
}
}
}
End{}
}
================================================
FILE: Functions/New-SysmonConfiguration.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonConfiguration
{
[CmdletBinding(HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonConfiguration.md')]
Param
(
# Path to write XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[String]
$Path,
# Specify one or more hash algorithms used for image identification
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('ALL', 'MD5', 'SHA1', 'SHA256', 'IMPHASH')]
[string[]]
$HashingAlgorithm,
# Log Network Connections
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[Switch]
$NetworkConnect,
# Log process loading of modules.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[Switch]
$DriverLoad,
# Log process loading of modules.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[Switch]
$ImageLoad,
# Log create remote thread actions.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=5)]
[Switch]
$CreateRemoteThread,
# Log file creation time modifications.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=6)]
[Switch]
$FileCreateTime,
# Log process creation.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=7)]
[Switch]
$ProcessCreate,
# Log process termination.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=8)]
[Switch]
$ProcessTerminate,
# Log when a running process opens another process.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=9)]
[Switch]
$ProcessAccess,
# Log raw access reads of files.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=10)]
[Switch]
$RawAccessRead,
# Check for signature certificate revocation.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=11 )]
[Switch]
$CheckRevocation,
# Log Registry events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=12 )]
[Switch]
$RegistryEvent,
# Log File Creation events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=13 )]
[Switch]
$FileCreate,
# Log File Stream creations events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=14 )]
[Switch]
$FileCreateStreamHash,
# Log NamedPipes connection and creations events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=15 )]
[Switch]
$PipeEvent,
# WMI Permanent Event component events.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true,
Position=16 )]
[Switch]
$WmiEvent,
# Comment for purpose of the configuration file.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true)]
[String]
$Comment,
# Schema Vesion for the configuration file, default is 4.1.
[Parameter(Mandatory=$False,
ValueFromPipelineByPropertyName=$true)]
[ValidateSet('4.0','4.1')]
[string]
$SchemaVersion = '4.1'
)
Begin{}
Process {
if ($HashingAlgorithm -contains 'ALL') {
$Hash = '*'
} else {
$Hash = $HashingAlgorithm -join ','
}
$Config = ($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path))
# get an XMLTextWriter to create the XML
$XmlWriter = New-Object System.XMl.XmlTextWriter($Config,$Null)
# choose a pretty formatting:
$xmlWriter.Formatting = 'Indented'
$xmlWriter.Indentation = 1
# write the header
if ($Comment)
{
$xmlWriter.WriteComment($Comment)
}
$xmlWriter.WriteStartElement('Sysmon')
$XmlWriter.WriteAttributeString('schemaversion', $SchemaVersion)
Write-Verbose -Message "Enabling hashing algorithms : $($Hash)"
$xmlWriter.WriteElementString('HashAlgorithms',$Hash)
# Enable checking revocation.
if ($CheckRevocation) {
Write-Verbose -message 'Enabling CheckRevocation.'
$xmlWriter.WriteElementString('CheckRevocation','')
}
# Create empty EventFiltering section.
$xmlWriter.WriteStartElement('EventFiltering')
if ($NetworkConnect) {
Write-Verbose -Message 'Enabling network connection logging for all connections by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('NetworkConnect')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($DriverLoad) {
Write-Verbose -Message 'Enabling logging all driver loading by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('DriverLoad ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ImageLoad) {
Write-Verbose -Message 'Enabling logging all image loading by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ImageLoad ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($CreateRemoteThread) {
Write-Verbose -Message 'Enabling logging all CreateRemoteThread API actions by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('CreateRemoteThread ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ProcessCreate) {
Write-Verbose -Message 'Enabling logging all process creation by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ProcessCreate ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ProcessTerminate) {
Write-Verbose -Message 'Enabling logging all process termination by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ProcessTerminate ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($FileCreateTime) {
Write-Verbose -Message 'Enabling logging all process creation by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('FileCreateTime ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($ProcessAccess) {
Write-Verbose -Message 'Enabling logging all process access by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('ProcessAccess ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
if ($RawAccessRead) {
Write-Verbose -Message 'Enabling logging all process access by setting no filter and onmatch to exclude.'
$xmlWriter.WriteStartElement('RawAccessRead ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# Log registry events.
if ($RegistryEvent) {
Write-Verbose -message 'Enabling RegistryEvent.'
$xmlWriter.WriteStartElement('RegistryEvent ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# Log file create events.
if ($FileCreate) {
Write-Verbose -message 'Enabling FileCreate.'
$xmlWriter.WriteStartElement('FileCreate ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# Log file create events.
if ($FileCreateStreamHash) {
Write-Verbose -message 'Enabling FileCreateStreamHash.'
$xmlWriter.WriteStartElement('FileCreateStreamHash ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# NamedPipes create and connect events.
if ($PipeEvent) {
Write-Verbose -message 'Enabling PipeEvent.'
$xmlWriter.WriteStartElement('PipeEvent ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# NamedPipes create and connect events.
if ($WmiEvent) {
Write-Verbose -message 'Enabling WmiEvent.'
$xmlWriter.WriteStartElement('WmiEvent ')
$XmlWriter.WriteAttributeString('onmatch', 'exclude')
$xmlWriter.WriteFullEndElement()
}
# End Element of EventFiltering
$xmlWriter.WriteFullEndElement()
# Sysmon
$xmlWriter.WriteEndElement()
# finalize the document:
#$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()
Write-Verbose -Message "Config file created as $($Config)"
write-verbose -Message "Configuration is for Sysmon $($sysmonVerMap[$SchemaVersion])"
}
End {}
}
================================================
FILE: Functions/New-SysmonCreateRemoteThreadFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonCreateRemoteThreadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonCreateRemoteThreadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('SourceImage', 'TargetImage')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin { }
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'CreateRemoteThread'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonDriverLoadFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonDriverLoadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonDriverLoadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ImageLoaded',
'Hashes', 'Signed', 'Signature')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'DriverLoad'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonFileCreateFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonFileCreateFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonFileCreateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'TargetFilename', 'CreationUtcTime',
'PreviousCreationUtcTime')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'FileCreateStreamHash'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonFileCreateStreamHashFilter.ps1
================================================
<#
.SYNOPSIS
Create a new filter for the logging of the saving of data on a file stream.
.DESCRIPTION
Create a new filter for the logging of the saving of data on a file stream.
#>
function New-SysmonFileCreateStreamHashFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonFileCreateStreamHashFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('TargetFilename', 'ProcessGuid', 'ProcessId',
'Image')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'FileCreateStreamHash'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonImageLoadFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonImageLoadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonImageLoadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'ImageLoaded', 'Hashes', 'Signed',
'Signature', 'FileVersion',
'Description', 'Product', 'Company')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
$ConfigVer = Select-Xml -Path $Path -XPath '//Sysmon/@schemaversion'
}
'LiteralPath'
{
$ConfigVer = Select-Xml -LiteralPath $LiteralPath -XPath '//Sysmon/@schemaversion'
}
}
if ($ConfigVer.Node."#text" -lt 4.0 -and ($EventField -in @('FileVersion','Description', 'Product', 'Company'))) {
Write-Error -Message "The event field $($EventField) is not supported under this schema."
Return
}
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ImageLoad'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch($psCmdlet.ParameterSetName)
{
'Path'
{
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath'
{
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End { }
}
================================================
FILE: Functions/New-SysmonNetworkConnectFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonNetworkConnectFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonNetworkConnectFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'User', 'Protocol', 'Initiated', 'SourceIsIpv6',
'SourceIp', 'SourceHostname', 'SourcePort',
'SourcePortName', 'DestinationIsIpv6',
'DestinationIp', 'DestinationHostname',
'DestinationPort', 'DestinationPortName')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'NetworkConnect'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonPipeFilter.ps1
================================================
<#
.SYNOPSIS
Create a new filter for when a Named Pipe is created or connected.
.DESCRIPTION
Create a new filter for when a Named Pipe is created or connected.
Useful for watching malware inter process communication.
#>
function New-SysmonPipeFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonPipeFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Pipe', 'ProcessGuid', 'ProcessId',
'Image')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'PipeEvent'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonProcessAccessFilter.ps1
================================================
<#
.SYNOPSIS
Create a new filter for the logging of when a running process opens another.
.DESCRIPTION
Create a new filter for the logging of when a running process opens another.
.EXAMPLE
C:\PS> New-SysmonProcessAccessFilter -Path .\testver31.xml -OnMatch include -Condition Contains -EventField TargetImage lsass.exe
Log any process trying to open lsass.exe.
#>
function New-SysmonProcessAccessFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonProcessAccessFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'SourceProcessGUID',
'SourceProcessId', 'SourceThreadId', 'SourceImage',
'TargetProcessGUID', 'TargetProcessId', 'TargetImage',
'GrantedAccess','CallTrace')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ProcessAccess'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonProcessCreateFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonProcessCreateFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonProcessCreateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId', 'Image',
'CommandLine', 'User', 'LogonGuid', 'LogonId',
'TerminalSessionId', 'IntegrityLevel',
'Hashes', 'ParentProcessGuid', 'ParentProcessId',
'ParentImage', 'ParentCommandLine', 'FileVersion',
'Description', 'Product', 'Company')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
switch($psCmdlet.ParameterSetName)
{
'Path'
{
$ConfigVer = Select-Xml -Path $Path -XPath '//Sysmon/@schemaversion'
}
'LiteralPath'
{
$ConfigVer = Select-Xml -LiteralPath $LiteralPath -XPath '//Sysmon/@schemaversion'
}
}
if ($ConfigVer.Node."#text" -lt 4.0 -and ($EventField -in @('FileVersion','Description', 'Product', 'Company'))) {
Write-Error -Message "The event field $($EventField) is not supported under this schema."
Return
}
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ProcessCreate'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch($psCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End { }
}
================================================
FILE: Functions/New-SysmonProcessTerminateFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonProcessTerminateFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonProcessTerminateFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process
{
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'ProcessTerminate'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch($psCmdlet.ParameterSetName)
{
'Path'
{
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath'
{
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonRawAccessReadFilter.ps1
================================================
<#
.SYNOPSIS
Create a new filter for the logging of file raw access read actions.
.DESCRIPTION
Create a new filter for the logging of file raw access read actions.
.EXAMPLE
C:\PS> New-SysmonRawAccessReadFilter -Path .\testver31.xml -OnMatch include -Condition Contains -EventField Image NTDS.dit
Log any raw access read of the file NTDS.dit.
#>
function New-SysmonRawAccessReadFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonRawAccessReadFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('UtcTime', 'ProcessGuid', 'ProcessId',
'Image', 'Device')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'RawAccessRead'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonRegistryFilter.ps1
================================================
<#
.SYNOPSIS
Create a new filter for the actions against the registry.
.DESCRIPTION
Create a new filter for actions against the registry. Supports filtering
by aby of the following event types:
* CreateKey
* DeleteKey
* RenameKey
* CreateValue
* DeleteValue
* RenameValue
* SetValue
Hives on Schema 3.2 in TargetObject are referenced as:
* \REGISTRY\MACHINE\HARDWARE
* \REGISTRY\USER\Security ID number
* \REGISTRY\MACHINE\SECURITY
* \REGISTRY\USER\.DEFAULT
* \REGISTRY\MACHINE\SYSTEM
* \REGISTRY\MACHINE\SOFTWARE
* \REGISTRY\MACHINE\SAM
Hives on Schema 3.3 and above in TargetObject are referenced as:
* HKLM
* HKCR
* HKEY_USER
.EXAMPLE
C:\PS> New-SysmonRegistryFilter -Path .\32config.xml -OnMatch include -Condition Contains -EventField TargetObject 'RunOnce'
Capture persistance attemp by creating a registry entry in the RunOnce keys.
#>
function New-SysmonRegistryFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonRegistryFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({ Test-Path -Path $_ })]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('TargetObject', 'ProcessGuid', 'ProcessId',
'Image', 'EventType')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {
# Event types used to validate right type and string case
$EventTypeMap = @{
CreateKey = 'CreateKey'
DeleteKey = 'DeleteKey'
RenameKey = 'RenameKey'
CreateValue = 'CreateValue'
DeleteValue = 'DeleteValue'
RenameValue = 'RenameValue'
SetValue = 'SetValue'
}
$Etypes = $EventTypeMap.Keys
}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
if ($EventField -in 'EventType') {
if ($Value -in $Etypes) {
$Value = $EventTypeMap[$Value]
} else {
Write-Error -Message "Not a supported EventType. Supported Event types $($Etypes -join ', ')"
return
}
}
$cmdoptions = @{
'EventType' = 'RegistryEvent'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/New-SysmonWmiFilter.ps1
================================================
<#
.SYNOPSIS
Create a new filter for WMI Permamanent Event Classes.
.DESCRIPTION
Create a new filter for WMI permamanent event classes are created or connected.
Useful for monitoring for persistence actions.
#>
function New-SysmonWmiFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/New-SysmonWmiFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Name', 'EventNamespace', 'Destination',
'Type', 'Query', 'Operation', 'Consumer', 'Filter')]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin {}
Process {
$FieldString = $MyInvocation.MyCommand.Module.PrivateData[$EventField]
$cmdoptions = @{
'EventType' = 'WmiEvent'
'Condition' = $Condition
'EventField' = $FieldString
'Value' = $Value
'OnMatch' = $OnMatch
}
if($RuleName) {
$cmdoptions.Add('RuleName',$RuleName)
}
switch ($PSCmdlet.ParameterSetName) {
'Path' {
$cmdOptions.Add('Path',$Path)
New-RuleFilter @cmdOptions
}
'LiteralPath' {
$cmdOptions.Add('LiteralPath',$LiteralPath)
New-RuleFilter @cmdOptions
}
}
}
End {}
}
================================================
FILE: Functions/Remove-SysmonRule.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Remove-SysmonRule
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Remove-SysmonRule.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type to remove. It is case sensitive.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad', 'CreateRemoteThread',
'ProcessAccess', 'RawAccessRead', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent','RuleName')]
[string[]]
$EventType,
# Action for event type rule and filters.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Include', 'Exclude')]
[String]
$OnMatch = 'Exclude'
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$Rules = $config.SelectSingleNode('//Sysmon/EventFiltering')
foreach ($rule in $rules.ChildNodes)
{
if ($rule.name -in $EventType -and $rule.onmatch -eq $OnMatch)
{
[void]$rule.ParentNode.RemoveChild($rule)
Write-Verbose -Message "Removed rule for $($EventType)."
}
}
$config.Save($FileLocation)
}
End{}
}
================================================
FILE: Functions/Remove-SysmonRuleFilter.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Remove-SysmonRuleFilter {
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Remove-SysmonRuleFilter.md')]
Param (
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type to update.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread', 'RawAccessRead', 'ProcessAccess',
'FileCreateStreamHash', 'RegistryEvent', 'FileCreate',
'PipeEvent', 'WmiEvent')]
[string]
$EventType,
# Event type on match action.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=5)]
[string[]]
$Value
)
Begin{}
Process {
$EvtType = $null
# Check if the file is a valid XML file and if not raise and error.
try {
switch($psCmdlet.ParameterSetName) {
'Path' {
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath' {
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException] {
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null) {
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
$Rules = $Config.SelectSingleNode('//Sysmon/EventFiltering')
# Select the proper condition string.
switch ($Condition) {
'Is' {$ConditionString = 'is'}
'IsNot' {$ConditionString = 'is not'}
'Contains' {$ConditionString = 'contains'}
'Excludes' {$ConditionString = 'excludes'}
'Image' {$ConditionString = 'image'}
'BeginWith' {$ConditionString = 'begin with'}
'EndWith' {$ConditionString = 'end with'}
'LessThan' {$ConditionString = 'less than'}
'MoreThan' {$ConditionString = 'more than'}
Default {$ConditionString = 'is'}
}
# Check if the event type exists if not create it.
if ($Rules -eq '') {
Write-Error -Message 'Rule element does not exist. This appears to not be a valid config file'
return
} else {
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$EventType]
$EventRule = $Rules.SelectNodes("//EventFiltering/$($EvtType)")
}
if($EventRule -eq $null) {
Write-Warning -Message "No rule for $($EvtType) was found."
return
}
if($EventRule -eq $null) {
Write-Error -Message "No rule for $($EvtType) was found."
return
} else {
if ($EventRule.count -eq $null -or $EventRule.Count -eq 1) {
if ($EventRule.onmatch -eq $OnMatch) {
$Filters = $EventRule.SelectNodes('*')
if ($Filters.count -gt 0) {
foreach($val in $Value) {
foreach($Filter in $Filters) {
if ($Filter.Name -eq $EventField) {
if (($Filter.condition -eq $null) -and ($Condition -eq 'is') -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
} elseif (($Filter.condition -eq $Condition) -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
}
}
}
}
Get-RuleWithFilter($EventRule)
}
}
} else {
Write-Verbose -Message 'Mutiple nodes.'
foreach ($rule in $EventRule) {
if ($rule.onmatch -eq $OnMatch) {
$Filters = $rule.SelectNodes('*')
if ($Filters.count -gt 0) {
foreach($val in $Value) {
foreach($Filter in $Filters) {
if ($Filter.Name -eq $EventField) {
if (($Filter.condition -eq $null) -and ($Condition -eq 'is') -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
} elseif (($Filter.condition -eq $Condition) -and ($Filter.'#text' -eq $val)) {
[void]$Filter.ParentNode.RemoveChild($Filter)
Write-Verbose -Message "Filter for field $($EventField) with condition $($Condition) and value of $($val) removed."
}
}
}
}
Get-RuleWithFilter($rule)
}
}
}
}
}
$config.Save($FileLocation)
}
End{}
}
================================================
FILE: Functions/Schemas/SysmonConfigurationSchema_3_40.xsd
================================================
Represents the set of supported onmatch attribute values.
Represents the set of supported condition attribute values.
Represents the set of supported condition attribute values in the case where it only makes sense to support "is" and "is not".
Represents the set of supported process integrity levels.
Represents the set of supported WMI events.
Represents the set of supported WMI operations.
Represents the set of supported digital signature validation results.
Represents a well-formatted GUID.
Represents a well-formatted hexadecimal string. Note that the hex digits must be upper case.
Represents the set of supported hash algorithms.
Represents a well-formatted major.minor version number where both number can be represented with up to two digits.
This type is applied to a Sysmon rule element where there are no constraints on the value.
This type is applied to a Sysmon rule element where the value is expected to be a GUID.
This type is applied to a Sysmon rule element where the value is expected to be a hexadecimal value.
This type is applied to a Sysmon rule element where the value is expected to be a specific process integrity level.
This type is applied to a Sysmon rule element where the value is expected to be a specific WMI operation.
This type is applied to a Sysmon rule element where the value is expected to be a specific WMI event.
This type is applied to a Sysmon rule element where the value is expected to be either "true" or "false".
This type is applied to a Sysmon rule element where the value is expected to be an unsigned integer.
This type is applied to a Sysmon rule element where the value is expected to be an unsigned short.
This type is applied to a Sysmon rule element where the value is expected to be a specific signature validation status.
Sysmon 3.4[0] schema
Specifies a set of events to trigger on.
Event ID: 1
Event ID: 2
Event ID: 3
Event ID: 5
Event ID: 6
Event ID: 7
Event ID: 8
Event ID: 9
Event ID: 10
Event ID: 11
Event ID: 12, 13, 14
Event ID: 15
Event ID: 17, 18
Event ID: 19, 20, 21
Specifies the hashes that will be calculated upon an event firing.
Specifies the name of the Sysmon driver to be used upon installation of the Sysmon service. This is an alternative to the sysmon.exe "-d" switch.
The purpose of ProcessAccessConfig is unknown now that ProcessAccess event rules are supported. Perhaps this offers legacy schema support.
The purpose of PipeMonitoringConfig is unknown now that PipeEvent event rules are supported. Perhaps this offers legacy schema support.
CheckRevocation is an empty element where when present, indicates that certificate revocation checking should be performed. This is an alternative to the sysmon.exe "-r" switch.
Specifies the sysmon schema version number.
================================================
FILE: Functions/Schemas/SysmonConfigurationSchema_4_00.xsd
================================================
Represents the set of supported onmatch attribute values.
Represents the set of supported condition attribute values.
Represents the set of supported condition attribute values in the case where it only makes sense to support "is" and "is not".
Represents the set of supported process integrity levels.
Represents the set of supported WMI events.
Represents the set of supported WMI operations.
Represents the set of supported digital signature validation results.
Represents a well-formatted GUID.
Represents a well-formatted hexadecimal string. Note that the hex digits must be upper case.
Represents the set of supported hash algorithms.
Represents a well-formatted major.minor version number where both number can be represented with up to two digits.
This type is applied to a Sysmon rule element where there are no constraints on the value.
This type is applied to a Sysmon rule element where the value is expected to be a GUID.
This type is applied to a Sysmon rule element where the value is expected to be a hexadecimal value.
This type is applied to a Sysmon rule element where the value is expected to be a specific process integrity level.
This type is applied to a Sysmon rule element where the value is expected to be a specific WMI operation.
This type is applied to a Sysmon rule element where the value is expected to be a specific WMI event.
This type is applied to a Sysmon rule element where the value is expected to be either "true" or "false".
This type is applied to a Sysmon rule element where the value is expected to be an unsigned integer.
This type is applied to a Sysmon rule element where the value is expected to be an unsigned short.
This type is applied to a Sysmon rule element where the value is expected to be a specific signature validation status.
Sysmon 4.0[0] schema
Specifies a set of events to trigger on.
Event ID: 1
Event ID: 2
Event ID: 3
Event ID: 5
Event ID: 6
Event ID: 7
Event ID: 8
Event ID: 9
Event ID: 10
Event ID: 11
Event ID: 12, 13, 14
Event ID: 15
Event ID: 17, 18
Event ID: 19, 20, 21
Specifies the hashes that will be calculated upon an event firing.
Specifies the name of the Sysmon driver to be used upon installation of the Sysmon service. This is an alternative to the sysmon.exe "-d" switch.
The purpose of ProcessAccessConfig is unknown now that ProcessAccess event rules are supported. Perhaps this offers legacy schema support.
The purpose of PipeMonitoringConfig is unknown now that PipeEvent event rules are supported. Perhaps this offers legacy schema support.
CheckRevocation is an empty element where when present, indicates that certificate revocation checking should be performed. This is an alternative to the sysmon.exe "-r" switch.
Specifies the sysmon schema version number.
================================================
FILE: Functions/Set-SysmonHashingAlgorithm.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Set-SysmonHashingAlgorithm
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Set-SysmonHashingAlgorithm.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Specify one or more hash algorithms used for image identification
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('ALL', 'MD5', 'SHA1', 'SHA256', 'IMPHASH')]
[string[]]
$HashingAlgorithm
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [System.Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
Write-Verbose -Message 'Updating Hashing option.'
if ($HashingAlgorithm -contains 'ALL')
{
$Hash = '*'
}
else
{
$Hash = $HashingAlgorithm -join ','
}
# Check if Hashing Alorithm node exists.
if($Config.SelectSingleNode('//Sysmon/HashAlgorithms') -ne $null)
{
$Config.Sysmon.HashAlgorithms = $Hash
}
else
{
$HashElement = $Config.CreateElement('HashAlgorithms')
[void]$Config.Sysmon.Configuration.AppendChild($HashElement)
$Config.Sysmon.Configuration.Hashing = $Hash
}
Write-Verbose -Message 'Hashing option has been updated.'
Write-Verbose -Message "Option have been set on $($FileLocation)"
$Config.Save($FileLocation)
}
End{}
}
================================================
FILE: Functions/Set-SysmonRule.ps1
================================================
# .ExternalHelp Posh-SysMon.psm1-Help.xml
function Set-SysmonRule
{
[CmdletBinding(DefaultParameterSetName = 'Path',
HelpUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Set-SysmonRule.md')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
$LiteralPath,
# Event type to update.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad', 'CreateRemoteThread',
'ProcessAccess', 'RawAccessRead', 'FileCreateStreamHash',
'RegistryEvent', 'FileCreate', 'PipeEvent', 'WmiEvent')]
[string[]]
$EventType,
# Action for event type rule and filters.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('Include', 'Exclude')]
[String]
$OnMatch = 'Exclude',
# Action to take for Schema 3.0 files.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[ValidateSet('Modify', 'Add')]
[String]
$Action = 'Modify'
)
Begin{}
Process
{
# if no elemrnt create one either if it is schema 2.0 or 3.0.
# If one is present we modify that one if Schema 2.0 and if Schema 3.0 and action modify.
# If Schema 3.0 and action add we check if only is present and that it is not the same OnMatch
# as being specified if it is we do nothing if not we add.
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$Rules = $config.SelectSingleNode('//Sysmon/EventFiltering')
foreach($Type in $EventType)
{
$EvtType = $MyInvocation.MyCommand.Module.PrivateData[$Type]
$RuleData = $Rules.SelectSingleNode("//EventFiltering/$($EvtType)")
$elements = $Rules."$($EvtType)" | Select-Object -property onmatch -Unique
if($RuleData -ne $null)
{
if ($Rules."$($EvtType)".count -eq $null)
{
if (($Config.Sysmon.schemaversion -eq '2.0') -or ($Config.Sysmon.schemaversion -ge 3.0 -and $Action -eq 'Modify'))
{
Write-Verbose -Message "Setting as default action for $($EvtType) the rule on match of $($OnMatch)."
$RuleData.SetAttribute('onmatch',($OnMatch.ToLower()))
Write-Verbose -Message 'Action has been set.'
}
elseif ($Config.Sysmon.schemaversion -ge 3.0 -and $Action -eq 'Add')
{
if ($RuleData.onmatch -ne $OnMatch)
{
Write-Verbose -Message "Creating rule for event type with action of $($OnMatch)"
$TypeElement = $config.CreateElement($EvtType)
$TypeElement.SetAttribute('onmatch',($OnMatch.ToLower()))
$RuleData = $Rules.AppendChild($TypeElement)
Write-Verbose -Message 'Action has been set.'
}
else
{
Write-Verbose -Message 'A rule with the specified onmatch action already exists.'
}
}
}
elseif ($Config.Sysmon.schemaversion -ge 3.0 -and $elements.count -eq 2)
{
Write-Verbose -Message 'A rule with the specified onmatch action already exists.'
}
else
{
Write-Error -Message 'This XML file does not conform to the schema.'
return
}
}
else
{
Write-Verbose -Message "No rule for $($EvtType) was found."
Write-Verbose -Message "Creating rule for event type with action of $($OnMatch)"
$TypeElement = $config.CreateElement($EvtType)
$TypeElement.SetAttribute('onmatch',($OnMatch.ToLower()))
$RuleData = $Rules.AppendChild($TypeElement)
Write-Verbose -Message 'Action has been set.'
}
Get-RuleWithFilter($RuleData)
}
$config.Save($FileLocation)
}
End{}
}
================================================
FILE: LICENSE
================================================
Copyright (c) 2016, Carlos Perez
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Posh-Sysmon nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: Posh-SysMon.psm1
================================================
# Load functions
. "$($PSScriptRoot)\Functions\Get-SysmonEventData.ps1"
. "$($PSScriptRoot)\Functions\Get-SysmonHashingAlgorithm.ps1"
. "$($PSScriptRoot)\Functions\Get-SysmonRule.ps1"
. "$($PSScriptRoot)\Functions\Get-SysmonRuleFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonConfiguration.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonCreateRemoteThreadFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonDriverLoadFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonFileCreateFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonFileCreateStreamHashFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonImageLoadFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonNetworkConnectFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonPipeFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonProcessAccessFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonProcessCreateFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonProcessTerminateFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonRawAccessReadFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonRegistryFilter.ps1"
. "$($PSScriptRoot)\Functions\New-SysmonWmiFilter.ps1"
. "$($PSScriptRoot)\Functions\Remove-SysmonRule.ps1"
. "$($PSScriptRoot)\Functions\Remove-SysmonRuleFilter.ps1"
. "$($PSScriptRoot)\Functions\Set-SysmonHashingAlgorithm.ps1"
. "$($PSScriptRoot)\Functions\Set-SysmonRule.ps1"
. "$($PSScriptRoot)\Functions\Get-SysmonConfiguration.ps1"
. "$($PSScriptRoot)\Functions\ConvertTo-SysmonXMLConfiguration.ps1"
. "$($PSScriptRoot)\Functions\ConvertFrom-SysmonBinaryConfiguration.ps1"
# Supporteted Sysmon schema versions.
$SysMonSupportedVersions = @(
'4.0'
'4.1'
)
# Table that maps schema version to Sysmon version.
$sysmonVerMap = @{
'2.0' = '3.0'
'3.0' = '4.0'
'3.1' = '4.11'
'3.2' = '5.0'
'3.3' = '6.0'
'3.4' = '6.1, 6.2'
'4.0' = '7.0'
'4.1' = '8.0'
}
function Get-RuleWithFilter
{
Param
(
[Parameter(Mandatory=$true)]
$Rules
)
foreach ($rule in $Rules)
{
$RuleObjOptions = [ordered]@{}
$RuleObjOptions['EventType'] = $Rule.Name
if ($Rule.onmatch -eq $null -or $Rule.onmatch -eq 'exclude')
{
$RuleObjOptions.Add('DefaultAction','Exclude')
}
else
{
$RuleObjOptions.Add('DefaultAction','Include')
}
# Process individual filters
$Nodes = $Rule.selectnodes('*')
if ($Nodes.count -eq 0)
{
$RuleObjOptions.add('Scope','All Events')
}
else
{
$RuleObjOptions.add('Scope','Filtered')
$Filters = @()
foreach ($Node in $Nodes)
{
$FilterObjProps = [ordered]@{}
$FilterObjProps['EventField'] = $Node.LocalName
$FilterObjProps['RuleName'] = $Node.Name
$FilterObjProps['Condition'] = &{if($Node.condition -eq $null){'is'}else{$Node.condition}}
$FilterObjProps['Value'] = $Node.'#text'
$FilterObj = New-Object -TypeName psobject -Property $FilterObjProps
$FilterObj.pstypenames.insert(0,'Sysmon.Rule.Filter')
$Filters += $FilterObj
}
$RuleObjOptions.add('Filters',$Filters)
}
$RuleObj = New-Object -TypeName psobject -Property $RuleObjOptions
$RuleObj.pstypenames.insert(0,'Sysmon.Rule')
$RuleObj
}
}
<#
.Synopsis
Creates a filter for an event field for an event type in a Sysmon XML configuration file.
.DESCRIPTION
Creates a filter for an event field for an event type in a Sysmon XML configuration file.
.EXAMPLE
New-nRuleFilter -Path .\pc_cofig.xml -EventType NetworkConnect -EventField image -Condition Is -Value 'iexplorer.exe' -Verbose
VERBOSE: No rule for NetworkConnect was found.
VERBOSE: Creating rule for event type with default action if Exclude
VERBOSE: Rule created succesfully
C:\PS>Get-GetSysmonRules -Path .\pc_cofig.xml -EventType NetworkConnect
EventType : NetworkConnect
Scope : Filtered
DefaultAction : Exclude
Filters : {@{EventField=image; Condition=Is; Value=iexplorer.exe}}
Create a filter to capture all network connections from iexplorer.exe.
#>
function New-RuleFilter
{
[CmdletBinding(DefaultParameterSetName = 'Path')]
Param
(
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='Path',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[string]$Path,
# Path to XML config file.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
ParameterSetName='LiteralPath',
Position=0)]
[ValidateScript({Test-Path -Path $_})]
[Alias('PSPath')]
[string]$LiteralPath,
# Event type to create filter for.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=1)]
[ValidateSet('NetworkConnect', 'ProcessCreate', 'FileCreateTime',
'ProcessTerminate', 'ImageLoad', 'DriverLoad',
'CreateRemoteThread', 'ProcessAccess','RawAccessRead',
'FileCreate', 'RegistryEvent', 'FileCreateStreamHash',
'PipeEvent', 'WmiEvent',IgnoreCase = $false)]
[string]
$EventType,
# Event type to create filter for.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=2)]
[ValidateSet('include', 'exclude')]
[string]
$OnMatch,
# Condition for filtering against and event field.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=3)]
[ValidateSet('Is', 'IsNot', 'Contains', 'Excludes', 'Image',
'BeginWith', 'EndWith', 'LessThan', 'MoreThan')]
[string]
$Condition,
# Event field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=4)]
[string]
$EventField,
# Value of Event Field to filter on.
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=5)]
[string[]]
$Value,
# Rule Name for the filter.
[Parameter(Mandatory=$false,
ValueFromPipelineByPropertyName=$true)]
[string]
$RuleName
)
Begin{}
Process
{
# Check if the file is a valid XML file and if not raise and error.
try
{
switch($psCmdlet.ParameterSetName)
{
'Path'
{
[xml]$Config = Get-Content -Path $Path
$FileLocation = (Resolve-Path -Path $Path).Path
}
'LiteralPath'
{
[xml]$Config = Get-Content -LiteralPath $LiteralPath
$FileLocation = (Resolve-Path -LiteralPath $LiteralPath).Path
}
}
}
catch [Management.Automation.PSInvalidCastException]
{
Write-Error -Message 'Specified file does not appear to be a XML file.'
return
}
# Validate the XML file is a valid Sysmon file.
if ($Config.SelectSingleNode('//Sysmon') -eq $null)
{
Write-Error -Message 'XML file is not a valid Sysmon config file.'
return
}
if ($Config.Sysmon.schemaversion -notin $SysMonSupportedVersions)
{
Write-Error -Message 'This version of Sysmon Rule file is not supported.'
return
}
$Rules = $Config.SelectSingleNode('//Sysmon/EventFiltering')
# Select the proper condition string and make sure it is the proper case.
switch ($Condition)
{
'Is' {$ConditionString = 'is'}
'IsNot' {$ConditionString = 'is not'}
'Contains' {$ConditionString = 'contains'}
'Excludes' {$ConditionString = 'excludes'}
'Image' {$ConditionString = 'image'}
'BeginWith' {$ConditionString = 'begin with'}
'EndWith' {$ConditionString = 'end with'}
'LessThan' {$ConditionString = 'less than'}
'MoreThan' {$ConditionString = 'more than'}
Default {$ConditionString = 'is'}
}
# Check if the event type exists if not create it.
$RuleData = $Rules.SelectNodes("//EventFiltering/$($EventType)")
if($RuleData -eq $null)
{
Write-Error -Message "No rule for $($EventType) was found."
return
} # If only one element this will return null, more than one this will provide a value.
else
{
if ($RuleData.count -eq 1)
{
if ($RuleData.Attributes."#text" -eq $OnMatch)
{
Write-Verbose -Message 'Single node.'
Write-Verbose -Message "Creating filters for event type $($EventType)."
# For each value for the event type create a filter.
foreach($val in $value)
{
Write-Verbose -Message "Creating filter for event filed $($EventField) with condition $($Condition) for value $($val)."
$FieldElement = $Config.CreateElement($EventField)
$Filter = $RuleData.AppendChild($FieldElement)
if ($RuleName) {
$Filter.SetAttribute('name',$RuleName)
}
$Filter.SetAttribute('condition',$ConditionString)
$filter.InnerText = $val
$Config.Save($FileLocation)
}
}
else
{
write-error -Message "Event type $($EventType) with a on match condition of $($OnMatch) was not found."
return
}
}
else
{
Write-Verbose -Message 'Mutiple nodes.'
foreach ($rule in $RuleData)
{
if ($rule.onmatch -eq $OnMatch)
{
Write-Verbose -Message "Found rule for event type $($EventType) with $($OnMatch)"
Write-Verbose -Message "Creating filters for event type $($EventType)."
# For each value for the event type create a filter.
foreach($val in $value)
{
Write-Verbose -Message "Creating filter for event filed $($EventField) with condition $($Condition) for value $($val)."
$FieldElement = $Config.CreateElement($EventField)
$Filter = $rule.AppendChild($FieldElement)
if ($RuleName) {
$Filter.SetAttribute('name',$RuleName)
}
$Filter.SetAttribute('condition',$ConditionString)
$filter.InnerText = $val
$Config.Save($FileLocation)
}
$RuleData = $rule
}
}
}
}
Get-RuleWithFilter($RuleData)
}
End{}
}
================================================
FILE: Posh-Sysmon.psd1
================================================
#
# Module manifest for module 'PSGet_Posh-Sysmon'
#
# Generated by: Carlos Perez carlos_Perez@darkoperator.com
#
# Generated on: 8/16/2016
#
@{
# Script module or binary module file associated with this manifest.
RootModule = '.\Posh-SysMon.psm1'
# Version number of this module.
ModuleVersion = '1.2'
# Supported PSEditions
# CompatiblePSEditions = @()
# ID used to uniquely identify this module
GUID = 'a8ade6cb-39d5-45a1-b4aa-acf29ee34aed'
# Author of this module
Author = 'Carlos Perez carlos_Perez@darkoperator.com'
# Company or vendor of this module
CompanyName = 'Darkoperator.com'
# Copyright statement for this module
Copyright = '(c) 2018 Carlos Perez carlos_Perez@darkoperator.com. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Module for the creation and managing of Sysinternal Sysmon configuration XML files.'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '3.0'
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
FormatsToProcess = 'Format\Sysmon.ConfigOption.ps1xml', 'Format\Sysmon.Rule.ps1xml',
'Format\Sysmon.Rule.Filter.ps1xml'
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'Get-SysmonHashingAlgorithm', 'Get-SysmonRule',
'New-SysmonConfiguration', 'New-SysmonDriverLoadFilter',
'New-SysmonFileCreateFilter', 'New-SysmonImageLoadFilter',
'New-SysmonNetworkConnectFilter', 'New-SysmonProcessCreateFilter',
'New-SysmonProcessTerminateFilter', 'Remove-SysmonRule',
'Remove-SysmonRuleFilter', 'Set-SysmonHashingAlgorithm',
'Set-SysmonRule', 'Get-SysmonEventData', 'Get-SysmonRuleFilter',
'New-SysmonProcessAccessFilter', 'New-SysmonFileCreateStreamHashFilter',
'New-SysmonRegistryFilter', 'New-SysmonFileCreateFilter',
'New-SysmonPipeFIlter', 'New-SysmonWmiFilter', 'New-SysmonWmiFilter',
'ConvertFrom-SysmonBinaryConfiguration', 'ConvertTo-SysmonXMLConfiguration',
'Get-SysmonConfiguration'
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()
# Variables to export from this module
# VariablesToExport = @()
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
#NetworkConnect of this module
NetworkConnect = 'NetworkConnect'
#DriverLoad of this module
DriverLoad = 'DriverLoad'
#ProcessAccess of this module
ProcessAccess = 'ProcessAccess'
#CommandLine of this module
CommandLine = 'CommandLine'
#SourceImage of this module
SourceImage = 'SourceImage'
#Protocol of this module
Protocol = 'Protocol'
#TargetProcessGUID of this module
TargetProcessGUID = 'TargetProcessGUID'
#CallTrace of this module
CallTrace = 'CallTrace'
#RawAccessRead of this module
RawAccessRead = 'RawAccessRead'
#DestinationPort of this module
DestinationPort = 'DestinationPort'
#SourceHostname of this module
SourceHostname = 'SourceHostname'
#DestinationIp of this module
DestinationIp = 'DestinationIp'
#SourceIsIpv6 of this module
SourceIsIpv6 = 'SourceIsIpv6'
#Initiated of this module
Initiated = 'Initiated'
#SourceProcessGUID of this module
SourceProcessGUID = 'SourceProcessGUID'
#SourcePort of this module
SourcePort = 'SourcePort'
#PreviousCreationUtcTime of this module
PreviousCreationUtcTime = 'PreviousCreationUtcTime'
#TargetProcessId of this module
TargetProcessId = 'TargetProcessId'
#ProcessTerminate of this module
ProcessTerminate = 'ProcessTerminate'
#ParentProcessId of this module
ParentProcessId = 'ParentProcessId'
#SourceThreadId of this module
SourceThreadId = 'SourceThreadId'
#IntegrityLevel of this module
IntegrityLevel = 'IntegrityLevel'
#ProcessGuid of this module
ProcessGuid = 'ProcessGuid'
#ProcessCreate of this module
ProcessCreate = 'ProcessCreate'
#CreateRemoteThread of this module
CreateRemoteThread = 'CreateRemoteThread'
#TargetImage of this module
TargetImage = 'TargetImage'
#Hashes of this module
Hashes = 'Hashes'
#UtcTime of this module
UtcTime = 'UtcTime'
#SourcePortName of this module
SourcePortName = 'SourcePortName'
#SourceIp of this module
SourceIp = 'SourceIp'
#ParentCommandLine of this module
ParentCommandLine = 'ParentCommandLine'
#ImageLoaded of this module
ImageLoaded = 'ImageLoaded'
#TerminalSessionId of this module
TerminalSessionId = 'TerminalSessionId'
#ProcessId of this module
ProcessId = 'ProcessId'
#GrantedAccess of this module
GrantedAccess = 'GrantedAccess'
#FileCreateTime of this module
FileCreateTime = 'FileCreateTime'
#ParentImage of this module
ParentImage = 'ParentImage'
#ImageLoad of this module
ImageLoad = 'ImageLoad'
#ParentProcessGuid of this module
ParentProcessGuid = 'ParentProcessGuid'
#Signed of this module
Signed = 'Signed'
#DestinationHostname of this module
DestinationHostname = 'DestinationHostname'
#Signature of this module
Signature = 'Signature'
#LogonGuid of this module
LogonGuid = 'LogonGuid'
#Image of this module
Image = 'Image'
#User of this module
User = 'User'
#DestinationPortName of this module
DestinationPortName = 'DestinationPortName'
#LogonId of this module
LogonId = 'LogonId'
#TargetFilename of this module
TargetFilename = 'TargetFilename'
#CreationUtcTime of this module
CreationUtcTime = 'CreationUtcTime'
#DestinationIsIpv6 of this module
DestinationIsIpv6 = 'DestinationIsIpv6'
# hash for FileCreateStreamHash events.
Hash = 'Hash'
# Target object in registry events.
TargetObject = 'TargetObject'
FileCreateStreamHash = 'FileCreateStreamHash'
RegistryEvent = 'RegistryEvent'
FileCreate = 'FileCreate'
Pipe = 'Pipe'
PipeEvent = 'PipeEvent'
WmiEvent = 'WmiEvent'
EventType = 'EventType'
EventNamespace = 'EventNamespace'
# Name given to a WMI object.
Name = 'Name'
# Namespace where a WMI object was created at.
Destination = 'Destination'
Type = 'Type'
# Query used by a WMI Filter.
Query = 'Query'
# Operation of a WMI component event.
Operation = 'Operation'
# Consumer name of a WMI binding event.
Consumer = 'Consumer'
# WMI Filter in a EventFilter event.
Filter = 'Filter'
FileVersion = 'FileVersion'
Description = 'Description'
Product = 'Product'
Company = 'Company'
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = 'Sysmon','Security','Logging'
# A URL to the license for this module.
LicenseUri = 'https://github.com/darkoperator/Posh-Sysmon/blob/master/LICENSE'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/darkoperator/Posh-Sysmon'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
# ReleaseNotes = ''
# External dependent modules of this module
# ExternalModuleDependencies = ''
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
# HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
================================================
FILE: README.md
================================================
# Posh-Sysmon
PowerShell 3.0 or above module for creating and managing Sysinternals Sysmon v2.0 config files. System Monitor ([Sysmon](https://technet.microsoft.com/en-us/sysinternals/dn798348)) is a Windows system service and device driver that is part of the SysInternal tools from Microsoft. It is written by Mark Russinovich and Thomas Garnier to monitor a Windows system actions and log such actions in to the Windows Event Log. When the tool is installed on a system it can be given a XML configuration file so as to control what is logged and the same file can be used to update the configuration of a previously installed instance of the tool.
All functions in the PowerShell module include help information and example of usage that can be view using the Get-Help cmdlet.
## Installation
For installation it is highly recomended that you install from the PowerShell Gallery using the Install-Module cmdlet.
On PowerShell v5 and above:
``` Powershell
Install-Module -Name Posh-Sysmon
```
If you are running PS 3.0 to 4.0 you can use the PowerShell Gallery also following instruction in [PowerShell Gallery Documentation](https://msdn.microsoft.com/powershell/gallery/readme)
## Change Log
### Version 1.2
* Module only supports the last 2 Schema versions.**[Breaking Change]**
* Support for Sysmon 8.0 Schema version 4.1 RuleName
* Fixed issue when adding a filter for a none existing rule. It will properly error now.
### Version 1.0
* Module only supports the last 2 Schema versions.**[Breaking Change]**
* Support for Sysmon 7.0 Schema version 4.0
* Added new fields for filtering introduced in Sysmon 7.0.
* Modified organization of functions in to their own files for better management while coding.
* Fixed typo in the enabling of rules in rule creation.
### Version 0.7.6
* Support for Schema 3.4 of Sysmon v6.2
* New function New-SysmonWmiEvent.
* Updated Rule and Filter functions for WmiEvents.
* Fixed where some functions did not support PipeEvents.
### Version 0.7.5
* Support for Schema 3.3 of Sysmon v6.
* New function New-SysmonPipeEvent for filtering for named pipeline cration and connection events.
* Support of PipeEvent in config creation and event type functions.
* Several bug fixes on filtering functions when give an array of values.
### Version 0.7.3
* Several bug fixes when creating RawAccess and ProcessOpen rules.
* By default the new schema is 3.2 for the latest version of Sysmon 5.0
* New-SysmonConfiguration function has options to enable all logging for FileCreate, RegistryEvent and FileCreateStreamHash
* Get-SysmonEventData can now parse File Create, Registry and File Stream creation events.
* New function New-SysmonFileCreateFilter for creating file creation filters.
* New function New-SysmonRegistryEvent for creating registry event filters.
* New function New-SysmonFileCreateStreamHash for creating file stream hash event filters.
* Updated Get-SysmonRule, Set-SysmonRule, Remove-SysmonRule and Remove-SysmonRuleFilter for the new event type rules.
* Added Online Help option for all functions.
### Version 0.7.2
* Added missing Event Types to Get-SysmonEventData.
### Version 0.7.1
* Fixed issue with conditions with filters with space in them.
### Version 0.7
* Added support for ProcessAccess filtering added in Sysmon 4.1
* Added function New-SysmonProcessAccess for creating ProcessAccess filters.
* Fixed issue where command was displayed and not ran with New-SysmonDriverLoadFilter.
* Added ProcessAccess type in Get-SysmonEventData and Get-SysmonRuleFilter.
* In verbose output it shows with what version of Sysmon the file will be compatible with after creating it.
### Version 0.6
* Added support for Sysmon 4.0 XML schemea (Schema version 3.0)
* One can select the version of schema to support when creating the configuration file.
* All functions have been updated to support the use of more than one rule as per Schema 3.0
### Version 0.5
* Added Get-SysmonEventData to get the Event Data information as custom object for selected Event Types.
* Added Get-SysmonRuleFilter to get all filters under a specific Event Type Rule.
### Version 0.4
Version 3.0 is a full re-write om how rules work and new event types. This update is SysMon 3.0 only. If you wish to work on SysMon 2.0 rules I recommend you use version 0.3 version of the module.
* When creating a new sysmon rule it will allow you to enable logging of event types supported.
* Checks that it is only working with the proper XML schema for the rules.
* Can now create specific filter for CreateRemoteThread event type.
* Since Rules and Config got merger config functions (Get-SysmonConfigOptio, Set-SysmonConfigOption) where removed and replaced with Get-SysmonHashingAlgorithm and Set-SysmonHashingAlgorithm
### Version 0.3
* Tons of fixes do to a bad re-facor.
* Filter creation is now done by specific funtions per event type.
* Filter creation functions are now in their own sub-module.
### Version 0.2
* Validate that the file is an XML file and a valid Sysmon configuration file.
* Change option ConfigFile to Path and LiteralPath so as to match other cmdlets that work with files.
* Fixed typos on verbose messages and examples.
* Functions should work better now when passing files through the pipeline using Get-ChildItem.
### Version 0.1
* Initial version for Sysmon 2.0 with XML Schema 1.0
## Examples
## Create a XML Configuration File
PS C:\> New-SysmonConfiguration -Path .\pc_marketing.xml -HashingAlgorithm IMPHASH,SHA1 -Network -Comment "Sysmon config for deployment in the Marketing PC OU" -Verbose
VERBOSE: Enabling hashing algorithms : IMPHASH,SHA1
VERBOSE: Enabling network connection logging.
VERBOSE: Config file created as C:\pc_marketing.xml
PS C:\> Set-SysmonRule -Path .\pc_marketing.xml -EventType ImageLoad -Verbose
VERBOSE: No rule for ImageLoad was found.
VERBOSE: Creating rule for event type with action of Exclude
VERBOSE: Action has been set.
EventType : ImageLoad
Scope : All Events
DefaultAction : Exclude
Filters :
## Remove One or More Filters
PS C:\> Get-SysmonRule -Path .\pc_marketing.xml -EventType NetworkConnect
EventType : NetworkConnect
Scope : Filtered
DefaultAction : Exclude
Filters : {@{EventField=Image; Condition=Image; Value=C:\Windows\System32\svchost.exe},
@{EventField=Image; Condition=Image; Value=C:\Program Files (x86)\Internet Explorer\iexplore.exe},
@{EventField=Image; Condition=Image; Value=C:\Program Files\Internet Explorer\iexplore.exe},
@{EventField=Image; Condition=Image; Value=C:\Program Files (x86)\Google\Chrome\Application\chrome.exe}...}
PS C:\> Remove-SysmonRuleFilter -Path .\pc_marketing.xml -EventType NetworkConnect -Condition Image -EventField Image -Value $images -Verbose
VERBOSE: Filter for field Image with condition Image and value of C:\Windows\System32\svchost.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files (x86)\Internet Explorer\iexplore.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files\Internet Explorer\iexplore.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files (x86)\Google\Chrome\Application\chrome.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files (x86)\PuTTY\putty.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files (x86)\PuTTY\plink.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files (x86)\PuTTY\pscp.exe removed.
VERBOSE: Filter for field Image with condition Image and value of C:\Program Files (x86)\PuTTY\psftp.exe removed.
EventType : NetworkConnect
Scope : All Events
DefaultAction : Exclude
Filters :
## Remove Rule
PS C:\> Remove-SysmonRule -Path .\pc_marketing.xml -EventType ImageLoad,NetworkConnect -Verbose
VERBOSE: Removed rule for ImageLoad.
VERBOSE: Removed rule for NetworkConnect.
================================================
FILE: build.ps1
================================================
[CmdletBinding()]
param(
[ValidateSet("Release","Debug")]
$Configuration = "Release"
)
Push-Location $PSScriptRoot
try {
$BuildTimer = New-Object System.Diagnostics.Stopwatch
$BuildTimer.Start()
$ModuleName = Split-Path $PSScriptRoot -Leaf
$ErrorActionPreference = "Stop"
$version = Get-Metadata ".\Source\${ModuleName}.psd1"
$folder = mkdir $version -Force
Get-ChildItem Source -filter "${ModuleName}.*" |
Copy-Item -Dest $folder.FullName -PassThru |
ForEach-Object {
Write-Host " $($_.Name) -> $($_.FullName)"
}
Get-ChildItem Source\Private, Source\Public -Filter *.ps1 -Recurse |
Sort-Object Directory, Name |
Get-Content |
Set-Content "$($folder.FullName)\${ModuleName}.psm1"
Write-Host " $($ModuleName) -> $($folder.FullName)\${ModuleName}.psm1"
Write-Host
Write-Host "Module build finished." -ForegroundColor Green
$BuildTimer.Stop()
Write-Host "Total Elapsed $($BuildTimer.Elapsed.ToString("hh\:mm\:ss\.ff"))"
} catch {
throw $_
} finally {
Pop-Location
}
================================================
FILE: docs/Get-SysmonEventData.md
================================================
---
external help file: Posh-SysMon-help.xml
Module Name: Posh-SysMon
online version:
schema: 2.0.0
---
# Get-SysmonEventData
## SYNOPSIS
Searches for specified SysMon Events and retunrs the Event Data as a custom object.
## SYNTAX
### ID (Default)
```
Get-SysmonEventData [-EventId] [[-MaxEvents] ] [-Path ] [-StartTime ]
[-EndTime ] []
```
### Type
```
Get-SysmonEventData [[-EventType] ] [[-MaxEvents] ] [-Path ] [-StartTime ]
[-EndTime ] []
```
## DESCRIPTION
Searches for specified SysMon Events and retunrs the Event Data as a custom object.
## EXAMPLES
### EXAMPLE 1
```
Get-SysMonEventData -EventId 1 -MaxEvents 10 -EndTime (Get-Date) -StartTime (Get-Date).AddDays(-1)
```
All process creation events in the last 24hr
### EXAMPLE 2
```
Get-SysMonEventData -EventId 3 -MaxEvents 20 -Path .\export.evtx
```
last 20 network connection events from a exported SysMon log.
## PARAMETERS
### -EventId
Sysmon Event ID of records to show
```yaml
Type: Int32[]
Parameter Sets: ID
Aliases:
Required: True
Position: 1
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### -EventType
EventType that a Rule can be written against.
```yaml
Type: String[]
Parameter Sets: Type
Aliases:
Required: False
Position: 1
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### -MaxEvents
Specifies the maximum number of events that Get-WinEvent returns.
Enter an integer.
The default is to return all the events in the logs or files.
```yaml
Type: Int32
Parameter Sets: (All)
Aliases:
Required: False
Position: 2
Default value: 0
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### -Path
Specifies a path to one or more exported SysMon events in evtx format.
```yaml
Type: String[]
Parameter Sets: (All)
Aliases: PSPath
Required: False
Position: Named
Default value: None
Accept pipeline input: True (ByPropertyName, ByValue)
Accept wildcard characters: False
```
### -StartTime
Start Date to get all event going forward.
```yaml
Type: DateTime
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### -EndTime
End data for searching events.
```yaml
Type: DateTime
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
## OUTPUTS
## NOTES
## RELATED LINKS
================================================
FILE: docs/Get-SysmonHashingAlgorithm.md
================================================
---
external help file: Posh-SysMon-help.xml
Module Name: Posh-SysMon
online version: https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonHashingAlgorithm.md
schema: 2.0.0
---
# Get-SysmonHashingAlgorithm
## SYNOPSIS
{{Fill in the Synopsis}}
## SYNTAX
### Path (Default)
```
Get-SysmonHashingAlgorithm [-Path] []
```
### LiteralPath
```
Get-SysmonHashingAlgorithm [-LiteralPath] []
```
## DESCRIPTION
{{Fill in the Description}}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -LiteralPath
{{Fill LiteralPath Description}}
```yaml
Type: String
Parameter Sets: LiteralPath
Aliases: PSPath
Required: True
Position: 0
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### -Path
{{Fill Path Description}}
```yaml
Type: String
Parameter Sets: Path
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### System.String
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
[https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonHashingAlgorithm.md](https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonHashingAlgorithm.md)
================================================
FILE: docs/Get-SysmonRule.md
================================================
---
external help file: Posh-SysMon-help.xml
Module Name: Posh-SysMon
online version: https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRule.md
schema: 2.0.0
---
# Get-SysmonRule
## SYNOPSIS
{{Fill in the Synopsis}}
## SYNTAX
### Path (Default)
```
Get-SysmonRule [-Path] [[-EventType] ] []
```
### LiteralPath
```
Get-SysmonRule [-LiteralPath] [[-EventType] ] []
```
## DESCRIPTION
{{Fill in the Description}}
## EXAMPLES
### Example 1
```powershell
PS C:\> {{ Add example code here }}
```
{{ Add example description here }}
## PARAMETERS
### -EventType
{{Fill EventType Description}}
```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Accepted values: ALL, NetworkConnect, ProcessCreate, FileCreateTime, ProcessTerminate, ImageLoad, DriverLoad, ProcessAccess, RawAccessRead, ProcessAccess, FileCreateStreamHash, RegistryEvent, FileCreate, PipeEvent, WmiEvent
Required: False
Position: 1
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### -LiteralPath
{{Fill LiteralPath Description}}
```yaml
Type: String
Parameter Sets: LiteralPath
Aliases: PSPath
Required: True
Position: 0
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### -Path
{{Fill Path Description}}
```yaml
Type: String
Parameter Sets: Path
Aliases:
Required: True
Position: 0
Default value: None
Accept pipeline input: True (ByPropertyName)
Accept wildcard characters: False
```
### CommonParameters
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
## INPUTS
### System.String
### System.String[]
## OUTPUTS
### System.Object
## NOTES
## RELATED LINKS
[https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRule.md](https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRule.md)
================================================
FILE: docs/Get-SysmonRuleFilter.md
================================================
---
external help file: Posh-SysMon-help.xml
Module Name: Posh-SysMon
online version: https://github.com/darkoperator/Posh-Sysmon/blob/master/docs/Get-SysmonRule.md
schema: 2.0.0
---
# Get-SysmonRuleFilter
## SYNOPSIS
Get the configured filters for a specified Event Type Rule in a Sysmon configuration file.
## SYNTAX
### Path (Default)
```
Get-SysmonRuleFilter [-Path]