Monthly Archives: August 2022

Intune Proactive Remediation: Detect & Remove User-installed Instances of Zoom

Had a requirement to detect and remove any user installations of Zoom (i.e. installed using standard user permissions and located in the user profile) via Intune. The supported route for uninstalling Zoom is use a Zoom-provided tool called ‘CleanZoom.exe’ so the script checks for that tool being present and if not, downloads and extracts it directly from Zoom before running the tool to remove any user installations of Zoom. Also needed a log file to show when this has been done from the client (this can obviously be removed if not needed).

Proactive Remediations to the rescue again!

Detection:

<#
.DESCRIPTION
	Proactive Remediation | Detection
.EXAMPLE
	PowerShell.exe -ExecutionPolicy ByPass -File <ScriptName>.ps1
.NOTES
	VERSION     AUTHOR              CHANGE
    1.0         Jonathan Conway     Initial script creation
#>

# Discovery
try {
    # Run Test and store as variable
    $Test = Get-ChildItem -Path "C:\Users\" -Filter "Zoom.exe" -Recurse -Force -ErrorAction SilentlyContinue

    # Check where test is compliant or not - if no instances of Zoom are discovered then mark as 'Compliant' and exit with 0
    if ($null -eq $Test) {
        Write-Output "Compliant"
        exit 0
    }
    # If instances of Zoom are discovered then mark as 'Non Compliant' and exit with 1
    else {
        Write-Warning "Non Compliant"
        exit 1
    }
}

catch {
    # If any errors occur then return 'Non Compliant'
    Write-Warning "Non Compliant"
    exit 1
}

Remediation:

<#
.DESCRIPTION
	Proactive Remediation | Remediation
.EXAMPLE
	PowerShell.exe -ExecutionPolicy ByPass -File <ScriptName>.ps1
.NOTES
	VERSION     AUTHOR              CHANGE
    1.0         Jonathan Conway     Initial script creation
#>

# Logging
$LogPath = "C:\Support\Zoom\"
Start-Transcript -Path $LogPath\ZoomCleanup.log -Append -NoClobber

# Variables
$CleanZoomTool = "C:\Support\Zoom\CleanZoom.exe"

# Check to see if 'C:\Support\Zoom' exists
$CheckZoomFolder = Test-Path -Path "C:\Support\Zoom\" -PathType Container

# If 'C:\Support\Zoom' folder does not exist then create it
if ($CheckZoomFolder -eq $false) {

	# Create folder
	Write-Output "'C:\Support\Zoom' folder does not exist - creating it"
	New-Item -Path "C:\Support" -Name "Zoom" -ItemType "Directory" -Force

}
else {
	Write-Output "'C:\Support\Zoom' folder exists - continuing"
}

# Check if CleanZoom.exe exists on the device
$CheckZoomClean = Test-Path -Path $CleanZoomTool -PathType "Leaf"

# If CleanZoom.exe does not exist on the device - download from Zoom website and extract locally
if ($CheckZoomClean -eq $false) {

	Write-Output "'C:\Support\Zoom\CleanZoom.exe' does not exist - downloading and extracting it"
	Invoke-WebRequest -Uri "https://assets.zoom.us/docs/msi-templates/CleanZoom.zip" -OutFile "C:\Support\Zoom\CleanZoom.zip"
	Expand-Archive -Path "C:\Support\Zoom\CleanZoom.zip" -DestinationPath "C:\Support\Zoom" -Force
	Remove-Item -Path "C:\Support\Zoom\CleanZoom.zip" -Force

}
else {
	Write-Output "'C:\Support\Zoom\CleanZoom.exe' exists - continuing"
}

try {
	# Run CleanZoom.exe to remove any installed instances of Zoom client in User Profiles
	Write-Output "Running CleanZoom.exe to remove Zoom instances from User Profile areas"
	Start-Process -FilePath $CleanZoomTool -ArgumentList "/silent"
	exit 0
}
catch {
	Write-Output "CleanZoom.exe failed to run"
	exit 1
}

Stop-Transcript

/ JC

Intune Proactive Remediation: BitLocker Key Escrow to Azure AD After MECM OSD Task Sequence

Recently had a customer requirement to encrypt Windows 10 devices using a MECM Task Sequence and then have the Recovery Keys escrowed into AAD once an Intune Drive Encryption policy was applied via Co-management workload shift (Endpoint Protection).

By default, Windows will escrow to where you tell it in the Task Sequence and not escrow into AAD. In my case the Task Sequence was storing the Recovery Key into on-prem Active Directory.

The Discovery script checks Event Viewer for an Event 845 including the text “was backed up successfully to your Azure AD” having been logged in the last 7 days (this can obviously be amended to suit individual requirements).

If non-compliant then the Remediation script forces the key to be escrowed using the ‘BackupToAAD-BitLockerKeyProtector’ PowerShell cmdlet.

Detection:

<#
.DESCRIPTION
    Script to check for BitLocker Key escrow into Azure AD
.EXAMPLE
    PowerShell.exe -ExecutionPolicy ByPass -File <ScriptName>.ps1
.NOTES
    VERSION     AUTHOR              CHANGE
    1.0         Jonathan Conway     Initial script creation
#>

# Check for Event 845 in BitLocker API Management Event Log over last 7 days - if contains text "was backed up successfully to your Azure AD" then Detection is complete
try {
    $Result = Get-WinEvent -FilterHashTable @{LogName = "Microsoft-Windows-BitLocker/BitLocker Management"; StartTime = (Get-Date).AddDays(-7) } | Where-Object { ($_.Id -eq "845" -and $_.Message -match "was backed up successfully to your Azure AD") } | Format-Table -Property "Message"
    $ID = $Result | Measure-Object

    if ($ID.Count -ge 1) {
        Write-Output "BitLocker Recovery Key escrow to Azure AD succeeded = Compliant"
        exit 0
    }

    # If Event is not detected then mark as 'Non Compliant' and exit with 1
    else {
        Write-Warning "BitLocker Escrow Event Missing = Non Compliant"
        exit 1
    }
}

catch {
    Write-Warning "An error occurred = Non Compliant"
    exit 1
}

Remediation:

<#
.DESCRIPTION
    Script to remediate BitLocker Key escrow into Azure AD
.EXAMPLE
    PowerShell.exe -ExecutionPolicy ByPass -File <ScriptName>.ps1
.NOTES
	VERSION     AUTHOR              CHANGE
    1.0         Jonathan Conway     Initial script creation
#>

# Escrow BitLocker Recovery Key for OSDrive into Azure AD
$BitLockerVolume = Get-BitLockerVolume -MountPoint $env:SystemRoot
$RecoveryPasswordKeyProtector = $BitLockerVolume.KeyProtector | Where-Object { $_.KeyProtectorType -like "RecoveryPassword" }
BackupToAAD-BitLockerKeyProtector -MountPoint $BitLockerVolume.MountPoint -KeyProtectorId $RecoveryPasswordKeyProtector.KeyProtectorId -ErrorAction SilentlyContinue

/ JC