Skip to main content
Question

Worklet? Crowdstrike Uninstall to Move Asset to another Crowdstrike Console

  • April 10, 2024
  • 1 reply
  • 373 views

james.whiting.gsl
Forum|alt.badge.img

We’ve just set up 2 extra Crowdstrike consoles to allow segregation of assets and users. However, I’m struggling to find a way to move these assets in bulk, as I need to uninstall the sensor on each asset, and then reinstall with a different Customer ID.

 

Does anyone think this would be possible via a couple of worklets? Otherwise I’m looking at a huge manual job… Thanks!

1 reply

jack.smith
Forum|alt.badge.img+1
  • All Star
  • 168 replies
  • April 10, 2024

@james.whiting.gsl  I’d log into their support portal and grab a copy of CsUninstallTool.exe

It has been awhile since I’ve used this, so if you run into a snag let me know!

 

# Evaluation

$cs = get-service csagent -ErrorAction SilentlyContinue
IF($cs)
{
  Exit 1
} 
else 
{
  Exit 0
}

# Remediation

$log = 'C:\windows\temp\crowdstrike-removal.log'
Start-Process CsUninstallTool.exe -argumentlist "/quiet /log $log"
Start-Sleep -Seconds 120
$cs = get-service csagent -ErrorAction SilentlyContinue
IF($cs)
{
  write-output "Something went wrong with uninstall."
  IF(!(Test-Path C:\windows\temp\CsUninstallTool.exe)){ Copy-Item .\CsUninstallTool.exe C:\windows\temp\CsUninstallTool.exe }
  IF(Test-Path $log){
    Get-Content $log
  }else{
    Write-output "Unable to locate $log"
  }
    # Installed Software
  $scriptblock = {
      $Paths  = @("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall","SOFTWARE\\Wow6432node\\Microsoft\\Windows\\CurrentVersion\\Uninstall")         
      ForEach($Path in $Paths) { 

          Write-Verbose  "Checking Path: $Path"

          #  Create an instance of the Registry Object and open the HKLM base key 
          #Try  { $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer,'Registry64') } Catch  { Write-Error $_ ; Continue } 
          Try  { $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine',$Computer,'Registry64') } Catch  { Continue }
          #  Drill down into the Uninstall key using the OpenSubKey Method 

          Try  {

              $regkey=$reg.OpenSubKey($Path)  

              # Retrieve an array of string that contain all the subkey names 
              $subkeys=$regkey.GetSubKeyNames()      

              # Open each Subkey and use GetValue Method to return the required  values for each 
              ForEach ($key in $subkeys){   
                  Write-Verbose "Key: $Key"
                  $thisKey=$Path+"\\"+$key 
                  Try {

                      $thisSubKey=$reg.OpenSubKey($thisKey)   

                      # Prevent Objects with empty DisplayName 
                      $DisplayName =  $thisSubKey.getValue("DisplayName")

                      If ($DisplayName -AND $DisplayName -notmatch '^Update  for|rollup|^Security Update|^Service Pack|^HotFix') {

                          $Date = $thisSubKey.GetValue('InstallDate')
                          #If ($Date) { Try { $Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null) } Catch { Write-Warning "$($Computer): $_ <$($Date)>"; $Date = $Null } } 
                          If ($Date) { Try { $Date = [datetime]::ParseExact($Date, 'yyyyMMdd', $Null) } Catch { $Date = $Null } } 
                          # Create New Object with empty Properties 
                          $Publisher =  Try { $thisSubKey.GetValue('Publisher').Trim() } Catch { $thisSubKey.GetValue('Publisher') }
                          $Version = Try {
                              #Some weirdness with trailing [char]0 on some strings
                              $thisSubKey.GetValue('DisplayVersion').TrimEnd(([char[]](32,0)))
                          } Catch { $thisSubKey.GetValue('DisplayVersion') }
                          $UninstallString =  Try { $thisSubKey.GetValue('UninstallString').Trim() } Catch { $thisSubKey.GetValue('UninstallString') }
                          $InstallLocation =  Try { $thisSubKey.GetValue('InstallLocation').Trim() } Catch { $thisSubKey.GetValue('InstallLocation') }
                          $InstallSource =  Try { $thisSubKey.GetValue('InstallSource').Trim() } Catch { $thisSubKey.GetValue('InstallSource') }
                          $HelpLink = Try { $thisSubKey.GetValue('HelpLink').Trim() } Catch { $thisSubKey.GetValue('HelpLink') }

                          $Object = [pscustomobject]@{
                              Computername = $env:COMPUTERNAME
                              DisplayName = $DisplayName
                              Version  = $Version
                              InstallDate = $Date
                              Publisher = $Publisher
                              UninstallString = $UninstallString
                              InstallLocation = $InstallLocation
                              InstallSource  = $InstallSource
                              HelpLink = $thisSubKey.GetValue('HelpLink')
                              EstimatedSizeMB = [decimal]([math]::Round(($thisSubKey.GetValue('EstimatedSize')*1024)/1MB,2))
                          }
                          $Object.pstypenames.insert(0,'System.Software.Inventory')
                          Write-Output $Object
                      }

                  } Catch { Write-Warning "$Key : $_" }   
              }
          } Catch  {}
          $reg.Close() 
      } # end IF Paths
  }
  # Run the scriptblock and store results in the $64bit variable
  $softwares = & "$env:SystemRoot\sysnative\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -WindowStyle Hidden -NoProfile -NonInteractive -Command $scriptblock | where DisplayName -eq 'Crowdstrike Sensor Platform'

  foreach ($software in $softwares)
  {
      IF($software){
        Write-Output "Currently $($software.Displayname) version $($software.Version) Installed. Attempting removal with Msiexec "
        IF($software.UninstallString -match 'WindowsSensor.x64'){
            $e = ($software.UninstallString).split('"')[1]
            Write-Output "Running $e /uninstall /quiet"
            Start-Process $e -ArgumentList "/uninstall /quiet"
        }
        Write-Output "Extracting Uninstall string from $($software.UninstallString)"
        $UninstallString = $software.UninstallString | Select-String -Pattern '{[-0-9A-F]+?}' -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value
        Start-Process MsiExec -ArgumentList "/X $UninstallString /qn" -Wait
        $cs = get-service csagent -ErrorAction SilentlyContinue
        IF($cs){
          Write-Output "Failed to remove Crowdstrike using MSIExec."
          $events = Get-WinEvent -FilterHashtable @{
           LogName='Application'
           ProviderName='MSIInstaller'
          } -MaxEvents 10 | Where-Object Message -match "Crowdstrike"
          ForEach($event in $events){
            Write-Output "$($event.TimeCreated) >> $($event.Message)"
          }
        }else{ Write-Output "Removed Crowdstrike with MSIExec. "}
      }else{
        Write-Output "Did not detect Crowdstrike as installed software in registry."
      }
  }
} 
else 
{
  write-output "Falcon Agent removed"
}

 


Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings