Repository: p0w3rsh3ll/AutoRuns Branch: master Commit: da12c76bc51e Files: 8 Total size: 253.7 KB Directory structure: gitextract_vn2oso41/ ├── .github/ │ └── ISSUE_TEMPLATE/ │ ├── bug.yml │ └── config.yml ├── AutoRuns.cat ├── AutoRuns.psd1 ├── AutoRuns.psm1 ├── LICENSE ├── README.md └── Tests/ └── AutoRuns.Tests.ps1 ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/bug.yml ================================================ name: "🐞 Bug report" description: Report a reproducible bug with steps, expected behavior, and environment details. title: "[Bug]: title " labels: ["Bug", "Needs Triage"] assignees: "p0w3rsh3ll" body: - type: markdown attributes: value: | Please fill out the following template. - type: textarea id: steps attributes: label: Steps to reproduce description: Provide the exact steps to reproduce the issue. placeholder: | ```powershell # Add your reproduction steps here ``` render: powershell validations: required: false - type: textarea id: expected attributes: label: Expected behavior description: What did you expect to happen? A concise description of what you expected to happen. placeholder: | ```none ``` render: text validations: required: false - type: textarea id: actual attributes: label: Current behavior description: What actually happened? A concise description of what you're experiencing. placeholder: | ```none ``` render: text validations: required: false - type: textarea id: environment attributes: label: Environment data description: Provide the output of `$PSVersionTable`. placeholder: | ```powershell > $PSVersionTable ``` render: powershell validations: required: false - type: textarea attributes: label: Anything else? description: | Links? References? Anything that will give us more context about the issue you are encountering! Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. validations: required: false ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false ================================================ FILE: AutoRuns.psd1 ================================================ @{ # Script module or binary module file associated with this manifest. RootModule = 'AutoRuns.psm1' # Version number of this module. ModuleVersion = '14.0.2' # ID used to uniquely identify this module GUID = '5df29b51-5627-43f6-bcae-a07a62887a2f' # Author of this module Author = 'Emin Atac' # Copyright statement for this module Copyright = 'BSD 3-Clause' # Description of the functionality provided by this module Description = 'AutoRuns is a module that will help do live incident response and enumerate autoruns artifacts that may be used by legitimate programs as well as malware to achieve persistence' # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '4.0' # Minimum version of Microsoft .NET Framework required by this module # DotNetFrameworkVersion = '4.0' # Minimum version of the common language runtime (CLR) required by this module # CLRVersion = '4.0' # Functions to export from this module FunctionsToExport = @('Get-PSAutorun','New-AutoRunsBaseLine','Compare-AutoRunsBaseLine') # FunctionsToExport = '*' PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. Tags = @('security','defense','PSEdition_Core','PSEdition_Desktop') # A URL to the license for this module. LicenseUri = 'https://opensource.org/licenses/BSD-3-Clause' # A URL to the main website for this project. ProjectUri = 'https://github.com/p0w3rsh3ll/AutoRuns' } # End of PSData hashtable } # End of PrivateData hashtable } ================================================ FILE: AutoRuns.psm1 ================================================ #Requires -Version 4.0 Function Get-PSAutorun { <# .SYNOPSIS Get Autorun entries. .DESCRIPTION Retrieve a list of programs configured to autostart at boot or logon. .PARAMETER All Switch to gather artifacts from all categories. If it's turned on, all other category switches will be ignored. .PARAMETER BootExecute Switch to gather artifacts from the Boot Execute category. .PARAMETER AppinitDLLs Switch to gather artifacts from the Appinit category. .PARAMETER ExplorerAddons Switch to gather artifacts from the Explorer category. .PARAMETER ImageHijacks Switch to gather artifacts from the Image Hijacks category. .PARAMETER InternetExplorerAddons Switch to gather artifacts from the Intenet Explorer category. .PARAMETER KnownDLLs Switch to gather artifacts from the KnownDLLs category. .PARAMETER Logon Switch to gather artifacts from the Logon category. .PARAMETER Winsock Switch to gather artifacts from the Winsock and network providers category. .PARAMETER Codecs Switch to gather artifacts from the Codecs category. .PARAMETER OfficeAddins Switch to gather artifacts from Office Addins .PARAMETER PrintMonitorDLLs Switch to gather artifacts from the Print Monitors category. .PARAMETER LSAsecurityProviders Switch to gather artifacts from the LSA Providers category. .PARAMETER ServicesAndDrivers Switch to gather artifacts from the Services and Drivers categories. .PARAMETER ScheduledTasks Switch to gather artifacts from the Scheduled tasks category. .PARAMETER Winlogon Switch to gather artifacts from the Winlogon category. .PARAMETER WMI Switch to gather artifacts from the WMI category. .PARAMETER PSProfiles Switch to gather artifacts from the PowerShell profiles category. .PARAMETER ShowFileHash Switch to enable and display MD5, SHA1 and SHA2 file hashes. .PARAMETER VerifyDigitalSignature Switch to report if a file is digitally signed with the built-in Get-AuthenticodeSignature cmdlet. .EXAMPLE Get-PSAutorun -BootExecute -AppinitDLLs .EXAMPLE Get-PSAutorun -KnownDLLs -LSAsecurityProviders -ShowFileHash .EXAMPLE Get-PSAutorun -All -ShowFileHash -VerifyDigitalSignature .EXAMPLE Get-PSAutorun -All -User * -ShowFileHash -VerifyDigitalSignature .NOTES DYNAMIC PARAMETER User Specify what user hive to be scanned. Scans by default HKCU when the parameter isn't explicitly used. '*' can be used to indicate that all loaded user hives will be scanned. #> [CmdletBinding(DefaultParameterSetName='Pretty')] Param( [switch]$All, [Switch]$BootExecute, [Switch]$AppinitDLLs, [Switch]$ExplorerAddons, [Switch]$ImageHijacks, [Switch]$InternetExplorerAddons, [Switch]$KnownDLLs, [Switch]$Logon, [Switch]$Winsock, [Switch]$Codecs, [Switch]$OfficeAddins, [Switch]$PrintMonitorDLLs, [Switch]$LSAsecurityProviders, [Switch]$ServicesAndDrivers, [Switch]$ScheduledTasks, [Switch]$Winlogon, [Switch]$WMI, [Switch]$PSProfiles, [Parameter(ParameterSetName='Plain')] [Switch]$Raw, [Parameter(ParameterSetName='Pretty')] [Switch]$ShowFileHash, [Parameter(ParameterSetName='Pretty')] [Switch]$VerifyDigitalSignature ) DynamicParam { Function Test-isValidSid { [CmdletBinding()] [OutputType([System.Boolean])] Param( [Parameter(Mandatory,ValueFromPipeline)] [string]$SID ) Begin {} Process { try { $null = [System.Security.Principal.SecurityIdentifier]$SID $true } catch { $false } } End {} } Function Get-UserNameFromSID { [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeline)] [ValidateScript({ $_ | Test-isValidSid})] [string]$SID ) Begin {} Process { try { ([System.Security.Principal.SecurityIdentifier]$SID).Translate( [System.Security.Principal.NTAccount] ).Value } catch { Write-Warning -Message "Cannot translate SID to UserName for $($SID)" } } End {} } $Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $AttribColl1 = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $Param1Att = New-Object System.Management.Automation.ParameterAttribute $Param1Att.Mandatory = $false $AttribColl1.Add($Param1Att) try { If (-not(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) { $null = New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS -ErrorAction SilentlyContinue } $allUsers = (Get-Item -Path 'HKU:' -ErrorAction SilentlyContinue).GetSubKeyNames() | ForEach-Object -Process { if ($_ | Test-isValidSid) { $_ | Get-UserNameFromSID } } -End {'*'} } catch { Throw 'Unable list available users' } if ($allUsers) { $AttribColl1.Add((New-Object System.Management.Automation.ValidateSetAttribute($allUsers))) $Dictionary.Add('User',(New-Object System.Management.Automation.RuntimeDefinedParameter('User', [string], $AttribColl1))) $Dictionary } } Begin { #region Dynamic parameter users: $Users = New-Object -TypeName System.Collections.ArrayList (Get-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' -ErrorAction SilentlyContinue).GetSubKeyNames() | ForEach-Object -Process { if ($_ | Test-isValidSid) { $_ | Get-UserNameFromSID } } | ForEach-Object { $n = $_ $sid = ([System.Security.Principal.NTAccount]$n).Translate([System.Security.Principal.SecurityIdentifier]).Value $null = $Users.Add( @{ UserName = $_ SID = $sid Hive = "HKU:\$($sid)" ProfilePath = $( try { (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$($sid)" -Name 'ProfileImagePath' -ErrorAction Stop ).'ProfileImagePath' -replace '%(s|S)(y|Y)(s|S)(t|T)(e|E)(m|M)(r|R)(o|O)(o|O)(t|T)%','C:\Windows' } catch { Write-Error 'Failed to get the profilepath' } ) } ) } $allUsers = $Users if ($PSBoundParameters.ContainsKey('User')) { if ($PSBoundParameters['User'] -eq '*') { $Users = $Users } else { $Users = $Users | Where-Object { $_['UserName'] -eq "$($PSBoundParameters['User'])" } } } else { $Users = $Users | Where-Object { $_['UserName'] -eq $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) } $Users['Hive'] = 'HKCU:' } #endregion #region Helperfunctions Function Get-RegValue { [CmdletBinding()] Param( [string]$Path, [string[]]$Name, [string]$Category ) Begin{ if ($Path -match 'Wow6432Node') { $cp = 'SOFTWARE\Wow6432Node\Classes\CLSID' } else { $cp = 'SOFTWARE\Classes\CLSID' } if ($Path -match '^HKCU:\\') { $ClassesPath = Join-Path -Path (Split-Path $Path -Qualifier) -ChildPath $cp } else { $ClassesPath = Join-Path -Path ((($Path -split '\\',3)[0..1]) -join '\' ) -ChildPath $cp } Write-Verbose -Message "Classes path set to $($ClassesPath)" } Process { try { $Values = Get-Item -LiteralPath $Path -ErrorAction Stop if ($Name -eq '*') { $Name = $Values.GetValueNames() } $Name | ForEach-Object -Process { # Need to differentiate between empty string and really non existing values if ($null -ne $Values.GetValue($_)) { $Value = Switch -regex($Values.GetValue($_)) { '^\{[A-Z0-9]{4}([A-Z0-9]{4}-){4}[A-Z0-9]{12}\}$' { (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' break } default { $_ } } if ($Value) { [pscustomobject]@{ Path = $Path Item = $_ Value = $Value Category = $Category } } } } } catch { } } End {} } Function Get-AllScheduledTask { [CmdletBinding()] Param ( [Parameter(Mandatory=$false,ValueFromPipeline=$true)] [System.String[]]$ComputerName = $env:COMPUTERNAME ) Begin { Function Get-SubFolder ($folder,[switch]$recurse) { $folder if ($recurse) { $TaskService.GetFolder($folder).GetFolders(0) | ForEach-Object { Get-SubFolder $_.Path -Recurse } } else { $TaskService.GetFolder($folder).GetFolders(0) } } } Process { $ComputerName | ForEach-Object -Process { $alltasks = @() $Computer = $_ $TaskService = New-Object -com schedule.service try { $null = $TaskService.Connect($Computer) } catch { Write-Warning "Cannot connect to $Computer because $($_.Exception.Message)" return } Get-SubFolder -folder '\' -recurse | ForEach-Object -Process { $TaskService.GetFolder($_).GetTasks(1) | ForEach-Object -Process { $obj = New-Object -TypeName pscustomobject -Property @{ ComputerName = $Computer Path = Split-Path $_.Path Name = $_.Name } $alltasks += $obj } } Write-Verbose -Message "There's a total of $($alltasks.Count) tasks on $Computer" $alltasks } } End {} } Function Get-Task { [CmdletBinding()] [OutputType('System.Object[]')] param ( [parameter(ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true,Mandatory=$false)] [system.string[]] ${ComputerName} = $env:computername, [parameter(ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true,Mandatory=$false, HelpMessage="The task folder string must begin by '\'")] [ValidatePattern('^\\')] [system.string[]] ${Path} = '\', [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [ValidateNotNullOrEmpty()] [system.string[]] ${Name} = $null ) Begin {} Process { $resultsar = @() $ComputerName | ForEach-Object -Process { $Computer = $_ $TaskService = New-Object -com schedule.service try { $null = $TaskService.Connect($Computer) } catch { Write-Warning "Failed to connect to $Computer" } if ($TaskService.Connected) { Write-Verbose -Message "Connected to the scheduler service of computer $Computer" Foreach ($Folder in $Path) { Write-Verbose -Message "Dealing with folder task $Folder" $RootFolder = $null try { $RootFolder = $TaskService.GetFolder($Folder) } catch { Write-Warning -Message "The folder task $Folder cannot be found" } if ($RootFolder) { Foreach ($Task in $Name) { $TaskObject = $null try { Write-Verbose -Message "Dealing with task name $Task" $TaskObject = $RootFolder.GetTask($Task) } catch { Write-Warning -Message "The task $Task cannot be found under $Folder" } if ($TaskObject) { # Status # http://msdn.microsoft.com/en-us/library/windows/desktop/aa383617%28v=vs.85%29.aspx switch ($TaskObject.State) { 0 { $State = 'Unknown' ; break} 1 { $State = 'Disabled' ; break} 2 { $State = 'Queued' ; break} 3 { $State = 'Ready' ; break} 4 { $State = 'Running' ; break} default {$State = $_ } } $resultsar += New-Object -TypeName pscustomobject -Property @{ ComputerName = $Computer Name = $TaskObject.Name Path = $Folder State = $State Enabled = $TaskObject.Enabled Xml = $TaskObject.XML } } } } } } } $resultsar } End {} } # From David Wyatt # http://gallery.technet.microsoft.com/scriptcenter/Normalize-file-system-5d33985a Function Get-NormalizedFileSystemPath { <# .Synopsis Normalizes file system paths. .DESCRIPTION Normalizes file system paths. This is similar to what the Resolve-Path cmdlet does, except Get-NormalizedFileSystemPath also properly handles UNC paths and converts 8.3 short names to long paths. .PARAMETER Path The path or paths to be normalized. .PARAMETER IncludeProviderPrefix If this switch is passed, normalized paths will be prefixed with 'FileSystem::'. This allows them to be reliably passed to cmdlets such as Get-Content, Get-Item, etc, regardless of Powershell's current location. .EXAMPLE Get-NormalizedFileSystemPath -Path '\\server\share\.\SomeFolder\..\SomeOtherFolder\File.txt' Returns '\\server\share\SomeOtherFolder\File.txt' .EXAMPLE '\\server\c$\.\SomeFolder\..\PROGRA~1' | Get-NormalizedFileSystemPath -IncludeProviderPrefix Assuming you can access the c$ share on \\server, and PROGRA~1 is the short name for "Program Files" (which is common), returns: 'FileSystem::\\server\c$\Program Files' .INPUTS String .OUTPUTS String .NOTES Paths passed to this command cannot contain wildcards; these will be treated as invalid characters by the .NET Framework classes which do the work of validating and normalizing the path. .LINK Resolve-Path #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias('PSPath', 'FullName')] [string[]] $Path, [switch] $IncludeProviderPrefix ) Process{ foreach ($_path in $Path) { $_resolved = $_path if ($_resolved -match '^([^:]+)::') { $providerName = $matches[1] if ($providerName -ne 'FileSystem') { Write-Error "Only FileSystem paths may be passed to Get-NormalizedFileSystemPath. Value '$_path' is for provider '$providerName'." continue } $_resolved = $_resolved.Substring($matches[0].Length) } if (-not [System.IO.Path]::IsPathRooted($_resolved)) { $_resolved = Join-Path -Path $PSCmdlet.SessionState.Path.CurrentFileSystemLocation -ChildPath $_resolved } try { $dirInfo = New-Object System.IO.DirectoryInfo($_resolved) } catch { $exception = $_.Exception while ($null -ne $exception.InnerException) { $exception = $exception.InnerException } Write-Error "Value '$_path' could not be parsed as a FileSystem path: $($exception.Message)" continue } $_resolved = $dirInfo.FullName if ($IncludeProviderPrefix) { $_resolved = "FileSystem::$_resolved" } Write-Output $_resolved } } } Function Get-PSRawAutoRun { [CmdletBinding()] Param( [switch]$All, [Switch]$BootExecute, [Switch]$AppinitDLLs, [Switch]$ExplorerAddons, [Switch]$ImageHijacks, [Switch]$InternetExplorerAddons, [Switch]$KnownDLLs, [Switch]$Logon, [Switch]$Winsock, [Switch]$Codecs, [Switch]$OfficeAddins, [Switch]$PrintMonitorDLLs, [Switch]$LSAsecurityProviders, [Switch]$ServicesAndDrivers, [Switch]$ScheduledTasks, [Switch]$Winlogon, [Switch]$WMI, [Switch]$PSProfiles, [Switch]$ShowFileHash, [Switch]$VerifyDigitalSignature, [Switch]$Raw, [PSObject]$User=$Users ) Begin { ## Add 'All' if nothing else was supplied $parametersToIgnore = ('ShowFileHash','VerifyDigitalSignature','User','Raw') + [System.Management.Automation.PSCmdlet]::CommonParameters + [System.Management.Automation.PSCmdlet]::OptionalCommonParameters if(($PSBoundParameters.Keys | Where-Object { $_ -notin $parametersToIgnore }).Count -eq 0) { $All = [switch]::Present } } Process { if ($All -or $BootExecute) { Write-Verbose -Message 'Looking for Boot Execute entries' #region Boot Execute $Category = @{ Category = 'Boot Execute'} # REG_MULTI_SZ 'BootExecute','SetupExecute','Execute','S0InitialCommand' | ForEach-Object { $item = $_ $v = $null $v = (Get-RegValue -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager' -Name $_ @Category) if ($v) { $v.Value | ForEach-Object { if ($_ -ne '""') { [pscustomobject]@{ Path = 'HKLM:\System\CurrentControlSet\Control\Session Manager' Item = $item Value = $_ Category = 'Boot Execute' } } } } } #endregion Boot Execute } if ($All -or $AppinitDLLs) { Write-Verbose -Message 'Looking for Appinit DLLs entries' #region AppInit $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows NT\CurrentVersion\Windows" -Name 'Appinit_Dlls' -Category 'AppInit' } if (Test-Path -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\AppCertDlls' -PathType Container) { Get-RegValue -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\AppCertDlls' -Name '*' -Category 'AppInit' } #endregion AppInit } if ($All -or $ExplorerAddons) { Write-Verbose -Message 'Looking for Explorer Add-ons entries' #region Explorer $Category = @{ Category = 'Explorer'} # Filter & Handler 'Filter','Handler' | ForEach-Object -Process { $key = "HKLM:\SOFTWARE\Classes\Protocols\$($_)" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { if ($_ -eq 'ms-help') { # if ([environment]::Is64BitOperatingSystem) { # $ClassesPath = 'HKLM:\SOFTWARE\Wow6432Node\Classes\CLSID' # } else { # $ClassesPath = 'HKLM:\SOFTWARE\Classes\CLSID' # } $i = (Get-ItemProperty -Path "$key\ms-help" -Name 'CLSID').CLSID [pscustomobject]@{ Path = "$key\ms-help" Item = $i Value = $( (Get-ItemProperty -Path (Join-Path -Path 'HKLM:\SOFTWARE\Wow6432Node\Classes\CLSID' -ChildPath "$($i)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)'; (Get-ItemProperty -Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($i)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)'; ) | Where-Object { $null -ne $_ } | Sort-Object -Unique Category = 'Explorer' } } else { Get-RegValue -Path "$key\$($_)" -Name 'CLSID' @Category } } } } # SharedTaskScheduler $null,'Wow6432Node' | Foreach-Object -Process { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\Explorer\SharedTaskScheduler" -Name '*' @Category } # ShellServiceObjects $null,'Wow6432Node' | Foreach-Object -Process { $ClassesPath = "HKLM:\SOFTWARE\$($_)\Classes\CLSID" $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\Explorer\ShellServiceObjects" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = $( try { (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction Stop).'(default)' } catch { $null } ) Category = 'Explorer' } } } # ShellExecuteHooks $null,'Wow6432Node' | Foreach-Object -Process { $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks" if (Test-Path -Path $key -PathType Container) { $ClassesPath = "HKLM:\SOFTWARE\$($_)\Classes\CLSID" (Get-Item -Path $key).GetValueNames() | ForEach-Object { # Get-RegValue -Path $key -Name $_ @Category [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)').'(default)' Category = 'Explorer' } } } } # ShellServiceObjectDelayLoad $null,'Wow6432Node' | Foreach-Object -Process { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad" -Name '*' @Category } # Handlers @( @{Name = '*' ; Properties = @('ContextMenuHandlers','PropertySheetHandlers')}, @{Name ='Drive' ; Properties = @('ContextMenuHandlers')}, @{Name ='AllFileSystemObjects' ; Properties = @('ContextMenuHandlers','DragDropHandlers','PropertySheetHandlers')}, @{Name ='Directory' ; Properties = @('ContextMenuHandlers','DragDropHandlers','PropertySheetHandlers', 'CopyHookHandlers')}, @{Name ='Directory\Background' ; Properties = @('ContextMenuHandlers')}, @{Name ='Folder' ; Properties = @('ColumnHandlers','ContextMenuHandlers','DragDropHandlers','ExtShellFolderViews','PropertySheetHandlers')} ) | ForEach-Object -Process { $Name = $_.Name $Properties = $_.Properties $null,'Wow6432Node' | Foreach-Object -Process { $key = "HKLM:\Software\$($_)\Classes\$Name\ShellEx" $ClassPath = "HKLM:\Software\$($_)\Classes\CLSID" $Hive = $_ $Properties | ForEach-Object -Process { $subkey = Join-Path -Path $key -ChildPath $_ try { (Get-Item -LiteralPath $subkey -ErrorAction SilentlyContinue).GetSubKeyNames() | ForEach-Object -Process { if ($(try { [system.guid]::Parse($_) | Out-Null $true } catch { $false })) { if (Test-Path -Path (Join-Path -Path $ClassPath -ChildPath "$($_)\InprocServer32") -PathType Container) { # don't change anything } else { if ($Hive) { $ClassPath = 'HKLM:\Software\Classes\CLSID' } else { $ClassPath = 'HKLM:\Software\Wow6432Node\Classes\CLSID' } } if (Test-PAth -Path (Join-Path -Path $ClassPath -ChildPath "$($_)\InprocServer32") -PathType Container) { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassPath -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' Category = 'Explorer' } } } else { Get-RegValue -Path "$subkey\$($_)" -Name '*' @Category } } } catch { } } } } # ShellIconOverlayIdentifiers $null,'Wow6432Node' | Foreach-Object -Process { $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name '*' @Category } } } # LangBarAddin $null,'Wow6432Node' | Foreach-Object -Process { Get-RegValue -Path "HKLM:\Software\$($_)\Microsoft\Ctf\LangBarAddin" -Name '*' @Category } #endregion Explorer #region User Explorer $Users | ForEach-Object { $Hive = $_['Hive'] # Filter & Handler 'Filter','Handler' | ForEach-Object -Process { $key = "$($Hive)\SOFTWARE\Classes\Protocols\$($_)" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'CLSID' @Category } } } if (Test-Path -Path "$($Hive)\SOFTWARE\Microsoft\Internet Explorer\Desktop\Components" -PathType Container) { $key = "$($Hive)\SOFTWARE\Microsoft\Internet Explorer\Desktop\Components" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'Source' @Category } } # ShellServiceObjects if (Test-Path -Path "$($Hive)\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellServiceObjects" -PathType Container) { $ClassesPath = "$($Hive)\SOFTWARE\$($_)\Classes\CLSID" $key = "$($Hive)\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellServiceObjects" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)').'(default)' Category = 'Explorer' } } } # ShellServiceObjectDelayLoad Get-RegValue -Path "$($Hive)\SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad" -Name '*' @Category # Handlers @( @{Name = '*' ; Properties = @('ContextMenuHandlers','PropertySheetHandlers')}, @{Name ='Drive' ; Properties = @('ContextMenuHandlers')}, @{Name ='AllFileSystemObjects' ; Properties = @('ContextMenuHandlers','DragDropHandlers','PropertySheetHandlers')}, @{Name ='Directory' ; Properties = @('ContextMenuHandlers','DragDropHandlers','PropertySheetHandlers', 'CopyHookHandlers')}, @{Name ='Directory\Background' ; Properties = @('ContextMenuHandlers')}, @{Name ='Folder' ; Properties = @('ColumnHandlers','ContextMenuHandlers','DragDropHandlers','ExtShellFolderViews','PropertySheetHandlers')} ) | ForEach-Object -Process { $Name = $_.Name $Properties = $_.Properties $key = "$($Hive)\Software\Classes\$Name\ShellEx" $Properties | ForEach-Object -Process { $subkey = Join-Path -Path $key -ChildPath $_ try { (Get-Item -LiteralPath $subkey -ErrorAction SilentlyContinue).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path $subkey\$($_) -Name '*' @Category } } catch { } } } # ShellIconOverlayIdentifiers $key = "$($Hive)\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name '*' @Category } } # LangBarAddin Get-RegValue -Path "$($Hive)\Software\Microsoft\Ctf\LangBarAddin" -Name '*' @Category # NEW! POWELIKS use of Window's thumbnail cache if (Test-Path -Path "$($Hive)\Software\Classes\Clsid\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}") { Write-Warning -Message 'Infected by PoweLiks malware' # Step1: restore read access try { $ParentACL = Get-Acl -Path "$($Hive)\Software\Classes\Clsid" # !!! Adapt here current user !!! $k = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software\Classes\Clsid\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}','ReadWriteSubTree','TakeOwnership') $acl = $k.GetAccessControl() $acl.SetAccessRuleProtection($false,$true) $rule = New-Object System.Security.AccessControl.RegistryAccessRule ($ParentACL.Owner,'FullControl','Allow') $acl.SetAccessRule($rule) $k.SetAccessControl($acl) Write-Verbose -Message "Successuflly restored read access for $($ParentACL.Owner) on registry key" } catch { Write-Warning -Message "Failed to restore read access for $($ParentACL.Owner) on registry key" } # Step2: read the content of subkeys 'Inprocserver32','localserver32' | ForEach-Object { try { (Get-ItemProperty -Path "$($Hive)\Software\Classes\Clsid\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}\$($_)" -Name '(default)' -ErrorAction Stop).'(default)' } catch { } } } } #endregion User Explorer } if ($All -or $ImageHijacks) { Write-Verbose -Message 'Looking for Image hijacks' #region Image Hijacks $Category = @{ Category = 'Image Hijacks'} $null,'Wow6432Node' | Foreach-Object { $key = "HKLM:\Software\$($_)\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'Debugger' @Category if ((Get-ItemProperty -Path "$key\$($_)" -Name 'GlobalFlag' -ErrorAction SilentlyContinue).'GlobalFlag' -eq 512) { Get-RegValue -Path "$($key -replace 'Image\sFile\sExecution\sOptions','SilentProcessExit')\$($_)" -Name 'MonitorProcess' @Category } } } # Autorun macro $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\Software\$($_)\Microsoft\Command Processor" -Name 'Autorun' @Category } # Exefile [pscustomobject]@{ Path = 'HKLM:\SOFTWARE\Classes\Exefile\Shell\Open\Command' Item = 'exefile' Value = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Classes\Exefile\Shell\Open\Command' -Name '(default)').'(default)' Category = 'Image Hijacks' } '.exe','.cmd' | Foreach-Object { $assoc = (Get-ItemProperty -Path "HKLM:\Software\Classes\$($_)" -Name '(default)').'(default)' [pscustomobject]@{ Path = "HKLM:\Software\Classes\$assoc\shell\open\command" Item = $_ Value = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\$assoc\Shell\Open\Command" -Name '(default)').'(default)' Category = 'Image Hijacks' } } # Htmlfile [pscustomobject]@{ Path = 'HKLM:\SOFTWARE\Classes\htmlfile\shell\open\command' Item = 'htmlfile' Value = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Classes\htmlfile\shell\open\command' -Name '(default)').'(default)' Category = 'Image Hijacks' } #endregion Image Hijacks #region User Image Hijacks $Users | ForEach-Object { $Hive = $_['Hive'] Get-RegValue -Path "$($Hive)\Software\Microsoft\Command Processor" -Name 'Autorun' @Category # Exefile if (Test-Path -Path "$($Hive)\SOFTWARE\Classes\Exefile\Shell\Open\Command") { [pscustomobject]@{ Path = "$($Hive)\SOFTWARE\Classes\Exefile\Shell\Open\Command" Item = 'exefile' Value = (Get-ItemProperty -Path "$($Hive)\SOFTWARE\Classes\Exefile\Shell\Open\Command" -Name '(default)').'(default)' Category = 'Image Hijacks' } } '.exe','.cmd' | Foreach-Object { if (Test-Path -Path "$($Hive)\Software\Classes\$($_)") { $assoc = (Get-ItemProperty -Path "$($Hive)\Software\Classes\$($_)" -Name '(default)'-ErrorAction SilentlyContinue).'(default)' if ($assoc) { [pscustomobject]@{ Path = "$($Hive)\Software\Classes\$assoc\shell\open\command" Item = $_ Value = (Get-ItemProperty -Path "$($Hive)\SOFTWARE\Classes\$assoc\Shell\Open\Command" -Name '(default)' -ErrorAction SilentlyContinue).'(default)' Category = 'Image Hijacks' } } } } # Htmlfile if (Test-Path -Path "$($Hive)\SOFTWARE\Classes\htmlfile\shell\open\command") { [pscustomobject]@{ Path = "$($Hive)\SOFTWARE\Classes\htmlfile\shell\open\command" Item = 'htmlfile' Value = (Get-ItemProperty -Path "$($Hive)\SOFTWARE\Classes\htmlfile\shell\open\command" -Name '(default)').'(default)' Category = 'Image Hijacks' } } } #endregion User Image Hijacks } if ($All -or $InternetExplorerAddons) { Write-Verbose -Message 'Looking for Internet Explorer Add-ons entries' #region Internet Explorer $Category = @{ Category = 'Internet Explorer'} # Browser Helper Objects $null,'Wow6432Node' | Foreach-Object { $ClassesPath = "HKLM:\SOFTWARE\$($_)\Classes\CLSID" $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)').'(default)' Category = 'Internet Explorer' } } } } # IE Toolbars $null,'Wow6432Node' | Foreach-Object -Process { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Internet Explorer\Toolbar" -Name '*' @Category } # Explorer Bars $null,'Wow6432Node' | Foreach-Object -Process { $ClassesPath = "HKLM:\SOFTWARE\$($_)\Classes\CLSID" $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Internet Explorer\Explorer Bars" try { (Get-Item -Path $key -ErrorAction Stop).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)').'(default)' Category = 'Internet Explorer' } } } catch { } } # IE Extensions $null,'Wow6432Node' | Foreach-Object { $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Internet Explorer\Extensions" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key -ErrorAction SilentlyContinue).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'ClsidExtension' @Category } } } #endregion Internet Explorer #region User Internet Explorer $Users | ForEach-Object { $Hive = $_['Hive'] # UrlSearchHooks $ClassesPath = 'HKLM:\SOFTWARE\Classes\CLSID' $key = "$($Hive)\Software\Microsoft\Internet Explorer\UrlSearchHooks" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetValueNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)').'(default)' Category = 'Internet Explorer' } } } # Explorer Bars $null,'Wow6432Node' | Foreach-Object -Process { $ClassesPath = "HKLM:\SOFTWARE\$($_)\Classes\CLSID" $key = "$($Hive)\SOFTWARE\$($_)\Microsoft\Internet Explorer\Explorer Bars" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $ClassesPath -ChildPath "$($_)\InprocServer32") -Name '(default)').'(default)' Category = 'Internet Explorer' } } } } # IE Extensions $null,'Wow6432Node' | Foreach-Object { $key = "$($Hive)\SOFTWARE\$($_)\Microsoft\Internet Explorer\Extensions" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key -ErrorAction SilentlyContinue).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'ClsidExtension' @Category } } } } #endregion User Internet Explorer } if ($All -or $KnownDLLs) { Write-Verbose -Message 'Looking for Known DLLs entries' #region Known Dlls Get-RegValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs' -Name '*' -Category 'Known Dlls' #endregion Known Dlls } if ($All -or $Logon) { Write-Verbose -Message 'Looking for Logon Startup entries' #region Logon $Category = @{ Category = 'Logon'} # Winlogon Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'VmApplet','Userinit','Shell','TaskMan','AppSetup' @Category # UserInitMprLogonScript if (Test-Path -Path 'HKLM:\Environment' -PathType Container) { Get-RegValue -Path 'HKLM:\Environment' -Name 'UserInitMprLogonScript' @Category } # GPExtensions $key = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions' if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { try { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $key -ChildPath $_) -Name 'DllName' -ErrorAction Stop).'DllName' Category = 'Logon' } } catch {} } } # Domain Group Policies scripts 'Startup','Shutdown','Logon','Logoff' | ForEach-Object -Process { $key = "HKLM:\Software\Policies\Microsoft\Windows\System\Scripts\$($_)" if (Test-Path -Path $key) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { $subkey = (Join-Path -Path $key -ChildPath $_) (Get-Item -Path $subkey).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path (Join-Path -Path $subkey -ChildPath $_) -Name 'script' @Category } } } } # Local GPO scripts 'Startup','Shutdown','Logon','Logoff' | ForEach-Object -Process { $t = $_ $key = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\$($_)" if (Test-Path -Path $key) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { $subkey = (Join-Path -Path $key -ChildPath $_) $gn = (Get-ItemProperty -Path $subkey -Name GPOName -ErrorAction SilentlyContinue).'GPOName' (Get-Item -Path $subkey).GetSubKeyNames() | ForEach-Object -Process { if ($gn -match '^{[A-F0-9-]+}') { $ds = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\Machine' $ab = (Get-ItemProperty -Path "$($ds)" -Name CurrentActiveBit -ErrorAction SilentlyContinue).'CurrentActiveBit' $dn = (Get-ItemProperty -Path "$($ds)\$($ab)" -Name DomainName).'DomainName' $p = "C:\Windows\system32\GroupPolicy\DataStore\$($ab)\SysVol\$($dn)\Policies\$($gn)\Machine\Scripts\$($t)" } else { $p = Join-Path -Path "$((Get-ItemProperty -Path $subkey -Name FileSysPath -ErrorAction SilentlyContinue).FileSysPath)" -ChildPath "Scripts\$($t)" } try { [pscustomobject]@{ Path = Join-Path -Path $subkey -ChildPath $_ Item = 'Script' Value = Join-Path -Path $p -ChildPath "$((Get-ItemProperty -Path (Join-Path -Path $subkey -ChildPath $_) -Name 'Script' -ErrorAction Stop).'Script')" Category = 'Logon' } } catch {} } } } } # Shell override by GPO Get-RegValue -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'Shell' @Category # AlternateShell Get-RegValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SafeBoot' -Name 'AlternateShell' @Category # AvailableShells Get-RegValue -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\AlternateShells' -Name 'AvailableShells' @Category # Terminal server # Removed from 13.82 but key/value still exist > restored as of 13.90 Get-RegValue -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\Wds\rdpwd' -Name 'StartupPrograms' @Category # Restored as of 13.90 Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Runonce' -Name '*' @Category Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx' -Name '*' @Category $key = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx' if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name '*' @Category if (Test-Path -Path "$key\$($_)\Depend" -PathType Container) { Get-RegValue -Path "$key\$($_)\Depend" -Name '*' @Category } } } Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run' -Name '*' @Category Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Software\Microsoft\Windows\CurrentVersion\Run' -Name '*' @Category # Removed from 13.82 but key/value still exist > restored in 13.90 Get-RegValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name 'InitialProgram' @Category # Run $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\Run" -Name '*' @Category } # RunOnce $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\RunOnce" -Name '*' @Category } # RunOnceEx $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\RunOnceEx" -Name '*' @Category } $null,'Wow6432Node' | Foreach-Object { $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\RunOnceEx" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name '*' @Category if (Test-Path -Path "$key\$($_)\Depend" -PathType Container) { Get-RegValue -Path "$key\$($_)\Depend" -Name '*' @Category } } } } if ($PSVersionTable.PSEdition -ne 'Core') { $HT = @{ Encoding = 'Byte' } } else { $HT = @{ AsByteStream = [switch]::Present } } # HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders # TODO: iterate on 'Common Startup','Common AltStartup' # Read first 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Common Startup' and follow the value # LNK files or direct executable 'Common Startup','Common AltStartup' | ForEach-Object -Begin { $key = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" } -Process { $n = $PSItem if (Test-Path -Path $key -PathType Container) { # Show what the Startup value contains (could be a file) Get-RegValue -Path $key -Name $PSItem @Category $USF = $null # If it's a folder, explore its content $USF = (Get-ItemProperty -Path $key -Name $PSItem -ErrorAction SilentlyContinue)."$($PSItem)" if ($USF) { if (Test-Path -Path "$($USF)") { $Wsh = New-Object -ComObject 'WScript.Shell' Get-ChildItem -Path "$($USF)" -Force -Exclude 'desktop.ini' | ForEach-Object { $File = $_ if ($File -is [System.IO.FileInfo]) { $header = (Get-Content -Path $($_.FullName) @HT -ReadCount 1 -TotalCount 2) -as [string] Switch ($header) { '77 90' { [pscustomobject]@{ Path = "$($key)\$($n)" Item = $File.Name Value = $File.FullName Category = 'Logon' } break } '76 0' { $shortcut = $Wsh.CreateShortcut($File.FullName) [pscustomobject]@{ Path = "$($key)\$($n)" Item = $File.Name Value = "$($shortcut.TargetPath) $($shortcut.Arguments)" Category = 'Logon' } break } # Anything else: not lnk and not PE default { [pscustomobject]@{ Path = "$($key)\$($n)" Item = $File.Name Value = $File.FullName Category = 'Logon' } } } } } } } } } # Run by GPO Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run' -Name '*' @Category # Show all subkey that have a StubPath value $null,'Wow6432Node' | Foreach-Object { $key = "HKLM:\SOFTWARE\$($_)\Microsoft\Active Setup\Installed Components" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'StubPath' @Category } } Get-RegValue -Path 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Windows' -Name 'IconServiceLib' @Category $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows CE Services\AutoStartOnConnect" -Name '*' @Category } $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows CE Services\AutoStartDisconnect" -Name '*' @Category } $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\SOFTWARE\$($_)\Microsoft\Windows CE Services\AutoStartOnDisconnect" -Name '*' @Category } #endregion Logon #region User Logon $Users | ForEach-Object { $Hive = $_['Hive'] # Local GPO scripts 'Startup','Shutdown','Logon','Logoff' | ForEach-Object -Process { $t = $_ $key = "$($Hive)\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\$($_)" if (Test-Path -Path $key) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { $subkey = (Join-Path -Path $key -ChildPath $_) $gn = (Get-ItemProperty -Path $subkey -Name GPOName -ErrorAction SilentlyContinue).'GPOName' (Get-Item -Path $subkey).GetSubKeyNames() | ForEach-Object -Process { if ($gn -match '^{[A-F0-9-]+}') { $ds = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\Machine' $ab = (Get-ItemProperty -Path "$($ds)" -Name CurrentActiveBit -ErrorAction SilentlyContinue).'CurrentActiveBit' $dn = (Get-ItemProperty -Path "$($ds)\$($ab)" -Name DomainName).'DomainName' $p = "C:\Windows\system32\GroupPolicy\DataStore\$($ab)\SysVol\$($dn)\Policies\$($gn)\Machine\Scripts\$($t)" } else { $p = Join-Path -Path "$((Get-ItemProperty -Path $subkey -Name FileSysPath -ErrorAction SilentlyContinue).FileSysPath)" -ChildPath "Scripts\$($t)" } try { [pscustomobject]@{ Path = Join-Path -Path $subkey -ChildPath $_ Item = 'Script' Value = Join-Path -Path $p -ChildPath "$((Get-ItemProperty -Path (Join-Path -Path $subkey -ChildPath $_) -Name 'Script' -ErrorAction Stop).'Script')" Category = 'Logon' } } catch {} } } } } # UserInitMprLogonScript if (Test-Path -Path "$($Hive)\Environment" -PathType Container) { Get-RegValue -Path "$($Hive)\Environment" -Name 'UserInitMprLogonScript' @Category } # Shell override by GPO Get-RegValue -Path "$($Hive)\Software\Microsoft\Windows\CurrentVersion\Policies\System" -Name 'Shell' @Category Get-RegValue -Path "$($Hive)\Software\Microsoft\Windows NT\CurrentVersion\Windows" -Name 'Load' @Category Get-RegValue -Path "$($Hive)\Software\Microsoft\Windows NT\CurrentVersion\Windows" -Name 'Run' @Category # Run by GPO Get-RegValue -Path "$($Hive)\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run" -Name '*' @Category # Run $null,'Wow6432Node' | ForEach-Object { Get-RegValue -Path "$($Hive)\Software\$($_)\Microsoft\Windows\CurrentVersion\Run" -Name '*' @Category } # RunOnce $null,'Wow6432Node' | ForEach-Object { Get-RegValue -Path "$($Hive)\Software\$($_)\Microsoft\Windows\CurrentVersion\RunOnce" -Name '*' @Category } # RunOnceEx $null,'Wow6432Node' | ForEach-Object { Get-RegValue -Path "$($Hive)\Software\$($_)\Microsoft\Windows\CurrentVersion\RunOnceEx" -Name '*' @Category } $null,'Wow6432Node' | Foreach-Object { $key = "$($Hive)\SOFTWARE\$($_)\Microsoft\Windows\CurrentVersion\RunOnceEx" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name '*' @Category if (Test-Path -Path "$key\$($_)\Depend" -PathType Container) { Get-RegValue -Path "$key\$($_)\Depend" -Name '*' @Category } } } } # Restored as of 13.90 Get-RegValue -Path "$($Hive)\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Runonce" -Name '*' @Category Get-RegValue -Path "$($Hive)\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx" -Name '*' @Category $key = "$($Hive)\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name '*' @Category if (Test-Path -Path "$key\$($_)\Depend" -PathType Container) { Get-RegValue -Path "$key\$($_)\Depend" -Name '*' @Category } } } Get-RegValue -Path "$($Hive)\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run" -Name '*' @Category # Scan the User Shell Folders key and its startup and AltStartup non expanded value 'Startup','AltStartup' | ForEach-Object -Begin { $Wsh = New-Object -ComObject 'WScript.Shell' } -Process { if (Test-Path -Path $key -PathType Container) { $key = "$($Hive)\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" $regKey = '{0}\{1}' -f ($key -replace ':','' -replace 'HKU','HKEY_USERS'),$PSItem if (Get-ItemProperty -Path $key -Name $PSItem -ErrorAction SilentlyContinue) { [pscustomobject]@{ Path = "$($key)" Item = $PSItem Value = $Wsh.RegRead($regKey) Category = 'Logon' } } } } # Scan the Shell folders key and its startup value if they exist 'Startup','AltStartup' | ForEach-Object -Begin { $key = "$($Hive)\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" } -Process { $n = $PSItem if (Test-Path -Path $key -PathType Container) { # Show what the Startup value contains (could be a file) Get-RegValue -Path $key -Name $PSItem @Category $USF = $null # If it's a folder, explore its content $USF = (Get-ItemProperty -Path $key -Name $PSItem -ErrorAction SilentlyContinue)."$($PSItem)" if ($USF) { if (Test-Path -Path "$($USF)") { $Wsh = New-Object -ComObject 'WScript.Shell' Get-ChildItem -Path "$($USF)" -Force -Exclude 'desktop.ini' | ForEach-Object { $File = $_ if ($File -is [System.IO.FileInfo]) { $header = (Get-Content -Path $($_.FullName) @HT -ReadCount 1 -TotalCount 2) -as [string] Switch ($header) { '77 90' { [pscustomobject]@{ Path = "$($key)\$($n)" Item = $File.Name Value = $File.FullName Category = 'Logon' } break } '76 0' { $shortcut = $Wsh.CreateShortcut($File.FullName) [pscustomobject]@{ Path = "$($key)\$($n)" Item = $File.Name Value = "$($shortcut.TargetPath) $($shortcut.Arguments)" Category = 'Logon' } break } # Anything else: not lnk and not PE default { [pscustomobject]@{ Path = "$($key)\$($n)" Item = $File.Name Value = $File.FullName Category = 'Logon' } } } } } } } } } } #endregion User Logon } if ($All -or $Winsock) { Write-Verbose -Message 'Looking for Winsock protocol and network providers entries' #region Winsock providers $Category = @{ Category = 'Winsock Providers'} $null,'64' | ForEach-Object -Process { $key = "HKLM:\System\CurrentControlSet\Services\WinSock2\Parameters\Protocol_Catalog9\Catalog_Entries$($_)" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = "$key\$($_)" Item = 'PackedCatalogItem' Value = ((New-Object -TypeName System.Text.ASCIIEncoding).GetString( (Get-ItemProperty -Path "$key\$($_)" -Name PackedCatalogItem).PackedCatalogItem,0,211 ) -split ([char][int]0))[0] Category = 'Winsock Providers' } } } $null,'64' | ForEach-Object -Process { $key = "HKLM:\System\CurrentControlSet\Services\WinSock2\Parameters\NameSpace_Catalog5\Catalog_Entries$($_)" (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'LibraryPath' @Category } } #endregion Winsock providers #region Network providers $Category = @{ Category = 'Network Providers'} $key = 'HKLM:\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order' (Get-RegValue -Path $key -Name 'ProviderOrder' @Category).Value -split ',' | ForEach-Object { Get-RegValue -Path "HKLM:\SYSTEM\CurrentControlSet\services\$($_)\NetworkProvider" -Name 'ProviderPath' @Category } #endregion Network providers } if ($All -or $Codecs) { Write-Verbose -Message 'Looking for Codecs' #region Codecs $Category = @{ Category = 'Codecs'} # Drivers32 $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "HKLM:\Software\$($_)\Microsoft\Windows NT\CurrentVersion\Drivers32" -Name '*' @Category } # Filter $null,'Wow6432Node' | Foreach-Object { $key = "HKLM:\Software\$($_)Classes\Filter" $clsidp = "HKLM:\Software\$($_)\Classes\CLSID" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $clsidp -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' Category = 'Codecs' } } } } # Instances @('{083863F1-70DE-11d0-BD40-00A0C911CE86}','{AC757296-3522-4E11-9862-C17BE5A1767E}', '{7ED96837-96F0-4812-B211-F13C24117ED3}','{ABE3B9A4-257D-4B97-BD1A-294AF496222E}') | Foreach-Object -Process { $Item = $_ $null,'Wow6432Node' | Foreach-Object { $key = "HKLM:\Software\$($_)\Classes\CLSID\$Item\Instance" $clsidp = "HKLM:\Software\$($_)\Classes\CLSID" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { try { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path $clsidp -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction Stop).'(default)' Category = 'Codecs' } } catch {} } } } } #endregion Codecs #region User Codecs $Users | ForEach-Object { $Hive = $_['Hive'] # Drivers32 $null,'Wow6432Node' | Foreach-Object { Get-RegValue -Path "$($Hive)\Software\$($_)\Microsoft\Windows NT\CurrentVersion\Drivers32" -Name '*' @Category } # Filter $key = "$($Hive)\Software\Classes\Filter" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path "$($Hive)\SOFTWARE\Classes\CLSID" -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' Category = 'Codecs' } } } # Instances @('{083863F1-70DE-11d0-BD40-00A0C911CE86}','{AC757296-3522-4E11-9862-C17BE5A1767E}', '{7ED96837-96F0-4812-B211-F13C24117ED3}','{ABE3B9A4-257D-4B97-BD1A-294AF496222E}') | Foreach-Object -Process { $Item = $_ $null,'Wow6432Node' | Foreach-Object { $key = "$($Hive)\Software\$($_)\Classes\CLSID\$Item\Instance" if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { try { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path "$($Hive)\SOFTWARE\Classes\CLSID" -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction Stop).'(default)' Category = 'Codecs' } } catch { } } } } } } #endregion User Codecs } if ($All -or $OfficeAddins) { Write-Verbose -Message 'Looking for Office Addins entries' #region Office Addins <# # FileName value or # HKEY_LOCAL_MACHINE\SOFTWARE\Classes\OneNote.OutlookAddin\CLSID #> $Category = @{ Category = 'Office Addins'} $null,'Wow6432Node' | Foreach-Object { $arc = $_ 'HKLM:',$Users.ForEach({ $_['Hive']}) | ForEach-Object { $root = $_ if (Test-Path -Path "$($root)\SOFTWARE\$($arc)\Microsoft\Office") { (Get-Item -Path "$($root)\SOFTWARE\$($arc)\Microsoft\Office").GetSubKeyNames() | ForEach-Object { if (Test-Path -Path (Join-Path -Path "$($root)\SOFTWARE\$($arc)\Microsoft\Office" -ChildPath "$($_)\Addins") -PathType Container) { $key = (Join-Path -Path "$($root)\SOFTWARE\$($arc)\Microsoft\Office" -ChildPath "$($_)\Addins") # Iterate through the Addins names (Get-item -Path $key).GetSubKeyNames() | ForEach-Object { try { [pscustomobject]@{ Path = $key Item = $_ Value = $( $clsid = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\$($_)\CLSID" -Name '(default)' -ErrorAction Stop).'(default)'; if ((Get-ItemProperty -Path "HKLM:\SOFTWARE\$arc\Classes\CLSID\$clsid\InprocServer32" -Name '(default)' -ErrorAction SilentlyContinue).'(default)') { (Get-ItemProperty -Path "HKLM:\SOFTWARE\$arc\Classes\CLSID\$clsid\InprocServer32" -Name '(default)' -ErrorAction SilentlyContinue).'(default)' } else { # $clsid (Get-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Classes\CLSID\$clsid\InprocServer32" -Name '(default)' -ErrorAction SilentlyContinue).'(default)' } # (Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\CLSID\$clsid\InprocServer32" -Name '(default)' -ErrorAction SilentlyContinue).'(default)'; ) # | Where-Object { $null -ne $_ } | Sort-Object -Unique # | Select-Object -First 1 Category = 'Office Addins'; } } catch { } } } } } } # hklm or hkcu } # Microsoft Office Memory Corruption Vulnerability (CVE-2015-1641) 'HKLM:',$Users.ForEach({ $_['Hive']}) | ForEach-Object { $root = $_ $null,'Wow6432Node' | Foreach-Object { $key = "$($root)\SOFTWARE\$($_)\Microsoft\Office test\Special\Perf" if (Test-Path "$($root)\SOFTWARE\$($_)\Microsoft\Office test\Special\Perf") { if ((Get-ItemProperty -Path "$($root)\SOFTWARE\$($_)\Microsoft\Office test\Special\Perf" -Name '(default)' -ErrorAction SilentlyContinue).'(default)') { [pscustomobject]@{ Path = $key Item = '(default)' Value = (Get-ItemProperty -Path "$($root)\SOFTWARE\$($_)\Microsoft\Office test\Special\Perf" -Name '(default)' -ErrorAction SilentlyContinue).'(default)' Category = 'Office Addins'; } } } } } #endregion Office Addins } if ($All -or $PrintMonitorDLLs) { Write-Verbose -Message 'Looking for Print Monitor DLLs entries' #region Print monitors $Category = @{ Category = 'Print Monitors'} $key = 'HKLM:\SYSTEM\CurrentControlSet\Control\Print\Monitors' (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'Driver' @Category } Write-Verbose -Message 'Looking for Print Providers DLLs entries' $key = 'HKLM:\SYSTEM\CurrentControlSet\Control\Print\Providers' (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'Name' @Category } Write-Verbose -Message 'Looking for Print Ports entries' $key = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports' if (Test-Path -Path $key -PathType Container) { (Get-Item -Path $key).GetValueNames() | Where-Object -FilterScript { $_ -notmatch '^(COM|LPT|PORTPROMPT|FILE|nul|Ne)(\d{1,2})?:' } | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = 'Port' Value = "$($_)" Category = 'Print Monitors' } } } #endregion Print monitors } if ($All -or $LSAsecurityProviders) { Write-Verbose -Message 'Looking for LSA Security Providers entries' #region LSA providers $Category = @{ Category = 'LSA Providers'} # REG_SZ Get-RegValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders' -Name 'SecurityProviders' @Category # REG_MULTI_SZ 'Authentication Packages','Notification Packages','Security Packages' | ForEach-Object { $item = $_ (Get-RegValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' -Name $_ @Category).Value | ForEach-Object { if ($_ -ne '""') { [pscustomobject]@{ Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' Item = $item Value = $_ Category = 'LSA Providers' } } } } # HKLM\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\Security Packages if (Test-Path -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig' -PathType Container) { (Get-RegValue -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig' -Name 'Security Packages' @Category).Value | ForEach-Object { if ($null -ne $_) { [pscustomobject]@{ Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig' Item = 'Security Packages' Value = $_ Category = 'LSA Providers' } } } } #endregion LSA providers } if ($All -or $ServicesAndDrivers) { Write-Verbose -Message 'Looking for Services and Drivers' #region Services (Get-Item -Path 'HKLM:\System\CurrentControlSet\Services').GetSubKeyNames() | ForEach-Object { $Type = $null $key = "HKLM:\System\CurrentControlSet\Services\$($_)" try { $Type = Get-ItemProperty -Path $key -Name Type -ErrorAction Stop } catch { } if ($Type) { Switch ($Type.Type) { 1 { Get-RegValue -Path $key -Name 'ImagePath' -Category 'Drivers' break } 16 { Get-RegValue -Path $key -Name 'ImagePath' -Category 'Services' Get-RegValue -Path "$key\Parameters" -Name 'ServiceDll' -Category 'Services' break } 32 { Get-RegValue -Path $key -Name 'ImagePath' -Category 'Services' Get-RegValue -Path "$key\Parameters" -Name 'ServiceDll' -Category 'Services' break } default { # $_ } } } } # Font drivers Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Font Drivers' -Name '*' -Category 'Services' #endregion Services } if ($All -or $ScheduledTasks) { Write-Verbose -Message 'Looking for Scheduled Tasks' #region Scheduled Tasks Get-AllScheduledTask | Get-Task | ForEach-Object { $Task = $_ $node = ([xml]$_.XML).Task.get_ChildNodes() | Where-Object { $_.Name -eq 'Actions'} if ($node.HasChildNodes) { # $node can have Exec or comHandler or both childs (ex: MediaCenter tasks) $node.get_ChildNodes() | ForEach-Object { $Value = $null $subnode = $_ $Value = switch ($_.Name) { Exec { # $subnode = ($node.get_ChildNodes() | Where-Object { $_.Name -eq 'Exec'}) if ($subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'Arguments' } | Select-Object -ExpandProperty '#text') { '{0} {1}' -f ($subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'Command' } | Select-Object -ExpandProperty '#text'), ($subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'Arguments' } | Select-Object -ExpandProperty '#text'); } else { $subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'Command' } | Select-Object -ExpandProperty '#text' ; } break; } ComHandler { # $subnode = ($node.get_ChildNodes() | Where-Object { $_.Name -eq 'ComHandler'}) if ($subnode.get_ChildNodes()| Where-Object { $_.Name -eq 'Data'} | Select-Object -ExpandProperty InnerText) { '{0} {1}'-f ($subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'ClassId'} | Select-Object -ExpandProperty '#text'), ($subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'Data'} | Select-Object -ExpandProperty InnerText); } else { $subnode.get_ChildNodes() | Where-Object { $_.Name -eq 'ClassId'} | Select-Object -ExpandProperty '#text'; } break; } default {} } [pscustomobject]@{ Path = (Join-Path -Path "$($env:systemroot)\system32\Tasks" -ChildPath "$($Task.Path)\$($Task.Name)") ; Item = $Task.Name Value = $Value ; Category = 'Task' ; } } } } #endregion Scheduled Tasks } if ($All -or $Winlogon) { Write-Verbose -Message 'Looking for Winlogon entries' #region Winlogon $Category = @{ Category = 'Winlogon'} Get-RegValue -Path 'HKLM:\SYSTEM\Setup' -Name 'CmdLine' @Category 'Credential Providers','Credential Provider Filters','PLAP Providers' | ForEach-Object { $key = Join-Path -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication' -ChildPath $_ (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { [pscustomobject]@{ Path = $key Item = $_ Value = (Get-ItemProperty -Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($_)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' Category = 'Winlogon' } } } <# # deprecated 'System','SaveDumpStart' | ForEach-Object { Get-RegValue -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name $_ @Category } #> # Notify doesn't exist on Windows 8.1 <# # deprecated if (Test-Path -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify' -PathType Container) { $key = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify' (Get-Item -Path $key).GetSubKeyNames() | ForEach-Object -Process { Get-RegValue -Path "$key\$($_)" -Name 'DLLName' @Category } } #> if (Test-Path -Path 'HKLM:\System\CurrentControlSet\Control\BootVerificationProgram' -PathType Container) { Get-RegValue -Path 'HKLM:\System\CurrentControlSet\Control\BootVerificationProgram' -Name 'ImagePath' @Category } #endregion Winlogon #region User Winlogon $Users | ForEach-Object { $Hive = $_['Hive'] Get-RegValue -Path "$($Hive)\SOFTWARE\Policies\Microsoft\Windows\Control Panel\Desktop" -Name 'Scrnsave.exe' @Category Get-RegValue -Path "$($Hive)\Control Panel\Desktop" -Name 'Scrnsave.exe' @Category } #endregion User Winlogon } if ($All -or $WMI) { Write-Verbose -Message 'Looking for WMI Database entries' # Temporary events created with Register-CimIndicationEvent or Register-WMIEvent <# Get-EventSubscriber -ErrorAction SilentlyContinue | ForEach-Object -Process { $job = $_ | Select-Object -ExpandProperty Action if ($job.Command) { Write-Warning -Message 'A temporary WMI Event subscription was found' } } #> # Permanent events Get-CimInstance -Namespace root\Subscription -ClassName __EventConsumer -ErrorAction SilentlyContinue -Verbose:$false | Where-Object { $_.PSBase.CimClass.CimClassName -eq 'ActiveScriptEventConsumer' } | ForEach-Object { if ($_.ScriptFileName) { [pscustomobject]@{ Path = "\\.\$($_.PSBase.CimSystemProperties.Namespace -replace '/','\'):ActiveScriptEventConsumer.Name='$($_.Name)'" ; Item = $_.Name Value = $_.ScriptFileName ; Category = 'WMI' ; } } elseif ($_.ScriptText) { [pscustomobject]@{ Path = "\\.\$($_.PSBase.CimSystemProperties.Namespace -replace '/','\'):ActiveScriptEventConsumer.Name='$($_.Name)'" ; Item = $_.Name Value = $null ; Category = 'WMI' ; } } } Get-CimInstance -Namespace root\Subscription -ClassName __EventConsumer -ErrorAction SilentlyContinue -Verbose:$false | Where-Object { $_.PSBase.CimClass.CimClassName -eq 'CommandLineEventConsumer' } | ForEach-Object { [pscustomobject]@{ Path = "\\.\$($_.PSBase.CimSystemProperties.Namespace -replace '/','\'):CommandLineEventConsumer.Name='$($_.Name)'" ; Item = $_.Name Value = "$($_.WorkingDirectory)$($_.ExecutablePath)" ;# $($_.CommandLineTemplate)" ; Category = 'WMI' ; } } # List recursiveley registered and resolved WMI providers Function Get-WmiNamespace { Param ( [string]$Namespace='root' ) try { Get-CimInstance -Namespace $Namespace -ClassName __Namespace -ErrorAction Stop -Verbose:$false | ForEach-Object { ($ns = '{0}/{1}' -f $_.PSBase.CimSystemProperties.Namespace,$_.Name) Get-WmiNamespace -Namespace $ns } } catch { Write-Warning -Message "Failed to enumerate NS: $ns because $($_.Exception.Message)" } } Function Get-WmiProvider { Param ( [string]$Namespace='root' ) try { Get-CimInstance -Namespace $Namespace -ClassName __Provider -ErrorAction Stop -Verbose:$false } catch { Write-Warning -Message "Failed to enumerate NS: $ns because $($_.Exception.Message)" } } Get-WmiNamespace | ForEach-Object { Get-WmiProvider -Namespace $_ | ForEach-Object { Write-Verbose -Message "Found provider clsid $($_.CLSID) from under the $($_.PSBase.CimSystemProperties.Namespace) namespace" if (($clsid = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\CLSID\$($_.CLSID)\InprocServer32" -Name '(default)' -ErrorAction SilentlyContinue).'(default)')) { [pscustomobject]@{ Path = "\\.\$($_.PSBase.CimSystemProperties.Namespace -replace '/','\'):__Win32Provider.Name='$($_.Name)'" Item = $_.Name Value = $clsid Category = 'WMI' ; } } } } } if ($All -or $PSProfiles) { $profiles = New-Object -TypeName System.Collections.ArrayList 'C:\Windows\SysWOW64\WindowsPowerShell\v1.0', 'C:\Windows\System32\WindowsPowerShell\v1.0', $global:home | ForEach-Object { $null = $profiles.Add($_) } if ($PSVersionTable.PSEdition -eq 'Core') { $null = $profiles.Add($global:PSHOME) # for PS Core, use public constant } $profiles | ForEach-Object { $root = $_ 'profile.ps1', 'Microsoft.PowerShell_profile.ps1', 'Microsoft.PowerShellISE_profile.ps1' | ForEach-Object { if (Test-Path -Path (Join-Path -Path $root -ChildPath $_) -PathType Leaf) { [pscustomobject]@{ Path = $root Item = $_ Value = (Join-Path -Path $root -ChildPath $_) Category = 'PowerShell profiles' } } } } } } End { } } Function Get-PSPrettyAutorun { [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeLine)] [system.object[]]$RawAutoRun ) Begin {} Process { $RawAutoRun | ForEach-Object { $Item = $_ Switch ($Item.Category) { Task { Write-Verbose -Message "Reading Task $($Item.Path)" $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value ) { #GUID '^(\{)?[A-Za-z0-9]{4}([A-Za-z0-9]{4}\-?){4}[A-Za-z0-9]{12}(\})?' { # $clsid = ($_ -split '\s')[0] $clsid = ([system.guid]::Parse( ($_ -split '\s')[0])).ToString('B') if (Test-Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($clsid)\InprocServer32") -PathType Container) { Write-Verbose -Message 'Reading from InprocServer32' (Get-ItemProperty -Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($clsid)\InprocServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' } elseif (Test-Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($clsid)\LocalServer32") -PathType Container) { Write-Verbose -Message 'Reading from LocalServer32' (Get-ItemProperty -Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($clsid)\LocalServer32") -Name '(default)' -ErrorAction SilentlyContinue).'(default)' } else { try { Write-Verbose -Message 'Reading from AppID' # $appid = (Get-ItemProperty -Path (Join-Path -Path 'HKLM:\SOFTWARE\Classes\CLSID' -ChildPath "$($clsid)") -Name 'AppId' -ErrorAction Stop).'AppId' "$($env:systemroot)\system32\sc.exe" } catch { # Write-Warning -Message "AppId not found for $clsid" } } break } # Rundll32 '^((%windir%|%(s|S)ystem(r|R)oot%)\\(s|S)ystem32\\)?rundll32\.exe\s(/[a-z]\s)?.*,.*' { Join-Path -Path "$($env:systemroot)\system32" -ChildPath ( @([regex]'^((%windir%|%(s|S)ystem(r|R)oot%)\\(s|S)ystem32\\)?rundll32\.exe\s(/[a-z]\s)?((%windir%|%(s|S)ystem(r|R)oot%)\\(s|S)ystem32\\)?(?.*),').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # cscript '^((%windir%|%(s|S)ystem(r|R)oot%)\\(s|S)ystem32\\)?(c|w)script\.exe\s(//?[a-zA-Z:]+\s){0,}.*' { Join-Path -Path "$($env:systemroot)\system32" -ChildPath ( @([regex]'^((%windir%|%(s|S)ystem(r|R)oot%)\\(s|S)ystem32\\)?(c|w)script\.exe\s(//?[a-zA-Z:]+\s){0,}((%windir%|%(s|S)ystem(r|R)oot%)\\(s|S)ystem32\\)?(?.*\.[a-zA-Z0-9]{1,3})\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # special powershell '[pP][oO][wW][eE][rR][sS][hH][eE][lL]{2}' { Function Get-EnvReplacement { [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeline)] [string]$Value ) Begin {} Process {} End { $envVar= ($Value -split '%')[1] # Write-Verbose -Message "-$($envVar)-" -Verbose if ($envVar) { Get-ChildItem -Path 'Env:' | Where-Object {$_.Name -eq "$($envVar)"} | ForEach-Object { if ($Value -match "$($_.Name)") { $Value -replace "%$($_.Name)%","$($_.Value)" } } } else { $Value } } } switch -regex ($_) { '\s-[fF]' { @([regex]'(-[fF][iI]?[lL]?[eE]?)\s{1,}?"?(?.+\.[pP][sS]1)"?\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value | ForEach-Object { ($_ -replace '"','').Trim()} break } '.[pP][sS]1\s' { @([regex]'([^\s]+)(?<=\.[pP][sS]1)').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 -ExpandProperty Value | Get-EnvReplacement break } '.[pP][sS]1"' { @([regex]'([^"]+)(?<=\.[pP][sS]1)').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 -ExpandProperty Value | Get-EnvReplacement break } '.[pP][sS]1' { @([regex]'\s{1,}"?(?.+\.[pP][sS]1)"?\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value break } default { $_ } } break } # Windir\system32 '^"?(%(w|W)(i|I)(n|N)(d|D)(i|I)(r|R)%|%(s|S)ystem(r|R)oot%|C:\\[Ww][iI][nN][dD][oO][Ww][sS])\\(s|S)ystem32\\.[^\\]+\.(exe|vbs)' { Join-Path -Path "$($env:systemroot)\system32" -ChildPath ( @([regex]'^"?(%(w|W)(i|I)(n|N)(d|D)(i|I)(r|R)%|%(s|S)ystem(r|R)oot%|C:\\[Ww][iI][nN][dD][oO][Ww][sS])\\(s|S)ystem32\\(?.[^\\]+\.(exe|vbs))("|\s)?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # windir\somethingelse '^"?(%(w|W)(i|I)(n|N)(d|D)(i|I)(r|R)%|%(s|S)ystem(r|R)oot%|C:\\[Ww][iI][nN][dD][oO][Ww][sS])\\.*\\.*\.(exe|vbs)' { Join-Path -Path "$($env:systemroot)" -ChildPath ( @([regex]'^"?(%(w|W)(i|I)(n|N)(d|D)(i|I)(r|R)%|%(s|S)ystem(r|R)oot%|C:\\[Ww][iI][nN][dD][oO][Ww][sS])\\(?.*\\.*\.(exe|vbs))(\s)?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^%localappdata%\\Microsoft\\OneDrive\\OneDriveStandaloneUpdater\.exe\s/reporting' { $s = $Item.Item -replace 'OneDrive\sReporting\sTask-','' $f = $allusers | Where-Object { $_.SID -eq $s } if ($f) { Join-Path -Path "$($f.ProfilePath)\AppData\Local" -ChildPath 'Microsoft\OneDrive\OneDriveStandaloneUpdater.exe' } else { if (Test-isValidSid -SID $s) { Join-Path -Path "C:\Users\$(((Get-UserNameFromSID -SID $s) -split '\\')[1])" -ChildPath 'AppData\Local\Microsoft\OneDrive\OneDriveStandaloneUpdater.exe' } else { 'AppData\Local\Microsoft\OneDrive\OneDriveStandaloneUpdater.exe' } } break } # localappdata variable '^%localappdata%' { $s = $Item.Item -replace 'OneDrive\sStandalone\sUpdate\sTask-','' $f = $allusers | Where-Object { $_.SID -eq $s } $cp = @([regex]'^%localappdata%\\(?.*)').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value if ($f) { Join-Path -Path "$($f.ProfilePath)\AppData\Local" -ChildPath $cp } else { if (Test-isValidSid -SID $s) { Join-Path -Path "C:\Users\$(((Get-UserNameFromSID -SID $s) -split '\\')[1])\AppData\Local" -ChildPath $cp } else { $cp } } break } # special W7 case with media center '^%SystemRoot%\\ehome\\.*\s' { # "$($env:systemroot)\ehome\ehrec.exe" Join-Path -Path "$($env:systemroot)\ehome" -ChildPath "$( @([regex]'^%SystemRoot%\\ehome\\(?.*)\s').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ).exe" break } # special case Office 2016 License Heartbeat '%ProgramFiles%\\Common\sFiles\\Microsoft\sShared\\Office16\\OLicenseHeartbeat\.exe' { if ([environment]::Is64BitOperatingSystem) { 'C:\Program Files (x86)\Common Files\microsoft shared\OFFICE16\OLicenseHeartbeat.exe' } else { 'C:\Program Files\Common Files\microsoft shared\OFFICE16\OLicenseHeartbeat.exe' } break } # ProgramData '^"?C:\\ProgramData\\' { Join-Path -Path "$($env:ProgramData)" -ChildPath ( @([regex]'^"?C:\\ProgramData\\(?.*\.exe)("|\s)?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # ProgramFiles starts with a quote '^"(C:\\Program\sFiles|%ProgramFiles%)\\' { Join-Path -Path "$($env:ProgramFiles)" -ChildPath ( @([regex]'^"(C:\\Program\sFiles|%ProgramFiles%)\\(?.+\.[A-Za-z0-9]{1,})"').Matches($_)| Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # ProgramFiles with no quote '^(C:\\Program\sFiles|%ProgramFiles%)\\' { Switch -Regex ($_) { '^((C|c):\\Program\sFiles|%ProgramFiles%)\\(?.+\.[A-Za-z0-9]{1,})\s' { Join-Path -Path "$($env:ProgramFiles)" -ChildPath ( @([regex]'^((C|c):\\Program\sFiles|%ProgramFiles%)\\(?.+\.[A-Za-z0-9]{1,})\s').Matches($_)| Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^(C:\\Program\sFiles|%ProgramFiles%)\\(?.+\.[A-Za-z0-9]{1,})$' { Join-Path -Path "$($env:ProgramFiles)" -ChildPath ( @([regex]'^((C|c):\\Program\sFiles|%ProgramFiles%)\\(?.+\.[A-Za-z0-9]{1,})$').Matches($_)| Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } default {$_} } break } # ProgramFilesx86 starts with a quote '^"(C:\\Program\sFiles\s\(x86\)|%ProgramFiles\(x86\)%)\\' { Join-Path -Path "$(${env:ProgramFiles(x86)})" -ChildPath ( @([regex]'^"(C:\\Program\sFiles\s\(x86\)|%ProgramFiles\(x86\)%)\\(?.*\.[a-z0-9]{1,})"').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # ProgramFilesx86 with no quote '^(C:\\Program\sFiles\s\(x86\)|%ProgramFiles\(x86\)%)\\' { Join-Path -Path "$(${env:ProgramFiles(x86)})" -ChildPath ( @([regex]'^(C:\\Program\sFiles\s\(x86\)|%ProgramFiles\(x86\)%)\\(?.*\.[a-z0-9]{1,})\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # Users '^"?C:\\[uU][sS][eE][rR][sS]\\(?.+\.[A-Za-z0-9]{1,})("|\s)?' { Join-Path -Path 'C:\Users' -ChildPath ( @([regex]'^"?C:\\[uU][sS][eE][rR][sS]\\(?.+\.[A-Za-z0-9]{1,})("|\s)?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # C:\users? '^"?[A-Za-z]:\\' { $_ -replace '"','' break; } # FileName.exe '[a-zA-Z0-9]*\.exe(\s)?' { # '[a-zA-Z0-9]*(\.exe\s)?' { Join-Path -Path "$($env:systemroot)\system32" -ChildPath "$( @([regex]'^(?[a-zA-Z0-9]*)(\.exe\s)?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ).exe" break } '^sc\s[a-zA-Z]' { "$($env:systemroot)\system32\sc.exe" break } '^aitagent(\s/increment)?' { "$($env:systemroot)\system32\aitagent.exe" break } default { $_ } } #endof switch ) -Force -PassThru break; } AppInit { if ($Item.Value -eq [string]::Empty) { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $null -Force -PassThru } else { # Switch ? malware example $Item.Value -split '\s|,' | ForEach-Object { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value "$($_)" -Force -PassThru } } break } 'Boot Execute' { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value) { '^autocheck\sautochk\s' { "$($env:SystemRoot)\system32\autochk.exe" break; } '^C:\\Windows\\System32\\poqexec\.exe\s' { "$($env:SystemRoot)\system32\poqexec.exe" break; } default { $Item.Value } } ) -Force -PassThru break } Codecs { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value) { '^[A-Z]:\\Windows\\' { if ($Item.Path -match 'Wow6432Node') { $_ -replace 'system32','SysWOW64' } else { $_ } break } # '^[A-Z]:\\Program\sFiles' { '^[A-Z]:\\[Pp]rogra' { $_ | Get-NormalizedFileSystemPath break } default { if ($Item.Path -match 'Wow6432Node') { Join-Path "$($env:systemroot)\Syswow64" -ChildPath $_ } else { Join-Path "$($env:systemroot)\System32" -ChildPath $_ } } } ) -Force -PassThru break } Drivers { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( switch -Regex ($Item.Value) { '^\\SystemRoot\\System32\\' { $_ -replace '\\Systemroot',"$($env:systemroot)" break; } '^System32\\[dD][rR][iI][vV][eE][rR][sS]\\' { Join-Path -Path "$($env:systemroot)" -ChildPath $_ break; } '^System32\\DriverStore\\FileRepository\\' { Join-Path -Path "$($env:systemroot)" -ChildPath $_ break; } '^SysWow64\\[dD][rR][iI][vV][eE][rR][sS]\\' { Join-Path -Path "$($env:systemroot)" -ChildPath $_ break; } '^\\\?\?\\[A-Z]:\\' { $_ -replace '\\\?\?\\','' break; } '^System32\\CLFS\.sys' { $_ -replace 'System32\\',"$($env:systemroot)\system32\" } '^("|\\\?\?\\)?[A-Za-z]:\\[Pp]rogram\s[fF]iles\\(?.*\.[A-Za-z]{3})\s?' { Join-Path -Path "$($env:ProgramFiles)" -ChildPath ( @([regex]'^("|\\\?\?\\)?[A-Za-z]:\\[Pp]rogram\s[fF]iles\\(?.*\.[A-Za-z]{3})\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^("|\\\?\?\\)?[A-Za-z]:\\[Pp]rogram\s[fF]iles(\s\(x86\))\\(?.*\.[A-Za-z]{3})\s?' { Join-Path -Path "$(${env:ProgramFiles(x86)})" -ChildPath ( @([regex]'^("|\\\?\?\\)?[A-Za-z]:\\[Pp]rogram\s[fF]iles(\s\(x86\))\\(?.*\.[A-Za-z]{3})\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^"?C:\\ProgramData' { $_ -replace '"','' break; } 'SysmonDrv.sys' { $env:PATH -split ';'| ForEach-Object { Get-ChildItem -Path $_\*.sys -Include SysmonDrv.sys -Force -ErrorAction SilentlyContinue } | Select-Object -First 1 -ExpandProperty FullName break } default { $_ } }) -Force -PassThru break } Explorer { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( if ($Item.Value) { if ($Item.Value -match '^"?[A-Z]:\\') { if ($Item.Path -match 'Wow6432Node') { $Item.Value -replace 'system32','syswow64' | Get-NormalizedFileSystemPath } else { $Item.Value -replace '"','' | Get-NormalizedFileSystemPath } } else { if ($Item.Path -match 'Wow6432Node') { Join-Path -Path "$($env:systemroot)\syswow64" -ChildPath $Item.Value } else { Join-Path -Path "$($env:systemroot)\system32" -ChildPath $Item.Value } } } ) -Force -PassThru break } 'Image Hijacks' { if ($Item.Value -eq '"%1" %*') { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $null -Force -PassThru } else { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value) { '^"?(?.*\.[A-Za-z0-9]{3})"?\s?%?' { @([regex]'^"?(?.*\.[A-Za-z0-9]{3})"?\s?%?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value break } default { $_ } }) -Force -PassThru } break } 'Internet Explorer' { if ($Item.Item -ne 'Locked') { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( $Item.Value | Get-NormalizedFileSystemPath ) -Force -PassThru } break } 'Known Dlls' { if ( (Test-Path -Path $Item.Value -PathType Container) -and ($Item.Item -match 'DllDirectory')) { } else { # Duplicate objects $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Join-Path -Path "$($env:SystemRoot)\System32" -ChildPath $Item.Value ) -Force -PassThru if ([environment]::Is64BitOperatingSystem) { # Duplicate if target file exists if (Test-Path -Path (Join-Path -Path "$($env:SystemRoot)\Syswow64" -ChildPath $Item.Value) -PathType Leaf) { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Join-Path -Path "$($env:SystemRoot)\Syswow64" -ChildPath $Item.Value ) -Force -PassThru } } } break } Logon { If ($Item.Item -eq 'UserInit') { $Item.Value -split ',' | ForEach-Object { $s = $_ if ($_ -ne [string]::Empty) { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( if ($s -match '^"?[A-Z]:\\') { if ($Item.Path -match 'Wow6432Node') { $s -replace 'system32','syswow64' | Get-NormalizedFileSystemPath } else { $s -replace '"','' | Get-NormalizedFileSystemPath } } else { if ($Item.Path -match 'Wow6432Node') { Join-Path -Path "$($env:systemroot)\syswow64" -ChildPath $s } else { Join-Path -Path "$($env:systemroot)\system32" -ChildPath $s } } ) -Force -PassThru } } } elseif ($Item.Path -imatch 'runonceEx' -and $Item.Value -match '|') { $Item.Value -split '\|' | ForEach-Object { if ($_ -ne [string]::Empty) { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( $_ ) -Force -PassThru } } } else { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( switch -Regex ($Item.Value) { '\\Rundll32\.exe\s' { (($_ -split '\s')[1] -split ',')[0] break } '\\Rundll32\.exe"' { (($_ -split '\s',2)[1] -split ',')[0] -replace '"','' break; } '^"[A-Z]:\\Program' { ($_ -split '"')[1] break } '^"[A-Z]:\\Windows' { ($_ -split '"')[1] break } 'C:\\WINDOWS\\inf\\unregmp2\.exe\s/ShowWMP' { 'C:\WINDOWS\system32\unregmp2.exe' break } 'rdpclip' { "$($env:SystemRoot)\system32\$($_).exe" break } '^Explorer\.exe$' { "$($env:SystemRoot)\$($_)" break } # regsvr32.exe /s /n /i:U shell32.dll '^regsvr32\.exe\s/s\s/n\s/i:U\sshell32\.dll' { if ($Item.Path -match 'Wow6432Node') { "$($env:SystemRoot)\syswow64\shell32.dll" }else { "$($env:SystemRoot)\system32\shell32.dll" } break } '^C:\\Windows\\system32\\regsvr32\.exe\s/s\s/n\s/i:/UserInstall\sC:\\Windows\\system32\\themeui\.dll' { if ($Item.Path -match 'Wow6432Node') { "$($env:SystemRoot)\syswow64\themeui.dll" }else { "$($env:SystemRoot)\system32\themeui.dll" } break } '^C:\\Windows\\system32\\cmd\.exe\s/D\s/C\sstart\sC:\\Windows\\system32\\ie4uinit\.exe\s\-ClearIconCache' { if ($Item.Path -match 'Wow6432Node') { "$($env:SystemRoot)\syswow64\ie4uinit.exe" }else { "$($env:SystemRoot)\system32\ie4uinit.exe" } break } '^[A-Z]:\\Windows\\' { if ($Item.Path -match 'Wow6432Node') { (($_ -split '\s')[0] -replace ',','') -replace 'System32','Syswow64' } else { (($_ -split '\s')[0] -replace ',','') } break } '^[a-zA-Z0-9]+\.(exe|dll)' { if ($Item.Path -match 'Wow6432Node') { Join-Path -Path "$($env:SystemRoot)\syswow64" -ChildPath ($_ -split '\s')[0] } else { Join-Path -Path "$($env:SystemRoot)\system32" -ChildPath ($_ -split '\s')[0] } break } '^RunDLL32\s' { Join-Path -Path "$($env:SystemRoot)\system32" -ChildPath (($_ -split '\s')[1] -split ',')[0] break } # ProgramFiles '^[A-Za-z]:\\Program\sFiles\\' { Join-Path -Path "$($env:ProgramFiles)" -ChildPath ( @([regex]'[A-Za-z]:\\Program\sFiles\\(?.*\.(e|E)(x|X)(e|E))\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # ProgramFilesx86 '^[A-Za-z]:\\Program\sFiles\s\(x86\)\\' { Join-Path -Path "$(${env:ProgramFiles(x86)})" -ChildPath ( @([regex]'[A-Za-z]:\\Program\sFiles\s\(x86\)\\(?.*\.(e|E)(x|X)(e|E))\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # C:\Users with a quote '^"C:\\[uU][sS][eE][rR][sS]\\(?.[^"]+\.[A-Za-z0-9]{1,})"' { Join-Path -Path 'C:\Users' -ChildPath ( @([regex]'^"C:\\[uU][sS][eE][rR][sS]\\(?.[^"]+\.[A-Za-z0-9]{1,})"').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # C:\Users with a space at the end '^C:\\[uU][sS][eE][rR][sS]\\(?.+\.[A-Za-z0-9]{1,})\s' { Join-Path -Path 'C:\Users' -ChildPath ( @([regex]'^C:\\[uU][sS][eE][rR][sS]\\(?.+\.[A-Za-z0-9]{1,})\s').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # C:\Users with nothing at the end '^C:\\[uU][sS][eE][rR][sS]\\(?.+\.[A-Za-z0-9]{1,})' { Join-Path -Path 'C:\Users' -ChildPath ( @([regex]'^C:\\[uU][sS][eE][rR][sS]\\(?.+\.[A-Za-z0-9]{1,})').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } # "C:\ '^"[A-Za-z]:\\' { ($_ -split '"')[1] break } # C:\ProgramData\ # '^[A-Za-z]:\\ProgramData\\' { '^[A-Za-z]:\\[pP][rR][oO][gG][rR][aA][mM][dD][aA][tT][aA]\\(?.+\.[A-Za-z0-9]{1,})' { Join-Path -Path 'C:\ProgramData' -ChildPath ( @([regex]'C:\\[pP][rR][oO][gG][rR][aA][mM][dD][aA][tT][aA]\\(?.+\.[A-Za-z0-9]{1,})').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) } default { Write-Verbose -Message "default: $_" [string]::Empty # $_ } } ) -Force -PassThru } break } 'LSA Providers' { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( if ($Item.Value -match '\.dll$') { Join-Path -Path "$($env:SystemRoot)\system32" -ChildPath $Item.Value } else { Join-Path -Path "$($env:SystemRoot)\system32" -ChildPath "$($Item.Value).dll" } ) -Force -PassThru break } 'Network Providers' { $Item | Add-Member -MemberType ScriptProperty -Name ImagePath -Value $({$this.Value}) -Force -PassThru } 'Office Addins' { if ($Item.Path -match 'Wow6432Node' -and $Item.Value -imatch 'system32') { $Item.Value = $Item.Value -replace 'system32','syswow64' } if ($Item.Value) { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value ) { #GUID '^(\{)?[A-Za-z0-9]{4}([A-Za-z0-9]{4}\-?){4}[A-Za-z0-9]{12}(\})?' { ([system.guid]::Parse( ($_ -split '\s')[0])).ToString('B') break } default { $Item.Value -replace '"','' | Get-NormalizedFileSystemPath } } ) -Force -PassThru } break } 'Print Monitors' { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( switch -Regex ($Item.Value) { '^"?[A-Za-z]:\\' { $Item.Value } default { Join-Path -Path "$($env:SystemRoot)\System32" -ChildPath $Item.Value } } ) -Force -PassThru break } Services { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( switch -Regex ($Item.Value) { '^"?[A-Za-z]:\\[Ww][iI][nN][dD][oO][Ww][sS]\\(?.*\.(exe|dll))\s?' { Join-Path -Path "$($env:systemroot)" -ChildPath ( @([regex]'^"?[A-Za-z]:\\[Ww][iI][nN][dD][oO][Ww][sS]\\(?.*\.(exe|dll))\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^"?[A-Za-z]:\\[Pp]rogram\s[fF]iles\\(?.*\.[eE][xX][eE])\s?' { Join-Path -Path "$($env:ProgramFiles)" -ChildPath ( @([regex]'^"?[A-Za-z]:\\[Pp]rogram\s[fF]iles\\(?.*\.[eE][xX][eE])\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^"?[A-Za-z]:\\[Pp]rogram\s[fF]iles\s\(x86\)\\(?.*\.[eE][xX][eE])\s?' { Join-Path -Path "$(${env:ProgramFiles(x86)})" -ChildPath ( @([regex]'^"?[A-Za-z]:\\[Pp]rogram\s[fF]iles\s\(x86\)\\(?.*\.[eE][xX][eE])\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^"?[A-Za-z]:\\[Pp]rogram[dD]ata\\(?.*\.[eE][xX][eE])\s?' { Join-Path -Path "$($env:ProgramData)" -ChildPath ( @([regex]'^"?[A-Za-z]:\\[Pp]rogram[dD]ata\\(?.*\.[eE][xX][eE])\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value ) break } '^"?(?[A-Za-z]:\\.*\.[eE][xX][eE])\s?' { @([regex]'^"?(?[A-Za-z]:\\.*\.[eE][xX][eE])\s?').Matches($_) | Select-Object -Expand Groups | Select-Object -Last 1 | Select-Object -ExpandProperty Value break } 'winhttp.dll' { Join-Path -Path "$($env:SystemRoot)\System32" -ChildPath 'winhttp.dll' break } 'atmfd.dll' { Join-Path -Path "$($env:SystemRoot)\System32" -ChildPath 'atmfd.dll' break } default { $_ } }) -Force -PassThru break } Winlogon { # this works on W8.1 # $Item | Add-Member -MemberType ScriptProperty -Name ImagePath -Value $({$this.Value}) -Force -PassThru # for backward compatibility with W7 we do: $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value) { '^[a-zA-Z0-9]*\.[dDlL]{3}' { Join-Path -Path "$($env:SystemRoot)\System32" -ChildPath $Item.Value break } default { $_; } } ) -Force -PassThru break } 'Winsock Providers' { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex ($Item.Value) { '^%SystemRoot%\\system32\\' { $_ -replace '%SystemRoot%',"$($env:SystemRoot)"; break; } default { $_; } } ) -Force -PassThru break } WMI { if ($Item.Value) { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $( Switch -Regex (($Item.Value -replace '"','')) { '^%SystemRoot%\\system32\\' { $_ -replace '%SystemRoot%',"$($env:SystemRoot)"; break; } default { $_; } } ) -Force -PassThru } else { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value $null -Force -PassThru } break } 'PowerShell Profiles' { $Item | Add-Member -MemberType NoteProperty -Name ImagePath -Value "$($Item.Value)" -Force -PassThru break } default { } } } } End {} } Function Add-PSAutoRunExtendedInfo { [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeLine)] [system.object[]]$RawAutoRun ) Begin {} Process { $RawAutoRun | ForEach-Object { $o = [pscustomobject]@{ Path = $_.Path ; Item = $_.Item ; Category = $_.Category ; Value = $_.Value ImagePath = $_.ImagePath ; Size = $null; LastWriteTime = $null; Version = $null; } If ($_.ImagePath) { try { $extinfo = Get-Item -Path $_.ImagePath -ErrorAction Stop $o.Size = $extinfo.Length; $o.Version = $extinfo.VersionInfo.ProductVersion; $o.LastWriteTime = $extinfo.LastWriteTime; $o } catch { $o } } else { $o } } } End{} } Function Add-PSAutoRunHash { [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeLine)] [system.object[]]$RawAutoRun, [Switch]$ShowFileHash ) Begin {} Process { $RawAutoRun | ForEach-Object { If ($ShowFileHash) { if ($_.ImagePath) { If (Test-Path -Path $($_.ImagePath) -PathType Leaf -ErrorAction SilentlyContinue) { $_ | Add-Member -MemberType NoteProperty -Name MD5 -Value $( (Get-FileHash -Path $($_.ImagePath) -Algorithm MD5).Hash ) -Force -PassThru | Add-Member -MemberType NoteProperty -Name SHA1 -Value $( (Get-FileHash -Path $($_.ImagePath) -Algorithm SHA1).Hash ) -Force -PassThru | Add-Member -MemberType NoteProperty -Name SHA256 -Value $( (Get-FileHash -Path $($_.ImagePath) -Algorithm SHA256).Hash ) -Force -PassThru } else { $_ | Add-Member -MemberType NoteProperty -Name MD5 -Value $null -Force -PassThru | Add-Member -MemberType NoteProperty -Name SHA1 -Value $null -Force -PassThru | Add-Member -MemberType NoteProperty -Name SHA256 -Value $null -Force -PassThru } } else { $_ | Add-Member -MemberType NoteProperty -Name MD5 -Value $null -Force -PassThru | Add-Member -MemberType NoteProperty -Name SHA1 -Value $null -Force -PassThru | Add-Member -MemberType NoteProperty -Name SHA256 -Value $null -Force -PassThru } } else { $_ } } } End {} } Function Add-PSAutoRunAuthentiCodeSignature { [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeLine)] [system.object[]]$RawAutoRun, [Switch]$VerifyDigitalSignature ) Begin {} Process { $RawAutoRun | ForEach-Object { If ($VerifyDigitalSignature) { if ($_.ImagePath) { If (Test-Path -Path $_.ImagePath -PathType Leaf -ErrorAction SilentlyContinue) { ## Add the signature status to the entry $signature = Get-AuthenticodeSignature -FilePath $_.ImagePath -ErrorAction Stop $signed = switch ($signature.Status) { 'Valid' { $true break } 'NotSigned' { $false break } default { $false } } $_ = $_ | Add-Member -MemberType NoteProperty -Name Signed -Value $signed -Force -PassThru ## Add a note whether this is an OS binary to allow for easy filtering: ## Get-PSAutorun -VerifyDigitalSignature | ? { -not $_.IsOSBinary } if($signature.IsOSBinary) { $_ = $_ | Add-Member -MemberType NoteProperty -Name IsOSBinary -Value $signature.IsOSBinary -Force -PassThru } ## Add the signer itself $_ | Add-Member -MemberType NoteProperty -Name Publisher -Value $signature.SignerCertificate.Subject -Force -PassThru } else { $_ = $_ | Add-Member -MemberType NoteProperty -Name Signed -Value $null -Force -PassThru $_ = $_ | Add-Member -MemberType NoteProperty -Name IsOSBinary -Value $null -Force -PassThru $_ | Add-Member -MemberType NoteProperty -Name Publisher -Value $null -Force -PassThru } } else { $_ = $_ | Add-Member -MemberType NoteProperty -Name Signed -Value $null -Force -PassThru $_ = $_ | Add-Member -MemberType NoteProperty -Name IsOSBinary -Value $null -Force -PassThru $_ | Add-Member -MemberType NoteProperty -Name Publisher -Value $null -Force -PassThru } } else { $_ } } } End{} } #endregion Helperfunctions } Process { Switch ($PSCmdlet.ParameterSetName) { 'Plain' { Get-PSRawAutoRun @PSBoundParameters break } 'Pretty' { if ($PSBoundParameters.ContainsKey('ShowFileHash')) { $GetHash = $true } else { $GetHash = $false } if ($PSBoundParameters.ContainsKey('VerifyDigitalSignature')) { $GetSig = $true } else { $GetSig = $false } if ($PSBoundParameters.ContainsKey('User')) { $null = $PSBoundParameters.Remove('User') } $PSBoundParameters.Add('User',$Users) Get-PSRawAutoRun @PSBoundParameters | Get-PSPrettyAutorun | Add-PSAutoRunExtendedInfo | Add-PSAutoRunHash -ShowFileHash:$GetHash | Add-PSAutoRunAuthentiCodeSignature -VerifyDigitalSignature:$GetSig break } default {} } } End {} } <# Get-PSAutorun -BootExecute -AppinitDLLs Get-PSAutorun -All | Format-Table -Property Path,ImagePath,Category Get-PSAutorun -Logon -LSAsecurityProviders | Format-Table -Property Path,ImagePath,Category Get-PSAutorun -All -ShowFileHash -VerifyDigitalSignature Get-PSAutorun -ServicesAndDrivers | ? path -match 'OSE' | fl * Get-PSAutorun -ServicesAndDrivers | ? path -match 'sysmon' | fl * Get-PSAutorun -ServicesAndDrivers | ? path -match 'psexesvc' | fl * Get-PSAutorun -OfficeAddins | Format-Table -Property Path,ImagePath,Category Get-PSAutorun -WMI -VerifyDigitalSignature | Where { -not $_.isOSBinary } # From 11.70 to 12.0 +HKLM\SYSTEM\CurrentControlSet\Control\Lsa\OSConfig\Security Packages +WMI Database Entries # From 12.0 to 12.3 -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\System -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SaveDumpStart +HKCU\SOFTWARE\Classes\Htmlfile\Shell\Open\Command\(Default) +HKLM\SOFTWARE\Classes\Htmlfile\Shell\Open\Command\(Default) # From 12.3 to 13.4 +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GpExtensions +HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\AlternateShells\AvailableShells +HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run +HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnce +HKCU\Software\Classes\Clsid\{AB8902B4-09CA-4bb6-B78D-A8F59079A8D5}\Inprocserver32 +Office Addins # From 13.4 to 13.5 +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Font Drivers # From 13.5 to 13.51 +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx +HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx +HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnceEx +HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx +HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\RunOnceEx +HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx # From 13.51 to 13.61 +HKLM\SOFTWARE\Microsoft\Office test\Special\Perf\(Default) +HKCU\SOFTWARE\Microsoft\Office test\Special\Perf\(Default) # From 13.61 to 13.62 +HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages # From 13.62 to 13.7 +HKLM\SYSTEM\CurrentControlSet\Control\Print\Providers # From 13.71 to 13.80 +HKCU\Environment\UserInitMprLogonScript +HKLM\Environment\UserInitMprLogonScript # From 13.80 to 13.82 +HKLM\Software\Microsoft\Office\Onenote\Addins +HKCU\Software\Microsoft\Office\Onenote\Addins +HKLM\Software\Wow6432Node\Microsoft\Office\Onenote\Addins +HKCU\Software\Wow6432Node\Microsoft\Office\Onenote\Addins -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AppSetup -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Runonce -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx -HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run -HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Runonce -HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx -HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run -HKLM\System\CurrentControlSet\Control\ServiceControlManagerExtension # From 13.82 to 13.90 -AppData\Local\Microsoft\Windows Sidebar\Settings.ini +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AppSetup +HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Startup +HKCU\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Shutdown +HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logon +HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy\Scripts\Logoff +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Runonce +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx +HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run +HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Runonce +HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\RunonceEx +HKCU\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\Install\Software\Microsoft\Windows\CurrentVersion\Run #> Function Get-NewAutoRunsFlatArtifact { <# .SYNOPSIS Get a flat autoruns artifact .DESCRIPTION Get a flat autoruns artifact as strings sent into the output stream to be stored in a .ps1 file .PARAMETER InputObject Objects produced by the Get-PSAutorun function .PARAMETER NoEnd Switch to indicate that it should not append a last comma #> [CmdletBinding()] Param( [Parameter(Mandatory,ValueFromPipeline)] [object[]]$InputObject, [switch]$NoEnd ) Begin{} Process { $properties = $InputObject | Select-Object -First 1 | ForEach-Object { $_.PSObject.Properties }| Select-Object -Expand Name Write-Verbose -Message "Found $($properties)" $InputObject | ForEach-Object -Process { $Item = $_ Write-Verbose -Message "Item: $($Item)" $properties | ForEach-Object -Begin { ' [PSCustomObject]@{' } -Process { $p = $_ Write-Verbose -Message "Dealing with $($p)" if ($null -ne $Item.$p) { Switch ($Item.$p) { {$_ -is [string]} { Write-Verbose -Message "Its value $($Item.$p) is a String" " {0}='{1}'" -f $p,[Management.Automation.Language.CodeGeneration]::EscapeSingleQuotedStringContent($Item.$p) break } {$_ -eq [string]::Empty} { Write-Verbose -Message "Its value $($Item.$p) is an empty String" " {0}=''" -f $p break } {$_ -is [long]} { Write-Verbose -Message "Its value $($Item.$p) is an Long" ' {0}=[long]{1}' -f $p,$Item.$p break } {$_ -is [DateTime]} { Write-Verbose -Message "Its value $($Item.$p) is a DateTime" ' {0}=[datetime]{1} # {2}' -f $p,$Item.$p.Ticks,$Item.$p.ToString('u') break } {$_ -is [bool]} { Write-Verbose -Message "Its value $($Item.$p) is a Boolean" " {0}=[bool]'{1}'" -f $p,$Item.$p } default { Write-Warning -Message "Shouldn't be here for $($p) = $($Item.$p)" } } } else { ' {0}=$null' -f $p } } -End { if ($NoEnd) { ' }' } else { ' },' } } } } End {} } Function New-AutoRunsBaseLine { <# .SYNOPSIS Create a baseline file from Autoruns artifact(s). .DESCRIPTION Create a baseline from Autoruns artifact(s) as a PowerShell script (.ps1) file. .PARAMETER InputObject Objects produced by the Get-PSAutorun function .PARAMETER FilePath String that indicates an alternative file location. #> [CmdletBinding(SupportsShouldProcess)] Param( [Parameter(Mandatory,ValueFromPipeline)] [object[]]$InputObject, [Parameter()] [string]$FilePath = "~/Documents/PSAutoRunsBaseLine-$((Get-Date).ToString('yyyyMMddHHmmss')).ps1" ) Begin { $Count = 0 $Results = New-Object -TypeName System.Collections.ArrayList if ($PSBoundParameters.Keys.Contains('InputObject')) { $FromPipeLine = $false } else { $FromPipeLine = $true } $OFHT = @{ ErrorAction = 'Stop' FilePath = "$($FilePath)" NoClobber = ([switch]::Present) Force = ([switch]::Present) Encoding = 'UTF8' Append = $false } } Process { $InputObject | ForEach-Object { $Count++ if ($Count -eq 1) { $First = $_ } if ($Count -ge 2) { $null = $Results.Add( ($_ | Get-NewAutoRunsFlatArtifact -Verbose:$false) ) } } } End { try { $( '@(' if ($Count -eq 1) { $InputObject | Get-NewAutoRunsFlatArtifact -Verbose:$false -NoEnd } elseif ($Count -eq 2) { $First | Get-NewAutoRunsFlatArtifact -Verbose:$false if ($FromPipeLine) { $InputObject | Get-NewAutoRunsFlatArtifact -Verbose:$false -NoEnd } else { $InputObject[1] | Get-NewAutoRunsFlatArtifact -Verbose:$false -NoEnd } } elseif ($Count -gt 2) { $First | Get-NewAutoRunsFlatArtifact -Verbose:$false $Results[0..$($Results.Count - 2)] if ($FromPipeLine) { $InputObject | Get-NewAutoRunsFlatArtifact -Verbose:$false -NoEnd } else { $InputObject[-1] | Get-NewAutoRunsFlatArtifact -Verbose:$false -NoEnd } } ')' ) | Out-File @OFHT Write-Verbose -Message "PSAutoRunsBaseLine $($FilePath) successfully created" } catch { Write-Warning -Message "Failed to create baseline because $($_.Exception.Message)" } } } Function Compare-AutoRunsBaseLine { <# .SYNOPSIS Compare two baseline files of Autoruns artifact(s). .DESCRIPTION Compare two baseline files of Autoruns artifact(s). .PARAMETER ReferenceBaseLineFile String that indicates the location of a baseline file. .PARAMETER DifferenceBaseLineFile String that indicates the location of the other baseline file. #> [CmdletBinding()] Param( [Parameter()] [string]$ReferenceBaseLineFile = "$((Get-Item -Path ~/Documents/PSAutoRunsBaseLine*.ps1 | Select-Object -First 1).FullName)", [Parameter()] [string]$DifferenceBaseLineFile = "$((Get-Item -Path ~/Documents/PSAutoRunsBaseLine*.ps1 | Select-Object -First 2 | Select-Object -Last 1).FullName)" ) Begin { Write-Verbose -Message "Reference file set to $($ReferenceBaseLineFile)" Write-Verbose -Message "Difference file set to $($DifferenceBaseLineFile)" $L1 = . $ReferenceBaseLineFile $L2 = . $DifferenceBaseLineFile $Props = 'Path','Item','Category','Value','ImagePath','Size','LastWriteTime','Version', 'MD5','SHA1','SHA256','Signed','IsOSBinary','Publisher' } Process {} End { Compare-Object -ReferenceObject $L1 -DifferenceObject ($L2) -Property $Props } } ================================================ FILE: LICENSE ================================================ AutoRuns is provided under the 3-clause BSD license below. ************************************************************* Copyright (c) 2016, Emin Atac All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ AutoRuns PowerShell Module ========================== **AutoRuns module was designed to help do live incident response and enumerate autoruns artifacts that may be used by legitimate programs as well as malware to achieve persistence.** ## Table of Contents * [Usage](#Usage) * [Install the module](#Install) * [Functions](#Functions) * [Help](#Help) * [Issues](#issues) * [Todo](#Todo) * [Credits](#Credits) * [Original Autoruns doc](#AutorunsDoc) * [Original Autoruns.exe release history](#AutorunsHistory) ## Usage ### Install the module The module is located on the [PowerShellGallery](https://www.powershellgallery.com/packages/AutoRuns/14.0.2) ```powershell # Check the module on powershellgallery.com using PowerShellGet cmdlets Find-Module -Name Autoruns -Repository PSGallery ``` ``` Version Name Repository Description ------- ---- ---------- ----------- 14.0.2 AutoRuns PSGallery AutoRuns is a module ... ``` ```powershell # Save the module locally in Downloads folder Save-Module -Name AutoRuns -Repository PSGallery -Path ~/Downloads ``` Stop and please review the content of the module, I mean the code to make sure it's trustworthy :-) You can also verify that the SHA256 hashes of downloaded files match those stored in the catalog file ```powershell $HT = @{ CatalogFilePath = "~/Downloads/AutoRuns/14.0.2/AutoRuns.cat" Path = "~/Downloads/AutoRuns/14.0.2" Detailed = $true FilesToSkip = 'PSGetModuleInfo.xml' } Test-FileCatalog @HT ``` ```powershell # Import the module Import-Module ~/Downloads/AutoRuns/14.0.2/AutoRuns.psd1 -Force -Verbose ``` ### Check the command available ```powershell Get-Command -Module AutoRuns ``` ``` CommandType Name Version Source ----------- ---- ------- ------ Function Compare-AutoRunsBaseLine 14.0.2 AutoRuns Function Get-PSAutorun 14.0.2 AutoRuns Function New-AutoRunsBaseLine 14.0.2 AutoRuns ``` ### Find the syntax #### Get-PSAutorun ```powershell # View the syntax of Get-PSAutorun Get-Command Get-PSAutorun -Syntax Get-PSAutorun [-All] [-BootExecute] [-AppinitDLLs] [-ExplorerAddons] [-ImageHijacks] [-InternetExplorerAddons] [-KnownDLLs] [-Logon] [-Winsock] [-Codecs] [-OfficeAddins] [-PrintMonitorDLLs] [-LSAsecurityProviders] [-ServicesAndDrivers] [-ScheduledTasks] [-Winlogon] [-WMI] [-PSProfiles] [-ShowFileHash] [-VerifyDigitalSignature] [-User ] [] Get-PSAutorun [-All] [-BootExecute] [-AppinitDLLs] [-ExplorerAddons] [-ImageHijacks] [-InternetExplorerAddons] [-KnownDLLs] [-Logon] [-Winsock] [-Codecs] [-OfficeAddins] [-PrintMonitorDLLs] [-LSAsecurityProviders] [-ServicesAndDrivers] [-ScheduledTasks] [-Winlogon] [-WMI] [-PSProfiles] [-Raw] [-User ] [] ``` #### New-AutoRunsBaseLine ```powershell # View the syntax of New-AutoRunsBaseLine Get-Command New-AutoRunsBaseLine -Syntax New-AutoRunsBaseLine [-InputObject] [[-FilePath] ] [-WhatIf] [-Confirm] [] ``` #### Compare-AutoRunsBaseLine ```powershell # View the syntax of Compare-AutoRunsBaseLine Get-Command Compare-AutoRunsBaseLine -Syntax Compare-AutoRunsBaseLine [[-ReferenceBaseLineFile] ] [[-DifferenceBaseLineFile] ] [] ``` ### View examples provided in the help #### Get-PSAutorun ```powershell # Get examples from the help Get-Help Get-PSAutorun -Examples NAME Get-PSAutorun SYNOPSIS Get Autorun entries. -------------------------- EXAMPLE 1 -------------------------- PS C:\>Get-PSAutorun -BootExecute -AppinitDLLs -------------------------- EXAMPLE 2 -------------------------- PS C:\>Get-PSAutorun -KnownDLLs -LSAsecurityProviders -ShowFileHash -------------------------- EXAMPLE 3 -------------------------- PS C:\>Get-PSAutorun -All -ShowFileHash -VerifyDigitalSignature -------------------------- EXAMPLE 4 -------------------------- PS C:\>Get-PSAutorun -All -User * -ShowFileHash -VerifyDigitalSignature ``` #### New-AutoRunsBaseLine ```powershell # Piping the filtered output of the Get-PSAutorun to the New-AutoRunsBaseLine function will create a .ps1 file in ~/Documents Get-PSAutorun -VerifyDigitalSignature | Where { -not($_.isOSbinary)} | New-AutoRunsBaseLine -Verbose # On Windows PowerShell, you can use the Out-GridView cmdlet to run and view the content of the file created ~\Documents\PSAutoRunsBaseLine-20201102214715.ps1 | Out-GridView -PassThru ``` #### Compare-AutoRunsBaseLine ```powershell # You need two files in ~/Documents generated by the New-AutoRunsBaseLine function Compare-AutoRunsBaseLine -Verbose ``` ## Issues * What are registrations in the WMI\Default namespace introduced in Autoruns v13.7? see [c7eab48c77f578e0dcff61d2b46a479b28225a56](https://github.com/p0w3rsh3ll/AutoRuns/commit/c7eab48c77f578e0dcff61d2b46a479b28225a56) * If you run PowerShell 5.1 and Applocker in allow mode, you need to add a local appplocker rule that allows the module to be loaded. The module files aren't signed anymore with a DigiCert certificate. If your corporate admin has turned off local group policy objects processing on a domain joined device, you'll need to add the trusted publisher rule in a Domain group policy. ```powershell gp 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System' -Name DisableLGPOProcessing -EA 0 ``` ## Todo #### Coding best practices - [x] Use PSScriptAnalyzer module to validate the code follows best practices - [x] Write Pester tests for this module #### OS and Software compatibility - [x] Test the module in PowerShell Core 7.x (latest) - [ ] Test the module on various versions of Windows 10 - [x] 21H2 - [x] 22H2 - [x] Test the module on various versions of Windows 11 - [x] 21H2 - [x] 22H2 - [ ] Review Office Add-ins code with Office x86 and x64 versions #### General improvements - [ ] Write a better implementation of the internal Get-RegValue function - [ ] Review and improve regex used by the internal Get-PSPrettyAutorun function (ex: external paths) #### New features - [x] Replace HKCU and add an option to specify what user hive is being investigated - [ ] Add timestamps on registry keys - [ ] Analyze an offline image of Windows - [x] Create a baseline of artifacts - [x] Compare two baselines of artifacts #### Help - [ ] More examples - [ ] Use external help? - [ ] Internationalization? - [ ] Copy the changelog at the end of the module in README.md - [x] Document issues and write a pester tests to validate the module behavior if fixed ## Credits Thanks go to: * **[@LeeHolmes](https://github.com/LeeHolmes/)**: * Improving common parameters [7fe8e7ea983325b5543da1300cb8a4636c7062ef](https://github.com/p0w3rsh3ll/AutoRuns/commit/7fe8e7ea983325b5543da1300cb8a4636c7062ef) * Filtering OS binaries [8efb0fad4585ecd4517b55ff5b5cec91f7dd364a](https://github.com/p0w3rsh3ll/AutoRuns/commit/8efb0fad4585ecd4517b55ff5b5cec91f7dd364a) ```powershell Get-PSAutorun -VerifyDigitalSignature | ? { -not $_.IsOSBinary } ``` ## Other links - [https://live.sysinternals.com](https://live.sysinternals.com/) - [https://docs.microsoft.com/en-us/sysinternals](https://docs.microsoft.com/en-us/sysinternals/) - [https://docs.microsoft.com/en-us/archive/blogs/sysinternals](https://docs.microsoft.com/en-us/archive/blogs/sysinternals/) ## Original [Autoruns.exe](https://docs.microsoft.com/en-us/sysinternals/downloads/autoruns) from Mark Russinovich [Autoruns v14.1](https://techcommunity.microsoft.com/t5/sysinternals-blog/sysmon-v15-0-autoruns-v14-1-and-process-monitor-v3-95/ba-p/3857916) >This update to Autoruns, a utility for monitoring startup items, fixes a bug with detecting non-shortcut files in startup folders, fixes a bug with handling non-UNC, non-absolute paths, and improves theming support. [Autoruns v14.09](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-09-procmon-v3-89-sysmon-v13-33-and-zoomit-v5-10/ba-p/3176054) >This Autoruns update fixes a bug preventing the enabling/disabling of startup folder items. [Autoruns v14.08](https://techcommunity.microsoft.com/t5/sysinternals-blog/zoomit-v5-0-rdcman-v2-90-autoruns-procmon-tcpview-vmmap-sysmon/ba-p/3075276) >This Autoruns update fixes a series of application crashes, now correctly parses paths with spaces passed as command line arguments and improves .arn import functionality. [Autoruns v14.07](https://techcommunity.microsoft.com/t5/sysinternals-blog/adexplorer-v1-51-autoruns-v14-07-cacheset-v1-02-process-monitor/ba-p/3040515) >This Autoruns update can open .arn files from the command line, fixes RunDll32 parameter handling in some cases, supports toggling Active Setup entries, fixes a crash when no ProcExp can be found in the path and improves 32/64 bit redirection. [Autoruns v14.06](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-06-and-sysmon-v13-30/ba-p/2887598) >This Autoruns release fixes a crash happening for scheduled tasks containing spaces. [Autoruns v14.05](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-05/ba-p/2844204) >This update for Autoruns addresses a bug preventing opening and comparing .arn files. [Autoruns v14.04](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-04-high-dpi-icons-for-winobj-tcpview-process/ba-p/2839719) >This update for Autoruns adds a series of display/theme fixes, restores autorunsc, fixes a regression for rundll32 entries, limits per-user scans to the user locations, fixes Microsoft entry hiding and adds a high DPI application icon. [Autoruns v14.03](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-03/ba-p/2800248) >This update for Autoruns restores entries previously shown in v13.100, improves Wow64 redirection handling and entry name resolution. [Autoruns v14.02](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-02-winobj-v3-12-tcpview-v4-15-and-process-monitor/ba-p/2775709) >Autoruns, a utility for monitoring startup items, receives a series of UI improvements related to the dark theme and general Windows 10 tweaks, VirusTotal and signed files regressions fixes. [Autoruns v14.01](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-01/ba-p/2708458) >This update for Autoruns fixes a regression with VirusTotal submissions introduced in v14.0. [Autoruns v14.0](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v14-0-rdcman-v2-83-procdump-v10-11-dark-theme-updates/ba-p/2661936) >Autoruns, a utility for monitoring startup items, is the latest Sysinternals tool to receive a UI overhaul including a dark theme. [Autoruns v13.100](https://techcommunity.microsoft.com/t5/sysinternals-blog/autoruns-v13-100/ba-p/2282998) >This update to Autoruns fixes a crash reported in v13.99. [Autoruns v13.99](https://techcommunity.microsoft.com/t5/sysinternals-blog/procmon-v3-70-sysmon-v13-10-autoruns-v13-99-tcpview-v4-01-and/ba-p/2280263) >This update to Autoruns fixes a bug that resulted in some empty locations being hidden when the Include Empty Locations option is selected. [Autoruns v13.98](https://techcommunity.microsoft.com/t5/sysinternals-blog/sysmon-v11-10-sigcheck-v2-80-autoruns-v13-98/ba-p/1485287) >This release of Autoruns resolves an issue where Microsoft Defender binaries were being flagged as unsigned. [Autoruns v13.95](https://blogs.technet.microsoft.com/sysinternals/2019/06/12/sysmon-v10-0-autoruns-v13-95-vmmap-v3-26/) >This Autoruns update adds support for user Shell folders redirections. [Autoruns v13.94](https://blogs.technet.microsoft.com/sysinternals/2019/02/19/sysmon-v9-0-autoruns-v13-94/) >This Autoruns update fixes a bug that prevented the correct display of the target of image hosts such as svchost.exe, rundll32.exe, and cmd.exe. [Autoruns v13.93](https://blogs.technet.microsoft.com/sysinternals/2018/12/09/autoruns-v13-93-handle-v4-21-process-explorer-v16-22-sdelete-v2-02-sigcheck-v2-71-sysmon-v8-02-and-vmmap-v3-25/) >This Autoruns update fixes a bug that prevented UserInitMprLogonScript from being scanned and by-default enables HCKU scanning for the console version. [Autoruns v13.90](https://blogs.technet.microsoft.com/sysinternals/2018/07/05/sysmon-v8-0-autoruns-v13-90/) >Autoruns, a comprehensive Windows autostart entry point (ASEP) manager, now includes Runonce\*\Depend keys and GPO logon and logoff locations, as well as fixes a bug in WMI path parsing. [Autoruns v13.82](https://blogs.technet.microsoft.com/sysinternals/2018/02/17/process-monitor-v3-50-autoruns-v13-82-du-v1-61-sdelete-v2-01/) >This Autoruns release shows Onenote addins and fixes several bugs. [Autoruns v13.81](https://blogs.technet.microsoft.com/sysinternals/2017/12/12/autoruns-v13-81-bginfo-v423-handle-v4-11/) > This update to Autoruns fixes a Wow64 bug in Autorunsc that could cause 32-bit paths to result in 'file not found' errors, and expands the set of images not considered part of Windows for the Windows filter in order to reveal malicious files masquerading as Windows images [Autoruns v13.80](https://blogs.technet.microsoft.com/sysinternals/2017/09/12/sysinternals-update-sysmon-v6-1-process-monitor-v3-4-autoruns-v13-8-accesschk-v6-11/) > This release of Autoruns, a utility for viewing and managing autostart execution points (ASEPs), adds additional autostart entry points, has asynchronous file saving, fixes a bug parsing 32-bit paths on 64-bit Windows, shows the display name for drivers and services, and fixes a bug in offline Virus Total scanning. [Autoruns v13.71](https://blogs.technet.microsoft.com/sysinternals/2017/05/16/sysinternals-update-procdump-v9-autoruns-v13-71-bginfo-v4-22-livekd-v5-62-process-monitor-v3-33-process-explorer-v16-21/) > This update to Autoruns, a comprehensive autostart execution point manager, adds Microsoft HTML Application Host (mshta.exe) as hosting image so it displays the hosted image details, and now doesn’t apply filters to hosting images. [Autoruns v13.7](https://blogs.technet.microsoft.com/sysinternals/2017/02/17/update-sysmon-v6-autoruns-v13-7-accesschk-v6-1-process-monitor-v3-32-process-explorer-v16-2-livekd-v5-61-and-bginfo-v4-21/) > Autoruns, an autostart entry point management utility, now reports print providers, registrations in the WMI\Default namespace, fixes a KnownDLLs enumeration bug, and has improved toolbar usability on high-DPI displays. [Autoruns v13.51](https://blogs.technet.microsoft.com/sysinternals/2016/01/05/update-sigcheck-v2-4-sysmon-v3-2-process-explorer-v16-1-autoruns-v13-51-accesschk-v6-01/) > This release of Autoruns, a comprehensive autostart entry manager, fixes a WMI command-line parsing bug, emits a UNICODE BOM in the file generated when saving results to a text file, and adds back the ability to selectively verify the signing status of individual entries. [Autoruns v13.5](https://blogs.technet.microsoft.com/sysinternals/2015/10/26/update-autoruns-v13-5-sigcheck-v2-3-rammap-v1-4-bginfo-v4-21-sysmon-v3-11-adinsight-v1-2/) >This update to Autoruns, the most comprehensive autostart viewer and manager available for Windows, now shows 32-bit Office addins and font drivers, and enables resubmission of known images to Virus Total for a new scan. [Autoruns v13.4](https://blogs.technet.microsoft.com/sysinternals/2015/05/26/update-accesschk-v6-0-autoruns-v13-4-process-monitor-v3-2-vmmap-v3-2/) >Autoruns, the most comprehensive utility available for showing what executables, DLLs, and drivers are configured to automatically start and load, now reports Office addins, adds several additional autostart locations, and no longer hides hosting executables like cmd.exe, powershell.exe and others when Windows and Microsoft filters are in effect. [Autoruns v13.3](https://blogs.technet.microsoft.com/sysinternals/2015/04/20/update-sysmon-v3-0-autornus-v13-3-regjump-v1-1-process-monitor-v3-11/) >Autoruns, a utility that shows what processes, DLLs, and drivers are configured to automatically load, adds reporting of GP extension DLLs and now shows the target of hosting processes like cmd.exe and rundll32.exe. [Autoruns v13.2](https://blogs.technet.microsoft.com/sysinternals/2015/03/10/update-livekd-v5-4-autoruns-v13-2-sigcheck-v2-2-process-explorer-v16-05/) >In addition to bug fixes to CSV and XML output, Autorunsc introduces import-hash reporting, and Autoruns now excludes command-line and other host processes from the Microsoft and Windows filters. [Autoruns v13.01](https://blogs.technet.microsoft.com/sysinternals/2015/02/09/update-autoruns-v13-01/) >This release fixes a bug in v13 that caused autostart entry lines not to show when you enter a filter string into the toolbar's filter control [Autoruns v13.0](https://blogs.technet.microsoft.com/sysinternals/2015/01/29/update-autoruns-v13-0/) > This major update to Autoruns, an autostart execution point (ASEP) manager, now has integration with Virustotal.com to show the status of entries with respect to scans by over four dozen antimalware engines. It also includes a revamped scanning architecture that supports dynamic filters, including a free-form text filter, a greatly improved compare feature that highlights not just new items but deleted ones as well, and file saving and loading that preserves all the information of a scan [Autoruns v12.03](https://blogs.technet.microsoft.com/sysinternals/2014/09/11/updates-handle-v4-0-procdump-v7-01-procexp-v16-04-regjump-v1-02-autoruns-v12-03/) >This update to Autoruns adds the registered HTML file extension, fixes a bug that could cause disabling of specific entry types to fail with a “path not found” error, and addresses another that could prevent the Jump-to-image function from opening the selected image on 64-bit Windows. [Autoruns v12.02](https://blogs.technet.microsoft.com/sysinternals/2014/08/19/updates-autoruns-v12-02-coreinfo-v3-31-sysmon-v1-01-whois-v1-12/) >This fixes a bug that could cause Autoruns to crash on startup, updates the image path parsing for Installed Components to remove false positive file-not-found entries, and correctly reports image entry timestamps in local time instead of UTC. [Autoruns v12.01](https://blogs.technet.microsoft.com/sysinternals/2014/08/08/new-sysmon-v1-0-updates-autoruns-v12-01-coreinfo-v3-3-procexp-v16-03/) >This update to Autoruns, a utility that comes in Windows application and command-line forms, has numerous bug fixes, adds a profile attribute/column to CSV and XML output, and interprets the CodeBase value for COM object registrations. [Autoruns v12.0](https://blogs.technet.microsoft.com/sysinternals/2014/05/13/updates-autoruns-v12-0-procdump-v7-0/) >This release of Autoruns, a Windows application and command-line utility for viewing autostart entries, now reports the presence of batch file and executable image entries in the WMI database, a vector used by some types of malware. [Autoruns v11.70](https://blogs.technet.microsoft.com/sysinternals/2013/08/01/autoruns-v11-70-bginfo-v4-20-disk2vhd-v1-64-process-explorer-v15-40/) >This release of Autoruns, a powerful utility for scanning and disabling autostart code, adds a new option to have it show only per-user locations, something that is useful when analyzing the autostarts of different accounts than the one that Autoruns is running under. [Autoruns v11.62](https://blogs.technet.microsoft.com/sysinternals/2013/07/01/update-autoruns-v11-62/) >This release fixes a bug in version 11.61’s jump-to-image functionality. ================================================ FILE: Tests/AutoRuns.Tests.ps1 ================================================ <# Use some Pester tests to find out if the internal Get-PSPrettyAutorun function: -implements fixes -doesn't introduce new issues We want for example to test that the regular expressions inside the Get-PSPrettyAutorun function work against some known (fixed) issues Use the AST to find and extract the Get-PSPrettyAutorun function and load it into a fake module as a function because it's harmless #> #region use AST to fake module $Ast = $File = $predicate = $sb = $flat = $null $File = (Resolve-Path $PSScriptRoot\..\AutoRuns.psm1).Path $Ast = [scriptblock]::Create((Get-Content -Path $File -Raw)).Ast [ScriptBlock] $predicate = { Param ([System.Management.Automation.Language.Ast] $Ast) $Ast -is [System.Management.Automation.Language.FunctionDefinitionAst] } # Parse the AST recursively and find all functions $sb = New-Object System.Text.StringBuilder $AST.FindAll($predicate,$true) | ForEach-Object { $null = $sb.Append("function $($_.Name) { $($_.Body.GetScriptBlock()) }`n") } $null = $sb.Append("Export-ModuleMember -Function '*'") $flat = [scriptblock]::Create($sb.ToString()) Remove-Module -Name FakeAutoRuns -Force -ErrorAction SilentlyContinue New-Module -Name FakeAutoRuns -ScriptBlock ($flat.GetNewClosure()) | Import-Module -Force -Verbose:$false #endregion InModuleScope FakeAutoRuns { #region Boot Execute Describe 'Testing Get-PSPrettyAutorun for BootExecute' -Tag 'BootExecute' { # https://github.com/p0w3rsh3ll/AutoRuns/issues/100 It 'issue 100 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Control\Session Manager' Item = 'SetupExecute' Category = 'Boot Execute' Value = 'C:\Windows\System32\poqexec.exe /display_progress \SystemRoot\WinSxS\pending.xml' } } -ParameterFilter { $BootExecute -eq [switch]::Present } $i = (Get-PSRawAutoRun -BootExecute | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\System32\poqexec.exe' | should be $true } } #endregion #region Print Monitors Describe 'Testing Get-PSPrettyAutorun for Print Monitors' -Tag 'PrintMonitorDLLs' { # Fix the ImagePath of Printer port #74 # https://github.com/p0w3rsh3ll/AutoRuns/issues/74 It 'issue 74 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports' Item = 'Port' Category = 'Print Monitors' Value = 'C:\windows\tracing\myport.txt' } } -ParameterFilter { $PrintMonitorDLLs -eq [switch]::Present } $i = (Get-PSRawAutoRun -PrintMonitorDLLs | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\windows\tracing\myport.txt' | should be $true } } #endregion #region ScheduledTasks Describe 'Testing ScheduledTasks' -Tag 'ScheduledTasks' { Context 'Inside Add-PSAutoRunHash' { It 'issue 80 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\ConfigAppIdSvc' Item = 'ConfigAppIdSvc' Category = 'Task' Value = 'whatever' # ImagePath = '-Command "& ''C:\Users\username\Documents\script.ps1' ImagePath = 'C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -Exec Bypass -Command "Set-Service -Name AppIDSvc -StartupType Automatic"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } { Get-PSRawAutoRun -ScheduledTasks | Add-PSAutoRunHash -ShowFileHash -ErrorAction Stop } | should not throw } } Context 'Inside Add-PSAutoRunAuthentiCodeSignature' { It 'issue 82 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\ConfigAppIdSvc' Item = 'ConfigAppIdSvc' Category = 'Task' Value = 'whatever' # ImagePath = '-Command "& ''C:\Users\username\Documents\script.ps1' ImagePath = 'C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -Exec Bypass -Command "Set-Service -Name AppIDSvc -StartupType Automatic"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } { Get-PSRawAutoRun -ScheduledTasks | Add-PSAutoRunAuthentiCodeSignature -VerifyDigitalSignature -ErrorAction Stop } | should not throw } } # Emulate what Get-PSRawAutoRun -ScheduledTasks returns & pass it to Get-PSPrettyAutorun Context 'Inside Get-PSRawAutoRun' { # Scheduled tasks with multiple programs started #36 # https://github.com/p0w3rsh3ll/AutoRuns/issues/36 It 'issue 36 should be solved' { Mock -CommandName Get-AllScheduledTask -MockWith { return [PSCustomObject]@{ Path = '\' ; Name = 'test' } } Mock -CommandName Get-Task -MockWith { return [PSCustomObject]@{ Path = '\' ; Name = 'test' Xml = @' DontCare MyComputer\UserName \test S-1-5-18 InteractiveToken C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Exec Bypass -Command "test" -File logoff.pS1 -Verbose C:\Windows\system32\wevtutil.exe el '@ } } $i = (Get-PSRawAutoRun -ScheduledTasks | Select-Object -First 1) $j = (Get-PSRawAutoRun -ScheduledTasks | Select-Object -First 2 | Select-Object -Last 1) (($i,$j).Count -eq 2) -and ($j.Value -eq 'C:\Windows\system32\wevtutil.exe el') -and ($i.Value -eq 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Exec Bypass -Command "test" -File logoff.pS1 -Verbose') | Should be $true } } Context 'Inside Get-PSPrettyAutorun' { # https://github.com/p0w3rsh3ll/AutoRuns/issues/114 It 'issue #114 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\NahimicSvc32Run' Item = 'NahimicSvc32Run' Category = 'Task' Value = '"C:\Windows\SysWOW64\NahimicSvc32.exe" $(Arg0) $(Arg1) $(Arg2) $(Arg3) $(Arg4) $(Arg5) $(Arg6) $(Arg7)' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\SysWOW64\NahimicSvc32.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/115 It 'issue #115 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\PI\SecureBootEncodeUEFI' Item = 'SecureBootEncodeUEFI' Category = 'Task' Value = '%WINDIR%\system32\SecureBootEncodeUEFI.exe' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\system32\SecureBootEncodeUEFI.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/109 # Related to issue #96 and 101 It 'issue #109 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = "C:\WINDOWS\system32\Tasks\OneDrive Standalone Update Task-$(([System.Security.Principal.NTAccount]'Administrator').Translate([System.Security.Principal.SecurityIdentifier]).Value)" Item = "OneDrive Standalone Update Task-$(([System.Security.Principal.NTAccount]'Administrator').Translate([System.Security.Principal.SecurityIdentifier]).Value)" Category = 'Task' Value = '%localappdata%\Microsoft\OneDrive\OneDriveStandaloneUpdater.exe' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Users\Administrator\AppData\Local\Microsoft\OneDrive\OneDriveStandaloneUpdater.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/107 It 'issue #107 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\windows\system32\Tasks\HP\Consent Manager Launcher' Item = 'Consent Manager Launcher' Category = 'Task' Value = 'sc start hptouchpointanalyticsservice' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\System32\sc.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/106 It 'issue #106 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\windows\system32\Tasks\Microsoft\Office\Office Feature Updates' Item = 'Office Feature Updates' Category = 'Task' Value = 'C:\Program Files\Microsoft Office\root\Office16\sdxhelper.exe' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\Program Files\Microsoft Office\root\Office16\sdxhelper.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/105 It 'issue #105 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\windows\system32\Tasks\HP\Sure Click\Tray icon 4.3.8.391' Item = 'Tray icon 4.3.8.391' Category = 'Task' Value = 'c:\Program Files\HP\Sure Click\servers\BrConsole.exe' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\HP\Sure Click\servers\BrConsole.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/104 It 'issue #104 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\windows\system32\Tasks\HP\Sure Click\Sure Click 4.3.8.391' Item = 'Sure Click 4.3.8.391' Category = 'Task' Value = 'c:\Program Files\HP\Sure Click\servers\BrLauncher.exe vSentry start' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\HP\Sure Click\servers\BrLauncher.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/103 It 'issue #103 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Mozilla\Firefox Background Update 308046B0AF4A39CB' Item = 'Firefox Background Update 308046B0AF4A39CB' Category = 'Task' Value = 'C:\Program Files\Mozilla Firefox\firefox.exe --MOZ_LOG sync,prependheader,timestamp,append,maxsize:1,Dump:5 --MOZ_LOG_FILE C:\ProgramData\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38\updates\308046B0AF4A39CB\backgroundupdate.moz_log --backgroundtask backgroundupdate' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\Mozilla Firefox\firefox.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/102 It 'issue #102 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\\TaskName' Item = 'TaskName' Category = 'Task' Value = '"C:\Windows\Folder1\Folder2\scriptfile.cmd"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\Folder1\Folder2\scriptfile.cmd' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/101 It 'issue #101 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\\OneDrive Reporting Task-SID' Item = 'OneDrive Reporting Task-SID' Category = 'Task' Value = '%localappdata%\Microsoft\OneDrive\OneDriveStandaloneUpdater.exe /reporting' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'AppData\Local\Microsoft\OneDrive\OneDriveStandaloneUpdater.exe' | should be $true } # Dropbox tasks #63 # https://github.com/p0w3rsh3ll/AutoRuns/issues/63 It 'issue #63.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\DropboxUpdateTaskUserS-1-5-21-SIDCore1d2376bef827e9d' Item = 'DropboxUpdateTaskUserS-1-5-21-SIDCore1d2376bef827e9d' Category = 'Task' Value = 'C:\Users\username\AppData\Local\Dropbox\Update\DropboxUpdate.exe /c' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\Users\username\AppData\Local\Dropbox\Update\DropboxUpdate.exe' | should be $true } It 'issue #63.2 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\DropboxUpdateTaskUserS-1-5-21-SIDUA1d2376befd2c972' Item = 'DropboxUpdateTaskUserS-1-5-21-SIDUA1d2376befd2c972' Category = 'Task' Value = 'C:\Users\username\AppData\Local\Dropbox\Update\DropboxUpdate.exe /ua /installsource scheduler' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\Users\username\AppData\Local\Dropbox\Update\DropboxUpdate.exe' | should be $true } # Lenovo\ImController #61 # https://github.com/p0w3rsh3ll/AutoRuns/issues/61 It 'issue #61 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Lenovo\ImController\Lenovo iM Controller Monitor' Item = 'Lenovo iM Controller Monitor' Category = 'Task' Value = '"%windir%\system32\ImController.InfInstaller.exe" -checkremoval' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\Windows\system32\ImController.InfInstaller.exe' | should be $true } # UninstallSMB1ClientTask & UninstallSMB1ServerTask #62 # https://github.com/p0w3rsh3ll/AutoRuns/issues/62 It 'issue #62.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\SMB\UninstallSMB1ClientTask' Item = 'UninstallSMB1ClientTask' Category = 'Task' Value = '%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NonInteractive -NoProfile -WindowStyle Hidden "& %windir%\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1 -Scenario Client"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose # !! the end of the above value was truncated, we don't have the parameters inside the scriptblock and its ending double quote # $i -eq '%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NonInteractive -NoProfile -WindowStyle Hidden "& %windir%\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1' | should be $true # $i -eq '%windir%\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1' | should be $true $i -eq 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1' | should be $true } It 'issue #62.2 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\SMB\UninstallSMB1ServerTask' Item = 'UninstallSMB1ServerTask' Category = 'Task' Value = '%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NonInteractive -NoProfile -WindowStyle Hidden "& %windir%\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1 -Scenario Server"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose # !! the end of the above value was truncated, we don't have the parameters inside the scriptblock and its ending double quote # $i -eq '%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NonInteractive -NoProfile -WindowStyle Hidden "& %windir%\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1' | should be $true $i -eq 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\SmbShare\DisableUnusedSmb1.ps1' | should be $true } It 'issue #62.3 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\FakeTask' Item = 'FakeTask' Category = 'Task' Value = '%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -NonInteractive -NoProfile -WindowStyle Hidden "C:\fakepathwith a space\FakeScript.ps1"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'C:\fakepathwith a space\FakeScript.ps1' | should be $true } It 'issue #62.4 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\FakeTaskPSEncoded' Item = 'FakeTaskPSEncoded' Category = 'Task' Value = 'powershell.exe -encodedCommand ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'powershell.exe -encodedCommand ZABpAHIAIAAiAGMAOgBcAHAAcgBvAGcAcgBhAG0AIABmAGkAbABlAHMAIgAgAA==' | should be $true } # ImagePath is wrong for scheduled tasks MicTray #60 # https://github.com/p0w3rsh3ll/AutoRuns/issues/60 It 'issue #60 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\Conexant\MicTray' Item = 'MicTray' Category = 'Task' Value = '"C:\Windows\System32\MicTray64.exe"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\System32\MicTray64.exe' | should be $true } # ImagePath is wrong for schelued task SA3 #59 # https://github.com/p0w3rsh3ll/AutoRuns/issues/59 It 'issue #59 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\Conexant\SA3' Item = 'SA3' Category = 'Task' Value = '"C:\Program Files\CONEXANT\SA3\HP-NB-AIO\SACpl.exe" /sa3 /nv:3.0+ /uid:HP-NB-AIO /s /dne' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\CONEXANT\SA3\HP-NB-AIO\SACpl.exe' | should be $true } # Scheduled task issue: CleanupOldPerfLogs #50 # https://github.com/p0w3rsh3ll/AutoRuns/issues/50 It 'issue #50 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\Server Manager\CleanupOldPerfLogs' Item = 'CleanupOldPerfLogs' Category = 'Task' Value = '%systemroot%\system32\cscript.exe /B /nologo %systemroot%\system32\calluxxprovider.vbs $(Arg0) $(Arg1) $(Arg2)' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\system32\calluxxprovider.vbs' | should be $true } # Scheduled task issue: Server Manager Performance Monitor #49 # https://github.com/p0w3rsh3ll/AutoRuns/issues/49 It 'issue #49 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\PLA\Server Manager Performance Monitor' Item = 'Server Manager Performance Monitor' Category = 'Task' Value = '%systemroot%\system32\rundll32.exe %systemroot%\system32\pla.dll,PlaHost "Server Manager Performance Monitor" "$(Arg0)"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\system32\pla.dll' | should be $true } # Scheduled task ReplaceOMCert on a Azure VM #41 # https://github.com/p0w3rsh3ll/AutoRuns/issues/41 It 'issue #41 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Microsoft\Windows\CertificateServicesClient\Notification\ReplaceOMCert' Item = 'ReplaceOMCert' Category = 'Task' Value = '%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -File "C:\Program Files\Microsoft Monitoring Agent\Agent\Tools\UpdateOMCert.ps1" -OldCertHash $(OldCertHash) -NewCertHash $(NewCertHash) -EventRecordId $(EventRecordId)' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\Microsoft Monitoring Agent\Agent\Tools\UpdateOMCert.ps1' | should be $true } # ImagePath is wrong for FODCleanupTask #38 # https://github.com/p0w3rsh3ll/AutoRuns/issues/38 It 'issue #38 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Microsoft\Windows\HelloFace\FODCleanupTask' Item = 'FODCleanupTask' Category = 'Task' Value = '%WinDir%\System32\WinBioPlugIns\FaceFodUninstaller.exe' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\system32\WinBioPlugIns\FaceFodUninstaller.exe' | should be $true } # Scheduled tasks with a powershell script file in quotes #37 # https://github.com/p0w3rsh3ll/AutoRuns/issues/37 It 'issue #37 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\Windows\TTest.ps1" -CustomParam' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\TTest.ps1' | should be $true } It 'issue #37.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\Windows\TTest.ps1"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\TTest.ps1' | should be $true } # Change image path for scheduled tasks that run powershell.exe #33 # https://github.com/p0w3rsh3ll/AutoRuns/issues/33 It 'issue #33 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\logoff PS' Item = 'logoff PS' Category = 'Task' Value = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Exec Bypass -File c:\windows\system32\logoff.ps1' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'c:\windows\system32\logoff.ps1' | should be $true } # special powershell.exe file.ps1 It 'issue #33.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'powershell.exe file.ps1' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'file.ps1' | should be $true } # special powershell.exe -f file.ps1 -exec bypass It 'issue #33.2 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'powershell.exe -f file.ps1 -exec bypass' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'file.ps1' | should be $true } # special powershell.exe -fil file.ps1 -exec bypass It 'issue #33.3 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'powershell.exe -fil file.ps1 -exec bypass' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'file.ps1' | should be $true } # special powershell.exe -exec bypass -file file.ps1 It 'issue #33.4 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'powershell.exe -exec bypass -file file.ps1' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'file.ps1' | should be $true } # special powershell.exe -exec bypass -file file.ps1 It 'issue #33.5 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'powershell.exe -exec bypass -file file.ps1' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'file.ps1' | should be $true } # but not powershell.exe -enc base64 or powershell.exe -command "cmd" It 'issue #33.6 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Windows\system32\Tasks\Test' Item = 'Test' Category = 'Task' Value = 'powershell.exe -enc base64 or powershell.exe -command "cmd"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'powershell.exe -enc base64 or powershell.exe -command "cmd"' | should be $true } # Wrong image path for a scheduled task that runs directly a bat file #32 # https://github.com/p0w3rsh3ll/AutoRuns/issues/32 It 'issue #32 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\action2' Item = 'action2' Category = 'Task' Value = '"C:\Program Files\action.bat"' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\action.bat' | should be $true } # Wrong imagepath for a scheduled task that runs directly a vbs file #31 # https://github.com/p0w3rsh3ll/AutoRuns/issues/31 It 'issue #31 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\\Action!' Item = 'Action!' Category = 'Task' Value = 'C:\Program Files (x86)\Mirillis\Action!\Action.vbs' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files (x86)\Mirillis\Action!\Action.vbs' | should be $true } # Specific scheduled task for O2016 heartbeat #25 # https://github.com/p0w3rsh3ll/AutoRuns/issues/25 It 'issue #25 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Office\Office 15 Subscription Heartbeat' Item = 'Office 15 Subscription Heartbeat' Category = 'Task' Value = '%ProgramFiles%\Common Files\Microsoft Shared\Office16\OLicenseHeartbeat.exe' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -match 'C:\\Program\sFiles\s(\(x86\))?\\Common\sFiles\\microsoft\sshared\\OFFICE16\\OLicenseHeartbeat\.exe' | Should be $true } # Defender related scheduled tasks don't have a correct imagepath #22 # https://github.com/p0w3rsh3ll/AutoRuns/issues/22 It 'issue #22 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\Windows Defender\Windows Defender Cache Maintenance' Item = 'Windows Defender Cache Maintenance' Category = 'Task' Value = 'C:\ProgramData\Microsoft\Windows Defender\platform\4.12.17007.18022-0\MpCmdRun.exe -IdleTask -TaskName WdCacheMaintenance' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\ProgramData\Microsoft\Windows Defender\platform\4.12.17007.18022-0\MpCmdRun.exe' | should be $true } It 'issue #22.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\WINDOWS\system32\Tasks\Microsoft\Windows\Windows Defender\Windows Defender Scheduled Scan' Item = 'Windows Defender Scheduled Scan' Category = 'Task' Value = 'C:\ProgramData\Microsoft\Windows Defender\platform\4.12.17007.18022-0\MpCmdRun.exe Scan -ScheduleJob -ScanTrigger 55' } } -ParameterFilter { $ScheduledTasks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ScheduledTasks | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\ProgramData\Microsoft\Windows Defender\platform\4.12.17007.18022-0\MpCmdRun.exe' | should be $true } } } #endregion ScheduledTasks #region WMI Describe 'Testing Get-PSPrettyAutorun for WMI' -Tag 'WMI' { # WMI provider issue: MSiSCSIInitiatorProvider #51 # https://github.com/p0w3rsh3ll/AutoRuns/issues/51 It 'issue 51 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = "\\.\ROOT\WMI:__Win32Provider.Name='MSiSCSIInitiatorProvider'" Item = 'MSiSCSIInitiatorProvider' Category = 'WMI' Value = '%SystemRoot%\System32\iscsiwmi.dll' } } -ParameterFilter { $WMI -eq [switch]::Present } $i = (Get-PSRawAutoRun -WMI | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\System32\iscsiwmi.dll' | should be $true } # Get-PSAutorun -WMI throws an error in PowerShell Core 6.0 #10 # https://github.com/p0w3rsh3ll/AutoRuns/issues/10 It 'issue 10 should be solved' { } #Describe 'Testing WMI' { # It 'Tests the WMI core function' { # { Get-PSRawAutoRun -WMI } | Should not Throw # } #} } #endregion WMI #region Logon Describe 'Testing Get-PSPrettyAutorun for Logon' -Tag 'Logon' { It 'issue 112 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKCU:\Software\\Microsoft\Windows\CurrentVersion\Run' Item = 'FACEIT' Category = 'Logon' Value = '"C:\Users\brand\AppData\Local\FACEIT\update.exe" --processStart "FACEIT.exe"' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Users\brand\AppData\Local\FACEIT\update.exe' | should be $true } It 'issue 84 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKCU:\Software\\Microsoft\Windows\CurrentVersion\Run' Item = 'Discord' Category = 'Logon' Value = 'C:\ProgramData\Etienne\Discord\app-0.0.0\Discord.exe' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'C:\ProgramData\Etienne\Discord\app-0.0.0\Discord.exe' | should be $true } # fake teams.exe with no quote or space It 'issue 70 bis should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKCU:\Software\\Microsoft\Windows\CurrentVersion\Run' Item = 'com.squirrel.Teams.Teams' Category = 'Logon' Value = 'C:\Users\username\AppData\Local\Microsoft\Teams\Update.exe' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'C:\Users\username\AppData\Local\Microsoft\Teams\Update.exe' | should be $true } # Teams.exe # https://github.com/p0w3rsh3ll/AutoRuns/issues/70 It 'issue 70 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKCU:\Software\\Microsoft\Windows\CurrentVersion\Run' Item = 'com.squirrel.Teams.Teams' Category = 'Logon' Value = 'C:\Users\username\AppData\Local\Microsoft\Teams\Update.exe --processStart "Teams.exe" -process-start-args "--system-initiated"' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'C:\Users\username\AppData\Local\Microsoft\Teams\Update.exe' | should be $true } # Dropbox.lnk #64 # https://github.com/p0w3rsh3ll/AutoRuns/issues/64 It 'issue 64 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Users\username\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup' Item = 'Dropbox.lnk' Category = 'Logon' Value = 'C:\Users\username\AppData\Roaming\Dropbox\bin\Dropbox.exe /systemstartup' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "#$($i)#" -Verbose $i -eq 'C:\Users\username\AppData\Roaming\Dropbox\bin\Dropbox.exe' | should be $true } # Startup lnk file has a wrong image path #43 # https://github.com/p0w3rsh3ll/AutoRuns/issues/43 It 'issue 43 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'C:\Users\myuser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup' Item = 'Send to OneNote.lnk' Category = 'Logon' Value = 'C:\Program Files (x86)\Microsoft Office\root\Office16\ONENOTEM.EXE /tsr' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath $i -match 'C:\\Program\sFiles(\s\(x86\))?\\Microsoft\sOffice\\root\\Office16\\ONENOTEM.EXE' | should be $true } # Logon Active Setup Installed Components C:\WINDOWS\inf\unregmp2.exe not found #24 # https://github.com/p0w3rsh3ll/AutoRuns/issues/24 # NB: The file unregmp2.exe exists under c:\Windows\System32 and c:\Windows\SysWOW64 It 'issue 24 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\\Microsoft\Active Setup\Installed Components\>{22d6f312-b0f6-11d0-94ab-0080c74c7e95}' Item = 'StubPath' Category = 'Logon' Value = 'C:\WINDOWS\inf\unregmp2.exe /ShowWMP' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\system32\unregmp2.exe' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/18 # https://oddvar.moe/2018/03/21/persistence-using-runonceex-hidden-from-autoruns-exe/ # Get-PSAutorun -Logon | ? Path -match 'RunOnceEx' # Split on pipe character # Detects ...RunonceEx\000x\Depend and RunOnceEx\Depend It 'issue 18.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx' Item = 'test' Category = 'Logon' Value = 'C:\malware.eXe' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\malware.eXe' | should be $true } It 'issue 18.2 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx\0001\Depend' Item = '1' Category = 'Logon' Value = 'C:\temp\messageBox64.dll' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\temp\messageBox64.dll' | should be $true } It 'issue 18.3 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnceEx\0001\Depend' Item = 'Line 1' Category = 'Logon' Value = 'c:\windows\system32\url.dll|OpenURL|"http://www.google.com"' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun | Select-Object -First 1).ImagePath $j = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun | Select-Object -First 2 | Select-Object -Last 1).ImagePath $k = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun | Select-Object -Last 1).ImagePath ( ($i -eq 'c:\windows\system32\url.dll') -and ($j -eq 'OpenURL') -and ($k -eq '"http://www.google.com"') ) | should be $true } # Handling of userinit registry value #17 # https://github.com/p0w3rsh3ll/AutoRuns/issues/17 <# The \SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\userinit value can be of the format: C:\Windows\System32\userinit.exe,"C:\malware.exe", Note: The trailing comma is necessary. It ensures that any settings added by another piece of software or GPO are delimited as necessary. #> It 'issue 17 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' Item = 'userinit' Category = 'Logon' Value = 'C:\Windows\System32\userinit.exe,"C:\malware.exe",' } } -ParameterFilter { $Logon -eq [switch]::Present } $i = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun | Select-Object -First 1).ImagePath $j = (Get-PSRawAutoRun -Logon | Get-PSPrettyAutorun | Select-Object -First 2 | Select-Object -Last 1).ImagePath ( ($i -eq 'C:\Windows\System32\userinit.exe') -and ($j -eq 'C:\malware.exe') ) | should be $true } } #endregion Logon #region AppinitDLLs Describe 'Testing Get-PSPrettyAutorun for AppinitDLLs' -Tag 'AppinitDLLs' { <# From https://support.microsoft.com/en-us/help/197571/working-with-the-appinit-dlls-registry-value: "The AppInit_DLLs value has type "REG_SZ." This value has to specify a NULL-terminated string of DLLs that is delimited by spaces or by commas. Because spaces are used as delimiters, do not use long file names. The system does not recognize semicolons as delimiters for these DLLs." Your script does not handle comma or space delimited strings, but assumes there is only one string. #> # comma or space delimited AppInit_DLLs #16 # https://github.com/p0w3rsh3ll/AutoRuns/issues/16 # test with a space as delimiter It 'issue 16.1 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows' Item = 'Appinit_Dlls' Category = 'AppInit' Value = 'c:\malWare1 C:\malware.eXe' } } -ParameterFilter { $AppinitDLLs-eq [switch]::Present } $i = (Get-PSRawAutoRun -AppinitDLLs | Get-PSPrettyAutorun | Select-Object -First 1).ImagePath $j = (Get-PSRawAutoRun -AppinitDLLs | Get-PSPrettyAutorun | Select-Object -First 2 | Select-Object -Last 1).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose # Write-Verbose -Message "-$($j)-" -Verbose ( ($i -eq 'c:\malWare1') -and ($j -eq 'C:\malware.eXe') ) | should be $true } # test with a comma as delimiter It 'issue 16.2 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows' Item = 'Appinit_Dlls' Category = 'AppInit' Value = 'c:\malWare1.eXe,C:\malware2.ExE' } } -ParameterFilter { $AppinitDLLs -eq [switch]::Present } $i = (Get-PSRawAutoRun -AppinitDLLs | Get-PSPrettyAutorun | Select-Object -First 1).ImagePath $j = (Get-PSRawAutoRun -AppinitDLLs | Get-PSPrettyAutorun | Select-Object -First 2 | Select-Object -Last 1).ImagePath (($i -eq 'c:\malWare1.eXe') -and ($j -eq 'C:\malware2.ExE')) | should be $true } } #endregion AppinitDLLs #region ServicesAndDrivers Describe 'Testing Get-PSPrettyAutorun for ServicesAndDrivers' -Tag 'ServicesAndDrivers' { # issue with ibtsiva (see also issue 53 below) # It 'issue file with no extension should be solved' { <# # if we had that in default block of the switch if ($_ -match '\.[eEDd][xXlL][eElL]$') { $_ } else { $Env:PATHEXT -split ';' | ForEach-Object -Process { if (Test-Path -Path "$($Item.Value)$_" -PathType Leaf) { "$($Item.Value)$_" Continue } } -End { "$($Item.Value)" } } #> # Mock -CommandName Get-PSRawAutoRun -MockWith { # return [PSCustomObject]@{ # Path = 'HKLM:\System\CurrentControlSet\Services\ibtsiva' # Item = 'ImagePath' # Category = 'Services' # Value = 'C:\Windows\system32\ibtsiva' # } # } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } # Mock -CommandName Test-Path -MockWith { return $true } -ParameterFilter { # $Path -eq 'C:\Windows\system32\ibtsiva.EXE' # } # $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun -Verbose).ImagePath # # Write-Verbose -Message "-$($i)-" -Verbose # $i -eq 'C:\Windows\system32\ibtsiva.EXE' | should be $true # } # https://github.com/p0w3rsh3ll/AutoRuns/issues/113 It 'issue #113 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\atvi-randgrid_sr' Item = 'ImagePath' Category = 'Drivers' Value = '\??\B:\SteamLibrary\steamapps\common\Call of Duty HQ\randgrid.sys' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'B:\SteamLibrary\steamapps\common\Call of Duty HQ\randgrid.sys' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/110 It 'issue #110 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\xhunter1' Item = 'ImagePath' Category = 'Drivers' Value = '\??\C:\WINDOWS\xhunter1.sys' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\WINDOWS\xhunter1.sys' | should be $true } # https://github.com/p0w3rsh3ll/AutoRuns/issues/98 It 'issue 98 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\PRM' Item = 'ImagePath' Category = 'Drivers' Value = 'System32\DriverStore\FileRepository\prm.inf_amd64_7fc9bb8ba2b73803\PRM.sys' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Windows\System32\DriverStore\FileRepository\prm.inf_amd64_7fc9bb8ba2b73803\PRM.sys' | should be $true } # Service located in C:\packages in Windows 10 Azure VM #40 # https://github.com/p0w3rsh3ll/AutoRuns/issues/40 It 'issue 40 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\MMAExtensionHeartbeatService' Item = 'ImagePath' Category = 'Services' Value = '"C:\Packages\Plugins\Microsoft.EnterpriseCloud.Monitoring.MicrosoftMonitoringAgent\1.0.11081.4\MMAExtensionHeartbeatService.exe"' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Packages\Plugins\Microsoft.EnterpriseCloud.Monitoring.MicrosoftMonitoringAgent\1.0.11081.4\MMAExtensionHeartbeatService.exe' | should be $true } # No size, version... for drivers #30 # https://github.com/p0w3rsh3ll/AutoRuns/issues/30 It 'issue 30 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\BEDaisy' Item = 'ImagePath' Category = 'Drivers' Value = '\??\C:\Program Files (x86)\Common Files\BattlEye\BEDaisy.sys' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files (x86)\Common Files\BattlEye\BEDaisy.sys' | should be $true } # No size, version if Drivers is in %programfile% and values has \??\ at the beginning #20 # https://github.com/p0w3rsh3ll/AutoRuns/issues/20 It 'issue 20 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\LGCoreTemp' Item = 'ImagePath' Category = 'Drivers' Value = '\??\C:\Program Files\Logitech Gaming Software\Drivers\LgCoreTemp\lgcoretemp.sys' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\Program Files\Logitech Gaming Software\Drivers\LgCoreTemp\lgcoretemp.sys' | should be $true } # No size, version... because of quotes for services located in ProgramData #19 # https://github.com/p0w3rsh3ll/AutoRuns/issues/19 It 'issue 19 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\WinDefend' Item = 'ImagePath' Category = 'Drivers' Value = '"C:\ProgramData\Microsoft\Windows Defender\platform\4.12.17007.18022-0\MsMpEng.exe"' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath $i -eq 'C:\ProgramData\Microsoft\Windows Defender\platform\4.12.17007.18022-0\MsMpEng.exe' | should be $true } # Wrong imagepath when the service value targets a file w/o extension #53 # https://github.com/p0w3rsh3ll/AutoRuns/issues/53 It 'issue 53 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\ibtsiva' Item = 'ImagePath' Category = 'Services' Value = 'C:\Windows\system32\ibtsiva' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\Windows\system32\ibtsiva' | should be $true } # Imagepath for drivers under SysWow64 #52 # https://github.com/p0w3rsh3ll/AutoRuns/issues/52 It 'issue 52 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\System\CurrentControlSet\Services\AsIO' Item = 'ImagePath' Category = 'Drivers' Value = 'SysWow64\drivers\AsIO.sys' } } -ParameterFilter { $ServicesAndDrivers -eq [switch]::Present } $i = (Get-PSRawAutoRun -ServicesAndDrivers | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\WINDOWS\SysWow64\drivers\AsIO.sys' | should be $true } } #endregion #region Image Hijacks Describe 'Testing Get-PSPrettyAutorun for ImageHijacks' -Tag 'ImageHijacks' { Context 'Inside Get-PSRawAutoRun' { # Persistence using GlobalFlags in Image File Execution Options #27 # https://github.com/p0w3rsh3ll/AutoRuns/issues/27 # https://oddvar.moe/2018/04/10/persistence-using-globalflags-in-image-file-execution-options-hidden-from-autoruns-exe/ <# reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe" /v GlobalFlag /t REG_DWORD /d 512 reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v ReportingMode /t REG_DWORD /d 1 reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v MonitorProcess /d "C:\temp\evil.exe" reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\notepad.exe" /v GlobalFlag /t REG_DWORD /d 512 reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v ReportingMode /t REG_DWORD /d 1 reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe" /v MonitorProcess /d "C:\temp\evil.exe" #> It 'issue 27 should be solved' { # Make sure the Users variable is defined and empty otherwise # it throws a RunTimeException when you call Get-PSRawAutoRun -ImageHijacks $Users = @{} Mock -CommandName Get-ItemProperty -ParameterFilter { $Name -eq 'GlobalFlag' } -MockWith { return [PSCustomObject]@{ 'GlobalFlag' = 512 } } Mock -CommandName Get-RegValue -ParameterFilter { $Name -eq 'MonitorProcess' } -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\notepad.exe' Item = 'MonitorProcess' Value = 'C:\temp\evil.exe' Category = 'Image Hijacks' } } # Write-Verbose -Message "-$(Get-PSRawAutoRun -ImageHijacks | Select -First 1)-" -Verbose (Get-PSRawAutoRun -ImageHijacks | Select-Object -First 1).Value -eq 'C:\temp\evil.exe' | should be $true Assert-MockCalled -CommandName Get-RegValue -Times 1 } # TODO: Do the same above test with TestRegistry drive # https://github.com/pester/Pester/wiki/TestRegistry } Context 'Inside Get-PSPrettyAutorun' { # Image Hijacks: target imagepath is null for htmlfile command #23 # https://github.com/p0w3rsh3ll/AutoRuns/issues/23 It 'issue 23 should be solved' { Mock -CommandName Get-PSRawAutoRun -MockWith { return [PSCustomObject]@{ Path = 'HKLM:\SOFTWARE\Classes\htmlfile\shell\open\command' Item = 'htmlfile' Category = 'Image Hijacks' Value = '"C:\Program Files\Internet Explorer\IEXPLORE.EXE" %1' } } -ParameterFilter { $ImageHijacks -eq [switch]::Present } $i = (Get-PSRawAutoRun -ImageHijacks | Get-PSPrettyAutorun).ImagePath # Write-Verbose -Message "-$($i)-" -Verbose $i -eq 'C:\Program Files\Internet Explorer\IEXPLORE.EXE' | should be $true } } } #endregion Image Hijacks #region OfficeAddins Describe 'Testing Get-PSPrettyAutorun for OfficeAddins' -Tag 'OfficeAddins' { # OfficeAddins don't have an imagepath when HKCU hive is in use #26 # https://github.com/p0w3rsh3ll/AutoRuns/issues/26 # fix is in Get-PSRawAutoRun It 'issue 26 should be solved' { $Users = @{ UserName = 'test' ; SID = 'bidon' ; Hive = 'HKCU:' ; ProfilePath = 'bidon' } Mock -CommandName Test-Path -MockWith { return $false } Mock -CommandName Test-Path -MockWith { return $true } -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office' } Mock -CommandName Test-Path -MockWith { return $true } -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\Outlook\Addins' } Mock -CommandName Get-Item -MockWith { [PSCustomObject]@{fakekey='valuedontcare'} | Add-Member -Type ScriptMethod -Name 'GetSubKeyNames' -Value { return $null } -Force -PassThru } Mock -CommandName Get-Item -MockWith { [PSCustomObject]@{fakekey='valuedontcare'}| Add-Member -Type ScriptMethod -Name 'GetSubKeyNames' -Value { return 'Outlook' } -Force -PassThru } -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office' } Mock -CommandName Get-Item -MockWith { [PSCustomObject]@{fakekey='valuedontcare'} | Add-Member -Type ScriptMethod -Name 'GetSubKeyNames' -Value { return 'UCAddin.LyncAddin.1' } -Force -PassThru } -ParameterFilter { $Path -eq 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Office\Outlook\Addins' } # mock this def to {a6a2383f-ad50-4d52-8110-3508275e77f7} # $clsid = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Classes\$($_)\CLSID" -Name '(default)' -ErrorAction Stop).'(default)'; # Get-PSRawAutoRun -OfficeAddins -Verbose # Write-Verbose -Message "$((Get-PSRawAutoRun -OfficeAddins | Select-Object -First 1).Value)" -Verbose # it appears to be 'solved' but it isn't. # TODO: we need a proper valid test } <# Get-PSAutorun -OfficeAddins | ? {-not($_.Size)} Path : HKCU:\SOFTWARE\\Microsoft\Office\Excel\Addins Item : AdHocReportingExcelClientLib.AdHocReportingExcelClientAddIn.1 Category : Office Addins Value : {509E7382-B849-49A4-8A3F-BEAB7E7D904C} ImagePath : {509e7382-b849-49a4-8a3f-beab7e7d904c} Path : HKCU:\SOFTWARE\\Microsoft\Office\Excel\Addins Item : PowerPivotExcelClientAddIn.NativeEntry.1 Category : Office Addins Value : {A2DBA3BE-42CC-4D0E-95FD-BCAA051BA798} ImagePath : {a2dba3be-42cc-4d0e-95fd-bcaa051ba798} Path : HKCU:\SOFTWARE\\Microsoft\Office\PowerPoint\Addins Item : OneNote.PowerPointAddinTakeNotesService Category : Office Addins Value : {3A7CAEBB-C5C3-4EFF-ADDF-C32663BDF8DA} ImagePath : {3a7caebb-c5c3-4eff-addf-c32663bdf8da} Path : HKCU:\SOFTWARE\\Microsoft\Office\Word\Addins Item : OneNote.WordAddinTakeNotesService Category : Office Addins Value : {C580A1B2-5915-4DC3-BE93-8A51F4CAB320} ImagePath : {c580a1b2-5915-4dc3-be93-8a51f4cab320} #> } #endregion #region KnownDLLs Describe 'Testing Get-PSPrettyAutorun for KnownDLLs' -Tag 'KnownDLLs' { # No size, version for Known dlls where image path is set to C:\WINDOWS\Syswow64 #21 # https://github.com/p0w3rsh3ll/AutoRuns/issues/21 It 'issue 21 should be solved' { } # fix was : always show system32 (untouched) + # if ([environment]::Is64BitOperatingSystem) { # # Duplicate if target file exists # Mock many things...? <# Get-PSAutorun -KnownDLLs | ? Value -match "wow64" | ? { -not($_.Size)} Path : HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs Item : _Wow64 Category : Known Dlls Value : Wow64.dll ImagePath : C:\WINDOWS\Syswow64\Wow64.dll Path : HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs Item : _Wow64cpu Category : Known Dlls Value : Wow64cpu.dll ImagePath : C:\WINDOWS\Syswow64\Wow64cpu.dll Path : HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs Item : _Wow64win Category : Known Dlls Value : Wow64win.dll ImagePath : C:\WINDOWS\Syswow64\Wow64win.dll These above dll files only exist in System32 #> } #endregion #region Other Describe 'Other' { # When ShowFileHash and VerifyDigitalSignature switches are used, don't drop items #34 # https://github.com/p0w3rsh3ll/AutoRuns/issues/34 # Get-PSAutorun -ShowFileHash -VerifyDigitalSignature # If the ImagePath has a value and Test-Path doesn't equal true, the object in the pipeline was dropped by the Add-PSAutoRunAuthentiCodeSignature function It 'issue 34 should be solved' { } # Question related to service path parsing #2 # https://github.com/p0w3rsh3ll/AutoRuns/issues/2 <# $value = 'C:\Program Files\te.exe st\te -st.exe -param1 testing' For example what if the path was: 'D:\test test\te.exe st\te -st.exe -param1 test\ing' What is the approach to parsing this logically? In the above example it seems your parser was specifically looking for Program Files folder but what if this is not the case. Would it still handle spaces, dashes, and periods in folder names and file names, as well as slashes in parameter values? I'm trying to understand your parsing logic for these situations where the file path is very tricky. I guess I'm hoping you could elaborate how the parsing is done to handle all these situations as I'm having trouble understanding it in the code. #> It 'issue 2 should be solved' { } } #endregion } #endof inmodulescope