Filters.ps1

# .ExternalHelp Posh-SysMon.psm1-Help.xml
function New-SysmonImageLoadFilter
{
  [CmdletBinding(DefaultParameterSetName = 'Path')]
  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')]
  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
            
    }

    foreach ($val in $Value)
    {

      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')]
  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')]
  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')]
  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' =  'FileCreateTime' 
            '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')]
  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-SysmonCreateRemoteThread
{
  [CmdletBinding(DefaultParameterSetName = 'Path')]
  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
  {
    foreach ($val in $Value)
    {
      $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-SysmonProcessAccess -Path .\testver31.xml -OnMatch include -Condition Contains -EventField TargetImage lsass.exe
  Log any process trying to open lsass.exe.
#>

function New-SysmonProcessAccess
{
  [CmdletBinding(DefaultParameterSetName = 'Path')]
  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
            
        }
    foreach ($val in $Value)
    {

      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-SysmonProcessAccess -Path .\testver31.xml -OnMatch include -Condition Contains -EventField Image NTDS.dit
  Log any raw access read of the file NTDS.dit.
#>

function New-SysmonRawAccessRead
{
  [CmdletBinding(DefaultParameterSetName = 'Path')]
  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' =  'ProcessAccess' 
            'Condition' = $Condition 
            'EventField' = $FieldString 
            'Value' = $Value 
            'OnMatch' = $OnMatch
            
        }
    foreach ($val in $Value)
    {

      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')]
  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')]
    [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')]
  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')]
    [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')]
  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,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')]
    $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
            Error = 255
        }

        $EventIdtoType = @{
            '1' = 'ProcessCreate'
            '2' = 'FileCreateTime'
            '3' = 'NetworkConnect'
            '5' = 'ProcessTerminate'
            '6' = 'DriverLoad'
            '7' = 'ImageLoad' 
            '8' = 'CreateRemoteThread'
            '9' = 'RawAccessRead'
            '10' = 'ProcessAccess'
            '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 {}
}