ArtifactRetrieval/UserAssist.ps1
|
function Get-CSUserAssist { <# .SYNOPSIS Retrieves and parses user assist entries. Author: Jesse Davis (@secabstraction) License: BSD 3-Clause .DESCRIPTION Get-CSUserAssist retrieves and parses user assist entry information stored in the registry. .PARAMETER CimSession Specifies the CIM session to use for this cmdlet. Enter a variable that contains the CIM session or a command that creates or gets the CIM session, such as the New-CimSession or Get-CimSession cmdlets. For more information, see about_CimSessions. .EXAMPLE Get-CSUserAssist .EXAMPLE Get-CSUserAssist -CimSession $CimSession .OUTPUTS CimSweep.UserAssistEntry Outputs objects consisting of relevant user assist information. Note: the LastExecutedTime of this object is a UTC datetime string in Round-trip format. #> [CmdletBinding()] [OutputType('CimSweep.UserAssistEntry')] param ( [Alias('Session')] [ValidateNotNullOrEmpty()] [Microsoft.Management.Infrastructure.CimSession[]] $CimSession ) begin { # If a CIM session is not provided, trick the function into thinking there is one. if (-not $PSBoundParameters['CimSession']) { $CimSession = '' $CIMSessionCount = 1 } else { $CIMSessionCount = $CimSession.Count } $CurrentCIMSession = 0 } process { foreach ($Session in $CimSession) { $ComputerName = $Session.ComputerName if (-not $Session.ComputerName) { $ComputerName = 'localhost' } # Display a progress activity for each CIM session Write-Progress -Id 1 -Activity 'CimSweep - UserAssist sweep' -Status "($($CurrentCIMSession+1)/$($CIMSessionCount)) Current computer: $ComputerName" -PercentComplete (($CurrentCIMSession / $CIMSessionCount) * 100) $CurrentCIMSession++ $CommonArgs = @{} if ($Session.Id) { $CommonArgs['CimSession'] = $Session } $UserSids = Get-HKUSID @CommonArgs foreach ($Sid in $UserSids) { $Parameters = @{ Hive = 'HKU' SubKey = "$Sid\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist" Recurse = $true } Get-CSRegistryKey @Parameters @CommonArgs | Where-Object { $_.SubKey -like "*Count" } | Get-CSRegistryValue @CommonArgs | ForEach-Object { # Decrypt Rot13 from https://github.com/StackCrash/PoshCiphers # truncated && streamlined algorithm a little $PlainCharList = New-Object Collections.Generic.List[char] foreach ($CipherChar in $_.ValueName.ToCharArray()) { switch ($CipherChar) { { $_ -ge 65 -and $_ -le 90 } { $PlainCharList.Add((((($_ - 65 - 13) % 26 + 26) % 26) + 65)) } # Uppercase characters { $_ -ge 97 -and $_ -le 122 } { $PlainCharList.Add((((($_ - 97 - 13) % 26 + 26) % 26) + 97)) } # Lowercase characters default { $PlainCharList.Add($CipherChar) } # Pass through symbols and numbers } } $ValueContent = $_.ValueContent # Parse LastExecutedTime from binary data $FileTime = switch ($ValueContent.Count) { 8 { [datetime]::FromFileTime(0) } 16 { [datetime]::FromFileTime([BitConverter]::ToInt64($ValueContent[8..15],0)) } default { [datetime]::FromFileTime([BitConverter]::ToInt64($ValueContent[60..67],0)) } } $ObjectProperties = [ordered] @{ PSTypeName = 'CimSweep.UserAssistEntry' Name = -join $PlainCharList UserSid = $Sid LastExecutedTime = $FileTime.ToUniversalTime().ToString('o') } if ($_.PSComputerName) { $ObjectProperties['PSComputerName'] = $_.PSComputerName } [PSCustomObject]$ObjectProperties } } } } end {} } Export-ModuleMember -Function Get-CSUserAssist |