Home > Powershell > Query Security Log Using Powershell

Query Security Log Using Powershell

I’ve just completed a script that will parse the Windows Security Event log for Event ID’s of type 4624 (user logons).    Once the events have been retrieved the script then creates and outputs a  custom object populated with the following properties:

  • Account Name
  • DateTime
  • Type  ( Interactive,Network,Unlock)

The script is composed of 2 functions:

  • Find-Matches
  • Query-SecurityLog

Query-SecurityLog is the main function and is responsible for creating and outputing the custom object.  Find-Matches is a helper function used to parse the event log message property for the following pattern: “Account Name:      SomeUserName”.    Prior to incorporating the Find-Matches function I had used the -Match operator but then realized that pattern was referenced twice  in the message and that the -Match operator returns only the first matching expression.  So, if you need to find more than one occurrence of a pattern in raw text, you have to switch over to the RegEx object underlying the -Match operator and use it directly.

This left me with 2 possible option that could be used to discover one or more matching values:

  • Select-String (as used in Find-Matches)
  • [regex]

The Find-Matches function was something I already had in my repository of scripts so I went that route, however after reading Chapter 13: Text and Regular Expression in the Powershell.com ebook I realized this could of been done with less code by using [regex].

$Pattern = [regex]"(?i)\baccount name:\s+\w+\b"
$Content = $Pattern.matches($i.message) | select -prop value | %{$_.value}

The example below demonstrates how Select-String is used in the Find-Matches function to output all matching patterns:


I then used an if\else statemtment block to determine  how many matches were returned and then set the $account parameter accordingly.

if($content.Count -eq 2) {
$account = $content[1]} else {$account =  $content }

I was also suprised to see just how many non-user account logon events were recorded and decided to remove any events that referenced the accounts below:

  • System
  • IUSER
  • LOCAL
  • NETWORK
  • $ENV:Computername

As well as filter the events based on the following Logon Types and assign the $logontype variable accordingly:

  • Interactive (2)
  • Network (3)
  • Computer Unlocked (7)

This was done using the following code:

$notmatch = "System|IUSR|LOCAL|NETWORK"
if($account -notmatch $notmatch)  {                        

    if($i.Message | Select-String -Pattern "Logon Type:\s+[2]") {
    $logontype = "Interactive" }
    if($i.Message | Select-String -Pattern "Logon Type:\s+[3]") {
    $logontype = "Network" }
    if($i.Message | Select-String -Pattern "Logon Type:\s+[7]") {
    $logontype = "Computer Unlocked" }
    }

It was then just a matter of creating and populating the custom object.  There are 2 ways to populate an object once created.  One way is to create the object and then use the Add-Member cmdlet to populate it and the other is to use the -Property property along with splatting ( @{} ).

  • $Obj | Add-Member -Noteproperty NameOfProperty  ValueOfProperty
  • -Property @{ NameOfProperty = “Value” }

I choose to go with the Splatting option as it requires less code.

$obj = New-Object PSObject -Property @{
       User = $user
       Date = $Date
       LogonType = $LogonType
       }

The end result was the following code.

Function Find-Matches {                        

 Param($Pattern)
 Process {
  $_ | Select-String -pattern $Pattern -AllMatches |
   select -ExpandProperty matches |
   select -ExpandProperty value
  }
 }                        

Function Query-SecurityLog {               

    Param(
        [int]$MaxEvents,
        [array]$global:Users = @(),
        [string]$Comp = $env:computername,
        $notmatch = "System|IUSR|LOCAL|NETWORK"            

        )                 

    if($MaxEvents)
    { $events = Get-WinEvent -LogName security -MaxEvents $MaxEvents |
    Where-Object{$_.id -eq "4624"}
    } Else {  $events = Get-WinEvent -LogName security  |
    Where-Object{$_.id -eq "4624"}}            

    Foreach($i in $events) {                        

    $content = $i.message| Find-Matches -Pattern "account name:\s+\w+"
    if($content.Count -eq 2) {
    $account = $content[1]} else {$account =  $content }
    $account = (($account -split ":")[1]) -replace "\s+",""                        

    if($account -notmatch $notmatch) {                        

        if($i.Message | Select-String -Pattern "Logon Type:\s+[2]") {
        $logontype = "Interactive" }
        if($i.Message | Select-String -Pattern "Logon Type:\s+[3]") {
        $logontype = "Network" }
        if($i.Message | Select-String -Pattern "Logon Type:\s+[7]") {
        $logontype = "Computer Unlocked" }                        

   $user = $account
   $Date = $i.TimeCreated
   $obj = New-Object PSObject -Property @{
       User = $user
       Date = $Date
       LogonType = $LogonType
       }            

  $Global:Users += $Obj                        

       }
    }                        

 write-output $Global:Users | Select User,Date,LogonType |
             Sort Date -Descending | Format-Table -Auto
}                        

Query-SecurityLog -MaxEvents 1000

The output of Query-SecurityLog  is:

Advertisement
Categories: Powershell Tags:
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.