Query Security Log Using Powershell

January 13, 2012 Leave a comment

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:

Categories: Powershell

Powershell Objects and .PS1XML Files

January 9, 2012 Leave a comment

Anyone who uses powershell on a regular basis knows that the output of any powershell cmdlet is of an object type.  Powershell produces objects. For example let’s look at the objects produced by two cmdlets that essentially do the same thing: Get-Eventlog and Get-WinEvent.   The below example uses the GetType() method to display the object type for an eventlog.

(Get-Eventlog -List | Select -First 1).Gettype() | FT -auto
(Get-WinEvent -Listlog Application).Gettype() | FT -auto

Both produce different objects, Eventlog and EventLogConfiguration.  The output of these objects is associated with a powershell formating file (.ps1xml) which defines the properties they will display.

The example below shows the output as it pertains to Get-Eventlog and Get-Winevent.

(Get-Eventlog -List | Select -First 1)
(Get-WinEvent -Listlog Application)

Although they both reference the same event log (Application) they are configured to display different properties, even though some of them reference the same values, like Log and LogName or Entries and RecordCount.

I then was curious which formatting files were associate with each object type, so I decided to view which .ps1xml files existed and ran the following command to browse the $pshome directory and filter for only *.ps1xml files.

dir $pshome\* -include *.ps1xml

My next step was to parse these files using Select-String  for references to the object types (Eventlog and EventLogConfiguration) but decided that the process should be automated and created a function that would create a custom object with the properties of my choosing.   This would also be useful to demo for the workshop I’m putting together called “Using Powershell to View Events and Event Logs” (not sure I did the title so it may change shortly).

Anyway, the result of all this was the creation of the Get-EventLogBaseObjects function.

Function Get-EventLogBaseObjects {
 $Array = "Get-EventLog","Get-WinEvent"
 $global:newarray =@()                                                

     Switch ($Array) {                                                

 "Get-Eventlog" {
    $GetEventLog = (get-eventlog -list | Select -first 1).gettype()
    $XMLFile = Select-String -Path $PSHOME\*.ps1xml -Pattern $GetEventlog |
        Select -First 1
    $Obj = New-Object PSObject -Property @{
            Cmdlet = "Get-Eventlog"
            SystemType = $GetEventLog.UnderlyingSystemType
            XMLFile = $XMLFile.filename
            }
    $global:newarray += $obj
    }                                    

 "Get-WinEvent" {
    $GetWinEvent = (Get-WinEvent -Listlog Application).gettype()
    $XMLFile = Select-String -Path $PSHOME\*.ps1xml -Pattern $GetWinEvent |
        Select -First 1
    $Obj = New-Object PSObject -Property @{
            Cmdlet = "Get-WinEvent"
            SystemType = $GetWinEvent.UnderlyingSystemType
            XMLFile = $XMLFile.filename
            }
    $global:newarray += $obj
     }
 }
 write-output $global:NewArray | Select Cmdlet,SytemType,XMLFile |
        Format-Table -AutoSize
}                        

Get-EventLogBaseObjects
Categories: Powershell

Determine Pipeline Input

January 7, 2012 Leave a comment

There was a recent post on the Powershell Forums titled Finding Function Name in which the user wanted to know if there was anyway to determine which cmdlet or function was being used to send input down the pipeline.  In order to assist I first needed to do some research as I was unsure how to make this determination.  It just so happened that the first response was by Kazun (PS MVP..enough said.. ) and he suggested using $MyInvocation.Line. 

So upon doing a google search I came across the following article PowerShell Deep Dive: Using $MyInvocation by Kirk Munro which went into great detail on how to use the $MyInvocation variable to make a similiar distinction.  From that article I came up with  the following script to demo $MyInvocation.  It includes 4 functions.  The one that anaylzes the pipeline input is Out-Name.   Here is the script…

Function Get-Svc {
      Get-Service | select -First 2
    }
Function Get-Proc {
      Get-Process | Select -First 2
    }
Function Get-File {
      GCI c:\ | Select -First 2
    }            

Function Out-Name {
    param($name)            

    Begin {
       $global:Invocation = $MyInvocation.line
    }            

    Process{
       if( $global:Invocation -match "Get-Svc" ) {
       $_.name
       }
       Elseif ( $global:Invocation -match "Get-Proc" ) {
       $_.vm
       }
       Else { Write-Host "Get-Svc was not used" }
    }
  }            

Get-Svc | out-Name
#Get-Proc | out-name
#Get-File | Out-Name
 

The script was created soley to demo $MyInvocation but could be altered (as with any script) to make it fit your needs.

Categories: Powershell Tags:

Powershell Execution Policies

January 16, 2011 Leave a comment

Windows Powershell execution polices let you determine the conditions under which Powershell loads configuration files (.ps1xml), module script files (.psm1) and scripts (.ps1).    By defaut Powershell doesn’t permit any of these files as it’s default execution policy is set to Restricted.  The available execution policies are as follows and can be found by running Help About_Execution_Policies Read more…

Categories: Powershell Tags:

Migrate DHCP Server Settings Using Powershell

January 10, 2011 Leave a comment

During my preparation to teach the “Updating Your Skills to Server 2008 R2″ class, I saw lot’s of potential to use Powershell to automate some of the mundane tasks, such as creating files and assigning permissions (Module 2) or restoring an AD Computer Object (Module 4) to the more advanced such as using the new Server Migration Tools to migrate the DHCP service from DC1 to SVR1 (Module 1). Read more…

Categories: Powershell

Appending a Function to a Powershell Profile

December 29, 2010 Leave a comment

Powershell profiles provide the opportunity to extend custom functionality either via the console or a scripting engine like PowerGui or the ISE.  They are normal PS scripts and end with a .ps1 file extension. Like all PS scripts they can be edited in notepad, ISE, PowerGUI (my favorite) or any other script\text editor. Read more…

Categories: Powershell

Domain Controller Automation Using Powershell

December 28, 2010 Leave a comment

I’ve recently completed the following Microsoft Test Lab Guides:

The DirectAccess lab required that the Base Configuration be setup first and considering that both labs were time consuming and, at times remedial, I decided to make the process more streamlined and automated by using Powershell to create a script ( for complete automation ) which I could  then convert into a module ( for a more step by step approach ).  I’m still in the begining phase of automating the Base Configuration but I’ve already created a few functions, one of which will turn a standalone server into the first Domain Controller for the Corp.Contoso.Com domain.  Read more…

Categories: Powershell

Deleting Default Shares Using Powershell – Part 2

November 29, 2010 Leave a comment

Having removed the default administrative shares in Part 1 has provided a minimal increase in my security confidence index for the time being but knowing all to well that when the machine is rebooted the shares will return once again takes me back to where I started.    This means that we must take it one step further and edit the registry to permanately remove them going forward. 
Read more…

Categories: Powershell

Deleting Default Shares Using Powershell – Part 1

November 22, 2010 Leave a comment

All Windows systems have several default administrative shares configured which are immediately available after installation.  These shares not only provided direct access to the %SystemRoot%\Windows directory (Admin$) but to the root of all hard drives (C$,D$).  There is also the Inter-Process Communication (IPC$) share which is used to facilitate communication between process and computers over Server Message Blocks (SMB). The shares can be enumerated in Powershell using the Win32_Share class.

Read more…

Categories: Powershell

Penetration Testing with Backtrack – Overview

July 14, 2010 Leave a comment

I recently signed up for an online hacking class offered by Offensive-Security.com called PWB (Penetration Testing with Backtrack).    The subsequent exam  “Offensive Security Certified Professional” (OSCP), will provide a solid baseline for demonstrating my knowledge on pentesting using BackTrack, which is a popular and free Linux based hacking distro. Below is the a full description of the OSCP certification:

The Offensive Security Certified Professional (OSCP) is a unique and industry leading IT Security Certification that tests real world skills in the penetration testing field. No multiple choice questions, no theoretical fluff – The student will be expected to dive into an unknown network, craft custom tailored exploits, find security flaws, and exploit weaknesses within the architecture in order to pass the certification process. Students who successfully complete the Offensive Security PWB Penetration Testing Training certification challenge receive the OSCP certification. Penetration Testing with BackTrack simulates a full penetration test from start to finish by injecting the student into a rich, diverse and vulnerable network environment. Pre-Requisites

The online class consists of a series of downloaded videos, lab book, lab guide(PDF), sample Pentest Report and an online lab environment that includes clients and servers divided into 4 networks.   I also opted to download a customized version of Backtrack for VMWare to use during the labs.  I have 30 days to work through the material, document my findings and then 24hrs to complete the certification challenge.   I will post my progress and challenges as I progess through the course.

Categories: Training
Follow

Get every new post delivered to your Inbox.