Retrieving Logon and Logoff from Event Log .evtx file

This topic contains 5 replies, has 3 voices, and was last updated by  David Mower 3 months, 1 week ago.

  • Author
    Posts
  • #74030

    David Mower
    Participant

    Hi,

    I trying to get the following script working and need helping as I can't solve the final issue with my changes.

    You can see that if I use Get-EventLog the script works as expected. If I change to Get-WinEvent (which I believe I need to do if I wish to use an older .evtx log from an older computer) then it produces no results even though I'm sure the provider name is correct? Ideas would be greatly appreciated. Thanks all in advance.

    function get-logonhistory{
     cls
     $Result = @()
     Write-Host "Gathering Event Logs, this can take awhile..."
     #$ELogs = Get-EventLog System -Source Microsoft-Windows-WinLogon
     $ELogs = Get-WinEvent -FilterHashtable @{Path = "c:\logtemp\System*.evtx"; ProviderName = "Microsoft-Windows-Winlogon"}
     If ($ELogs) 
     { Write-Host "Processing..."
     ForEach ($Log in $ELogs)
     { If ($Log.InstanceId -eq 7001)
       { $ET = "Logon"
       }
       ElseIf ($Log.InstanceId -eq 7002)
       { $ET = "Logoff"
       }
       Else
       { Continue
       }
       $Result += New-Object PSObject -Property @{
        Time = $Log.TimeWritten
        'Event Type' = $ET
        User = (New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])
       }
     }
     $Result | Select Time,"Event Type",User | Sort Time -Descending | Out-GridView
     Write-Host "Done."
     }
     Else
     { Write-Host "Problem with Computer"
     Write-Host "If you see a 'Network Path not found' error, try starting the Remote Registry service on that computer."
     Write-Host "Or there are no logon/logoff events (XP requires auditing be turned on)"
     }
    }
    
    
    get-logonhistory
    
  • #74035

    RShambo
    Participant

    Sorry I'm not on a Windows PC this afternoon so I cannot double-check this.

    But I believe that Get-WinEvents has a parameter call -LogFile so you can do something like this:

    Get-WinEvent -LogFile System

    Hope this helps.

  • #74326

    David Mower
    Participant

    I didn't think Get-WinEvent could be used on anything but the current event viewer? I want to be able to take reports from old event viewer log files.

    I've been working on this and have got the code as far as this

    #clear the screen
    cls
    
    
    #$Days = 1
    $SYSevents = @()
    $SECevents = @()
    
    
    #get location of folder containing log files
    Function Select-FolderDialog
    {
        param([string]$Description="SELECT FOLDER CONTAINING SYSTEM.EVTX LOGFILE",[string]$RootFolder="MyComputer")
    
        [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
         Out-Null     
    
        $objForm = New-Object System.Windows.Forms.FolderBrowserDialog
        $objForm.Rootfolder  = $RootFolder
        $objForm.Description = $Description
        $Show = $objForm.ShowDialog()
            If ($Show -eq "OK")
            {
                Return $objForm.SelectedPath
            }
            Else
            {
                Write-Error "Operation cancelled by user."
            }
        
    }
    $Drive = Select-FolderDialog # the variable contains user folder selection
    
    
    #System Log save dialog
    Function Get-SaveFileSYS
    {
        param([string]$Description="SELECT FOLDER TO SAVE SYSTEM REPORT",[string]$initialDirectorySYS="MyComputer")
    
        [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
        Out-Null
    
        $SaveFileDialogSYS = New-Object System.Windows.Forms.SaveFileDialog
        $SaveFileDialogSYS.initialDirectory = $initialDirectorySYS
        $SaveFileDialogSYS.filter = "HTML Files (*.htm)|*.htm"
        $SaveFileDialogSYS.ShowDialog() | Out-Null
        $SaveFileDialogSYS.filename #= "SystemLogsReport"
    } 
    $SYSresults = Get-SaveFileSYS # the variable contains save file location
    #$SYSresults = "c:\logtemp\SystemLogsReport.htm"
    
    
    #Security Log save dialog
    Function Get-SaveFileSEC
    {
        param([string]$Description="SELECT FOLDER TO SAVE SECURITY REPORT",[string]$initialDirectorySEC="MyComputer")
    
        [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
        Out-Null
    
        $SaveFileDialogSEC = New-Object System.Windows.Forms.SaveFileDialog
        $SaveFileDialogSEC.initialDirectory = $initialDirectorySEC
        $SaveFileDialogSEC.filter = "HTML Files (*.htm)|*.htm"
        $SaveFileDialogSEC.ShowDialog() | Out-Null
        $SaveFileDialogSEC.filename #= "SecurityLogsReport"
    } 
    $SECresults = Get-SaveFileSYS # the variable contains save file location
    #$SECresults = "c:\logtemp\SecurityLogsReport.htm"
    
    
    #set HTML style for results
    $HTMLstyle = ""
    $HTMLstyle = $HTMLstyle + "BODY{background-color:peachpuff;}"
    $HTMLstyle = $HTMLstyle + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
    $HTMLstyle = $HTMLstyle + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"
    $HTMLstyle = $HTMLstyle + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:palegoldenrod}"
    $HTMLstyle = $HTMLstyle + ""
    $HTMLbodySYS = "System Log - Logon, Logoff, Lock and Unlock"
    $HTMLbodySEC = "Security Log - UAC and logon"
    $CSSStyle = @'
        
        ul {
         padding-left: 5px;
        }
        body { background-color:White;
        font-family:Tahoma;
         font-size:12pt;
        }
        td, th {border:1px solid black;} 
        th {
         color: black;
         background-color:peachpuff;
        }
        td { border-width: 1px;padding: 1px;border-style: solid;border-color: black; }
        TR:Hover TD { Background-Color: #C1D5F8; }
        table, tr, td, th { align:left; padding: 10px; margin: 0px; }
        table { width:75% }
        table { margin-left:0px; }
        
    '@
    $Head = $HTMLstyle + $CSSStyle
    
    
    Write-Host "Processing... Please wait ..."
    
    
    #pull lock and unlock from system log
    $SYSevents  = Get-WinEvent -FilterHashtable @{ 
        Path		 = "$Drive\System.evtx"
        Id=@(7001,7002,20001,20003)
    }
        #put numbers into meaningful words
        $type_lu = @{
            7001 = 'SYSTEMLOG   - User Logon'
            7002 = 'SYSTEMLOG   - User Logoff'
            4800 = 'SECURITYLOG - Lock'
            4801 = 'SECURITYLOG - UnLock'
            4688 = 'SECURITYLOG - USB Device Connected'
           20001 = 'SYSTEMLOG   - Device Installation'
           20003 = 'SYSTEMLOG   - Service Installation'
            7036 = 'SECURITYLOG - Service Control Manager Device Installation'
            4672 = 'SECURITYLOG - Special Privileges assigned to current user'
            4624 = 'SECURITYLOG - Account logged on'
        }
    #pull lock and unlock from security log
    $SECevents  = Get-WinEvent -FilterHashtable @{ 
        Path		 = "$Drive\Security.evtx"
        Id=@(7036,4672,4624,4688,4800,4801)
    }
    
    
    #xml paths
    $ns = @{'ns'='http://schemas.microsoft.com/win/2004/08/events/event'}
    $target_xpath = "//ns:Data[@Name='TargetUserName']"
    $usersid_xpath = "//ns:Data[@Name='UserSid']"
    
    
    #check if previous logfile exists
    $SYStestexists = Test-Path $SYSresults
    $SECtestexists = Test-Path $SECresults
    
    
    #check if system log file exists and delete before running
        If ($SYStestexists -eq $True)
            { 
                Remove-Item $SYSresults
                Write-Host "Previous System logfile removed."
                
            } 
                else 
            {
                Write-Host "System logfile will be created as non exists."
            }
    #check if security log file exists and delete before running
         If ($SECtestexists -eq $True)
            { 
                Remove-Item $SECresults
                Write-Host "Previous Security logfile removed."
                
            } 
                else 
            {
                Write-Host "Security logfile will be created as non exists."
            }
    
    
    #pull data from xml for system log
    If($SYSevents) {
        $XMLSYSresults = ForEach($eventSYS in $SYSevents) {
            $xmlSYS = $eventSYS.ToXml()
            Switch -Regex ($eventSYS.Id) {
                '4...' {
                    $userSYS = (
                        Select-Xml -Content $xmlSYS -Namespace $ns -XPath $target_xpath
                    ).Node.'#text'
                    Break            
                }
                '7...' {
                    $SYSsid = (
                        Select-Xml -Content $xmlSYS -Namespace $ns -XPath $usersid_xpath
                    ).Node.'#text'
                    #.translates needed to make usernames readable
                    $userSYS = (
                        New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList $SYSsid
                    ).Translate([System.Security.Principal.NTAccount]).Value
    
                    Break
                }
            }
            New-Object -TypeName PSObject -Property @{
                Time = $eventSYS.TimeCreated
                User = $userSYS
                Id   = $eventSYS.Id
                Type = $type_lu[$eventSYS.Id]
                
            }
        }
    
        #write the results pulled.
        If($XMLSYSresults) {
            #puts out results as a HTML file
            $XMLSYSresults | Sort Time -Descending | ConvertTo-Html -head $Head -body $HTMLbodySYS | Set-Content $SYSresults
            }
    }
    
    
    #pull data from xml for system log
    If($SECevents) {
        $XMLSECresults = ForEach($eventSEC in $SECevents) {
            $xmlSEC = $eventSEC.ToXml()
            Switch -Regex ($eventSEC.Id) {
                '4...' {
                    $userSEC = (
                        Select-Xml -Content $xmlSEC -Namespace $ns -XPath $target_xpath
                    ).Node.'#text'
                    Break            
                }
                '7...' {
                    $SECsid = (
                        Select-Xml -Content $xmlSYS -Namespace $ns -XPath $usersid_xpath
                    ).Node.'#text'
                    #.translates needed to make usernames readable
                    $userSEC = (
                        New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList $SECsid
                    ).Translate([System.Security.Principal.NTAccount]).Value
                    Break
                }
            }
            New-Object -TypeName PSObject -Property @{
                Time = $eventSEC.TimeCreated
                User = $userSEC
                Id   = $eventSEC.Id
                Type = $type_lu[$eventSEC.Id]
                
            }
        }
    
        #write the results pulled.
        If($XMLSECresults) {
            #puts out results as a HTML file
            $XMLSECresults | Sort Time -Descending | ConvertTo-Html -head $Head -body $HTMLbodySEC | Set-Content $SECresults
            }
    }
    
    
    #success of fail test
    $TestSYSresults = Test-Path $SYSresults
    $TestSECresults = Test-Path $SECresults
    
    
    #open html file if the system was successful
        If ($TestSYSresults -eq $True)
            { 
                Write-Host "System logfile Success."
                Invoke-Item $SYSresults
            } 
                else 
            {
                Write-Host "Error - System logfile Failed"
            }
    #open html file if the security was successful
        If ($TestSECresults -eq $True)
            { 
                Write-Host "Security logfile Success."
                Invoke-Item $SECresults
            } 
                else 
            {
                Write-Host "Error - Security logfile Failed."
            }
    

    This is working great on old log files from my computer. I'm able to see the user's name and when they logged on and off.

    But when I use an eventlog file from another computer it doesn't pull the user's name from the system.evtx file? I need ideas for resolutions? I'm considering that log is from an older windows version? or is it a permissions issue I've overlooked? Thanks for all your help.

    • #74329

      Ivan
      Participant

      I hate being "that guy", but you have a typo in lines 152 and 163, it should read:

      Write-Host "System logfile will be created as none exists."
      

      Instead of:

      Write-Host "System logfile will be created as non exists."
      
    • #74332

      David Mower
      Participant

      No problem at all, thank you for the correction 🙂

  • #74417

    David Mower
    Participant
    
    
    
    #clear the screen
    cls
    
    
    #$Days = 1
    $SECevents = @()
    
    
    #get location of folder containing log files
    Function Select-FolderDialog
    {
        param([string]$Description="SELECT FOLDER CONTAINING SYSTEM.EVTX LOGFILE",[string]$RootFolder="MyComputer")
    
        [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
         Out-Null     
    
        $objForm = New-Object System.Windows.Forms.FolderBrowserDialog
        $objForm.Rootfolder  = $RootFolder
        $objForm.Description = $Description
        $Show = $objForm.ShowDialog()
            If ($Show -eq "OK")
            {
                Return $objForm.SelectedPath
            }
            Else
            {
                Write-Error "Operation cancelled by user."
            }
        
    }
    $Drive = Select-FolderDialog # the variable contains user folder selection
    
    
    
    #Security Log save dialog
    Function Get-SaveFileSEC
    {
        param([string]$Description="SELECT FOLDER TO SAVE SECURITY REPORT",[string]$initialDirectorySEC="MyComputer")
    
        [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
        Out-Null
    
        $SaveFileDialogSEC = New-Object System.Windows.Forms.SaveFileDialog
        $SaveFileDialogSEC.initialDirectory = $initialDirectorySEC
        $SaveFileDialogSEC.filter = "HTML Files (*.htm)|*.htm"
        $SaveFileDialogSEC.ShowDialog() | Out-Null
        $SaveFileDialogSEC.filename #= "SecurityLogsReport"
    } 
    $SECresults = Get-SaveFileSYS # the variable contains save file location
    
    
    
    #set HTML style for results
    $HTMLstyle = ""
    $HTMLstyle = $HTMLstyle + "BODY{background-color:peachpuff;}"
    $HTMLstyle = $HTMLstyle + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
    $HTMLstyle = $HTMLstyle + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:thistle}"
    $HTMLstyle = $HTMLstyle + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color:palegoldenrod}"
    $HTMLstyle = $HTMLstyle + ""
    $HTMLbodySYS = "System Log - Logon, Logoff, Lock and Unlock"
    $HTMLbodySEC = "Security Log - UAC and logon"
    $CSSStyle = @'
        
        ul {
         padding-left: 5px;
        }
        body { background-color:White;
        font-family:Tahoma;
         font-size:12pt;
        }
        td, th {border:1px solid black;} 
        th {
         color: black;
         background-color:peachpuff;
        }
        td { border-width: 1px;padding: 1px;border-style: solid;border-color: black; }
        TR:Hover TD { Background-Color: #C1D5F8; }
        table, tr, td, th { align:left; padding: 10px; margin: 0px; }
        table { width:75% }
        table { margin-left:0px; }
        
    '@
    $Head = $HTMLstyle + $CSSStyle
    
    
    Write-Host "Processing... Please wait ..."
    
    
    #pull lock and unlock from security log
    $SECevents  = Get-WinEvent -FilterHashtable @{ 
        Path		 = "$Drive\Security.evtx"
        Id=@(4624)
        #4672,4688,4800,4801,7036
    }
    
        #put numbers into meaningful words
        $type_lu = @{
            7001 = 'Service Start Operations'
            7002 = 'Service Start Operations'
            4800 = 'The workstation was locked'
            4801 = 'The workstation was unlocked'
            4688 = 'A new process has been created'
           20001 = 'Device Installation'
           20003 = 'Service Installation'
            7036 = 'Basic Service Operations'
            4672 = 'Special privileges assigned to new logon'
            4624 = 'An account was successfully logged on'
        }
    
    
    
    #xml paths
    $ns = @{'ns'='http://schemas.microsoft.com/win/2004/08/events/event'}
    $target_xpath = "//ns:Data[@Name='TargetUserName']"
    $usersid_xpath = "//ns:Data[@Name='UserSid']"
    
    
    #check if previous logfile exists
    $SECtestexists = Test-Path $SECresults
    
    
    #check if security log file exists and delete before running
         If ($SECtestexists -eq $True)
            { 
                Remove-Item $SECresults
                Write-Host "Previous Security logfile removed."
                
            } 
                else 
            {
                Write-Host "Security logfile will be created as none exists."
            }
    
    
    #pull data from xml for security log
    If($SECevents) {
        $XMLSECresults = ForEach($eventSEC in $SECevents) {
            $xmlSEC = $eventSEC.ToXml()
            Switch -Regex ($eventSEC.Id) {
                '4...' {
                    $userSEC = (
                        Select-Xml -Content $xmlSEC -Namespace $ns -XPath $target_xpath
                    ).Node.'#text'
                    Break            
                }
                '7...' {
                    $SECsid = (
                        Select-Xml -Content $xmlSEC -Namespace $ns -XPath $usersid_xpath
                    ).Node.'#text'
                    #.translates needed to make usernames readable
                    $userSEC = (
                        New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $SECsid
                    ).Translate([System.Security.Principal.NTAccount]).Value
                    Break
                }
            }
            New-Object -TypeName PSObject -Property @{
                Time = $eventSEC.TimeCreated
                User = $userSEC
                Id   = $eventSEC.Id
                Type = $type_lu[$eventSEC.Id]
            }
        }
    
        #write the results pulled.
        If($XMLSECresults) {
            #puts out results as a HTML file
            $XMLSECresults | Sort Time -Descending | ConvertTo-Html -head $Head -body $HTMLbodySEC | Set-Content $SECresults
            }
    }
    
    
    #success of fail test
    $TestSECresults = Test-Path $SECresults
    
    
    
    #open html file if the security was successful
        If ($TestSECresults -eq $True)
            { 
                Write-Host "Security logfile Success."
                Invoke-Item $SECresults
            } 
                else 
            {
                Write-Host "Error - Security logfile Failed."
            }
    

    This is my current version. What I'm trying to do now is filter the XML to only show certain 'LogOn Types'. don't want type 4 and type 5 included by the end.

    I've used event viewer and got this XML filter but I can't seem to work this in to my script. Would I filter the Select-XML and use a property? Help greatly appreciated

    #filter the xml data
    #
    #
    # *[System[(EventID=4624)]] and *[EventData[Data[@Name='LogonType'] and (Data=2 or Data=3 or Data=7 or Data=8 or Data=9 or Data=10 or Data=11)]]
    #
    #

You must be logged in to reply to this topic.