Skip to content

Commit

Permalink
Improved build process and added ARM64 support (#585)
Browse files Browse the repository at this point in the history
✅ The GitHub releases for the AppControl Manager will include symbol files for debugging purposes for both X64 and ARM64 architectures. They will also include complete build logs for end-user review. All of these additional files are securely attested and verified by the workflow.

✅ The entire process is completely transparent.

✅ Provided instructions for building the AppControl Manager locally on your own device directly from the source code using no 3rd party tools at all.

✅ The build process has also been improved in the GitHub workflow by uploading the generated files to the release first before running any other actions. This can improve security and ensure no action can run prior to package building and upload.

✅The Bootstrapper has been improved, reducing number of lines of codes in it and also added the ability to install MSIXBundle files which include ARM64 and X64 support for AppControl Manager.

✅ AppControl Manager version bump to 1.8.9.0

✅ Updated Nuget dependency: Microsoft.Graphics.Win2D
  • Loading branch information
HotCakeX authored Feb 7, 2025
1 parent e274d2a commit 99aff60
Show file tree
Hide file tree
Showing 8 changed files with 690 additions and 133 deletions.
409 changes: 353 additions & 56 deletions .github/workflows/Build AppControl Manager MSIX Package.yml

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Harden-Windows-Security Module/Harden Windows Security.csproj.user
AppControl Manager/.vs/
AppControl Manager/bin/
AppControl Manager/obj/
AppControl Manager/MSIXOutput
AppControl Manager/MSIXOutputX64
AppControl Manager/MSIXOutputARM64
AppControl Manager/MSIXBundleOutput
AppControl Manager/Generated Files/
AppControl Manager/AppControl Manager.csproj.user
39 changes: 31 additions & 8 deletions AppControl Manager/AppControl Manager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,18 @@


<!-- Defining custom directory in the root directory to be created if it doesn't exist. MSIX package after packing will be stored there -->
<AppxPackageDir>MSIXOutput\</AppxPackageDir>
<AppxPackageDir>MSIXOutputX64\</AppxPackageDir>
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
<GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundle>Always</AppxBundle>
<AppxBundlePlatforms>x64|arm64</AppxBundlePlatforms>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<AssemblyName>AppControlManager</AssemblyName>
<!-- https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/optimizing -->
<PublishAot>False</PublishAot>
<ErrorReport>send</ErrorReport>
<FileVersion>1.8.8.0</FileVersion>
<FileVersion>1.8.9.0</FileVersion>
<AssemblyVersion>$(FileVersion)</AssemblyVersion>
<NeutralLanguage>en-US</NeutralLanguage>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
Expand All @@ -112,7 +113,8 @@

</PropertyGroup>

<ItemGroup>
<!-- ARM64 doesn't support source generated XML de(serialization) -->
<ItemGroup Condition="'$(RuntimeIdentifier)' != 'win-arm64'">
<DotNetCliToolReference Include="Microsoft.XmlSerializer.Generator" Version="9.0.1" />
</ItemGroup>

Expand Down Expand Up @@ -143,15 +145,16 @@
<PackageReference Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.1.240916" />
<PackageReference Include="CommunityToolkit.WinUI.Lottie" Version="8.1.240821" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.1" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.67.2" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.162">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250108002" />
<PackageReference Include="Microsoft.XmlSerializer.Generator" Version="9.0.1" />
<!-- ARM64 doesn't support source generated XML de(serialization) -->
<PackageReference Include="Microsoft.XmlSerializer.Generator" Version="9.0.1" Condition="'$(RuntimeIdentifier)' != 'win-arm64'" />
<PackageReference Include="System.Diagnostics.EventLog" Version="9.0.1" />
<PackageReference Include="System.Management" Version="9.0.1" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="9.0.1" />
Expand Down Expand Up @@ -254,9 +257,29 @@
<Content Remove="DownloadURL.txt" />
<None Remove="DownloadURL.txt" />

<Compile Remove="MSIXOutput\**" />
<Content Remove="MSIXOutput\**" />
<None Remove="MSIXOutput\**" />
<Compile Remove="MSIXBundleDownloadURL.txt" />
<Content Remove="MSIXBundleDownloadURL.txt" />
<None Remove="MSIXBundleDownloadURL.txt" />

<Compile Remove="ARM64MSBuildLog.binlog" />
<Content Remove="ARM64MSBuildLog.binlog" />
<None Remove="ARM64MSBuildLog.binlog" />

<Compile Remove="X64MSBuildLog.binlog" />
<Content Remove="X64MSBuildLog.binlog" />
<None Remove="X64MSBuildLog.binlog" />

<Compile Remove="MSIXOutputX64\**" />
<Content Remove="MSIXOutputX64\**" />
<None Remove="MSIXOutputX64\**" />

<Compile Remove="MSIXOutputARM64\**" />
<Content Remove="MSIXOutputARM64\**" />
<None Remove="MSIXOutputARM64\**" />

<Compile Remove="MSIXBundleOutput\**" />
<Content Remove="MSIXBundleOutput\**" />
<None Remove="MSIXBundleOutput\**" />

<Compile Remove="Animated Icon Sources\**" />
<Content Remove="Animated Icon Sources\**" />
Expand Down
1 change: 1 addition & 0 deletions AppControl Manager/MSIXBundleDownloadURL.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
https://github.com/HotCakeX/Harden-Windows-Security/releases/download/AppControlManager.v.1.8.8.0/AppControl.Manager_1.8.8.0_x64.msix
2 changes: 1 addition & 1 deletion AppControl Manager/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Identity
Name="AppControlManager"
Publisher="CN=SelfSignedCertForAppControlManager"
Version="1.8.8.0" />
Version="1.8.9.0" />

<mp:PhoneIdentity PhoneProductId="199a23ec-7cb6-4ab5-ab50-8baca348bc79" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

Expand Down
2 changes: 1 addition & 1 deletion AppControl Manager/app.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<!-- INFO: https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<!-- INFO (for legacy UWP but its info can be used for better understanding): https://learn.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/root-elements -->
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.8.8.0" name="AppControlManager"/>
<assemblyIdentity version="1.8.9.0" name="AppControlManager"/>

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
Expand Down
88 changes: 37 additions & 51 deletions Harden-Windows-Security.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -37,33 +37,29 @@ Function AppControl {
.DESCRIPTION
Please refer to the provided link for all of the information about this function and detailed overview of the entire process.
https://github.com/HotCakeX/Harden-Windows-Security/wiki/AppControl-Manager
.PARAMETER MSIXBundlePath
The path to the AppControlManager MSIXBundle file. If not provided, the latest MSIXBundle file will be downloaded from the GitHub.
.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
The path to the Microsoft's Signtool.exe; If not provided, the function automatically downloads the latest SignTool.exe from the Microsoft website in Nuget and will use it for the signing operations.
#>
[CmdletBinding()]
param ([Parameter(Mandatory = $false)][string]$MSIXPath, [Parameter(Mandatory = $False)][string]$SignTool)
param ([Parameter(Mandatory = $false)][string]$MSIXBundlePath, [Parameter(Mandatory = $false)][string]$MSIXPath, [Parameter(Mandatory = $False)][string]$SignTool)
$ErrorActionPreference = 'Stop'
if ($ExecutionContext.SessionState.LanguageMode -ne 'ConstrainedLanguage') {
# We cannot use .NET methods in ConstrainedLanguage mode
if (!([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Warning -Message 'Please run this function as an Administrator'; return
}
}
$ErrorActionPreference = 'Stop'
Write-Verbose -Message 'Detecting the CPU Arch'
switch ($Env:PROCESSOR_ARCHITECTURE) {
'AMD64' { [string]$CPUArch = 'x64'; break }
'ARM64' { [string]$CPUArch = 'arm64'; break }
default { Throw [System.PlatformNotSupportedException] 'Only AMD64 and ARM64 architectures are supported.' }
}
[string]$CommonName = 'SelfSignedCertForAppControlManager'
[string]$WorkingDir = Join-Path -Path $env:TEMP -ChildPath $CommonName
[string]$CertificateOutputPath = Join-Path -Path $WorkingDir -ChildPath "$CommonName.cer"
[string]$HashingAlgorithm = 'Sha512'
# Pattern for AppControl Manager version and architecture extraction from file path and download link URL
[regex]$RegexPattern = '_(?<Version>\d+\.\d+\.\d+\.\d+)_(?<Architecture>x64|arm64)\.msix$'

[string]$_Package # Where the final package path will be stored, whether it's MSIX or MSIXBundle
[string]$CPUArch = @{AMD64 = 'x64'; ARM64 = 'arm64' }[$Env:PROCESSOR_ARCHITECTURE]
if ([System.String]::IsNullOrWhiteSpace($CPUArch)) { throw [System.PlatformNotSupportedException] 'Only AMD64 and ARM64 architectures are supported.' }
Write-Verbose -Message 'Creating the working directory in the TEMP directory'
if (Test-Path -Path $WorkingDir -PathType Container) { Remove-Item -Path $WorkingDir -Recurse -Force }
$null = New-Item -Path $WorkingDir -ItemType Directory -Force
Expand Down Expand Up @@ -104,53 +100,40 @@ Function AppControl {
Write-Verbose -Message 'Finding the latest version of the Microsoft.Windows.SDK.BuildTools package from NuGet and Downloading it'
[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\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'
Write-Verbose -Message 'Extracting the nupkg and finding the Signtool.exe path in the extracted directory'
Expand-Archive -Path (Join-Path -Path $WorkingDir -ChildPath 'Microsoft.Windows.SDK.BuildTools.zip') -DestinationPath $WorkingDir -Force # Saving .nupkg as .zip to satisfy Windows PowerShell
[string]$SignTool = (Get-Item -Path "$WorkingDir\bin\*\$CPUArch\signtool.exe").FullName
}

# Download the MSIX package if user did not provide the path to it
if ([string]::IsNullOrWhiteSpace($MSIXPath)) {
[string]$MSIXPath = Join-Path -Path $WorkingDir -ChildPath 'AppControl.Manager.msix'
# If user provided a valid path to the MSIXBundle file
if (![string]::IsNullOrWhiteSpace($MSIXBundlePath) -and (Test-Path -Path $MSIXBundlePath -PathType Leaf)) {
$_Package = $MSIXBundlePath
}
# If user provided a valid path to the MSIX file
elseif (![string]::IsNullOrWhiteSpace($MSIXPath) -and (Test-Path -Path $MSIXPath -PathType Leaf)) {
$_Package = $MSIXPath
}
# Download the MSIXBundle if user didn't provide any paths
else {
Write-Verbose -Message 'Downloading the latest AppControl Manager MSIXBundle file from GitHub'
$_Package = Join-Path -Path $WorkingDir -ChildPath 'AppControlManager.msixbundle'

# Download link for the latest version of AppControl manger is retrieved from this text file
[string]$MSIXPackageDownloadURL = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/refs/heads/main/AppControl%20Manager/DownloadURL.txt'

Write-Verbose -Message 'Downloading the MSIX package from the GitHub releases' -Verbose
$null = Invoke-WebRequest -Uri $MSIXPackageDownloadURL -OutFile $MSIXPath
[string]$MSIXBundleDownloadURL = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/refs/heads/main/AppControl%20Manager/MSIXBundleDownloadURL.txt'

# Get the version and architecture of the installing MSIX package app from the download URL
[System.Text.RegularExpressions.Match]$RegexMatch = $RegexPattern.Match($MSIXPackageDownloadURL)
if ($RegexMatch.Success) {
[string]$InstallingAppVersion = $RegexMatch.Groups['Version'].Value
[string]$InstallingAppArchitecture = $RegexMatch.Groups['Architecture'].Value
}
else {
throw 'Could not get the version of the installing app from the MSIX download URL.'
}
Write-Verbose -Message 'Downloading the MSIXBundle from the GitHub releases' -Verbose
$null = Invoke-WebRequest -Uri $MSIXBundleDownloadURL -OutFile $MSIXPath
}
else {
# Get the version and architecture of the installing MSIX package app from the User provided file path
[System.Text.RegularExpressions.Match]$RegexMatch = $RegexPattern.Match($MSIXPath)
if ($RegexMatch.Success) {
[string]$InstallingAppVersion = $RegexMatch.Groups['Version'].Value
[string]$InstallingAppArchitecture = $RegexMatch.Groups['Architecture'].Value
}
else {
throw 'Could not get the version of the installing app from the -MSIX parameter value that you provided.'
}
}
Write-Verbose -Message 'Signing the App Control Manager MSIX package'
Write-Verbose -Message 'Signing the App Control Manager package'

# In this step the SignTool detects the cert to use based on Common name + ThumbPrint + Hash Algo + Store Type + Store Name
if ($VerbosePreference -eq 'Continue') {
# Displays full debug logs if -Verbose is used or Verbose preference of the session is set to Continue
. $SignTool sign /debug /n $CommonName /fd $HashingAlgorithm /s 'My' /sha1 $NewCertificate.Thumbprint $MSIXPath
. $SignTool sign /debug /n $CommonName /fd $HashingAlgorithm /s 'My' /sha1 $NewCertificate.Thumbprint $_Package
}
else {
# Displays no output if the command runs successfully, and displays minimal output if the command fails.
$null = . $SignTool sign /q /n $CommonName /fd $HashingAlgorithm /s 'My' /sha1 $NewCertificate.Thumbprint $MSIXPath
$null = . $SignTool sign /q /n $CommonName /fd $HashingAlgorithm /s 'My' /sha1 $NewCertificate.Thumbprint $_Package
}
if ($LASTEXITCODE -ne 0) { throw "SignTool Failed. Exit Code: $LASTEXITCODE" }

Expand All @@ -164,11 +147,6 @@ Function AppControl {
[string[]]$PossiblePreviousASRExclusions = (Get-MpPreference).AttackSurfaceReductionOnlyExclusions | Where-Object -FilterScript { $_ -like '*__sadt7br7jpt02\AppControlManager*' }
if ($null -ne $PossiblePreviousASRExclusions -and $PossiblePreviousASRExclusions.Length -gt 0) { Remove-MpPreference -AttackSurfaceReductionOnlyExclusions $PossiblePreviousASRExclusions }

[string]$InstallingAppLocationToAdd = 'C:\Program Files\WindowsApps\AppControlManager_' + $InstallingAppVersion + '_' + $InstallingAppArchitecture + '__sadt7br7jpt02\'
Write-Verbose -Message "Adding the new app install's files To the ASR Rules exclusions."
# The cmdlet won't add duplicates
Add-MpPreference -AttackSurfaceReductionOnlyExclusions (($InstallingAppLocationToAdd + 'AppControlManager.exe'), ($InstallingAppLocationToAdd + 'AppControlManager.dll')) -ErrorAction Stop

[string]$ValidateAdminCodeSignaturesRegName = 'ValidateAdminCodeSignatures'
$ValidateAdminCodeSignaturesRegValue = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name $ValidateAdminCodeSignaturesRegName -ErrorAction SilentlyContinue
# This will cause the "A referral was returned from the server." error to show up when AppControl Manager tries to start.
Expand All @@ -178,8 +156,16 @@ Function AppControl {
}
catch { Write-Verbose -Message "You can safely ignore this error: $_" } # If this section fails for some reason such as running the script in Windows Sandbox, no error should be thrown

Write-Verbose -Message "Installing AppControl Manager MSIX Package version '$InstallingAppVersion' with architecture '$InstallingAppArchitecture'"
Add-AppPackage -Path $MSIXPath -ForceUpdateFromAnyVersion -DeferRegistrationWhenPackagesAreInUse
Write-Verbose -Message 'Installing the AppControl Manager'
Add-AppPackage -Path $_Package -ForceUpdateFromAnyVersion -DeferRegistrationWhenPackagesAreInUse

try {
[string]$InstallingAppLocationToAdd = (Get-AppxPackage -Name AppControlManager).InstallLocation
Write-Verbose -Message "Adding the new app's dll and exe (2 files) To the ASR Rules exclusions."
# The cmdlet won't add duplicates
Add-MpPreference -AttackSurfaceReductionOnlyExclusions (Join-Path -Path $InstallingAppLocationToAdd -ChildPath 'AppControlManager.exe'), (Join-Path -Path $InstallingAppLocationToAdd -ChildPath 'AppControlManager.dll') -ErrorAction Stop
}
catch { Write-Verbose -Message "You can safely ignore this error: $_" }
}
finally { Remove-Item -Path $WorkingDir -Recurse -Force } # Cleaning up the working directory in the TEMP directory
}
Loading

0 comments on commit 99aff60

Please sign in to comment.