Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AppControl Manager is now Native AOT and Fully Trimmed #608

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
if ($LASTEXITCODE -ne 0) { throw [System.InvalidOperationException]::New('Failed to install .NET SDK') }

Write-Host -Object "`nInstalling Visual Studio Build Tools" -ForegroundColor Magenta
$null = winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --accept-package-agreements --accept-source-agreements --uninstall-previous --force --source winget --override '--force --wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.UniversalBuildTools --add Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --includeRecommended'
$null = winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --accept-package-agreements --accept-source-agreements --uninstall-previous --force --source winget --override '--force --wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.UniversalBuildTools --add Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --includeRecommended --add Microsoft.VisualStudio.Component.VC.Tools.ARM64 --add Microsoft.VisualStudio.Component.UWP.VC.ARM64'
if ($LASTEXITCODE -ne 0) { throw [System.InvalidOperationException]::New('Failed to install Visual Studio Build Tools') }

Write-Host -Object "`nInstalling Visual C++ Redistributable" -ForegroundColor Magenta
Expand Down
49 changes: 25 additions & 24 deletions AppControl Manager/AppControl Manager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,6 @@
<PublishReadyToRun Condition="'$(Configuration)' == 'Debug'">False</PublishReadyToRun>
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>

<!-- Disabling trimming temporarily -->
<!-- There should be absolutely no trim warnings before this can be enabled
Otherwise there is no guarantee that the app will work as expected at all times -->
<!-- https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options -->


<PublishTrimmed>false</PublishTrimmed>
<!--

<TrimMode>partial</TrimMode>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
-->

<ImplicitUsings>disable</ImplicitUsings>
<Description>A modern secure application that simplifies management of Application Control in Windows.</Description>
<PackageProjectUrl>https://github.com/HotCakeX/Harden-Windows-Security</PackageProjectUrl>
Expand All @@ -90,9 +76,9 @@
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<AssemblyName>AppControlManager</AssemblyName>
<!-- https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/optimizing -->
<PublishAot>false</PublishAot>
<PublishAot>True</PublishAot>
<ErrorReport>send</ErrorReport>
<FileVersion>1.9.0.0</FileVersion>
<FileVersion>1.9.1.0</FileVersion>
<AssemblyVersion>$(FileVersion)</AssemblyVersion>
<NeutralLanguage>en-US</NeutralLanguage>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
Expand All @@ -108,7 +94,19 @@
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow>
<NuGetAuditMode>all</NuGetAuditMode>
<RepositoryType>git</RepositoryType>
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

<!-- There should be absolutely no trim warnings before this can be enabled
Otherwise there is no guarantee that the app will work as expected at all times -->
<!-- https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options -->
<PublishTrimmed>True</PublishTrimmed>
<TrimMode>full</TrimMode>
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
<XmlResolverIsNetworkingEnabledByDefault>false</XmlResolverIsNetworkingEnabledByDefault>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<MetricsSupport>false</MetricsSupport>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
</PropertyGroup>

<!--
Expand All @@ -121,8 +119,6 @@
-->

<!--
For trimming to exclude incompatible assemblies, but currently not working

<ItemGroup>
<TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>
Expand Down Expand Up @@ -154,7 +150,6 @@
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="8.2.250129-preview2" />
<PackageReference Include="CommunityToolkit.WinUI.Lottie" Version="8.1.240821" />
<PackageReference Include="CommunityToolkit.WinUI.Triggers" Version="8.2.250129-preview2" />
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.68.0" />
<PackageReference Include="Microsoft.IdentityModel.Abstractions" Version="8.5.0" />
Expand All @@ -169,9 +164,8 @@
<PackageReference Include="Microsoft.Windows.SDK.Win32Metadata" Version="63.0.31-preview" />
<PackageReference Include="Microsoft.Windows.WDK.Win32Metadata" Version="0.13.25-experimental" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.6.250205002" />
<PackageReference Include="System.CodeDom" Version="9.0.2" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.2" />

<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="3.0.0" />
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.2.250129-preview2" />

<!--
No longer needed - manual static code has been implemented
Expand All @@ -181,7 +175,6 @@
-->

<PackageReference Include="System.Diagnostics.EventLog" Version="9.0.2" />
<PackageReference Include="System.Management" Version="9.0.2" />
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="9.0.2" />
</ItemGroup>

Expand Down Expand Up @@ -244,8 +237,10 @@
<None Remove="Pages\ViewCurrentPolicies.xaml" />
<None Remove="Pages\ViewFileCertificates.xaml" />
<None Remove="Resources\AppControlManagerSupplementalPolicy.xml" />
<None Remove="Resources\DriversBlockListAutoUpdaterScheduledTask.ps1" />
<None Remove="Resources\EmptyPolicy.xml" />
<None Remove="Resources\ISGBasedSupplementalPolicy.xml" />
<None Remove="Resources\SnapBackGuaranteeScheduledTask.ps1" />
<None Remove="Resources\StrictKernelMode.xml" />
<None Remove="Resources\StrictKernelMode_NoFlightRoots.xml" />
</ItemGroup>
Expand All @@ -259,12 +254,18 @@
<Content Include="Resources\AppControlManagerSupplementalPolicy.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\DriversBlockListAutoUpdaterScheduledTask.ps1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\EmptyPolicy.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\ISGBasedSupplementalPolicy.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\SnapBackGuaranteeScheduledTask.ps1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Resources\StrictKernelMode.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Expand Down
11 changes: 10 additions & 1 deletion AppControl Manager/Main/BasePolicyCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Management;
using System.Net.Http;
using System.Text.Json;
using System.Text.RegularExpressions;
Expand All @@ -24,6 +23,8 @@ internal static void SetAutoUpdateDriverBlockRules()
{
Logger.Write("Creating scheduled task for fast weekly Microsoft recommended driver block list update");

/*

// Initialize ManagementScope to interact with Task Scheduler's WMI namespace
ManagementScope scope = new(@"root\Microsoft\Windows\TaskScheduler");
// Establish connection to the WMI namespace
Expand Down Expand Up @@ -164,6 +165,14 @@ internal static void SetAutoUpdateDriverBlockRules()

Logger.Write("Successfully created the Microsoft Recommended Driver Block Rules auto updater scheduled task.");

*/

// TODO: use a Native AOT compatible way that doesn't rely on System.Management


// Execute the script using PowerShell
ProcessStarter.RunCommand("powershell.exe", $"-NoProfile -ExecutionPolicy Bypass -File \"{GlobalVars.DriversBlockListAutoUpdaterScheduledTaskScriptFilePath}\"");

}

internal sealed class DriverBlockListInfo
Expand Down
1 change: 0 additions & 1 deletion AppControl Manager/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
xmlns:AnimatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
mc:Ignorable="d"
Expand Down
4 changes: 4 additions & 0 deletions AppControl Manager/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public sealed partial class MainWindow : Window

private readonly AppWindow m_AppWindow;

internal readonly Frame AppFrame;

// Used for the BreadCrumBar's data to define valid navigational paths in the app
internal sealed class PageTitleMap
{
Expand Down Expand Up @@ -246,6 +248,8 @@ public MainWindow()
// Assign this instance to the static field
_instance = this;

AppFrame = ContentFrame;

// Retrieve the window handle (HWND) of the main WinUI 3 window and store it in the global vars
GlobalVars.hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

Expand Down
4 changes: 1 addition & 3 deletions AppControl Manager/MyRoots.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
<linker>
<assembly fullname="CommunityToolkit.WinUI.UI.Controls.DataGrid" preserve="all"/>
</linker>

28 changes: 22 additions & 6 deletions AppControl Manager/Others/DeviceGuardInfo.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using System.Linq;
using System.Management;

namespace AppControlManager.Others;

internal sealed class DeviceGuardStatus
Expand All @@ -13,10 +10,10 @@ internal static class DeviceGuardInfo
{

// Define the WMI query to get the Win32_DeviceGuard class information
private const string query = "SELECT UsermodeCodeIntegrityPolicyEnforcementStatus, CodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard";
// private const string query = "SELECT UsermodeCodeIntegrityPolicyEnforcementStatus, CodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard";

// Define the scope (namespace) for the query
private const string scope = @"\\.\root\Microsoft\Windows\DeviceGuard";
// private const string scope = @"\\.\root\Microsoft\Windows\DeviceGuard";


/// <summary>
Expand All @@ -25,6 +22,9 @@ internal static class DeviceGuardInfo
/// <returns></returns>
internal static DeviceGuardStatus? GetDeviceGuardStatus()
{

/*

// Create a ManagementScope object for the WMI namespace
ManagementScope managementScope = new(scope);

Expand All @@ -49,6 +49,22 @@ internal static class DeviceGuardInfo
}
}

return new DeviceGuardStatus();
*/


// TODO: Create a Native AOT compatible source generated COM code that won't rely on System.Management or PowerShell

string UMscript = "(Get-CimInstance -Namespace \\\"root\\Microsoft\\Windows\\DeviceGuard\\\" -Query \\\"SELECT UsermodeCodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard\\\").UsermodeCodeIntegrityPolicyEnforcementStatus";
string UMoutput = ProcessStarter.RunCommandWithOutput("powershell.exe", $"-NoProfile -Command \"{UMscript}\"");


string KMscript = "(Get-CimInstance -Namespace \\\"root\\Microsoft\\Windows\\DeviceGuard\\\" -Query \\\"SELECT CodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard\\\").CodeIntegrityPolicyEnforcementStatus";
string KMoutput = ProcessStarter.RunCommandWithOutput("powershell.exe", $"-NoProfile -Command \"{KMscript}\"");

return new DeviceGuardStatus()
{
UsermodeCodeIntegrityPolicyEnforcementStatus = uint.Parse(UMoutput),
CodeIntegrityPolicyEnforcementStatus = uint.Parse(KMoutput)
};
}
}
2 changes: 1 addition & 1 deletion AppControl Manager/Others/FileCertificateInfoCol.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace AppControlManager.Others;

// a class that represents each certificate in a chain
// Used by the DataGrid in the View File Certificates page
// Used by the ListView in the View File Certificates page
public sealed class FileCertificateInfoCol
{
public int SignerNumber { get; set; }
Expand Down
6 changes: 6 additions & 0 deletions AppControl Manager/Others/GlobalVars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ internal static class GlobalVars
// Path to the empty policy file in app resources
internal static readonly string EmptyPolicyPath = Path.Combine(AppContext.BaseDirectory, "Resources", "EmptyPolicy.xml");

// Path to the PS Script that creates a scheduled task
internal static readonly string DriversBlockListAutoUpdaterScheduledTaskScriptFilePath = Path.Combine(AppContext.BaseDirectory, "Resources", "DriversBlockListAutoUpdaterScheduledTask.ps1");

// Path to the PS Script that creates a scheduled task for SnapBack guarantee in Allow New Apps page
internal static readonly string SnapBackGuaranteeScheduledTaskScriptFilePath = Path.Combine(AppContext.BaseDirectory, "Resources", "SnapBackGuaranteeScheduledTask.ps1");

// Get the current OS version
private static readonly Version CurrentOSVersion = Environment.OSVersion.Version;

Expand Down
67 changes: 67 additions & 0 deletions AppControl Manager/Others/MeasureTextWidth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Text;
using AppControlManager.IntelGathering;
using Microsoft.UI.Text;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.Foundation;

namespace AppControlManager.Others;

internal static class ListViewUIHelpers
{
// An offscreen TextBlock for measurement
private static readonly TextBlock tb = new()
{
// It's important to make sure this matches the header text style so column texts will be aligned properly
FontWeight = FontWeights.Bold,
Margin = new Thickness(10, 0, 2, 0),
TextWrapping = TextWrapping.NoWrap,
Padding = new Thickness(5),
};

// Padding to add to each column (in pixels)
private const double padding = 15;

/// <summary>
/// Measures the width (in pixels) required to display the given text.
/// If text is empty or null, the padding will be the only width returned.
/// </summary>
internal static double MeasureTextWidth(string? text)
{
tb.Text = text;

tb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

return tb.DesiredSize.Width + padding;
}

/// <summary>
/// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard.
/// </summary>
/// <param name="row">The selected FileIdentity row from the ListView.</param>
/// <returns>A formatted string of the row's properties with labels.</returns>
internal static string ConvertRowToText(FileIdentity row)
{
// Use StringBuilder to format each property with its label for easy reading
return new StringBuilder()
.AppendLine($"File Name: {row.FileName}")
.AppendLine($"Signature Status: {row.SignatureStatus}")
.AppendLine($"Original File Name: {row.OriginalFileName}")
.AppendLine($"Internal Name: {row.InternalName}")
.AppendLine($"File Description: {row.FileDescription}")
.AppendLine($"Product Name: {row.ProductName}")
.AppendLine($"File Version: {row.FileVersion}")
.AppendLine($"Package Family Name: {row.PackageFamilyName}")
.AppendLine($"SHA256 Hash: {row.SHA256Hash}")
.AppendLine($"SHA1 Hash: {row.SHA1Hash}")
.AppendLine($"Signing Scenario: {row.SISigningScenario}")
.AppendLine($"File Path: {row.FilePath}")
.AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}")
.AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}")
.AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}")
.AppendLine($"File Publishers: {row.FilePublishersToDisplay}")
.AppendLine($"Is ECC Signed: {row.IsECCSigned}")
.AppendLine($"Opus Data: {row.Opus}")
.ToString();
}
}
35 changes: 34 additions & 1 deletion AppControl Manager/Others/ProcessStarter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,43 @@ internal static void RunCommand(string command, string? arguments = null)

process.WaitForExit();

if (process.ExitCode != 0)
if (process.ExitCode is not 0)
{
throw new InvalidOperationException($"Command '{command} {arguments}' failed with exit code {process.ExitCode}. Error: {error}");
}
}

/// <summary>
/// Executes an executable with arguments and returns the output
/// </summary>
/// <param name="command"></param>
/// <param name="arguments"></param>
/// <returns>Standard output of the executed command</returns>
/// <exception cref="InvalidOperationException"></exception>
internal static string RunCommandWithOutput(string command, string? arguments = null)
{
ProcessStartInfo processInfo = new()
{
FileName = command,
Arguments = arguments ?? string.Empty,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true
};

using Process process = new() { StartInfo = processInfo };
_ = process.Start();

string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();

if (process.ExitCode is not 0)
{
throw new InvalidOperationException($"Command '{command} {arguments}' failed with exit code {process.ExitCode}. Error: {error}");
}

return output;
}
}
Loading