This is part 3 of our mini-series covering PowerShell script block logging. By default, PowerShell logs only code that is considered security relevant. Today, we’ll enable verbose logging. With verbose logging turned on, any PowerShell code executed on your machine by any user will be logged.

To enable verbose mode, you need Administrator privileges. Here is a function that enables verbose logging:

function Enable-VerboseLogging
{
  <#
      .SYNOPSIS
      Enables verbose script block logging. 
      Requires Administrator privileges.

      .DESCRIPTION
      Turns script block logging on. Any code that is sent to 
      PowerShell will be logged.

      .EXAMPLE
      Enable-VerboseLogging
      Enables script block logging. 
      Administrator privileges required.
  #>


  $path = "Registry::HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
  $exists = Test-Path -Path $path
  try
  {

  $ErrorActionPreference = 'Stop'
  if (!$exists) { $null = New-Item -Path $path -Force }
  
  Set-ItemProperty -Path $path -Name EnableScriptBlockLogging -Type DWord -Value 1
  Set-ItemProperty -Path $path -Name EnableScriptBlockInvocationLogging -Type DWord -Value 1

  }
  catch
  {
    Write-Warning "Administrator privileges required. Run this command from an elevated PowerShell."
  }
}

Once you run Enable-VerboseLogging, all PowerShell code will be written to the log. You can then use one of the approaches we introduced earlier to read the logged code, for example our function Get-LoggedCode:

function Get-LoggedCode
{
  # read all raw events
  $logInfo = @{ ProviderName="Microsoft-Windows-PowerShell"; Id = 4104 }
  Get-WinEvent -FilterHashtable $logInfo | 
  # take each raw set of data...
  ForEach-Object {
    # create a new object and extract the interesting
    # parts from the raw data to compose a "cooked"
    # object with useful data
    [PSCustomObject]@{
      # when this was logged
      Time = $_.TimeCreated
      # script code that was logged
      Code = $_.Properties[2].Value
      # if code was split into multiple log entries,
      # determine current and total part
      PartCurrent = $_.Properties[0].Value
      PartTotal = $_.Properties[1].Value
                
      # if total part is 1, code is not fragmented
      IsMultiPart = $_.Properties[1].Value -ne 1
      # path of script file (this is empty for interactive
      # commands)
      Path = $_.Properties[4].Value
      # log level
      # by default, only level "Warning" will be logged:
      Level = $_.LevelDisplayName
      # user who executed the code (SID)
      User = $_.UserId
    }
  } 
} 

Note that only changes to the logging settings require Administrator privileges. Any user can read the logged data.

If you’d like to disable verbose mode and return to the default settings, use this function:

function Get-LoggedCode
{
  # read all raw events
  $logInfo = @{ ProviderName="Microsoft-Windows-PowerShell"; Id = 4104 }
  Get-WinEvent -FilterHashtable $logInfo | 
  # take each raw set of data...
  ForEach-Object {
    # create a new object and extract the interesting
    # parts from the raw data to compose a "cooked"
    # object with useful data
    [PSCustomObject]@{
      # when this was logged
      Time = $_.TimeCreated
      # script code that was logged
      Code = $_.Properties[2].Value
      # if code was split into multiple log entries,
      # determine current and total part
      PartCurrent = $_.Properties[0].Value
      PartTotal = $_.Properties[1].Value
                
      # if total part is 1, code is not fragmented
      IsMultiPart = $_.Properties[1].Value -ne 1
      # path of script file (this is empty for interactive
      # commands)
      Path = $_.Properties[4].Value
      # log level
      # by default, only level "Warning" will be logged:
      Level = $_.LevelDisplayName
      # user who executed the code (SID)
      User = $_.UserId
    }
  } 
} 

Note that even when verbose script block logging is turned off, PowerShell will log certain code that is considered security relevant.

Twitter This Tip! ReTweet this Tip!

Anonymous