From eaca9666c80d4716ec43c5bd2494a03e3a8f04c6 Mon Sep 17 00:00:00 2001 From: metablaster <44481081+metablaster@users.noreply.github.com> Date: Thu, 7 Dec 2023 00:01:57 +0100 Subject: [PATCH] sysinternals suite trough MS Store --- .vscode/bookmarks.json | 10 - .../Public/Get-SystemApp.ps1 | 36 +- .../Public/Get-UserApp.ps1 | 36 +- .../Public/Search-Installation.ps1 | 21 +- .../Public/Test-VirusTotal.ps1 | 4 +- .../Software/Microsoft/SysInternals.ps1 | 81 ++-- Rules/IPv4/Outbound/StoreApps.ps1 | 450 +++++++++--------- docs/CHANGELOG.md | 2 + 8 files changed, 334 insertions(+), 306 deletions(-) diff --git a/.vscode/bookmarks.json b/.vscode/bookmarks.json index a59f71ef..25bf866a 100644 --- a/.vscode/bookmarks.json +++ b/.vscode/bookmarks.json @@ -84,16 +84,6 @@ "label": "" } ] - }, - { - "path": "Rules/IPv4/Outbound/StoreApps.ps1", - "bookmarks": [ - { - "line": 343, - "column": 10, - "label": "" - } - ] } ] } \ No newline at end of file diff --git a/Modules/Ruleset.ProgramInfo/Public/Get-SystemApp.ps1 b/Modules/Ruleset.ProgramInfo/Public/Get-SystemApp.ps1 index fda3897c..8786bd30 100644 --- a/Modules/Ruleset.ProgramInfo/Public/Get-SystemApp.ps1 +++ b/Modules/Ruleset.ProgramInfo/Public/Get-SystemApp.ps1 @@ -46,6 +46,8 @@ User name in form of: - user_name - SID-string +If not specified gets store apps for all user accounts on the computer + .PARAMETER Domain NETBIOS Computer name in form of "COMPUTERNAME" @@ -102,7 +104,7 @@ function Get-SystemApp [SupportsWildcards()] [string] $Name = "*", - [Parameter(Mandatory = $true)] + [Parameter()] [Alias("UserName")] [string] $User, @@ -146,7 +148,15 @@ function Get-SystemApp # TODO: it is possible to add -User parameter, what's the purpose? see also StoreApps.ps1 if ($Domain -eq [System.Environment]::MachineName) { - $Apps = Get-AppxPackage -Name $Name -User $User -PackageTypeFilter Main + if ([string]::IsNullOrEmpty($User)) + { + $Apps = Get-AppxPackage -Name $Name -AllUsers -PackageTypeFilter Main + } + else + { + $Apps = Get-AppxPackage -Name $Name -User $User -PackageTypeFilter Main + } + $DomainPath = $env:SystemDrive } else @@ -156,7 +166,14 @@ function Get-SystemApp # HACK: This will fail in Windows PowerShell with "The system cannot find the file specified" # ISSUE: https://github.com/MicrosoftDocs/windows-powershell-docs/issues/344 # See also: https://www.reddit.com/r/sysadmin/comments/lrm3nj/will_getappxpackage_allusers_work_in_remote - Get-AppxPackage -Name $using:Name -User $using:User -PackageTypeFilter Main + if ([string]::IsNullOrEmpty($using:User)) + { + Get-AppxPackage -Name $using:Name -AllUsers -PackageTypeFilter Main + } + else + { + Get-AppxPackage -Name $using:Name -User $using:User -PackageTypeFilter Main + } } # HACK: Hardcoded, a new functioned needed to get remote shares @@ -179,13 +196,16 @@ function Get-SystemApp { if ($App.SignatureKind -eq "System") { - # NOTE: This path will be missing for default apps on Windows server - # It may also be missing in fresh installed OS before connecting to internet - $RemotePath = "$DomainPath\Users\$User\AppData\Local\Packages\$($App.PackageFamilyName)\AC" - Write-Debug -Message "[$($MyInvocation.InvocationName)] Processing app path '$RemotePath'" + if (![string]::IsNullOrEmpty($User)) + { + # NOTE: This path will be missing for default apps on Windows server + # It may also be missing in fresh installed OS before connecting to internet + $RemotePath = "$DomainPath\Users\$User\AppData\Local\Packages\$($App.PackageFamilyName)\AC" + Write-Debug -Message "[$($MyInvocation.InvocationName)] Processing app path '$RemotePath'" + } # TODO: See if "$_.Status" property can be used to determine if app is valid - if (Test-Path -PathType Container -Path $RemotePath) + if ([string]::IsNullOrEmpty($User) -or (Test-Path -PathType Container -Path $RemotePath)) { # There is no Domain property, so add one, PSComputerName property is of no use here Add-Member -MemberType NoteProperty -InputObject $App -Name Domain -Value $Domain -PassThru diff --git a/Modules/Ruleset.ProgramInfo/Public/Get-UserApp.ps1 b/Modules/Ruleset.ProgramInfo/Public/Get-UserApp.ps1 index 96a21483..14f64188 100644 --- a/Modules/Ruleset.ProgramInfo/Public/Get-UserApp.ps1 +++ b/Modules/Ruleset.ProgramInfo/Public/Get-UserApp.ps1 @@ -46,6 +46,8 @@ User name in form of: - user_name - SID-string +If not specified gets store apps for all user accounts on the computer + .PARAMETER Domain NETBIOS Computer name in form of "COMPUTERNAME" @@ -102,7 +104,7 @@ function Get-UserApp [SupportsWildcards()] [string] $Name = "*", - [Parameter(Mandatory = $true)] + [Parameter()] [Alias("UserName")] [string] $User, @@ -155,7 +157,15 @@ function Get-UserApp # Xap: # Optional: Optional packages are dependent on another package that must be installed first. # NOTE: There is supposed to be no Bundle package that is also not Main - $Apps = Get-AppxPackage -Name $Name -User $User -PackageTypeFilter Main + if ([string]::IsNullOrEmpty($User)) + { + $Apps = Get-AppxPackage -Name $Name -AllUsers -PackageTypeFilter Main + } + else + { + $Apps = Get-AppxPackage -Name $Name -User $User -PackageTypeFilter Main + } + $DomainPath = $env:SystemDrive } else @@ -164,7 +174,14 @@ function Get-UserApp # HACK: This will fail in Windows PowerShell with "The system cannot find the file specified" # ISSUE: https://github.com/MicrosoftDocs/windows-powershell-docs/issues/344 # See also: https://www.reddit.com/r/sysadmin/comments/lrm3nj/will_getappxpackage_allusers_work_in_remote/ - Get-AppxPackage -Name $using:Name -User $using:User -PackageTypeFilter Main + if ([string]::IsNullOrEmpty($using:User)) + { + Get-AppxPackage -Name $using:Name -AllUsers -PackageTypeFilter Main + } + else + { + Get-AppxPackage -Name $using:Name -User $using:User -PackageTypeFilter Main + } } # HACK: Hardcoded, a new function needed to get remote shares @@ -214,13 +231,16 @@ function Get-UserApp continue } - # NOTE: This path will be missing for default apps on Windows server - # It may also be missing in fresh installed OS before connecting to internet - $RemotePath = "$DomainPath\Users\$User\AppData\Local\Packages\$($App.PackageFamilyName)\AC" - Write-Debug -Message "[$($MyInvocation.InvocationName)] Processing app path '$RemotePath'" + if (![string]::IsNullOrEmpty($User)) + { + # NOTE: This path will be missing for default apps on Windows server + # It may also be missing in fresh installed OS before connecting to internet + $RemotePath = "$DomainPath\Users\$User\AppData\Local\Packages\$($App.PackageFamilyName)\AC" + Write-Debug -Message "[$($MyInvocation.InvocationName)] Processing app path '$RemotePath'" + } # TODO: See if "$_.Status" property can be used to determine if app is valid - if (Test-Path -PathType Container -Path $RemotePath) + if ([string]::IsNullOrEmpty($User) -or (Test-Path -PathType Container -Path $RemotePath)) { # There is no Domain property, so add one, PSComputerName property is of no use here Add-Member -MemberType NoteProperty -InputObject $App -Name Domain -Value $Domain -PassThru diff --git a/Modules/Ruleset.ProgramInfo/Public/Search-Installation.ps1 b/Modules/Ruleset.ProgramInfo/Public/Search-Installation.ps1 index 7bc76a7b..78a29180 100644 --- a/Modules/Ruleset.ProgramInfo/Public/Search-Installation.ps1 +++ b/Modules/Ruleset.ProgramInfo/Public/Search-Installation.ps1 @@ -123,6 +123,7 @@ function Search-Installation $PSDefaultParameterValues["Edit-Table:CimSession"] = $CimSession $PSDefaultParameterValues["Update-Table:Session"] = $Session $PSDefaultParameterValues["Update-Table:CimSession"] = $CimSession + $PSDefaultParameterValues["Get-UserApp:Session"] = $Session } else { @@ -134,12 +135,14 @@ function Search-Installation $SessionParams.ComputerName = $Domain $PSDefaultParameterValues["Edit-Table:Domain"] = $Domain $PSDefaultParameterValues["Update-Table:Domain"] = $Domain + $PSDefaultParameterValues["Get-UserApp:Domain"] = $Domain if ($Credential) { $SessionParams.Credential = $Credential $PSDefaultParameterValues["Edit-Table:Credential"] = $Credential $PSDefaultParameterValues["Update-Table:Credential"] = $Credential + $PSDefaultParameterValues["Get-UserApp:Credential"] = $Credential } } } @@ -279,23 +282,7 @@ function Search-Installation } "SysInternals" { - if ($Domain -eq [System.Environment]::MachineName) - { - # TODO: Show warning instead of error when failed (ex. in non elevated run check is Admin) - # NOTE: There is supposed to be no Bundle package that is also not Main - # TODO: We have Get-UserApp but it doesn't have -AllUsers switch so this is duplicate code, - # either implement the switch or make a new function ex. Get-AllUsersApp - $SysinternalsSuite = Get-AppxPackage -Name "Microsoft.SysinternalsSuite" -AllUsers -PackageTypeFilter Main - } - else - { - $SysinternalsSuite = Invoke-Command @SessionParams -ScriptBlock { - # HACK: This will fail in Windows PowerShell with "The system cannot find the file specified" - # ISSUE: https://github.com/MicrosoftDocs/windows-powershell-docs/issues/344 - # See also: https://www.reddit.com/r/sysadmin/comments/lrm3nj/will_getappxpackage_allusers_work_in_remote/ - Get-AppxPackage -Name "Microsoft.SysinternalsSuite" -AllUsers -PackageTypeFilter Main - } - } + $SysinternalsSuite = Get-UserApp -Name "Microsoft.SysinternalsSuite" if ($SysinternalsSuite) { diff --git a/Modules/Ruleset.ProgramInfo/Public/Test-VirusTotal.ps1 b/Modules/Ruleset.ProgramInfo/Public/Test-VirusTotal.ps1 index d44b60f3..14f437a3 100644 --- a/Modules/Ruleset.ProgramInfo/Public/Test-VirusTotal.ps1 +++ b/Modules/Ruleset.ProgramInfo/Public/Test-VirusTotal.ps1 @@ -51,6 +51,7 @@ Specify path to sigcheck executable program. Do not specify sigcheck file, only path to where sigcheck is located. By default working directory and PATH is searched for sigcheck64.exe. On 32 bit operating system sigcheck.exe is searched instead. +If SysInternals suite was installed trough MS Store sigcheck is named sigcheck.exe ragless of OS bitness If location to sigcheck executable is not found then no VirusTotal scan and report is done. .PARAMETER SkipPositivies @@ -205,7 +206,7 @@ function Test-VirusTotal Set-Variable -Name SigcheckPath -Scope Global -Value "C:\tools" } - # Check if sigcheck is in PATH + # Check if sigcheck is in PATH, this includes sigcheck installed by MS Store Write-Debug -Message "[$InvocationName] Checking if sigcheck is in PATH" $Command = Get-Command -Name $SigcheckExecutable -CommandType Application -ErrorAction Ignore | Where-Object { @@ -384,6 +385,7 @@ function Test-VirusTotal $Publisher = $RawPublisher.Groups["publisher"] $Description = $RawDescription.Groups["description"] + # HACK: Somewhere around here is errors with "You cannot call a method with null value expression" if ($Detection.Success) { Write-Information -Tags $InvocationName -MessageData "INFO: VirusTotal report for '$Executable' is '$($Detection.Value)'" diff --git a/Rules/IPv4/Outbound/Software/Microsoft/SysInternals.ps1 b/Rules/IPv4/Outbound/Software/Microsoft/SysInternals.ps1 index 1873185a..02f27e28 100644 --- a/Rules/IPv4/Outbound/Software/Microsoft/SysInternals.ps1 +++ b/Rules/IPv4/Outbound/Software/Microsoft/SysInternals.ps1 @@ -123,10 +123,18 @@ $SysInternalsRoot = "%SystemDrive%\tools" # Test if installation exists on system if ((Confirm-Installation "SysInternals" ([ref] $SysInternalsRoot)) -or $ForceLoad) { - $Program = "$SysInternalsRoot\Autoruns64.exe" + # If installed manually instead trough MS store then add suffix is it's 64 bit OS + $AddSuffix = ($SysInternalsRoot -NotLike "*Microsoft.SysinternalsSuite*") -and [System.Environment]::Is64BitOperatingSystem + + $Program = "$SysInternalsRoot\Autoruns.exe" + if ($AddSuffix) + { + $Program.Insert($Program.Length - 4, "64") + } + if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals Autoruns x64" ` + New-NetFirewallRule -DisplayName "Sysinternals Autoruns" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` @@ -139,10 +147,15 @@ if ((Confirm-Installation "SysInternals" ([ref] $SysInternalsRoot)) -or $ForceLo # TODO: It also uses port 80 but not known for what, not setting here. # Most likely to fetch symbols - $Program = "$SysInternalsRoot\procexp64.exe" + $Program = "$SysInternalsRoot\procexp.exe" + if ($AddSuffix) + { + $Program.Insert($Program.Length - 4, "64") + } + if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals ProcessExplorer x64" ` + New-NetFirewallRule -DisplayName "Sysinternals Process Explorer" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` @@ -153,10 +166,15 @@ if ((Confirm-Installation "SysInternals" ([ref] $SysInternalsRoot)) -or $ForceLo -Description "Access to VirusTotal and symbol server" | Format-RuleOutput } - $Program = "$SysInternalsRoot\Procmon64.exe" + $Program = "$SysInternalsRoot\Procmon.exe" + if ($AddSuffix) + { + $Program.Insert($Program.Length - 4, "64") + } + if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals ProcessMonitor x64" ` + New-NetFirewallRule -DisplayName "Sysinternals Process Monitor" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` @@ -167,10 +185,15 @@ if ((Confirm-Installation "SysInternals" ([ref] $SysInternalsRoot)) -or $ForceLo -Description "Access to symbols server" | Format-RuleOutput } - $Program = "$SysInternalsRoot\Tcpview64.exe" + $Program = "$SysInternalsRoot\Tcpview.exe" + if ($AddSuffix) + { + $Program.Insert($Program.Length - 4, "64") + } + if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals TcpView x64" ` + New-NetFirewallRule -DisplayName "Sysinternals TCP View" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` @@ -181,10 +204,15 @@ if ((Confirm-Installation "SysInternals" ([ref] $SysInternalsRoot)) -or $ForceLo -Description "WhoIs access" | Format-RuleOutput } - $Program = "$SysInternalsRoot\whois64.exe" + $Program = "$SysInternalsRoot\whois.exe" + if ($AddSuffix) + { + $Program.Insert($Program.Length - 4, "64") + } + if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals WhoIs x64" ` + New-NetFirewallRule -DisplayName "Sysinternals WhoIs" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` @@ -197,25 +225,14 @@ that you specify" | Format-RuleOutput } $Program = "$SysInternalsRoot\psping.exe" - if ((Test-ExecutableFile $Program) -or $ForceLoad) + if ($AddSuffix) { - New-NetFirewallRule -DisplayName "Sysinternals PSPing client x86" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $Group ` - -Enabled False -Action Allow -Direction $Direction -Protocol Any ` - -LocalAddress Any -RemoteAddress Any ` - -LocalPort Any -RemotePort Any ` - -LocalUser $SysInternalsUsers ` - -InterfaceType $DefaultInterface ` - -Description "PsPing implements Ping functionality, TCP ping, latency and bandwidth measurement. -Due to wide range of address and port options these should be set to Any. -This rule serves to allow PSPing.exe to act as a client." | Format-RuleOutput + $Program.Insert($Program.Length - 4, "64") } - $Program = "$SysInternalsRoot\psping64.exe" if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals PSPing client x64" ` + New-NetFirewallRule -DisplayName "Sysinternals PSPing client" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol Any ` @@ -229,24 +246,14 @@ This rule serves to allow PSPing64.exe to act as a client." | Format-RuleOutput } $Program = "$SysInternalsRoot\sigcheck.exe" - if ((Test-ExecutableFile $Program) -or $ForceLoad) + if ($AddSuffix) { - New-NetFirewallRule -DisplayName "Sysinternals sigcheck x86" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $Group ` - -Enabled False -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $SysInternalsUsers ` - -InterfaceType $DefaultInterface ` - -Description "Connection to VirusTotal to upload file for scan" | - Format-RuleOutput + $Program.Insert($Program.Length - 4, "64") } - $Program = "$SysInternalsRoot\sigcheck64.exe" if ((Test-ExecutableFile $Program) -or $ForceLoad) { - New-NetFirewallRule -DisplayName "Sysinternals sigcheck x64" ` + New-NetFirewallRule -DisplayName "Sysinternals sigcheck" ` -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` -Service Any -Program $Program -Group $Group ` -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` diff --git a/Rules/IPv4/Outbound/StoreApps.ps1 b/Rules/IPv4/Outbound/StoreApps.ps1 index 927e9cca..c7e2b40d 100644 --- a/Rules/IPv4/Outbound/StoreApps.ps1 +++ b/Rules/IPv4/Outbound/StoreApps.ps1 @@ -335,231 +335,6 @@ foreach ($Principal in $Users) Update-Log } } - - # - # The following are special rules for executables within store app directories which are either not - # handled by auto generated store app rules or because the auto genrated rule doesn't work - # TODO: This is a hackery, a better design or function is needed to detect programs within app folders - # TODO: Not affected by $ForceLoad - # TODO: -LocalUser should be set to $Principal.User or otherwise rule moved outside foreach loop - # - - # - # A special rule for TerminalAzBridge.exe (Azure Cloud Shell) which is part of Windows Terminal - # which is distinct from autogenrated rule - # - $TerminalApp = Get-UserApp -User $Principal.User -Name "*WindowsTerminal*" -Session $SessionInstance - if ($TerminalApp) - { - $ParentPath = Split-Path -Path $TerminalApp.InstallLocation - - Invoke-Command -Session $SessionInstance -ScriptBlock { - # There are 2 paths one of which is invalid and should be ignored - Get-Item -Path "$using:ParentPath\Microsoft.WindowsTerminal*" -Exclude "*_~_*" - } | Select-Object PSPath | Convert-Path | ForEach-Object { - - $Program = Format-Path "$_\TerminalAzBridge.exe" - - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - $AzureShellUsers = Get-SDDL -Group $DefaultGroup -Merge - Merge-SDDL -SDDL ([ref] $AzureShellUsers) -From $AdminGroupSDDL -Unique - - New-NetFirewallRule -DisplayName "Azure Cloud Shell" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $AzureShellUsers ` - -InterfaceType $DefaultInterface ` - -Description "Rule for Azure Cloud Shell in Windows Terminal" | - Format-RuleOutput - } - } - } - - # - # A special rule for EngHost.exe because rule for WinDbg is distinct from this one - # - $WinDbgApp = Get-UserApp -User $Principal.User -Name "*WinDbg*" -Session $SessionInstance - if ($WinDbgApp) - { - $ParentPath = Split-Path -Path $WinDbgApp.InstallLocation - - Invoke-Command -Session $SessionInstance -ScriptBlock { - # There are 2 paths one of which is invalid and should be ignored - Get-Item -Path "$using:ParentPath\Microsoft.WinDbg_*" -Exclude "*_~_*" - } | Select-Object PSPath | Convert-Path | ForEach-Object { - - $Program = Format-Path "$_\amd64\EngHost.exe" - - # MSDN: WinDBG Preview is a UWP application that has very limited access to the system, certainly not enough to debug a process. - # Hence the WinDBG UI and the WinDBG debugger workhorse are in separate processes that communicate - # using the named pipe inter-process communication (IPC) mechanism. - # The WinDBG Preview UI process is DBG.X.Shell.exe which connects over a named pipe to EngHost.exe which is the process - # responsible for attaching or launching the process being debugged. - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - # Port 80 is needed for CRL (Certificate Revocation List), for MS symbol server - New-NetFirewallRule -DisplayName "WinDbg engine host" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 80, 443 ` - -LocalUser $UsersGroupSDDL ` - -InterfaceType $DefaultInterface ` - -Description "EngHost.exe is the process responsible for attaching or launching the process being debugged. -Because WinDbg UWP app has limited system access this process is used via the IPC mechanism" | - Format-RuleOutput - } - } - } - - # - # A special rule for Microsoft.Desktopappinstaller app - # - $DesktopappInstallerApp = Get-UserApp -User $Principal.User -Name "Microsoft.Desktopappinstaller" -Session $SessionInstance - if ($DesktopappInstallerApp) - { - $ParentPath = Split-Path -Path $DesktopappInstallerApp.InstallLocation - - Invoke-Command -Session $SessionInstance -ScriptBlock { - # There are multiple paths but only one is correct - Get-Item -Path "$using:ParentPath\Microsoft.Desktopappinstaller*" -Exclude "*neutral*" - } | Select-Object PSPath | Convert-Path | ForEach-Object { - - $Program = Format-Path "$_\WindowsPackageManagerServer.exe" - - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - New-NetFirewallRule -DisplayName "Windows Package Manager Server" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $UsersGroupSDDL ` - -InterfaceType $DefaultInterface ` - -Description "WindowsPackageManagerServer.exe is used to download apps" | - Format-RuleOutput - } - } - } - - # - # TODO: There is auto generated rule for Microsoft Teams app but it doesn't work - # This code should probably exist only for msteamsupdate.exe, auto generated rule is supposed to - # work for msteams.exe - # - $TeamsApp = Get-UserApp -User $Principal.User -Name "Microsoftteams" -Session $SessionInstance - if ($TeamsApp) - { - $ParentPath = Split-Path -Path $TeamsApp.InstallLocation - - Invoke-Command -Session $SessionInstance -ScriptBlock { - # There are multiple paths but only one is correct - Get-Item -Path "$using:ParentPath\Microsoftteams*" - } | Select-Object PSPath | Convert-Path | ForEach-Object { - - $Program = Format-Path "$_\msteams.exe" - - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - New-NetFirewallRule -DisplayName "Microsoft Teams" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $UsersGroupSDDL ` - -InterfaceType $DefaultInterface ` - -Description "Microsoft Teams app" | - Format-RuleOutput - } - - $Program = Format-Path "$_\msteamsupdate.exe" - - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - New-NetFirewallRule -DisplayName "Microsoft Teams update" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $UsersGroupSDDL ` - -InterfaceType $DefaultInterface ` - -Description "Microsoft Teams app updater" | - Format-RuleOutput - } - } - } - - # - # A special rule for Widgets.exe which is part of MicrosoftWindows.Client.WebExperience (Widgets) app - # Widgets.exe is invoked when adding new widgets by clicking "+" button - # TODO: Even though rule is made "add widget" dialog doesn't display contents as if no connection is made - # - $WidgetsApp = Get-UserApp -User $Principal.User -Name "MicrosoftWindows.Client.WebExperience" -Session $SessionInstance - if ($WidgetsApp) - { - $ParentPath = Split-Path -Path $WidgetsApp.InstallLocation - - Invoke-Command -Session $SessionInstance -ScriptBlock { - # There are 2 paths but only one is correct - Get-Item -Path "$using:ParentPath\MicrosoftWindows.Client.WebExperience*" -Exclude "*neutral*" - } | Select-Object PSPath | Convert-Path | ForEach-Object { - - $Program = Format-Path "$_\Dashboard\Widgets.exe" - - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - New-NetFirewallRule -DisplayName "Widgets" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $UsersGroupSDDL ` - -InterfaceType $DefaultInterface ` - -Description "Used when adding new widgets" | - Format-RuleOutput - } - } - } - - # - # A special rule for Microsoft Phone Link app to handle PhoneExperienceHost.exe - # - $PhoneLinkApp = Get-UserApp -User $Principal.User -Name "Microsoft.YourPhone" -Session $SessionInstance - if ($PhoneLinkApp) - { - $ParentPath = Split-Path -Path $PhoneLinkApp.InstallLocation - - Invoke-Command -Session $SessionInstance -ScriptBlock { - # There are multiple paths but only one is correct - Get-Item -Path "$using:ParentPath\Microsoft.YourPhone*" -Exclude "*neutral*" - } | Select-Object PSPath | Convert-Path | ForEach-Object { - - $Program = Format-Path "$_\PhoneExperienceHost.exe" - - if ((Test-ExecutableFile $Program) -or $ForceLoad) - { - New-NetFirewallRule -DisplayName "Microsoft Phone Link" ` - -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` - -Service Any -Program $Program -Group $AppSubGroup ` - -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` - -LocalAddress Any -RemoteAddress Internet4 ` - -LocalPort Any -RemotePort 443 ` - -LocalUser $UsersGroupSDDL ` - -InterfaceType $DefaultInterface ` - -Description "PhoneExperienceHost.exe is used to pair with your phone" | - Format-RuleOutput - } - } - } } # foreach # @@ -648,6 +423,231 @@ if ((Test-ExecutableFile $Program) -or $ForceLoad) Format-RuleOutput } +# +# The following are special rules for executables within store app directories which are either not +# handled by auto generated store app rules or because the auto genrated rule doesn't work +# TODO: This is a hackery, a better design or function is needed to detect programs within app folders +# TODO: Not affected by $ForceLoad +# + +# +# A special rule for TerminalAzBridge.exe (Azure Cloud Shell) which is part of Windows Terminal +# which is distinct from autogenrated rule +# +$TerminalApp = Get-UserApp -Name "*WindowsTerminal*" -Session $SessionInstance +if ($TerminalApp) +{ + $ParentPath = Split-Path -Path $TerminalApp.InstallLocation + + Invoke-Command -Session $SessionInstance -ScriptBlock { + # There are 2 paths one of which is invalid and should be ignored + Get-Item -Path "$using:ParentPath\Microsoft.WindowsTerminal*" -Exclude "*_~_*" + } | Select-Object PSPath | Convert-Path | ForEach-Object { + + $Program = Format-Path "$_\TerminalAzBridge.exe" + + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + $AzureShellUsers = Get-SDDL -Group $DefaultGroup -Merge + Merge-SDDL -SDDL ([ref] $AzureShellUsers) -From $AdminGroupSDDL -Unique + + New-NetFirewallRule -DisplayName "Azure Cloud Shell" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 443 ` + -LocalUser $AzureShellUsers ` + -InterfaceType $DefaultInterface ` + -Description "Rule for Azure Cloud Shell in Windows Terminal" | + Format-RuleOutput + } + } +} + +# +# A special rule for EngHost.exe because rule for WinDbg is distinct from this one +# +$WinDbgApp = Get-UserApp -Name "*WinDbg*" -Session $SessionInstance +if ($WinDbgApp) +{ + $ParentPath = Split-Path -Path $WinDbgApp.InstallLocation + + Invoke-Command -Session $SessionInstance -ScriptBlock { + # There are 2 paths one of which is invalid and should be ignored + Get-Item -Path "$using:ParentPath\Microsoft.WinDbg_*" -Exclude "*_~_*" + } | Select-Object PSPath | Convert-Path | ForEach-Object { + + $Program = Format-Path "$_\amd64\EngHost.exe" + + # MSDN: WinDBG Preview is a UWP application that has very limited access to the system, certainly not enough to debug a process. + # Hence the WinDBG UI and the WinDBG debugger workhorse are in separate processes that communicate + # using the named pipe inter-process communication (IPC) mechanism. + # The WinDBG Preview UI process is DBG.X.Shell.exe which connects over a named pipe to EngHost.exe which is the process + # responsible for attaching or launching the process being debugged. + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + # Port 80 is needed for CRL (Certificate Revocation List), for MS symbol server + New-NetFirewallRule -DisplayName "WinDbg engine host" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 80, 443 ` + -LocalUser $UsersGroupSDDL ` + -InterfaceType $DefaultInterface ` + -Description "EngHost.exe is the process responsible for attaching or launching the process being debugged. +Because WinDbg UWP app has limited system access this process is used via the IPC mechanism" | + Format-RuleOutput + } + } +} + +# +# A special rule for Microsoft.Desktopappinstaller app +# +$DesktopappInstallerApp = Get-UserApp -Name "Microsoft.Desktopappinstaller" -Session $SessionInstance +if ($DesktopappInstallerApp) +{ + $ParentPath = Split-Path -Path $DesktopappInstallerApp.InstallLocation + + Invoke-Command -Session $SessionInstance -ScriptBlock { + # There are multiple paths but only one is correct + Get-Item -Path "$using:ParentPath\Microsoft.Desktopappinstaller*" -Exclude "*neutral*" + } | Select-Object PSPath | Convert-Path | ForEach-Object { + + $Program = Format-Path "$_\WindowsPackageManagerServer.exe" + + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + New-NetFirewallRule -DisplayName "Windows Package Manager Server" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 443 ` + -LocalUser $UsersGroupSDDL ` + -InterfaceType $DefaultInterface ` + -Description "WindowsPackageManagerServer.exe is used to download apps" | + Format-RuleOutput + } + } +} + +# +# TODO: There is auto generated rule for Microsoft Teams app but it doesn't work +# This code should probably exist only for msteamsupdate.exe, auto generated rule is supposed to +# work for msteams.exe +# +$TeamsApp = Get-UserApp -Name "Microsoftteams" -Session $SessionInstance +if ($TeamsApp) +{ + $ParentPath = Split-Path -Path $TeamsApp.InstallLocation + + Invoke-Command -Session $SessionInstance -ScriptBlock { + # There are multiple paths but only one is correct + Get-Item -Path "$using:ParentPath\Microsoftteams*" + } | Select-Object PSPath | Convert-Path | ForEach-Object { + + $Program = Format-Path "$_\msteams.exe" + + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + New-NetFirewallRule -DisplayName "Microsoft Teams" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 443 ` + -LocalUser $UsersGroupSDDL ` + -InterfaceType $DefaultInterface ` + -Description "Microsoft Teams app" | + Format-RuleOutput + } + + $Program = Format-Path "$_\msteamsupdate.exe" + + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + New-NetFirewallRule -DisplayName "Microsoft Teams update" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 443 ` + -LocalUser $UsersGroupSDDL ` + -InterfaceType $DefaultInterface ` + -Description "Microsoft Teams app updater" | + Format-RuleOutput + } + } +} + +# +# A special rule for Widgets.exe which is part of MicrosoftWindows.Client.WebExperience (Widgets) app +# Widgets.exe is invoked when adding new widgets by clicking "+" button +# TODO: Even though rule is made "add widget" dialog doesn't display contents as if no connection is made +# +$WidgetsApp = Get-UserApp -Name "MicrosoftWindows.Client.WebExperience" -Session $SessionInstance +if ($WidgetsApp) +{ + $ParentPath = Split-Path -Path $WidgetsApp.InstallLocation + + Invoke-Command -Session $SessionInstance -ScriptBlock { + # There are 2 paths but only one is correct + Get-Item -Path "$using:ParentPath\MicrosoftWindows.Client.WebExperience*" -Exclude "*neutral*" + } | Select-Object PSPath | Convert-Path | ForEach-Object { + + $Program = Format-Path "$_\Dashboard\Widgets.exe" + + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + New-NetFirewallRule -DisplayName "Widgets" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 443 ` + -LocalUser $UsersGroupSDDL ` + -InterfaceType $DefaultInterface ` + -Description "Used when adding new widgets" | + Format-RuleOutput + } + } +} + +# +# A special rule for Microsoft Phone Link app to handle PhoneExperienceHost.exe +# +$PhoneLinkApp = Get-UserApp -Name "Microsoft.YourPhone" -Session $SessionInstance +if ($PhoneLinkApp) +{ + $ParentPath = Split-Path -Path $PhoneLinkApp.InstallLocation + + Invoke-Command -Session $SessionInstance -ScriptBlock { + # There are multiple paths but only one is correct + Get-Item -Path "$using:ParentPath\Microsoft.YourPhone*" -Exclude "*neutral*" + } | Select-Object PSPath | Convert-Path | ForEach-Object { + + # TODO: Test why no longer exists? possibly because phone app not configured? + $Program = Format-Path "$_\PhoneExperienceHost.exe" + + if ((Test-ExecutableFile $Program) -or $ForceLoad) + { + New-NetFirewallRule -DisplayName "Microsoft Phone Link" ` + -Platform $Platform -PolicyStore $PolicyStore -Profile $DefaultProfile ` + -Service Any -Program $Program -Group $AppSubGroup ` + -Enabled True -Action Allow -Direction $Direction -Protocol TCP ` + -LocalAddress Any -RemoteAddress Internet4 ` + -LocalPort Any -RemotePort 443 ` + -LocalUser $UsersGroupSDDL ` + -InterfaceType $DefaultInterface ` + -Description "PhoneExperienceHost.exe is used to pair with your phone" | + Format-RuleOutput + } + } +} + if ($UpdateGPO) { Invoke-Process gpupdate.exe diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1a857f4c..c378fc6d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -33,6 +33,7 @@ Here is a list of changes for each of the releases. - Updated rule description for Logitech G HUB - Added rules for Microsoft PowerToys - Updated rule for curl which ships with Git for automatic updates + - Updated rules for sysinternals suite to handle it if installed trough MS Store - Modules @@ -43,6 +44,7 @@ Here is a list of changes for each of the releases. warning is shown if NuGet package source was not set to trusted in that case only - `Update-Table` function no longer assumes wildcard search but accepts wildcards - `Get-SystemProgram` Updated to get executable if program name can't be determined, or skiped otherwise + - `Get-UserApp` and `Get-SystemApp`, if no user is specified gets store apps for all user accounts on the computer - Scripts