Automating with PowerShell: Shipping your logs

Wow! It’s been quite a while since I’ve blogged. I’ve been working on CIPP, and the CyberDrainCTF recently ended so all my time just disappeared trying to balance those two. Not that that’s over for a bit I have some time to teach about PowerShell again.

This time we’re going to use PowerShell to setup moving your logs to a centralized logging engine. This could be Graylog, ELK, etc, but it could also be your external SIEM/SOC product that you’re running. Storing your logs in a central location can help so much with troubleshooting, security issues, or auditability and accountability, so let’s get started.

We have three separate scripts available right now, because there’s 3 different options; all scripts are pretty simple and straight forward and mostly meant as an example on how you could do this, not how you should. I’m using some community examples in these scripts;

  • NXLog config generated by Poshim by Blumira
  • Winlogbeat config by jhochwald, but with edits as it’s no longer maintained for newer versions
  • Sysmon config by Olaf Hartong

First we install Sysmon, which allows us to monitor more information in the event log and has abilities to find stuff you would not normally find. After we install sysmon we get the choice to deploy either NXLog, or WinLogBeat. This is a case of personal preference.

Deploying Sysmon

Sysmon is the easiest in the equation; we download Sysmon, download the configuration, and set up the correct bitness version. As always I recommend to host these files yourself somewhere.

Invoke-WebRequest "https://raw.githubusercontent.com/olafhartong/sysmon-modular/master/sysmonconfig.xml" -OutFile sysmonlatest.xml -UseBasicParsing
Invoke-WebRequest "https://download.sysinternals.com/files/Sysmon.zip" -OutFile "sysmon.zip" -UseBasicParsing
Expand-Archive "sysmon.zip" -Force

if ([Environment]::Is64BitOperatingSystem) {
Copy-Item ".\sysmon64.exe" "C:\windows\system32\sysmon64.exe"
Start-Process "C:\Windows\system32\Sysmon64.exe" -ArgumentList "-accepteula -i sysmonlatest.xml"
Start-Process "C:\Windows\system32\Sysmon64.exe" -ArgumentList "-accepteula -c sysmonlatest.xml"
}
else {
Copy-Item ".\sysmon.exe" "C:\windows\system32\sysmon.exe"
Start-Process "C:\Windows\system32\Sysmon.exe" -ArgumentList "-accepteula -i sysmonlatest.xml"
Start-Process "C:\Windows\system32\Sysmon.exe" -ArgumentList "-accepteula -c sysmonlatest.xml"
}

Now that we’ve setup setup Sysmon, let’s move on to setting up NxLog

Setup NxLog

NxLog is one of the tools that actually ships the logs somewhere, in the case of our example we’ll setup a raw TCP connection to our target host. We’ve used Poshim to generate a basic configuration that picks up most common events, including our brand new setup of Sysmon.

$LoggingServer = "1.1.1.1"
$LoggingServerPort = "514"


Invoke-WebRequest "https://nxlog.co/system/files/products/files/348/nxlog-ce-3.0.2272.msi" -OutFile 'nxlog-ce-3.0.2272.msi' -UseBasicParsing
Invoke-WebRequest "https://cyberdrain.com/wp-content/uploads/2022/03/nxlog.conf" -OutFile ".\nxlog.conf" -UseBasicParsing
#Script uses parts of Blumira's Poshim, with permission.
Start-Process -FilePath "msiexec.exe" -ArgumentList @("/i nxlog-ce-3.0.2272", "/qn") -Wait

$logList = @(
    "Windows PowerShell"
    "System"
    "Security"
    "Application"
    "Setup"
    "Operational"
    "Network Isolation Operational"
    "Microsoft-Windows-WinRM/Operational"
    "Microsoft-Windows-WindowsUpdateClient/Operational"
    "Microsoft-Windows-Windows Defender/WHC"
    "Microsoft-Windows-Windows Defender/Operational"
    "Microsoft-Windows-User Profile Service/Operational"
    "Microsoft-Windows-TerminalServices-RDPClient/Operational"
    "Microsoft-Windows-TaskScheduler/Operational"
    "Microsoft-Windows-Sysmon/Operational"
    "Microsoft-Windows-PrintService/Operational"
    "Microsoft-Windows-PrintService/Admin"
    "Microsoft-Windows-PowerShell/Operational"
    "Microsoft-Windows-PowerShell/Admin"
    "Microsoft-Windows-NTLM/Operational"
    "Microsoft-Windows-NetworkProfile/Operational"
    "Microsoft-Windows-LSA/Operational"
    "Microsoft-Windows-Kernel-PnP/Configuration"
    "Microsoft-Windows-GroupPolicy/Operational"
    "Microsoft-Windows-CodeIntegrity/Operational"
    "Microsoft-Windows-CertificateServicesClient-Lifecycle-System/Operational"
    "Microsoft-Windows-CAPI2/Operational"
    "Microsoft-Windows-Bits-Client/Operational"
    "Microsoft-Windows-AppLocker/Packaged app-Execution"
    "Microsoft-Windows-AppLocker/Packaged app-Deployment"
    "Microsoft-Windows-AppLocker/MSI and Script"
    "Microsoft-Windows-AppLocker/EXE and DLL"
    "Microsoft-Windows-Application-Experience/Steps-Recorder"
    "Microsoft-Windows-Application-Experience/Program-Telemetry"
    "Microsoft-Windows-Application-Experience/Program-Inventory"
    "Microsoft-Windows-Application-Experience/Program-Compatibility-Troubleshooter"
    "Microsoft-Windows-Application-Experience/Program-Compatibility-Assistant"
    "Microsoft-Windows-Hyper-V-Hypervisor-Operational"
    "Microsoft-Windows-Hyper-V-Hypervisor-Admin"
    "Microsoft-Windows-SMBServer/Security"
    "Microsoft-Windows-SMBServer/Operational"
    "Microsoft-Windows-SMBServer/Connectivity"
    "Microsoft-Windows-SMBServer/Audit"
    "Microsoft-Windows-WinHttp/Operational"
    "Microsoft-Windows-WinHTTP-NDF/Diagnostic"
    "Microsoft-Windows-RRAS/Operational"
)
Write-Host "Enabling Windows Firewall Logging for both allowed and blocked attempts"
Set-NetFirewallProfile -LogFileName %SystemRoot%\System32\LogFiles\Firewall\pfirewall.log -LogMaxSizeKilobytes 4096 -LogBlocked True -LogAllowed true -LogIgnored False
Write-Host "Checking list of available event logs, and enabling them with 64MB Circular size."
$Logs = $LogList | ForEach-Object {
    $logSource = Get-WinEvent -ListLog $_
    if (!$logSource.IsEnabled) {
        $logSource.MaximumSizeInBytes = 64MB
        $logSource.LogMode = "Circular"
        $logSource.isEnabled = $true
        $logSource.SaveChanges()
    }
}
Write-Host "Setting NXLog config to $($LoggingServer) on port $($LoggingServerPort)"
(Get-Content '.\nxlog.conf') -Replace 'A.B.C.D', $LoggingServer -replace "SIEMPORT", $LoggingServerPort | Set-Content '.\nxlog.conf'
Write-Host "Copying NXLog config to new location"
Copy-Item -Path '.\nxlog.conf' -Destination  "C:\Program Files (x86)\nxlog\conf\nxlog.conf" -Force
Restart-Service -Name "nxlog"

NxLog is cool, but some tools work better with Beats, such as the ELK stack. Beats are log collectors that process data in a specific way. For our next example, we’ll use WinLogBeat.

Setup WinLogbeat

For WinLogBeat it’s the same approach we took as the NxLog configuration; the difference being we have more output types as options.

$LoggingServer = "1.1.1.1"
$LoggingServerPort = "514"
$OutputType = "logstash" #allowed: logstash, kafka, redis, elasticsearch

Expand-Archive winlogbeat.zip -Force
Invoke-WebRequest "https://cyberdrain.com/wp-content/uploads/2022/03/winlogbeat.zip" -OutFile ".\winlogbeat.zip" -UseBasicParsing
Write-Host "Enabling Windows Firewall Logging for both allowed and blocked attempts"
Set-NetFirewallProfile -LogFileName %SystemRoot%\System32\LogFiles\Firewall\pfirewall.log -LogMaxSizeKilobytes 4096 -LogBlocked True -LogAllowed true -LogIgnored False
Write-Host "Installing Winlogbeat Service"
Expand-Archive -Path WinLogBeat.zip -DestinationPath "$($PROGRAMDATA)" -Force

# Create the new service.

New-Service -Name winlogbeat-drmm ` -DisplayName Winlogbeat-drmm`
-BinaryPathName "`"C:\Programdata\winlogbeat\winlogbeat.exe`" --environment=windows_service -c `"C:\Programdata\winlogbeat\winlogbeat.yml`" --path.home `"C:\Programdata\winlogbeat`" --path.data `"$PROGRAMDATA\winlogbeat`" --path.logs `"$PROGRAMDATA\winlogbeat\logs`" -E logging.files.redirect_stderr=true"

# Attempt to set the service to delayed start using sc config.

Try {
Start-Process -FilePath sc.exe -ArgumentList 'config winlogbeat start= delayed-auto'
}
Catch {
Write-Host "An error occured setting the service to delayed start."
}

Write-Host "Setting WinLogBeat config to $($LoggingServer) on port $($LoggingServerPort)"
(Get-Content 'C:\Programdata\winlogbeat\winlogbeat.yml') -Replace 'A.B.C.D', "$($LoggingServer):$LoggingServerPort" -replace "outputtype", $OutputType | Set-Content 'C:\Programdata\winlogbeat\winlogbeat.yml'
Write-Host "Starting WinLogBeat"
& C:\Programdata\winlogbeat\winlogbeat.exe test config -c C:\Programdata\winlogbeat\winlogbeat.yml -e
Start-Service 'winlogbeat-drmm'

And that’s it! WinlogBeat is now configured and sending logs to your output service.

Closing remarks

These are just examples on how you could configure log shipping, I’d advise anyone to ship their logs to a central location for all the reasons mentioned above; even if you’re not super security focused this should help you in getting to the next level. When you set this up, you should also start monitoring the services involved like Sysmon, Nxlog, or Winlogbeat.

As always, Happy PowerShelling. 🙂

Recent Articles

The return of CyberDrain CTF

CyberDrain CTF returns! (and so do I!)

It’s been since september that I actually picked up a digital pen equivalent and wrote anything down. This was due to me being busy with life but also my side projects like CIPP. I’m trying to get back into the game of scripting and blogging about these scripts. There’s still so much to automate and so little time, right? ;)

Monitoring with PowerShell: Monitoring Acronis Backups

Intro

This is a monitoring script requested via Reddit, One of the reddit r/msp users wondered how they can monitor Acronis a little bit easier. I jumped on this because it happened pretty much at the same time that I was asked to speak at the Acronis CyberSummit so it kinda made sense to script this so I have something to demonstrate at my session there.

Monitoring with PowerShell: Monitoring VSS Snapshots

Intro

Wow! It’s been a while since I’ve blogged. I’ve just been so swamped with CIPP that I’ve just let the blogging go entirely. It’s a shame because I think out of all my hobbies it’s one I enjoy the most. It’s always nice helping others achieve their scripting target. I even got a couple of LinkedIn questions asking if I was done with blogging but I’m not. Writing always gives me some more piece of mind so I’ll try to catch up again. I know I’ve said that before but this time I’ll follow through. I’m sitting down right now and scheduling the release of 5 blogs in one go. No more whining and no more waiting.