From 1da28024cc79917b0a0c47e152f64876c880c00b Mon Sep 17 00:00:00 2001 From: Zehadi Alam <63765084+zehadialam@users.noreply.github.com> Date: Sun, 15 Sep 2024 00:41:04 -0400 Subject: [PATCH 1/4] Add support for updating latest Windows Malicious Software Removal Tool --- FFUDevelopment/Apps/InstallAppsandSysprep.cmd | 1 + FFUDevelopment/BuildFFUVM.ps1 | 90 ++++++++++++++++++- 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/FFUDevelopment/Apps/InstallAppsandSysprep.cmd b/FFUDevelopment/Apps/InstallAppsandSysprep.cmd index 2178783..fc3477b 100644 --- a/FFUDevelopment/Apps/InstallAppsandSysprep.cmd +++ b/FFUDevelopment/Apps/InstallAppsandSysprep.cmd @@ -5,6 +5,7 @@ REM d:\Office\setup.exe /configure d:\office\DeployFFU.xml REM Install Defender Platform Update REM Install Defender Definitions REM Install Windows Security Platform Update +REM Install Windows Malicious Software Removal Tool REM Install OneDrive Per Machine REM Install Edge Stable REM Winget Win32 Apps diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 68cc570..bf01154 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -115,6 +115,9 @@ When set to $true, will download and install the latest .NET Framework for Windo .PARAMETER UpdateLatestDefender When set to $true, will download and install the latest Windows Defender definitions and Defender platform update. Default is $false. +.PARAMETER UpdateLatestMSRT +When set to $true, will download and install the latest Windows Malicious Software Removal Tool. Default is $false + .PARAMETER UpdateEdge When set to $true, will download and install the latest Microsoft Edge for Windows 10/11. Default is $false. @@ -306,6 +309,7 @@ param( [bool]$UpdatePreviewCU, [bool]$UpdateLatestNet, [bool]$UpdateLatestDefender, + [bool]$UpdateLatestMSRT, [bool]$UpdateEdge, [bool]$UpdateOneDrive, [bool]$CopyPPKG, @@ -372,6 +376,7 @@ if (-not $FFUCaptureLocation) { $FFUCaptureLocation = "$FFUDevelopmentPath\FFU" if (-not $LogFile) { $LogFile = "$FFUDevelopmentPath\FFUDevelopment.log" } if (-not $KBPath) { $KBPath = "$FFUDevelopmentPath\KB" } if (-not $DefenderPath) { $DefenderPath = "$AppsPath\Defender" } +if (-not $MSRTPath) { $MSRTPath = "$AppsPath\MSRT" } if (-not $OneDrivePath) { $OneDrivePath = "$AppsPath\OneDrive" } if (-not $EdgePath) { $EdgePath = "$AppsPath\Edge" } if (-not $DriversFolder) { $DriversFolder = "$FFUDevelopmentPath\Drivers" } @@ -2309,6 +2314,39 @@ function Save-KB { return $fileName } +function Get-MSRTUrl { + param ( + [ValidateSet("x86", "x64")] + [string]$WindowsArch + ) + try { + # Retrieve content of Windows Malicious Software Removal Tool page + $pattern = '\"url\":\"(https://download\.microsoft\.com/download/[^"]+)\"' + $OriginalVerbosePreference = $VerbosePreference + $VerbosePreference = 'SilentlyContinue' + if ($WindowsArch -eq "x64") { + $MSRTWebPage = Invoke-RestMethod "https://www.microsoft.com/en-us/download/details.aspx?id=9905" -Headers $Headers -UserAgent $UserAgent + } + if ($WindowsArch -eq "x86") { + $MSRTWebPage = Invoke-RestMethod "https://www.microsoft.com/en-us/download/details.aspx?id=16" -Headers $Headers -UserAgent $UserAgent + } + $VerbosePreference = $OriginalVerbosePreference + # Extract download URL based on specified pattern + $MSRTMatch = [regex]::Match($MSRTWebPage, $pattern) + if (-not $MSRTMatch.Success) { + WriteLog "Failed to retrieve Malicious Software Removal Tool URL. Pattern match failed" + return + } + $MSRTUrl = $MSRTMatch.Groups[1].Value + return $MSRTUrl + } + catch { + WriteLog $_ + Write-Error "Error occurred while retrieving Windows Malicious Software Removal Tool link" + throw $_ + } +} + function New-AppsISO { #Create Apps ISO file $OSCDIMG = "$adkpath`Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe" @@ -3511,6 +3549,12 @@ function Get-FFUEnvironment { Remove-Item -Path $DefenderPath -Recurse -Force -ErrorAction SilentlyContinue WriteLog 'Removal complete' } + #Clean up $MSRTPath + if (Test-Path -Path $MSRTPath) { + WriteLog "Removing $MSRTPath" + Remove-Item -Path $MSRTPath -Recurse -Force -ErrorAction SilentlyContinue + WriteLog 'Removal complete' + } #Clean up $OneDrivePath If (Test-Path -Path $OneDrivePath) { WriteLog "Removing $OneDrivePath" @@ -3561,6 +3605,17 @@ function Clear-InstallAppsandSysprep { WriteLog 'Removal complete' } } + if ($UpdateLatestMSRT) { + WriteLog "Updating $AppsPath\InstallAppsandSysprep.cmd to remove Windows Malicious Software Removal Tool" + $CmdContent = Get-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" + $CmdContent -notmatch 'd:\\MSRT*' | Set-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" + #Clean up $MSRTPath + If (Test-Path -Path $MSRTPath) { + WriteLog "Removing $MSRTPath" + Remove-Item -Path $MSRTPath -Recurse -Force -ErrorAction SilentlyContinue + WriteLog 'Removal complete' + } + } if ($UpdateOneDrive) { WriteLog "Updating $AppsPath\InstallAppsandSysprep.cmd to remove OneDrive install" $CmdContent = Get-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" @@ -3727,8 +3782,8 @@ if (($LogicalSectorSizeBytes -eq 4096) -and ($installdrivers -eq $true)) { if ($BuildUSBDrive -eq $true) { $USBDrives, $USBDrivesCount = Get-USBDrive } -if (($InstallApps -eq $false) -and (($UpdateLatestDefender -eq $true) -or ($UpdateOneDrive -eq $true) -or ($UpdateEdge -eq $true))) { - WriteLog 'You have selected to update Defender, OneDrive, or Edge, however you are setting InstallApps to false. These updates require the InstallApps variable to be set to true. Please set InstallApps to true and try again.' +if (($InstallApps -eq $false) -and (($UpdateLatestDefender -eq $true) -or ($UpdateOneDrive -eq $true) -or ($UpdateEdge -eq $true) -or ($UpdateLatestMSRT -eq $true))) { + WriteLog 'You have selected to update Defender, Malicious Software Removal Tool, OneDrive, or Edge, however you are setting InstallApps to false. These updates require the InstallApps variable to be set to true. Please set InstallApps to true and try again.' throw "InstallApps variable must be set to `$true to update Defender, OneDrive, or Edge" } if (($WindowsArch -eq 'ARM64') -and ($InstallOffice -eq $true)) { @@ -3741,6 +3796,11 @@ if (($WindowsArch -eq 'ARM64') -and ($UpdateOneDrive -eq $true)) { WriteLog 'OneDrive currently fails to install on ARM64 VMs (even with the OneDrive ARM setup files). Setting UpdateOneDrive to false' } +if (($WindowsArch -eq 'ARM64') -and ($UpdateLatestMSRT -eq $true)) { + $UpdateLatestMSRT = $false + WriteLog 'Windows Malicious Software Removal Tool is not available for the ARM64 architecture.' +} + ###END PARAMETER VALIDATION #Get script variable values @@ -3887,6 +3947,32 @@ if ($InstallApps) { Set-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" -Value $UpdatedcmdContent WriteLog "Update complete" } + if ($UpdateLatestMSRT) { + WriteLog "`$UpdateLatestMSRT is set to true." + #Check if $MSRTPath exists, if not, create it + if (-not (Test-Path -Path $MSRTPath)) { + WriteLog "Creating $MSRTPath" + New-Item -Path $MSRTPath -ItemType Directory -Force | Out-Null + } + WriteLog "Getting Windows Malicious Software Removal Tool URL" + $MSRTUrl = Get-MSRTUrl -WindowsArch $WindowsArch + $MSRTFileName = Split-Path -Path $MSRTUrl -Leaf + try { + WriteLog "Windows Malicious Software Removal Tool URL for $WindowsArch is $MSRTUrl" + Start-BitsTransferWithRetry -Source $MSRTUrl -Destination "$MSRTPath\$MSRTFileName" + WriteLog "Windows Malicious Software Removal Tool downloaded to $MSRTPath\$MSRTFileName" + } + catch { + Write-Error "Downloading Windows Malicious Software Removal Tool failed" + WriteLog "Downloading Windows Malicious Software Removal Tool failed" + throw $_ + } + WriteLog "Updating $AppsPath\InstallAppsandSysprep.cmd to include Windows Malicious Software Removal Tool" + $CmdContent = Get-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" + $UpdatedcmdContent = $CmdContent -replace '^(REM Install Windows Malicious Software Removal Tool)', ("REM Install Windows Malicious Software Removal Tool`r`nStart /wait d:\MSRT\$MSRTFileName /quiet") + Set-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" -Value $UpdatedcmdContent + WriteLog "Update complete" + } #Download and Install OneDrive Per Machine if ($UpdateOneDrive) { WriteLog "`$UpdateOneDrive is set to true, checking for latest OneDrive client" From 7a2aab3204976e044f8981c9dcbb07a40d6af9d4 Mon Sep 17 00:00:00 2001 From: Zehadi Alam <63765084+zehadialam@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:36:22 -0400 Subject: [PATCH 2/4] Adjust install command for MSRT --- FFUDevelopment/BuildFFUVM.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index bf01154..4c2cec4 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -3969,7 +3969,7 @@ if ($InstallApps) { } WriteLog "Updating $AppsPath\InstallAppsandSysprep.cmd to include Windows Malicious Software Removal Tool" $CmdContent = Get-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" - $UpdatedcmdContent = $CmdContent -replace '^(REM Install Windows Malicious Software Removal Tool)', ("REM Install Windows Malicious Software Removal Tool`r`nStart /wait d:\MSRT\$MSRTFileName /quiet") + $UpdatedcmdContent = $CmdContent -replace '^(REM Install Windows Malicious Software Removal Tool)', ("REM Install Windows Malicious Software Removal Tool`r`nd:\MSRT\$MSRTFileName /quiet") Set-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" -Value $UpdatedcmdContent WriteLog "Update complete" } From ec7e9a546cc7da79ee4b12325953c08ca768a0f1 Mon Sep 17 00:00:00 2001 From: Zehadi Alam <63765084+zehadialam@users.noreply.github.com> Date: Tue, 17 Sep 2024 21:08:09 -0400 Subject: [PATCH 3/4] Adjust pattern for URL scraping --- FFUDevelopment/BuildFFUVM.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 4c2cec4..101df9c 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -2321,7 +2321,7 @@ function Get-MSRTUrl { ) try { # Retrieve content of Windows Malicious Software Removal Tool page - $pattern = '\"url\":\"(https://download\.microsoft\.com/download/[^"]+)\"' + $pattern = 'https:\/\/download\.microsoft\.com\/download\/[^\s]*\.exe' $OriginalVerbosePreference = $VerbosePreference $VerbosePreference = 'SilentlyContinue' if ($WindowsArch -eq "x64") { @@ -2337,7 +2337,7 @@ function Get-MSRTUrl { WriteLog "Failed to retrieve Malicious Software Removal Tool URL. Pattern match failed" return } - $MSRTUrl = $MSRTMatch.Groups[1].Value + $MSRTUrl = $MSRTMatch.Value return $MSRTUrl } catch { From c93c417dba2afb27c3b2e4753598a8d498a7bb3e Mon Sep 17 00:00:00 2001 From: Zehadi Alam <63765084+zehadialam@users.noreply.github.com> Date: Mon, 23 Sep 2024 23:42:09 -0400 Subject: [PATCH 4/4] Removed Get-MSRTUrl function and use Microsoft Update Catalog to retrieve latest MSRT --- FFUDevelopment/BuildFFUVM.ps1 | 48 +++-------------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/FFUDevelopment/BuildFFUVM.ps1 b/FFUDevelopment/BuildFFUVM.ps1 index 101df9c..6fa9984 100644 --- a/FFUDevelopment/BuildFFUVM.ps1 +++ b/FFUDevelopment/BuildFFUVM.ps1 @@ -2314,39 +2314,6 @@ function Save-KB { return $fileName } -function Get-MSRTUrl { - param ( - [ValidateSet("x86", "x64")] - [string]$WindowsArch - ) - try { - # Retrieve content of Windows Malicious Software Removal Tool page - $pattern = 'https:\/\/download\.microsoft\.com\/download\/[^\s]*\.exe' - $OriginalVerbosePreference = $VerbosePreference - $VerbosePreference = 'SilentlyContinue' - if ($WindowsArch -eq "x64") { - $MSRTWebPage = Invoke-RestMethod "https://www.microsoft.com/en-us/download/details.aspx?id=9905" -Headers $Headers -UserAgent $UserAgent - } - if ($WindowsArch -eq "x86") { - $MSRTWebPage = Invoke-RestMethod "https://www.microsoft.com/en-us/download/details.aspx?id=16" -Headers $Headers -UserAgent $UserAgent - } - $VerbosePreference = $OriginalVerbosePreference - # Extract download URL based on specified pattern - $MSRTMatch = [regex]::Match($MSRTWebPage, $pattern) - if (-not $MSRTMatch.Success) { - WriteLog "Failed to retrieve Malicious Software Removal Tool URL. Pattern match failed" - return - } - $MSRTUrl = $MSRTMatch.Value - return $MSRTUrl - } - catch { - WriteLog $_ - Write-Error "Error occurred while retrieving Windows Malicious Software Removal Tool link" - throw $_ - } -} - function New-AppsISO { #Create Apps ISO file $OSCDIMG = "$adkpath`Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\oscdimg.exe" @@ -3949,24 +3916,15 @@ if ($InstallApps) { } if ($UpdateLatestMSRT) { WriteLog "`$UpdateLatestMSRT is set to true." + $Name = "Windows Malicious Software Removal Tool" #Check if $MSRTPath exists, if not, create it if (-not (Test-Path -Path $MSRTPath)) { WriteLog "Creating $MSRTPath" New-Item -Path $MSRTPath -ItemType Directory -Force | Out-Null } WriteLog "Getting Windows Malicious Software Removal Tool URL" - $MSRTUrl = Get-MSRTUrl -WindowsArch $WindowsArch - $MSRTFileName = Split-Path -Path $MSRTUrl -Leaf - try { - WriteLog "Windows Malicious Software Removal Tool URL for $WindowsArch is $MSRTUrl" - Start-BitsTransferWithRetry -Source $MSRTUrl -Destination "$MSRTPath\$MSRTFileName" - WriteLog "Windows Malicious Software Removal Tool downloaded to $MSRTPath\$MSRTFileName" - } - catch { - Write-Error "Downloading Windows Malicious Software Removal Tool failed" - WriteLog "Downloading Windows Malicious Software Removal Tool failed" - throw $_ - } + $MSRTFileName = Save-KB -Name $Name -Path $MSRTPath + WriteLog "Latest Windows Malicious Software Removal Tool saved to $MSRTPath\$MSRTFileName" WriteLog "Updating $AppsPath\InstallAppsandSysprep.cmd to include Windows Malicious Software Removal Tool" $CmdContent = Get-Content -Path "$AppsPath\InstallAppsandSysprep.cmd" $UpdatedcmdContent = $CmdContent -replace '^(REM Install Windows Malicious Software Removal Tool)', ("REM Install Windows Malicious Software Removal Tool`r`nd:\MSRT\$MSRTFileName /quiet")