Public/Install-NSPSysmon.ps1
|
function Install-NSPSysmon { <# .SYNOPSIS Installs Sysmon with a configuration, or applies the configuration to the Sysmon already installed. Elevated. .DESCRIPTION With -Configuration the text is first written to -ConfigPath (UTF-8, CRLF - the bytes Test-NSPSysmonConfig expects). Not installed: "<SysmonPath> -accepteula -i <ConfigPath>". Installed: "<installed Sysmon> -c <ConfigPath>", using the installed copy so the binary and driver versions match. Sysmon has one configuration per computer. When the installed Sysmon is using a different configuration file - someone else's monitoring, perhaps - this stops unless -Force, since applying ours replaces theirs. Returns the status afterwards (Get-NSPSysmonStatus). .EXAMPLE $xml = New-NSPSysmonFileWatchConfig -Path 'D:\Jobs\Outbound' -ExcludeExtension '.pgp' Install-NSPSysmon -SysmonPath 'C:\Jobs\SetupFiles' -ConfigPath 'D:\Jobs\Sysmon.xml' -Configuration $xml .EXAMPLE Install-NSPSysmon -ConfigPath 'D:\Jobs\Sysmon.xml' -WhatIf #> [CmdletBinding(SupportsShouldProcess)] [OutputType('NSP.Win.Sysmon.Status')] param( [string]$SysmonPath, [Parameter(Mandatory)][string]$ConfigPath, [string]$Configuration, [switch]$Force ) $full = [IO.Path]::GetFullPath($ConfigPath) $status = Get-NSPSysmonStatus if ($status.Installed -and $status.ConfigFile -and [IO.Path]::GetFullPath($status.ConfigFile) -ne $full -and -not $Force) { throw "Sysmon here already uses $($status.ConfigFile). Sysmon has one configuration per computer, so applying $full replaces it. Merge the rules into one file, or pass -Force to replace it." } if (-not $Configuration -and -not (Test-Path -LiteralPath $full -PathType Leaf)) { throw "$full does not exist; pass -Configuration to write it." } if ($status.Installed) { $exe = $status.ImagePath $argList = @('-accepteula', '-c', $full) $what = "Apply Sysmon configuration $full" } else { $exe = Find-NSPSysmon -Path $SysmonPath if (-not $exe) { throw 'Sysmon not found. Pass -SysmonPath, set NSP_SYSMON, or put Sysmon64.exe on PATH (https://learn.microsoft.com/sysinternals/downloads/sysmon).' } $argList = @('-accepteula', '-i', $full) $what = "Install Sysmon ($exe) with configuration $full" } if (-not $PSCmdlet.ShouldProcess($env:COMPUTERNAME, $what)) { return } if ($Configuration) { $folder = Split-Path -Parent $full if (-not (Test-Path -LiteralPath $folder)) { $null = New-Item -ItemType Directory -Path $folder -Force } [IO.File]::WriteAllBytes($full, (ConvertTo-NSPSysmonConfigBytes -Configuration $Configuration)) } $run = Invoke-NSPSysmonExe -FilePath $exe -ArgumentList $argList if ($run.ExitCode -ne 0 -or @($run.Output) -match 'launch Sysmon as an Administrator|^Error|failed') { throw "Sysmon failed (exit code $($run.ExitCode)): $(@($run.Output) -join ' | ')" } @($run.Output) | ForEach-Object { Write-Verbose $_ } Get-NSPSysmonStatus } |