When and Why Would I Use Custom Detection Methods?
Although, Intune has some manual detection methods such as: File, MSI, and Registry based detections. There is always that ‘particular’ app for your environment that comes along that requires a little bit of extra attention… Perhaps we are given a remediation task from the security team for a specific application that we don’t typically deploy. We are next tasked with the research of having learn how to locate the application and how to deal with it. Here is how we can quickly identify which schema to approach it with.
What Common Detection Methods Are There?
Here is a list of common methods and commands typically used to find applications on workstations. Each of them has their limitations, but more often than not, one of them will be able to locate your search criteria that you are using for an application:
- Registry Parsing: HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
- Registry Parsing: HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\
- Get-Package (Not Available in PowerShell Core as of version 7.4.1)
- Windows App Detection
- Winget
- Get-AppxPackage
- Get-WMIObject -class Win32_Product (DON’T USE THIS, Win32_Product Is in fact, Evil)
- Get-cimInstance -class Win32_AddRemovePrograms64 | -class Win32_AddRemovePrograms
How Can We Save Time in Researching? ๐ฉ
The best way to tackle this for each new instance would be, to check them all at the same time! Here is an example of taking a search criterion and running it against all these methods, (..besides Win32_Product…), so we can quickly see which method will be applicable to our application.
Here is a script that can be used to do this. Once you run this script, it will Read-Host, and request a term to search for:
- “Chrome” For querying an application like Google Chrome
- “MSTeams” For querying the New Microsoft Teams Application
- “Ookla” For a less specific, less common application: Speedtest CLI by Ookla
#Example 1 = "Chrome"
#Example 2 = "MSTeams"
#Example 3 = "AppInstaller"
$SearchFor = $(Write-Host "Enter Search Criteria: " -ForegroundColor Cyan -NoNewline; Read-Host)
################################ Win32Reg_AddRemovePrograms64 Method
if (get-cimInstance -class Win32Reg_AddRemovePrograms64 | where-object { $_.Displayname -like "*$($SearchFor)*" })
{ Write-host "Win32Reg_AddRemovePrograms64 Class Successful" -ForegroundColor Green }
else { Write-host "Win32Reg_AddRemovePrograms64 Class Failed" -ForegroundColor Red }
################################ Win32Reg_AddRemovePrograms Method
if (get-cimInstance -class Win32Reg_AddRemovePrograms | where-object { $_.Displayname -like "*$($SearchFor)*" })
{ Write-host "Win32Reg_AddRemovePrograms Class Successful" -ForegroundColor Green }
else { Write-host "Win32Reg_AddRemovePrograms Class Failed" -ForegroundColor Red }
################################ Registry Parse Method
[array]$ProductCheck = @()
# Get 64 bits programs
$ProductCheck = Get-ItemProperty `
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |
Where-Object { $_.DisplayName -like "*$($SearchFor)*" }
# Add 32 bits programs
$ProductCheck += Get-ItemProperty `
HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* |
Where-Object { $_.DisplayName -like "*$($SearchFor)*" }
if ($ProductCheck)
{ Write-host "Registry Parse Successful" -ForegroundColor Green }
else { Write-host "Registry Parse Failed" -ForegroundColor Red }
################################ Get-Package Method
if ($PSVersionTable.PSEdition -ne "Core") {
if (Get-package *$SearchFor* -ErrorAction SilentlyContinue)
{ Write-host "Get-Package Successful" -ForegroundColor Green }
else { Write-host "Get-Package Failed" -ForegroundColor Red }
}
################################ Windows Apps Method
if (Get-ChildItem "C:\Program Files\WindowsApps" -Filter "*$($SearchFor)*")
{ Write-host "WindowsApps Location Successful" -ForegroundColor Green }
else { Write-host "WindowsApps Location Failed" -ForegroundColor Red }
################################ Winget Method
$WinGetResolve = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe\winget.exe"
$WinGetPathExe = $WinGetResolve[-1].Path
$WinGetPath = Split-Path -Path $WinGetPathExe -Parent
Push-Location $WinGetPath
$WingetList = .\winget.exe list $SearchFor --source winget
Pop-Location
$DetectedID = ( -split ($wingetlist[-1])) | select-string "$($SearchFor)*"
if ($DetectedID) {
Write-host "Winget Detection Successful" -ForegroundColor Green
$WingetVer = (-split $wingetlist[-1])[-1]
$WingetID = (-split $wingetlist[-1])[-2]
}
else { Write-host "Winget Detection Failed" -ForegroundColor Red }
################################ Get-AppX Method
$AppX = Get-AppxPackage | Where-Object name -Like "*$($SearchFor)*"
if ($AppX) { Write-host "AppX Detection Successful" -ForegroundColor Green }
else { Write-host "AppX Detection Failed" -ForegroundColor Red }
################################ Results
if ($ProductCheck.DisplayName) {
Write-host $ProductCheck.DisplayName -ForegroundColor Magenta
write-host $ProductCheck.DisplayVersion -ForegroundColor Magenta
}
if ($DetectedID) {
Write-host "Winget ID: $WingetID" -ForegroundColor Magenta
Write-host "Winget Version: $Wingetver" -ForegroundColor Magenta
}
if ($AppX) {
Write-host "AppX Name: $($AppX.Name)" -ForegroundColor Magenta
Write-host "Appx Version: $($AppX.Version)" -ForegroundColor Magenta
}
GitHub Link to Script: Intune/Find-DetectionMethods.ps1 at main ยท jagonzalez428/Intune (github.com)
Examples of Script Prompt & Results:
Using the search Term “Chrome“:
Using the search term “MSTeams“:
Using the search term “Ookla“
I Got the Results, But What’s Next?
Alright, you have gotten the common successful methods, how do you go about using them? Well, I have added a template for each of the detection methods used in script. Now that you know which ones your application should work with, you can use the template based on the successful response. I have made two types of each method: a “-like” method, and an “-equal” method. One will allow you query the term and see what data comes back and why it deems it successful. The other one will be an exact search of the term, which should be used for production detection method once you have determined the data you are looking for.
Detection Method Templates GitHub Link: Example of -like & -equal detection scripts
-like example of “Win32Reg_AddRemovePrograms”:
#You can replace it with your own variable directly
$SearchFor = $(Write-Host "Enter Search Criteria: " -ForegroundColor Cyan -NoNewline; Read-Host)
get-cimInstance -class Win32Reg_AddRemovePrograms | where-object { $_.Displayname -like "*$($SearchFor)*"}
Using, “Chrome” you get the following output:
DisplayName : Google Chrome
InstallDate : 20240222
ProdID : {37A0D46D-9BFE-352E-8B00-9ED6C296E9A5}
Publisher : Google LLC
Version : 122.0.6261.129
You can then throw it into the -equal example to utilize for a detection script. ๐
-equal example of “Win32Reg_AddRemovePrograms”:
try {
#You can replace these variables directly once you have the criteria from Like-WinReg_AddRemovePrograms.ps1
$DisplayName = "Google Chrome"
$Version = "122.0.6261.129"
$Detection = get-cimInstance -class Win32Reg_AddRemovePrograms | where-object { $_.Displayname -eq $DisplayName -and $_.Version -eq $Version }
if ($Detection) {
Write-Host "Application $DisplayName is currently installed." -ForegroundColor Green
exit 0
}
else {
Write-Host "Application $DisplayName is currently not installed." -ForegroundColor Green
exit 1
}
}
catch {
$errMSG = $_.Message.Exception
Write-Host $errMSG
exit 1
}
Your output would then be the following, while also applying the exit code for Success/Failure
Application Google Chrome is currently installed.
Don’t Stop there!
If you run across other successful methods of detection, feel free to branch of the Git, or just add on to the script for your own usage. Research is another time-consuming task, and at the end of the day we want to utilize tools as admins, so we effectively get the job done, as well as minimizing the window for remediation tasks. With that said, I hope this helps at least someone out there! ๐