CrowdStrike / CAST

CrowdStrike Archive Scan Tool
MIT License
83 stars 19 forks source link

IDEA: Deduplicate Paths so subdirectories are not scanned separately. #23

Closed jashley1992 closed 2 years ago

jashley1992 commented 2 years ago

@bk-cs What about something like this? There are probably better ways to do this, but it seems to work fairly well for me. Definitely not finalized, just some POC code to test the idea..

 $DirDelim = [System.IO.Path]::DirectorySeparatorChar
 $RegexDD = [regex]::Escape($DirDelim)

 $FinalList = New-Object 'System.Collections.Generic.List[string]'
 $RemovedPaths = New-Object 'System.Collections.Generic.List[string]'

 [array] $Directories = ('Software\Microsoft\Windows\CurrentVersion\Uninstall\*',
 'Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*').foreach{
     (Get-ItemProperty -Path "Registry::\HKEY_LOCAL_MACHINE\$_" | Where-Object InstallLocation).InstallLocation
     foreach ($UserSid in (Get-WmiObject Win32_UserProfile | Where-Object { $_.SID -like 'S-1-5-21-*' }).SID) {
         (Get-ItemProperty -Path "Registry::\HKEY_USERS\$UserSid\$_" | Where-Object InstallLocation).InstallLocation
     }
 }
 $Directories += (Get-Process | Where-Object { $_.Path }).Path | Split-Path
 $Directories = $Directories | Sort-Object -Unique | Where-Object { Test-Path $_ -EA SilentlyContinue }

 $Directories | % {

     $CurrentDir = $_.TrimEnd($RegexDD)

     if ($RemovedPaths -notcontains $CurrentDir) {

         foreach ($Path in $Directories) {
             If ($Path.StartsWith("$($CurrentDir)\","CurrentCultureIgnoreCase") -and $Path.TrimEnd($RegexDD) -ne $CurrentDir) {
                 Write-Warning "DUPLICATE PATH FOUND: $Path"
                 $RemovedPaths.Add($Path.TrimEnd($RegexDD))
             }
         }

         if ($FinalList -notcontains $CurrentDir -and $RemovedPaths -notcontains $CurrentDir) {

             Write-Warning "Final List Add: $CurrentDir"
             $FinalList.Add($CurrentDir)
         }
     }

 }

$FinalListCount = ($FinalList).Count
$OriginalCount = ($Directories).Count

Write-Host "Reduced in-scope paths by $($OriginalCount - $FinalListCount)" -ForegroundColor Green
Write-Host "Paths Removed:" -ForegroundColor Red
$RemovedPaths

Write-Host "Final Listing:" -ForegroundColor Green
$FinalList | Sort-Object

Originally posted by @jashley1992 in https://github.com/CrowdStrike/CAST/issues/22#issuecomment-1017146208

bk-cs commented 2 years ago

Sorry, I had this on my "to do" list but haven't had the chance to get around to do it.

cast.exe seems to scan fast enough that the targeted search isn't really required to get it done in a reasonable amount of time. The de-duplication of paths is a good idea for the PowerShell script, but I think the time difference will be minimal based on how fast CAST scans.

I'm going to close this since I won't have any time to review it myself, but if you'd like to pull, test and recommend changes yourself, please feel free to do so! :)