Skip to content

Commit

Permalink
Merge pull request #385 from HotCakeX/Improved-Bootstrapper-script
Browse files Browse the repository at this point in the history
Improved SignTool download process in the bootstrapper script
  • Loading branch information
HotCakeX authored Nov 2, 2024
2 parents d04c7b8 + b2d60e8 commit 9f1f9cd
Showing 1 changed file with 10 additions and 36 deletions.
46 changes: 10 additions & 36 deletions Harden-Windows-Security.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Function P {
Add-AppxPackage -Path 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle' -DependencyPath 'Microsoft.VCLibs.x64.14.00.Desktop.appx', $MicrosoftUIXamlDownloadedFileName
}
finally {
try {
try {
Remove-Item -Path 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle', 'Microsoft.VCLibs.x64.14.00.Desktop.appx', $MicrosoftUIXamlDownloadedFileName -Force
Pop-Location
}
Expand Down Expand Up @@ -151,14 +151,7 @@ Function P {
Function AppControl {
<#
.DESCRIPTION
This function installs the AppControl Manager MSIX package on the system.
It does so by securely generating a unique self-signed certificate on the user's system and then using it to sign the MSIX package.
Everything happens locally and no certificate comes from outside of the device.
The certificate is added to the Local Machine's Trust Root Certification Authorities Store with only public keys, ensuring no private key exists to be used to sign anything else.
Its existence with public key is needed so that you can use the AppControl Manager app; without it the app will not launch as it will be considered untrusted by the system.
The 2 files, AppControlManager.dll and AppControlManager.exe inside of the MSIX app installation folder will be added to the Attack Surface Reduction rules exclusion list if they don't already exist in there, so the app will work properly.
The function creates a new directory in the TEMP directory for its operations and it will be deleted at the end.
The function checks for the existence of any previous self-signed certificates generated by it and will remove them if it detects any, guaranteeing no unnecessary leftover remains on the user's system.
Please refer to the provided link for all of the information about this function and detailed overview of the entire process.
.PARAMETER MSIXPath
The path to the AppControlManager MSIX file. If not provided, the latest MSIX file will be downloaded from the GitHub. It must have the version number and architecture in its file name as provided on GitHub or produced by Visual Studio.
.PARAMETER SignTool
Expand All @@ -174,8 +167,7 @@ Function AppControl {
)
$ErrorActionPreference = 'Stop'
if (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Warning -Message 'Please run this function as an Administrator'
return
Write-Warning -Message 'Please run this function as an Administrator'; return
}
Write-Verbose -Message 'Detecting the CPU Arch'
switch ($Env:PROCESSOR_ARCHITECTURE) {
Expand Down Expand Up @@ -283,25 +275,11 @@ public static class SecureStringGenerator
}

if ([System.String]::IsNullOrWhiteSpace($SignTool)) {

Write-Verbose -Message 'Checking if nuget source is available in PowerShell'
if (-NOT (Get-PackageSource | Where-Object -FilterScript { $_.Name -ieq 'nuget.org' })) {
Write-Verbose -Message 'Registering the nuget.org package source because it was not found in the system.'
$null = Register-PackageSource -Name 'nuget.org' -ProviderName 'NuGet' -Location 'https://api.nuget.org/v3/index.json'
}

Write-Verbose -Message 'Finding the latest version of the Microsoft.Windows.SDK.BuildTools package from NuGet'

# Minimum is simply used to limit the number of the fetched packages
[Microsoft.PackageManagement.Packaging.SoftwareIdentity[]]$Package = Find-Package -Name 'Microsoft.Windows.SDK.BuildTools' -Source 'nuget.org' -AllVersions -Force -MinimumVersion '10.0.26100.1'
[Microsoft.PackageManagement.Packaging.SoftwareIdentity]$Package = $Package | Sort-Object -Property { [System.Version]$_.Version } -Descending | Select-Object -First 1

Write-Verbose -Message 'Downloading SignTool.exe from NuGet...'
$null = Save-Package -InputObject $Package -Path $WorkingDir -Force

Write-Verbose -Message 'Finding the latest version of the Microsoft.Windows.SDK.BuildTools package from NuGet and Downloading it'
[System.String]$LatestSignToolVersion = (Invoke-RestMethod -Uri 'https://api.nuget.org/v3-flatcontainer/Microsoft.Windows.SDK.BuildTools/index.json').versions | Select-Object -Last 1
Invoke-WebRequest -Uri "https://api.nuget.org/v3-flatcontainer/Microsoft.Windows.SDK.BuildTools/${LatestSignToolVersion}/Microsoft.Windows.SDK.BuildTools.${LatestSignToolVersion}.nupkg" -OutFile (Join-Path -Path $WorkingDir -ChildPath 'Microsoft.Windows.SDK.BuildTools.zip')
Write-Verbose -Message 'Extracting the nupkg'
Expand-Archive -Path "$WorkingDir\*.nupkg" -DestinationPath $WorkingDir -Force

Expand-Archive -Path "$WorkingDir\Microsoft.Windows.SDK.BuildTools.zip" -DestinationPath $WorkingDir -Force # Saving .nupkg as .zip to satisfy Windows PowerShell
Write-Verbose -Message 'Finding the Signtool.exe path in the extracted directory'
[System.String]$SignTool = (Get-Item -Path "$WorkingDir\bin\*\$CPUArch\signtool.exe").FullName
}
Expand Down Expand Up @@ -359,7 +337,6 @@ public static class SecureStringGenerator
$PossibleExistingApp | Remove-AppxPackage -AllUsers
}
}

# Get the details of the currently installed app before attempting to install the new one
[System.String]$InstalledAppVersionBefore = $PossibleExistingApp.Version
[System.String]$InstalledAppArchitectureBefore = $PossibleExistingApp.Architecture
Expand All @@ -369,14 +346,11 @@ public static class SecureStringGenerator
Write-Verbose -Message "Installing AppControl Manager MSIX Package version '$InstallingAppVersion' with architecture '$InstallingAppArchitecture'"
Add-AppPackage -Path $MSIXPath -ForceUpdateFromAnyVersion -DeferRegistrationWhenPackagesAreInUse # -ForceTargetApplicationShutdown will shutdown the application if its open.

Write-Verbose -Message "Finding the certificate that was just created by its thumbprint again from the 'Local Machine/Trusted Root Certification Authorities' store"
[System.Security.Cryptography.X509Certificates.X509Certificate2]$TheCert2 = foreach ($Cert2 in (Get-ChildItem -Path 'Cert:\LocalMachine\Root' -CodeSigningCert)) {
if ($Cert.Thumbprint -eq $NewCertificateThumbprint) { $Cert2 }
Write-Verbose -Message "Finding the certificate that was just created by its thumbprint again from the 'Local Machine/Trusted Root Certification Authorities' store and removing it"
foreach ($Cert2 in (Get-ChildItem -Path 'Cert:\LocalMachine\Root' -CodeSigningCert)) {
if ($Cert.Thumbprint -eq $NewCertificateThumbprint) { $Cert2 | Remove-Item -Force }
}

Write-Verbose -Message 'Removing the certificate that has private + public keys'
$TheCert2 | Remove-Item -Force

Write-Verbose -Message "Adding the certificate to the 'Local Machine/Trusted Root Certification Authorities' store with public key only. This safely stores the certificate on your device, ensuring its private key does not exist so cannot be used to sign anything else."
$null = Import-Certificate -FilePath $CertificateOutputPath -CertStoreLocation 'Cert:\LocalMachine\Root'

Expand Down

0 comments on commit 9f1f9cd

Please sign in to comment.