From 26cc92c6a6756ecbf761b404fdc1c954661c485a Mon Sep 17 00:00:00 2001 From: Violet Hansen <spynetgirl@outlook.com> Date: Sun, 5 Jan 2025 22:34:23 +0200 Subject: [PATCH] Implemented Apps and Windows Features Removal (#506) New Feature: Introduced the ability to remove built-in apps using the Harden Windows Security module. This functionality is available on a dedicated page. The list of removable apps is stored in a JSON file, providing flexibility and extensibility. New Feature: Added a new page for managing Optional Windows Features. While the Harden Windows Security module already includes an Optional Features category in the hardening measures section, this new page allows for granular control, enabling you to fine-tune which features to enable or disable. It also includes additional optional features that can be removed. Compliance Checking Enhancement: Added support for VBScript compliance checks. Code Improvements: Implemented several code enhancements and optimizations. UI Enhancements: Updated the button styles on the ASR Rules and Unprotect pages. The new design replaces the previous animated buttons with play icons, offering a cleaner and more modern look. This PR also completes the first half of this feature request: [Suggestion]: Offer Removal of telemetry and pre-installed apps from the OS in Harden Windows Security Module #479 --- Harden-Windows-Security Module/.editorconfig | 3 + .../Harden Windows Security.csproj | 10 + .../Main files/C#/CimInstances/MDM.cs | 3 +- .../Confirm Methods/SYSTEMScheduledTasks.cs | 2 +- .../Main files/C#/GUI/ASRRules/View.cs | 63 +- .../Main files/C#/GUI/BitLocker/View.cs | 9 +- .../Main files/C#/GUI/Confirm/SecOp.cs | 2 +- .../Main files/C#/GUI/Confirm/View.cs | 44 +- .../Main files/C#/GUI/Exclusions/View.cs | 5 - .../Main files/C#/GUI/Log/View.cs | 9 +- .../Main files/C#/GUI/Main/GUI.cs | 19 +- .../Main files/C#/GUI/Main/Variables.cs | 2 +- .../C#/GUI/OptionalFeatures/Variables.cs | 57 ++ .../C#/GUI/OptionalFeatures/View.cs | 795 ++++++++++++++++++ .../C#/GUI/Protection/EventHandlers.cs | 50 +- .../GUI/Protection/Miscellaneous methods.cs | 10 +- .../Main files/C#/GUI/Protection/Variables.cs | 6 +- .../Main files/C#/GUI/Protection/View.cs | 36 +- .../Main files/C#/GUI/Unprotect/View.cs | 47 +- .../Main files/C#/Others/AsyncDownloader.cs | 7 +- .../Main files/C#/Others/CSVImporter.cs | 6 +- .../Main files/C#/Others/Categoriex.cs | 2 +- .../C#/Others/CategoryProcessing.cs | 5 - .../C#/Others/ConditionalResultAdd.cs | 2 + .../Others/ConfirmSystemComplianceMethods.cs | 13 +- .../Main files/C#/Others/GetLocalUser.cs | 6 - .../Main files/C#/Others/GlobalVars.cs | 5 +- .../Main files/C#/Others/Initializer.cs | 9 +- .../Main files/C#/Others/NativeMethods.cs | 41 + .../Others/ProcessMitigationsApplication.cs | 3 +- .../C#/Others/ProcessMitigationsParser.cs | 11 +- .../C#/Others/SystemInfoNativeMethods.cs | 10 +- .../Main files/C#/Others/ToastNotification.cs | 20 +- .../C#/Others/VolumeWritabilityCheck.cs | 3 +- .../C#/Others/WindowsFeatureChecker.cs | 9 +- .../AttackSurfaceReductionRules.cs | 5 - .../C#/Protect Methods/BitLockerSettings.cs | 5 - .../DangerousScriptHostsBlocking.cs | 5 - .../C#/Protect Methods/DeviceGuard.cs | 5 - .../DeviceGuard_MandatoryVBS.cs | 6 - .../DownloadsDefenseMeasures.cs | 12 +- .../EdgeBrowserConfigurations.cs | 5 - .../C#/Protect Methods/LockScreen.cs | 6 - .../Protect Methods/LockScreen_CtrlAltDel.cs | 5 - .../LockScreen_LastSignedIn.cs | 7 - .../MSFTDefender_BetaChannels.cs | 6 - .../MSFTDefender_EnableDiagData.cs | 6 - .../C#/Protect Methods/MicrosoftDefender.cs | 5 - .../MicrosoftSecurityBaselines.cs | 5 - .../MiscellaneousConfigurations.cs | 5 - ...ellaneousConfigurations_LongPathSupport.cs | 6 - ...neousConfigurations_StrongKeyProtection.cs | 6 - ...ousConfigurations_WindowsProtectedPrint.cs | 6 - .../C#/Protect Methods/NonAdminCommands.cs | 5 - .../OptionalWindowsFeatures.cs | 40 +- .../Protect Methods/SecBaselines_Overrides.cs | 5 - .../C#/Protect Methods/TLSSecurity.cs | 4 - .../TLSSecurity_BattleNetClient.cs | 5 - .../C#/Protect Methods/UAC_NoFastSwitching.cs | 7 +- .../Protect Methods/UAC_OnlyElevateSigned.cs | 5 +- .../C#/Protect Methods/UserAccountControl.cs | 4 - .../C#/Protect Methods/WindowsFirewall.cs | 4 - .../C#/Protect Methods/WindowsNetworking.cs | 4 - .../WindowsNetworking_BlockNTLM.cs | 6 - .../WindowsUpdateConfigurations.cs | 5 - .../UnprotectWindowsSecurity.cs | 2 +- .../C#/Windows APIs/FirmwareType.cs | 8 +- .../Main files/C#/Windows APIs/TPM.cs | 19 +- .../Harden-Windows-Security-Module.psm1 | 2 +- .../Media/OptionalFeaturesMenuButtonIcon.png | Bin 0 -> 1752 bytes .../Resources/SafeToRemoveAppsList.json | 152 ++++ .../Main files/Resources/XAML/ASRRules.xaml | 314 +------ .../Main files/Resources/XAML/Main.xaml | 7 + .../Resources/XAML/OptionalFeatures.xaml | 141 ++++ .../Main files/Resources/XAML/Protect.xaml | 2 +- .../Main files/Resources/XAML/Unprotect.xaml | 310 +------ 76 files changed, 1413 insertions(+), 1068 deletions(-) create mode 100644 Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/Variables.cs create mode 100644 Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/View.cs create mode 100644 Harden-Windows-Security Module/Main files/C#/Others/NativeMethods.cs create mode 100644 Harden-Windows-Security Module/Main files/Resources/Media/OptionalFeaturesMenuButtonIcon.png create mode 100644 Harden-Windows-Security Module/Main files/Resources/SafeToRemoveAppsList.json create mode 100644 Harden-Windows-Security Module/Main files/Resources/XAML/OptionalFeatures.xaml diff --git a/Harden-Windows-Security Module/.editorconfig b/Harden-Windows-Security Module/.editorconfig index 5f3c5842c..5e4366fba 100644 --- a/Harden-Windows-Security Module/.editorconfig +++ b/Harden-Windows-Security Module/.editorconfig @@ -1039,3 +1039,6 @@ dotnet_diagnostic.CA1002.severity = error # SYSLIB1054: Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time dotnet_diagnostic.SYSLIB1054.severity = silent + +# CA1060: Move P/Invokes to NativeMethods class +dotnet_diagnostic.CA1060.severity = error diff --git a/Harden-Windows-Security Module/Harden Windows Security.csproj b/Harden-Windows-Security Module/Harden Windows Security.csproj index 9fb118682..eca4b5afc 100644 --- a/Harden-Windows-Security Module/Harden Windows Security.csproj +++ b/Harden-Windows-Security Module/Harden Windows Security.csproj @@ -59,6 +59,10 @@ </Content> </ItemGroup> + <ItemGroup> + <Page Remove="Main files\Resources\XAML\OptionalFeatures.xaml" /> + </ItemGroup> + <ItemGroup> <None Include="..\LICENSE"> <Pack>True</Pack> @@ -87,6 +91,12 @@ </Compile> </ItemGroup> + <ItemGroup> + <Content Update="Main files\Resources\XAML\OptionalFeatures.xaml"> + <Generator>MSBuild:Compile</Generator> + </Content> + </ItemGroup> + <ItemGroup> <EmbeddedResource Update="Properties\Resources.resx"> <Generator>ResXFileCodeGenerator</Generator> diff --git a/Harden-Windows-Security Module/Main files/C#/CimInstances/MDM.cs b/Harden-Windows-Security Module/Main files/C#/CimInstances/MDM.cs index 4148e8ea1..69cad6dfe 100644 --- a/Harden-Windows-Security Module/Main files/C#/CimInstances/MDM.cs +++ b/Harden-Windows-Security Module/Main files/C#/CimInstances/MDM.cs @@ -28,8 +28,7 @@ internal static Dictionary<string, List<Dictionary<string, object>>> Get() private static async Task<Dictionary<string, List<Dictionary<string, object>>>> GetAsync() { // Set the location of the CSV file containing the MDM list - string path = GlobalVars.path ?? throw new InvalidOperationException("GlobalVars.path is null"); - string csvFilePath = Path.Combine(path, "Resources", "MDMResultClasses.csv"); + string csvFilePath = Path.Combine(GlobalVars.path, "Resources", "MDMResultClasses.csv"); // Create a dictionary where keys are the class names and values are lists of dictionaries Dictionary<string, List<Dictionary<string, object>>> results = []; diff --git a/Harden-Windows-Security Module/Main files/C#/Confirm Methods/SYSTEMScheduledTasks.cs b/Harden-Windows-Security Module/Main files/C#/Confirm Methods/SYSTEMScheduledTasks.cs index 311b3e6c3..1f2a2644f 100644 --- a/Harden-Windows-Security Module/Main files/C#/Confirm Methods/SYSTEMScheduledTasks.cs +++ b/Harden-Windows-Security Module/Main files/C#/Confirm Methods/SYSTEMScheduledTasks.cs @@ -10,7 +10,7 @@ internal static void Invoke() Logger.LogMessage("Collecting Intune applied policy details from the System", LogTypeIntel.Information); // Path to the PowerShell script - string scriptPath = Path.Combine(GlobalVars.path!, "Shared", "SYSTEMInfoGathering.ps1"); + string scriptPath = Path.Combine(GlobalVars.path, "Shared", "SYSTEMInfoGathering.ps1"); // Load the PowerShell script into a string string script = File.ReadAllText(scriptPath); diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/ASRRules/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/ASRRules/View.cs index 17d6f6de1..44544027f 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/ASRRules/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/ASRRules/View.cs @@ -3,10 +3,9 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using System.Windows.Markup; -using System.Windows.Media.Imaging; namespace HardenWindowsSecurity; @@ -27,11 +26,6 @@ private void ASRRulesView(object obj) return; } - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path cannot be null."); - } - // if Admin privileges are not available, return and do not proceed any further // Will prevent the page from being loaded since the CurrentView won't be set/changed if (!UserPrivCheck.IsAdmin()) @@ -54,35 +48,8 @@ private void ASRRulesView(object obj) #region finding elements - // Finding the Execute Button Grid - Grid? ExecuteButtonGrid = GUIASRRules.ParentGrid.FindName("ExecuteButtonGrid") as Grid ?? throw new InvalidOperationException("ExecuteButtonGrid is null in the ASRRules View"); - - // Finding the Execute Button - if (ExecuteButtonGrid.FindName("ExecuteButton") is not ToggleButton ExecuteButton) - { - throw new InvalidOperationException("Couldn't find the ExecuteButton in ASRRules view"); - } - - // Apply the template to make sure it's available - _ = ExecuteButton.ApplyTemplate(); - - // Access the image within the Execute Button's template - if (ExecuteButton.Template.FindName("RefreshIconImage", ExecuteButton) is not Image RefreshIconImage) - { - throw new InvalidOperationException("RefreshIconImage could not be found in the ASRRules view"); - } - - // Update the image source for the Refresh button - // Load the Refresh icon image into memory and set it as the source - BitmapImage RefreshIconBitmapImage = new(); - RefreshIconBitmapImage.BeginInit(); - RefreshIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ExecuteButton.png")); - RefreshIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory - RefreshIconBitmapImage.EndInit(); - - RefreshIconImage.Source = RefreshIconBitmapImage; - Button RetrieveASRStatusButton = GUIASRRules.ParentGrid.FindName("RetrieveASRStatus") as Button ?? throw new InvalidOperationException("RetrieveASRStatus could not be found in the ASRRules view"); + Button ApplyASRRulesButton = GUIASRRules.ParentGrid.FindName("ApplyASRRulesButton") as Button ?? throw new InvalidOperationException("ApplyASRRulesButton could not be found in the ASRRules view"); #endregion @@ -121,11 +88,6 @@ void ProcessListViewItems(ListView listView) string GetASRRuleConfig(string ASRRuleName, byte ComboBoxIndex) { - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path is null."); - } - if (AttackSurfaceReductionIntel.ASRRulesCorrelation is null) { throw new InvalidOperationException("ASRRulesCorrelation is null"); @@ -169,12 +131,12 @@ string GetASRRuleConfig(string ASRRuleName, byte ComboBoxIndex) } - // Register the ExecuteButton as an element that will be enabled/disabled based on current activity - ActivityTracker.RegisterUIElement(ExecuteButton); + // Register the ApplyASRRulesButton as an element that will be enabled/disabled based on current activity + ActivityTracker.RegisterUIElement(ApplyASRRulesButton); - // Set up the Click event handler for the ExecuteButton button - ExecuteButton.Click += async (sender, e) => + // Set up the Click event handler for the ApplyASRRulesButton button + ApplyASRRulesButton.Click += async (sender, e) => { // Only continue if there is no activity other places if (!ActivityTracker.IsActive) @@ -183,7 +145,7 @@ string GetASRRuleConfig(string ASRRuleName, byte ComboBoxIndex) ActivityTracker.IsActive = true; // Set text blocks to empty while new data is being generated - System.Windows.Application.Current.Dispatcher.Invoke(() => + Application.Current.Dispatcher.Invoke(() => { // Get the ListViews if (GUIASRRules.ParentGrid.FindName("ASRRuleSet1") is not ListView ASRRuleSet1 || GUIASRRules.ParentGrid.FindName("ASRRuleSet2") is not ListView ASRRuleSet2) @@ -259,12 +221,6 @@ await System.Threading.Tasks.Task.Run(() => }); - // Update the UI Elements at the end of the run - await System.Windows.Application.Current.Dispatcher.InvokeAsync(() => - { - ExecuteButton.IsChecked = false; // Uncheck the ExecuteButton button to start the reverse animation - }); - // mark as activity completed ActivityTracker.IsActive = false; @@ -286,7 +242,7 @@ await System.Windows.Application.Current.Dispatcher.InvokeAsync(() => // Dictionary of ComboBoxes, key is ComboBox name and value is ComboBox element itself Dictionary<string, ComboBox> ComboBoxList = []; - System.Windows.Application.Current.Dispatcher.Invoke(() => + Application.Current.Dispatcher.Invoke(() => { // Get the ListViews if (GUIASRRules.ParentGrid.FindName("ASRRuleSet1") is not ListView ASRRuleSet1 || @@ -369,7 +325,7 @@ await System.Threading.Tasks.Task.Run(() => _ = ComboBoxList.TryGetValue(ComboBoxName!, out ComboBox? currentMatchingComboBox); // Use the GUI dispatcher to set the ComboBox selected index to the currently applied ASR rule's action - System.Windows.Application.Current.Dispatcher.Invoke(() => + Application.Current.Dispatcher.Invoke(() => { // Make the connection between ASR rule applied action and the ComboBox Item Indexes int selectedIndex = Convert.ToInt32(action, CultureInfo.InvariantCulture) switch @@ -395,7 +351,6 @@ await System.Threading.Tasks.Task.Run(() => }; - // Cache the view before setting it as the CurrentView _viewCache["ASRRulesView"] = GUIASRRules.View; diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/BitLocker/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/BitLocker/View.cs index cd5f19475..40e656097 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/BitLocker/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/BitLocker/View.cs @@ -28,11 +28,6 @@ private void BitLockerView(object obj) return; } - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path cannot be null."); - } - // if Admin privileges are not available, return and do not proceed any further // Will prevent the page from being loaded since the CurrentView won't be set/changed if (!UserPrivCheck.IsAdmin()) @@ -208,7 +203,7 @@ await Task.Run(() => // Add image to the BackupButtonIcon BitmapImage BackupButtonIconBitmapImage = new(); BackupButtonIconBitmapImage.BeginInit(); - BackupButtonIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ExportIconBlack.png")); + BackupButtonIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "ExportIconBlack.png")); BackupButtonIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory BackupButtonIconBitmapImage.EndInit(); BackupButtonIcon.Source = BackupButtonIconBitmapImage; @@ -265,7 +260,7 @@ await Task.Run(() => // Add the same Refresh image to multiple sources BitmapImage RefreshButtonIcon1BitmapImage = new(); RefreshButtonIcon1BitmapImage.BeginInit(); - RefreshButtonIcon1BitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "RefreshButtonIcon.png")); + RefreshButtonIcon1BitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "RefreshButtonIcon.png")); RefreshButtonIcon1BitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory RefreshButtonIcon1BitmapImage.EndInit(); RefreshButtonIcon1.Source = RefreshButtonIcon1BitmapImage; diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/SecOp.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/SecOp.cs index 662de69ba..ff132ebef 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/SecOp.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/SecOp.cs @@ -83,7 +83,7 @@ protected void OnPropertyChanged(string propertyName) private static BitmapImage LoadImage(string fileName) { // Construct the full path to the image file - string imagePath = Path.Combine(GlobalVars.path!, "Resources", "Media", fileName); + string imagePath = Path.Combine(GlobalVars.path, "Resources", "Media", fileName); // Return the loaded image as a BitmapImage return new BitmapImage(new Uri(imagePath, UriKind.Absolute)); } diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/View.cs index 05615a25c..2ff588da0 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Confirm/View.cs @@ -1,11 +1,17 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; +using System.Threading.Tasks; +using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Markup; +using System.Windows.Media; using System.Windows.Media.Imaging; #nullable disable @@ -25,7 +31,7 @@ public partial class NavigationVM : ViewModelBase private ICollectionView _SecOpsCollectionView; // Collection of SecOp objects - private System.Collections.ObjectModel.ObservableCollection<SecOp> __SecOpses; + private ObservableCollection<SecOp> __SecOpses; // Method to handle the "Confirm" view, including loading and modifying it private void ConfirmView(object obj) @@ -61,7 +67,7 @@ private void ConfirmView(object obj) string xamlContent = File.ReadAllText(xamlPath); // Parse the XAML content to create a UserControl object - GUIConfirmSystemCompliance.View = (UserControl)System.Windows.Markup.XamlReader.Parse(xamlContent); + GUIConfirmSystemCompliance.View = (UserControl)XamlReader.Parse(xamlContent); // Set the DataContext for the Confirm view GUIConfirmSystemCompliance.View.DataContext = new ConfirmVM(); @@ -131,7 +137,7 @@ void ApplyFilters(string filterText, bool includeCompliant, bool includeNonCompl __SecOpses = []; // Create a collection view based on the security options collection - _SecOpsCollectionView = System.Windows.Data.CollectionViewSource.GetDefaultView(__SecOpses); + _SecOpsCollectionView = CollectionViewSource.GetDefaultView(__SecOpses); // Set the ItemSource of the DataGrid in the Confirm view to the collection view if (GUIConfirmSystemCompliance.SecOpsDataGrid is not null) @@ -173,7 +179,7 @@ void ApplyFilters(string filterText, bool includeCompliant, bool includeNonCompl // Load the Refresh icon image into memory and set it as the source BitmapImage RefreshIconBitmapImage = new(); RefreshIconBitmapImage.BeginInit(); - RefreshIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ExecuteButton.png")); + RefreshIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "ExecuteButton.png")); RefreshIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory RefreshIconBitmapImage.EndInit(); @@ -221,7 +227,7 @@ void ApplyFilters(string filterText, bool includeCompliant, bool includeNonCompl // Disable the Refresh button while processing // Set text blocks to empty while new data is being generated - System.Windows.Application.Current.Dispatcher.Invoke(() => + Application.Current.Dispatcher.Invoke(() => { // Finding the elements TextBlock CompliantItemsTextBlock = (TextBlock)GUIConfirmSystemCompliance.View.FindName("CompliantItemsTextBlock"); @@ -243,7 +249,7 @@ void ApplyFilters(string filterText, bool includeCompliant, bool includeNonCompl }); // Run the method asynchronously in a different thread - await System.Threading.Tasks.Task.Run(() => + await Task.Run(() => { // Get fresh data for compliance checking Initializer.Initialize(null, true); @@ -280,7 +286,7 @@ await System.Threading.Tasks.Task.Run(() => }); // After InvokeConfirmation is completed, update the security options collection - await System.Windows.Application.Current.Dispatcher.InvokeAsync(() => + await Application.Current.Dispatcher.InvokeAsync(() => { LoadMembers(); // Load updated security options RefreshButton.IsChecked = false; // Uncheck the Refresh button @@ -307,33 +313,33 @@ await System.Windows.Application.Current.Dispatcher.InvokeAsync(() => /// </summary> /// <param name="category">Name of the category</param> /// <returns>The color of the category to be used for display purposes on the DataGrid GUI</returns> - private static System.Windows.Media.Brush GetCategoryColor(string category) + private static Brush GetCategoryColor(string category) { // Determine the background color for each category return category switch { // Light Pastel Sky Blue - "MicrosoftDefender" => new System.Windows.Media.BrushConverter().ConvertFromString("#B3E5FC") as System.Windows.Media.Brush, + "MicrosoftDefender" => new BrushConverter().ConvertFromString("#B3E5FC") as Brush, // Light Pastel Coral - "AttackSurfaceReductionRules" => new System.Windows.Media.BrushConverter().ConvertFromString("#FFDAB9") as System.Windows.Media.Brush, + "AttackSurfaceReductionRules" => new BrushConverter().ConvertFromString("#FFDAB9") as Brush, // Light Pastel Green - "BitLockerSettings" => new System.Windows.Media.BrushConverter().ConvertFromString("#C3FDB8") as System.Windows.Media.Brush, + "BitLockerSettings" => new BrushConverter().ConvertFromString("#C3FDB8") as Brush, // Light Pastel Lemon - "TLSSecurity" => new System.Windows.Media.BrushConverter().ConvertFromString("#FFFACD") as System.Windows.Media.Brush, + "TLSSecurity" => new BrushConverter().ConvertFromString("#FFFACD") as Brush, // Light Pastel Lavender - "LockScreen" => new System.Windows.Media.BrushConverter().ConvertFromString("#E6E6FA") as System.Windows.Media.Brush, + "LockScreen" => new BrushConverter().ConvertFromString("#E6E6FA") as Brush, // Light Pastel Aqua - "UserAccountControl" => new System.Windows.Media.BrushConverter().ConvertFromString("#C1F0F6") as System.Windows.Media.Brush, + "UserAccountControl" => new BrushConverter().ConvertFromString("#C1F0F6") as Brush, // Light Pastel Teal - "DeviceGuard" => new System.Windows.Media.BrushConverter().ConvertFromString("#B2DFDB") as System.Windows.Media.Brush, + "DeviceGuard" => new BrushConverter().ConvertFromString("#B2DFDB") as Brush, // Light Pastel Pink - "WindowsFirewall" => new System.Windows.Media.BrushConverter().ConvertFromString("#F8BBD0") as System.Windows.Media.Brush, + "WindowsFirewall" => new BrushConverter().ConvertFromString("#F8BBD0") as Brush, // Light Pastel Peach - "OptionalWindowsFeatures" => new System.Windows.Media.BrushConverter().ConvertFromString("#FFE4E1") as System.Windows.Media.Brush, + "OptionalWindowsFeatures" => new BrushConverter().ConvertFromString("#FFE4E1") as Brush, // Light Pastel Mint - "WindowsNetworking" => new System.Windows.Media.BrushConverter().ConvertFromString("#F5FFFA") as System.Windows.Media.Brush, + "WindowsNetworking" => new BrushConverter().ConvertFromString("#F5FFFA") as Brush, // Light Pastel Gray - _ => new System.Windows.Media.BrushConverter().ConvertFromString("#EDEDED") as System.Windows.Media.Brush, + _ => new BrushConverter().ConvertFromString("#EDEDED") as Brush, }; } diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Exclusions/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Exclusions/View.cs index 03f165d85..8ae351ab3 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Exclusions/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Exclusions/View.cs @@ -28,11 +28,6 @@ private void ExclusionsView(object obj) return; } - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path cannot be null."); - } - // if Admin privileges are not available, return and do not proceed any further // Will prevent the page from being loaded since the CurrentView won't be set/changed if (!UserPrivCheck.IsAdmin()) diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Log/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Log/View.cs index ed0b4b575..bc2dc1b5a 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Log/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Log/View.cs @@ -27,11 +27,6 @@ private void LogsView(object obj) return; } - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path cannot be null."); - } - // Construct the file path for the Logs view XAML string xamlPath = Path.Combine(GlobalVars.path, "Resources", "XAML", "Logs.xaml"); @@ -56,7 +51,7 @@ private void LogsView(object obj) // Add image to the ExportLogsIcon BitmapImage ExportLogsIconBitmapImage = new(); ExportLogsIconBitmapImage.BeginInit(); - ExportLogsIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ExportIconBlack.png")); + ExportLogsIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "ExportIconBlack.png")); ExportLogsIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory ExportLogsIconBitmapImage.EndInit(); ExportLogsIcon.Source = ExportLogsIconBitmapImage; @@ -65,7 +60,7 @@ private void LogsView(object obj) // Add image to the ClearLogsIcon BitmapImage ClearLogsIconBitmapImage = new(); ClearLogsIconBitmapImage.BeginInit(); - ClearLogsIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ClearLogsIcon.png")); + ClearLogsIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "ClearLogsIcon.png")); ClearLogsIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory ClearLogsIconBitmapImage.EndInit(); ClearLogsIcon.Source = ClearLogsIconBitmapImage; diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Main/GUI.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Main/GUI.cs index 38c2e7520..d4587d615 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Main/GUI.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Main/GUI.cs @@ -143,6 +143,7 @@ public object CurrentView public ICommand ExclusionsCommand { get; set; } public ICommand BitLockerCommand { get; set; } public ICommand LogsCommand { get; set; } + public ICommand OptionalFeaturesCommand { get; set; } // Dictionary to cache views by their identifiers private readonly Dictionary<string, object> _viewCache = []; @@ -158,6 +159,7 @@ public NavigationVM() ExclusionsCommand = new RelayCommand(ExclusionsView); // Command to handle the Exclusions action BitLockerCommand = new RelayCommand(BitLockerView); // Command to handle the BitLocker action LogsCommand = new RelayCommand(LogsView); // Command to handle the Logs action + OptionalFeaturesCommand = new RelayCommand(OptionalFeaturesView); // Command to handle the OptionalFeatures action // Load the Logs view initially to make it ready for logs to be written to it LogsView(null); @@ -183,11 +185,6 @@ static Btn() public static void LoadMainXaml() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - #region Load Resource Dictionaries (First) // Define the path to the ResourceDictionaries folder string resourceFolder = Path.Combine(GlobalVars.path, "Resources", "XAML", "ResourceDictionaries"); @@ -354,7 +351,7 @@ Harden Windows Security operation log end // Load the background image into memory and set it as the ImageSource for the ImageBrush BitmapImage BackgroundBitmapImage = new(); BackgroundBitmapImage.BeginInit(); - BackgroundBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "background.jpg")); + BackgroundBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "background.jpg")); BackgroundBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory BackgroundBitmapImage.EndInit(); @@ -501,6 +498,16 @@ Harden Windows Security operation log end LogsButtonImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory LogsButtonImage.EndInit(); LogsButtonIcon.Source = LogsButtonImage; + + // OptionalFeatures button icon + Grid OptionalFeaturesButtonGrid = SidebarGrid.FindName("OptionalFeaturesButtonGrid") as Grid; + Image OptionalFeaturesButtonIcon = LogsButtonGrid.FindName("OptionalFeaturesButtonIcon") as Image; + BitmapImage OptionalFeaturesButtonImage = new(); + OptionalFeaturesButtonImage.BeginInit(); + OptionalFeaturesButtonImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "OptionalFeaturesMenuButtonIcon.png")); + OptionalFeaturesButtonImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory + OptionalFeaturesButtonImage.EndInit(); + OptionalFeaturesButtonIcon.Source = OptionalFeaturesButtonImage; #endregion } diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Main/Variables.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Main/Variables.cs index 6d51aadaf..ec6e47417 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Main/Variables.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Main/Variables.cs @@ -11,7 +11,7 @@ namespace HardenWindowsSecurity; public partial class GUIMain { // Define the path to the main Window XAML file - public static readonly string xamlPath = Path.Combine(GlobalVars.path!, "Resources", "XAML", "Main.xaml"); + public static readonly string xamlPath = Path.Combine(GlobalVars.path, "Resources", "XAML", "Main.xaml"); // Main window instance public static Window? mainGUIWindow; diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/Variables.cs b/Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/Variables.cs new file mode 100644 index 000000000..e81f27d03 --- /dev/null +++ b/Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/Variables.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Windows; +using System.Windows.Controls; +using Windows.Management.Deployment; + +namespace HardenWindowsSecurity; + +public static class GUIOptionalFeatures +{ + internal static UserControl? View; + + internal static Grid? ParentGrid; + + + public class SafeToRemoveApp + { + [JsonPropertyName("Name")] + public required string Name { get; set; } + + [JsonPropertyName("Description")] + public required string Description { get; set; } + } + + // Class used to deserialize the SafeToRemoveAppsList.json file + public class SafeToRemoveAppsCol + { + [JsonPropertyName("SafeToRemoveAppsList")] + public required IReadOnlyCollection<SafeToRemoveApp> SafeToRemoveAppsList { get; set; } + } + + + internal static Dictionary<string, string> nameToDescriptionApps = []; + internal static Dictionary<string, string> descriptionToNameApps = []; + + + internal static readonly ControlTemplate CustomCheckBoxTemplate = (ControlTemplate)Application.Current.FindResource("CustomCheckBoxTemplate"); + + internal static readonly Thickness thicc = new(10, 10, 40, 10); + + // A dictionary to store all checkboxes for Apps ListView + internal static Dictionary<string, CheckBox> appsCheckBoxes = []; + + + internal static PackageManager packageMgr = new(); + + // Dictionary to store pairs of App Names and FullNames + internal static Dictionary<string, string> appNameToFullNameDictionary = []; + + internal static JsonSerializerOptions JsonSerializerOptions = new() + { + PropertyNameCaseInsensitive = true, // Case-insensitive property matching + WriteIndented = true, // Pretty-print JSON outputs + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull // Ignore null values + }; +} diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/View.cs new file mode 100644 index 000000000..ac168272c --- /dev/null +++ b/Harden-Windows-Security Module/Main files/C#/GUI/OptionalFeatures/View.cs @@ -0,0 +1,795 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Markup; +using Windows.ApplicationModel; +using Windows.Foundation; +using Windows.Management.Deployment; + +namespace HardenWindowsSecurity; + +public partial class GUIMain +{ + + // Partial class definition for handling navigation and view models + public partial class NavigationVM : ViewModelBase + { + + // Method to handle the OptionalFeatures view, including loading + private void OptionalFeaturesView(object obj) + { + + // Check if the view is already cached + if (_viewCache.TryGetValue("OptionalFeaturesView", out var cachedView)) + { + CurrentView = cachedView; + return; + } + + // Construct the file path for the OptionalFeatures view XAML + string xamlPath = Path.Combine(GlobalVars.path, "Resources", "XAML", "OptionalFeatures.xaml"); + + // Read the XAML content from the file + string xamlContent = File.ReadAllText(xamlPath); + + // Parse the XAML content to create a UserControl + GUIOptionalFeatures.View = (UserControl)XamlReader.Parse(xamlContent); + + // Find the Parent Grid + GUIOptionalFeatures.ParentGrid = (Grid)GUIOptionalFeatures.View.FindName("ParentGrid"); + + // Finding other elements + ListView OptionalFeatures = (ListView)(GUIOptionalFeatures.ParentGrid).FindName("OptionalFeatures"); + CheckBox SelectAllOptionalFeatures = (CheckBox)(GUIOptionalFeatures.ParentGrid).FindName("SelectAllOptionalFeatures"); + Button ApplyOptionalFeaturesButton = (Button)(GUIOptionalFeatures.ParentGrid).FindName("ApplyOptionalFeaturesButton"); + Button RetrieveOptionalFeaturesStatus = (Button)(GUIOptionalFeatures.ParentGrid).FindName("RetrieveOptionalFeaturesStatus"); + + ListView Apps = (ListView)(GUIOptionalFeatures.ParentGrid).FindName("Apps"); + CheckBox SelectAllApps = (CheckBox)(GUIOptionalFeatures.ParentGrid).FindName("SelectAllApps"); + Button RetrieveRemovableApps = (Button)(GUIOptionalFeatures.ParentGrid).FindName("RetrieveRemovableApps"); + Button RemoveApps = (Button)(GUIOptionalFeatures.ParentGrid).FindName("RemoveApps"); + + // A dictionary to store all checkboxes + Dictionary<string, CheckBox> featureCheckboxes = []; + + // Iterate through the ListView items to find CheckBoxes + foreach (ListViewItem item in OptionalFeatures.Items) + { + // Check if the content of the item is a CheckBox + if (item.Content is CheckBox checkbox) + { + // Add the checkbox to the dictionary with its name as the key + featureCheckboxes[checkbox.Name] = checkbox; + } + } + + + // Add click event for 'Check All' button + SelectAllOptionalFeatures.Checked += (sender, e) => + { + foreach (CheckBox item in featureCheckboxes.Values) + { + item.IsChecked = true; + + } + }; + + // Add click event for 'Uncheck All' button + SelectAllOptionalFeatures.Unchecked += (sender, e) => + { + foreach (CheckBox item in featureCheckboxes.Values) + { + item.IsChecked = false; + } + }; + + + // Register the elements that will be enabled/disabled based on current activity + ActivityTracker.RegisterUIElement(ApplyOptionalFeaturesButton); + ActivityTracker.RegisterUIElement(RetrieveOptionalFeaturesStatus); + ActivityTracker.RegisterUIElement(RemoveApps); + ActivityTracker.RegisterUIElement(RetrieveRemovableApps); + + + // Event handler for the apply button + ApplyOptionalFeaturesButton.Click += async (sender, e) => + { + + // Only continue if there is no activity other places + if (ActivityTracker.IsActive) + { + return; + } + + // mark as activity started + ActivityTracker.IsActive = true; + + try + { + + // Get the results of all optional features once and store them in the static variable to be reused later + WindowsFeatureChecker.FeatureStatus FeaturesCheckResults = await Task.Run(() => WindowsFeatureChecker.CheckWindowsFeatures()); + + // Get all checked checkboxes' contents from the dictionary + List<string> checkedCheckboxes = [.. featureCheckboxes + .Where(pair => pair.Value.IsChecked is true) + .Select(pair => pair.Value.Name)]; + + await Task.Run(() => + { + + foreach (string optionalFeatureName in checkedCheckboxes) + { + + switch (optionalFeatureName) + { + case "RemovePowerShellV2": + { + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(false, "MicrosoftWindowsPowerShellV2", "PowerShell v2", "PowerShellv2", FeaturesCheckResults); + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(false, "MicrosoftWindowsPowerShellV2Root", "PowerShell v2 root", "PowerShellv2Engine", FeaturesCheckResults); + break; + } + case "RemoveWorkFolders": + { + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(false, "WorkFolders-Client", "Work Folders", "WorkFoldersClient", FeaturesCheckResults); + break; + } + case "RemoveInternetPrintingClient": + { + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(false, "Printing-Foundation-InternetPrinting-Client", "Internet Printing Client", "InternetPrintingClient", FeaturesCheckResults); + break; + } + case "RemoveLegacyWindowsMediaPlayer": + { + OptionalWindowsFeatures.RemoveCapability("Media.WindowsMediaPlayer", "The old Windows Media Player"); + break; + } + case "RemoveMicrosoftDefenderApplicationGuard": + { + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(false, "Windows-Defender-ApplicationGuard", "Deprecated Microsoft Defender Application Guard (MDAG)", "MDAG", FeaturesCheckResults); + break; + } + case "RemoveLegacyNotepad": + { + OptionalWindowsFeatures.RemoveCapability("Microsoft.Windows.Notepad.System", "Old classic Notepad"); + break; + } + case "RemoveVBSCRIPT": + { + OptionalWindowsFeatures.RemoveCapability("VBSCRIPT", "Deprecated VBScript"); + break; + } + case "RemoveInternetExplorerModeForEdge": + { + OptionalWindowsFeatures.RemoveCapability("Browser.InternetExplorer", "Internet Explorer Mode for Edge"); + break; + } + case "RemoveWMIC": + { + OptionalWindowsFeatures.RemoveCapability("WMIC", "Deprecated WMIC"); + break; + } + case "RemoveWordPad": + { + OptionalWindowsFeatures.RemoveCapability("Microsoft.Windows.WordPad", "Deprecated WordPad"); + break; + } + case "RemovePowerShellISE": + { + OptionalWindowsFeatures.RemoveCapability("Microsoft.Windows.PowerShell.ISE", "PowerShell ISE"); + break; + } + case "RemoveStepsRecorder": + { + OptionalWindowsFeatures.RemoveCapability("App.StepsRecorder", "Deprecated Steps Recorder"); + break; + } + case "RemoveMathRecognizer": + { + OptionalWindowsFeatures.RemoveCapability("MathRecognizer", "Math Recognizer"); + break; + } + case "RemovePrintManagement": + { + OptionalWindowsFeatures.RemoveCapability("Print.Management.Console", "Print Management"); + break; + } + case "RemoveOpenSSHClient": + { + OptionalWindowsFeatures.RemoveCapability("OpenSSH.Client", "OpenSSH Client"); + break; + } + case "RemoveFacialRecognition": + { + OptionalWindowsFeatures.RemoveCapability("Hello.Face", "Windows Hello Facial Recognition"); + break; + } + case "RemoveExtendedThemeContent": + { + OptionalWindowsFeatures.RemoveCapability("Microsoft.Wallpapers.Extended", "Extended Windows Theme content"); + break; + } + case "EnableWindowsSandbox": + { + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(true, "Containers-DisposableClientVM", "Windows Sandbox", "WindowsSandbox", FeaturesCheckResults); + break; + } + case "EnableHyperV": + { + OptionalWindowsFeatures.ConfigureWindowsOptionalFeature(true, "Microsoft-Hyper-V", "Hyper-V", "HyperV", FeaturesCheckResults); + break; + } + default: + { + break; + } + } + + } + }); + + } + finally + { + // mark as activity completed + ActivityTracker.IsActive = false; + } + }; + + + + // Event handler for the button that retrieves features and capabilities status + RetrieveOptionalFeaturesStatus.Click += async (sender, e) => + { + + // Only continue if there is no activity other places + if (ActivityTracker.IsActive) + { + return; + } + + // mark as activity started + ActivityTracker.IsActive = true; + try + { + + // Defining the variables outside the Task so they are accessible after the task completes + string PowerShellv2 = "Unknown"; + string PowerShellv2Engine = "Unknown"; + string WorkFoldersClient = "Unknown"; + string InternetPrintingClient = "Unknown"; + string WindowsMediaPlayer = "Unknown"; + string MDAG = "Unknown"; + string WindowsSandbox = "Unknown"; + string HyperV = "Unknown"; + + string WMIC = "Unknown"; + string IEMode = "Unknown"; + string LegacyNotepad = "Unknown"; + string LegacyWordPad = "Unknown"; + string PowerShellISE = "Unknown"; + string StepsRecorder = "Unknown"; + string VBSCRIPT = "Unknown"; + + string MathRecognizer = "Unknown"; + string PrintManagementConsole = "Unknown"; + string OpenSSHClient = "Unknown"; + string HelloFace = "Unknown"; + string MicrosoftWallpapersExtended = "Unknown"; + + + await Task.Run(() => + { + + // Get the states of optional features using Cim Instance only once so that we can use it multiple times + Dictionary<string, string>? optionalFeatureStates = WindowsFeatureChecker.GetOptionalFeatureStates(); + + PowerShellv2 = optionalFeatureStates.GetValueOrDefault("MicrosoftWindowsPowerShellV2", "Unknown"); + PowerShellv2Engine = optionalFeatureStates.GetValueOrDefault("MicrosoftWindowsPowerShellV2Root", "Unknown"); + WorkFoldersClient = optionalFeatureStates.GetValueOrDefault("WorkFolders-Client", "Unknown"); + InternetPrintingClient = optionalFeatureStates.GetValueOrDefault("Printing-Foundation-InternetPrinting-Client", "Unknown"); + WindowsMediaPlayer = WindowsFeatureChecker.GetCapabilityState("Media.WindowsMediaPlayer"); + MDAG = optionalFeatureStates.GetValueOrDefault("Windows-Defender-ApplicationGuard", "Unknown"); + WindowsSandbox = optionalFeatureStates.GetValueOrDefault("Containers-DisposableClientVM", "Unknown"); + HyperV = optionalFeatureStates.GetValueOrDefault("Microsoft-Hyper-V", "Unknown"); + + WMIC = WindowsFeatureChecker.GetCapabilityState("Wmic"); + IEMode = WindowsFeatureChecker.GetCapabilityState("Browser.InternetExplorer"); + LegacyNotepad = WindowsFeatureChecker.GetCapabilityState("Microsoft.Windows.Notepad.System"); + LegacyWordPad = WindowsFeatureChecker.GetCapabilityState("Microsoft.Windows.WordPad"); + PowerShellISE = WindowsFeatureChecker.GetCapabilityState("Microsoft.Windows.PowerShell.ISE"); + StepsRecorder = WindowsFeatureChecker.GetCapabilityState("App.StepsRecorder"); + VBSCRIPT = WindowsFeatureChecker.GetCapabilityState("VBSCRIPT"); + + MathRecognizer = WindowsFeatureChecker.GetCapabilityState("MathRecognizer"); + PrintManagementConsole = WindowsFeatureChecker.GetCapabilityState("Print.Management.Console"); + OpenSSHClient = WindowsFeatureChecker.GetCapabilityState("OpenSSH.Client"); + HelloFace = WindowsFeatureChecker.GetCapabilityState("Hello.Face"); + MicrosoftWallpapersExtended = WindowsFeatureChecker.GetCapabilityState("Microsoft.Wallpapers.Extended"); + + }); + + + // Disable and uncheck the Checkboxes if their corresponding feature is already disabled/enabled + if (string.Equals(PowerShellv2, "Disabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(PowerShellv2, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemovePowerShellV2"].IsChecked = false; + featureCheckboxes["RemovePowerShellV2"].IsEnabled = false; + } + else + { + featureCheckboxes["RemovePowerShellV2"].IsEnabled = true; + } + + if (string.Equals(PowerShellv2Engine, "Disabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(PowerShellv2Engine, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemovePowerShellV2"].IsChecked = false; + featureCheckboxes["RemovePowerShellV2"].IsEnabled = false; + } + else + { + featureCheckboxes["RemovePowerShellV2"].IsEnabled = true; + } + + if (string.Equals(WorkFoldersClient, "Disabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(WorkFoldersClient, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveWorkFolders"].IsChecked = false; + featureCheckboxes["RemoveWorkFolders"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveWorkFolders"].IsEnabled = true; + } + + if (string.Equals(InternetPrintingClient, "Disabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(InternetPrintingClient, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveInternetPrintingClient"].IsChecked = false; + featureCheckboxes["RemoveInternetPrintingClient"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveInternetPrintingClient"].IsEnabled = true; + } + + if (string.Equals(WindowsMediaPlayer, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(WindowsMediaPlayer, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveLegacyWindowsMediaPlayer"].IsChecked = false; + featureCheckboxes["RemoveLegacyWindowsMediaPlayer"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveLegacyWindowsMediaPlayer"].IsEnabled = true; + } + + if (string.Equals(MDAG, "Disabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(MDAG, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveMicrosoftDefenderApplicationGuard"].IsChecked = false; + featureCheckboxes["RemoveMicrosoftDefenderApplicationGuard"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveMicrosoftDefenderApplicationGuard"].IsEnabled = true; + } + + if (string.Equals(WindowsSandbox, "Enabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(WindowsSandbox, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["EnableWindowsSandbox"].IsChecked = false; + featureCheckboxes["EnableWindowsSandbox"].IsEnabled = false; + } + else + { + featureCheckboxes["EnableWindowsSandbox"].IsEnabled = true; + } + + if (string.Equals(HyperV, "Enabled", StringComparison.OrdinalIgnoreCase) || + string.Equals(HyperV, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["EnableHyperV"].IsChecked = false; + featureCheckboxes["EnableHyperV"].IsEnabled = false; + } + else + { + featureCheckboxes["EnableHyperV"].IsEnabled = true; + } + + if (string.Equals(WMIC, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(WMIC, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveWMIC"].IsChecked = false; + featureCheckboxes["RemoveWMIC"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveWMIC"].IsEnabled = true; + } + + if (string.Equals(IEMode, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(IEMode, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveInternetExplorerModeForEdge"].IsChecked = false; + featureCheckboxes["RemoveInternetExplorerModeForEdge"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveInternetExplorerModeForEdge"].IsEnabled = true; + } + + if (string.Equals(LegacyNotepad, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(LegacyNotepad, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveLegacyNotepad"].IsChecked = false; + featureCheckboxes["RemoveLegacyNotepad"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveLegacyNotepad"].IsEnabled = true; + } + + if (string.Equals(LegacyWordPad, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(LegacyWordPad, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveWordPad"].IsChecked = false; + featureCheckboxes["RemoveWordPad"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveWordPad"].IsEnabled = true; + } + + if (string.Equals(PowerShellISE, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(PowerShellISE, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemovePowerShellISE"].IsChecked = false; + featureCheckboxes["RemovePowerShellISE"].IsEnabled = false; + } + else + { + featureCheckboxes["RemovePowerShellISE"].IsEnabled = true; + } + + if (string.Equals(StepsRecorder, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(StepsRecorder, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveStepsRecorder"].IsChecked = false; + featureCheckboxes["RemoveStepsRecorder"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveStepsRecorder"].IsEnabled = true; + } + + if (string.Equals(VBSCRIPT, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(VBSCRIPT, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveVBSCRIPT"].IsChecked = false; + featureCheckboxes["RemoveVBSCRIPT"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveVBSCRIPT"].IsEnabled = true; + } + + if (string.Equals(MathRecognizer, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(MathRecognizer, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveMathRecognizer"].IsChecked = false; + featureCheckboxes["RemoveMathRecognizer"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveMathRecognizer"].IsEnabled = true; + } + + if (string.Equals(PrintManagementConsole, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(PrintManagementConsole, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemovePrintManagement"].IsChecked = false; + featureCheckboxes["RemovePrintManagement"].IsEnabled = false; + } + else + { + featureCheckboxes["RemovePrintManagement"].IsEnabled = true; + } + + if (string.Equals(OpenSSHClient, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(OpenSSHClient, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveOpenSSHClient"].IsChecked = false; + featureCheckboxes["RemoveOpenSSHClient"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveOpenSSHClient"].IsEnabled = true; + } + + if (string.Equals(HelloFace, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(HelloFace, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveFacialRecognition"].IsChecked = false; + featureCheckboxes["RemoveFacialRecognition"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveFacialRecognition"].IsEnabled = true; + } + + if (string.Equals(MicrosoftWallpapersExtended, "Not Present", StringComparison.OrdinalIgnoreCase) || + string.Equals(MicrosoftWallpapersExtended, "Unknown", StringComparison.OrdinalIgnoreCase)) + { + featureCheckboxes["RemoveExtendedThemeContent"].IsChecked = false; + featureCheckboxes["RemoveExtendedThemeContent"].IsEnabled = false; + } + else + { + featureCheckboxes["RemoveExtendedThemeContent"].IsEnabled = true; + } + + + } + finally + { + + // mark as activity completed + ActivityTracker.IsActive = false; + } + }; + + + + + // Add click event for 'Check All' button for Apps + SelectAllApps.Checked += (sender, e) => + { + foreach (CheckBox item in GUIOptionalFeatures.appsCheckBoxes.Values) + { + item.IsChecked = true; + + } + }; + + // Add click event for 'Uncheck All' button for Apps + SelectAllApps.Unchecked += (sender, e) => + { + foreach (CheckBox item in GUIOptionalFeatures.appsCheckBoxes.Values) + { + item.IsChecked = false; + } + }; + + + // The private function that retrieves the apps list + async Task _RetrieveRemovableApps() + { + + // Clear any existing items in the ListView + Apps.Items.Clear(); + + // Clear the dictionary of CheckBoxes + GUIOptionalFeatures.appsCheckBoxes.Clear(); + + GUIOptionalFeatures.appNameToFullNameDictionary.Clear(); + + HashSet<string> namesList = []; + + await Task.Run(() => + { + + // The reason we have a dictionary of names and full names is because we can't store full names in the JSON + // Since they contain app versions, whereas Name is generic without any version limiting its applicability + // This retrieves all installed app packages. FindProvisionedPackages() method retrieves only limited number of packages. + foreach (Package item in GUIOptionalFeatures.packageMgr.FindPackages()) + { + GUIOptionalFeatures.appNameToFullNameDictionary[item.Id.Name] = item.Id.FullName; + } + + // Set the description of the package (i.e., friendlyName) to the Checkbox content + foreach (string item in GUIOptionalFeatures.appNameToFullNameDictionary.Keys) + { + if (GUIOptionalFeatures.nameToDescriptionApps.TryGetValue(item, out string? description)) + { + _ = namesList.Add(description); + } + } + + }); + + + foreach (string name in namesList) + { + // Create a CheckBox + CheckBox checkBox = new() + { + Content = name, + VerticalContentAlignment = VerticalAlignment.Center, + Padding = GUIOptionalFeatures.thicc, + ToolTip = $"Remove {name} from the system for all users", + Template = GUIOptionalFeatures.CustomCheckBoxTemplate + }; + + // Add the checkbox to the dictionary with its Content as the key + GUIOptionalFeatures.appsCheckBoxes[name] = checkBox; + + // Create a ListViewItem and add the CheckBox to it + ListViewItem listViewItem = new() + { + ToolTip = $"Remove {name} from the system for all users", + Content = checkBox + }; + + // Set tooltip delay + ToolTipService.SetInitialShowDelay(listViewItem, 1000); + + // Add ListViewItem to ListView + _ = Apps.Items.Add(listViewItem); + } + } + + + // Event handler for the button that retrieves removable apps on the system + RetrieveRemovableApps.Click += async (sender, e) => + { + + // Only continue if there is no activity other places + if (ActivityTracker.IsActive) + { + return; + } + + // mark as activity started + ActivityTracker.IsActive = true; + + try + { + await _RetrieveRemovableApps(); + } + finally + { + // mark as activity completed + ActivityTracker.IsActive = false; + } + }; + + + + // Event handler for the Remove Apps button + RemoveApps.Click += async (sender, e) => + { + + // Only continue if there is no activity other places + if (ActivityTracker.IsActive) + { + return; + } + + // mark as activity started + ActivityTracker.IsActive = true; + + try + { + + // Get all checked checkboxes' contents from the dictionary + List<string> checkedCheckboxes = [.. GUIOptionalFeatures.appsCheckBoxes + .Where(pair => pair.Value.IsChecked is true) + .Select(pair => pair.Value.Content.ToString())]; + + + HashSet<string> appsNamesToRemove = []; + + + // Get the selected apps' names based on their descriptions + foreach (string item in checkedCheckboxes) + { + if (GUIOptionalFeatures.descriptionToNameApps.TryGetValue(item, out string? name)) + { + _ = appsNamesToRemove.Add(name); + } + } + + + if (appsNamesToRemove.Count is 0) + { + Logger.LogMessage("No apps were selected for removal", LogTypeIntel.Information); + return; + } + + + // Loop over each user-selected app and remove them one by one + foreach (string appName in appsNamesToRemove) + { + + if (GUIOptionalFeatures.appNameToFullNameDictionary.TryGetValue(appName, out string? fullName)) + { + Logger.LogMessage($"Trying to remove the app with the FullName of '{fullName}'", LogTypeIntel.Information); + + try + { + + await Task.Run(() => + { + + IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = GUIOptionalFeatures.packageMgr.RemovePackageAsync(fullName, RemovalOptions.RemoveForAllUsers); + + // This event is signaled when the operation completes + ManualResetEvent opCompletedEvent = new(false); + + // Define the delegate using a statement lambda + deploymentOperation.Completed = (depProgress, status) => { _ = opCompletedEvent.Set(); }; + + // Wait until the operation completes + _ = opCompletedEvent.WaitOne(); + + // Check the status of the operation + if (deploymentOperation.Status is AsyncStatus.Error) + { + DeploymentResult deploymentResult = deploymentOperation.GetResults(); + Logger.LogMessage($"Error code: {deploymentOperation.ErrorCode} - Error Text: {deploymentResult.ErrorText}", LogTypeIntel.Error); + } + else if (deploymentOperation.Status is AsyncStatus.Canceled) + { + Logger.LogMessage("Removal canceled", LogTypeIntel.Information); + } + else if (deploymentOperation.Status is AsyncStatus.Completed) + { + Logger.LogMessage($"The app with the FullName of '{fullName}' has been successfully removed.", LogTypeIntel.Information); + } + else + { + Logger.LogMessage("Removal status unknown", LogTypeIntel.Information); + } + }); + } + catch (Exception ex) + { + Logger.LogMessage($"There was a problem removing the app with the FullName '{fullName}'. {ex.Message}", LogTypeIntel.Error); + } + } + } + + // Update the Apps list + await _RetrieveRemovableApps(); + } + finally + { + // mark as activity completed + ActivityTracker.IsActive = false; + } + }; + + + + #region Deserialize the JSON + + string SafeToRemoveAppsListJson = File.ReadAllText(Path.Combine(GlobalVars.path, "Resources", "SafeToRemoveAppsList.json")); + GUIOptionalFeatures.SafeToRemoveAppsCol appList = JsonSerializer.Deserialize<GUIOptionalFeatures.SafeToRemoveAppsCol>(SafeToRemoveAppsListJson, GUIOptionalFeatures.JsonSerializerOptions)!; + + foreach (GUIOptionalFeatures.SafeToRemoveApp app in appList.SafeToRemoveAppsList) + { + GUIOptionalFeatures.nameToDescriptionApps[app.Name] = app.Description; + GUIOptionalFeatures.descriptionToNameApps[app.Description] = app.Name; + } + + #endregion + + + // Cache the view before setting it as the CurrentView + _viewCache["OptionalFeaturesView"] = GUIOptionalFeatures.View; + + // Set the CurrentView to the Protect view + CurrentView = GUIOptionalFeatures.View; + + } + } +} diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/EventHandlers.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/EventHandlers.cs index 346cea656..7fe648623 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/EventHandlers.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/EventHandlers.cs @@ -95,11 +95,10 @@ public static void AddEventHandlers() // Add Checked and Unchecked event handlers to category checkboxes - foreach (var item in categories.Items) + foreach (ListViewItem item in categories.Items) { - ListViewItem categoryItem = (ListViewItem)item; - CheckBox checkBox = (CheckBox)categoryItem.Content; - checkBox.DataContext = categoryItem; + CheckBox checkBox = (CheckBox)item.Content; + checkBox.DataContext = item; checkBox.Checked += (sender, e) => UpdateSubCategories(); checkBox.Unchecked += (sender, e) => UpdateSubCategories(); } @@ -112,12 +111,11 @@ public static void AddEventHandlers() { throw new ArgumentNullException("GlobalVars.HardeningCategorieX cannot be null."); } - foreach (var item in categories.Items) + foreach (ListViewItem item in categories.Items) { - ListViewItem categoryItem = (ListViewItem)item; - if (GlobalVars.HardeningCategorieX.Contains(((CheckBox)categoryItem.Content).Name)) + if (GlobalVars.HardeningCategorieX.Contains(((CheckBox)item.Content).Name)) { - ((CheckBox)categoryItem.Content).IsChecked = true; + ((CheckBox)item.Content).IsChecked = true; } } }; @@ -125,9 +123,9 @@ public static void AddEventHandlers() // Add click event for 'Uncheck All' button selectAllCategories.Unchecked += (sender, e) => { - foreach (var item in categories.Items) + foreach (ListViewItem item in categories.Items) { - ((CheckBox)((ListViewItem)item).Content).IsChecked = false; + ((CheckBox)(item).Content).IsChecked = false; } }; @@ -135,12 +133,11 @@ public static void AddEventHandlers() selectAllSubCategories.Checked += (sender, e) => { - foreach (var item in subCategories.Items) + foreach (ListViewItem item in subCategories.Items) { - ListViewItem subCategoryItem = (ListViewItem)item; - if (subCategoryItem.IsEnabled) + if (item.IsEnabled) { - ((CheckBox)subCategoryItem.Content).IsChecked = true; + ((CheckBox)item.Content).IsChecked = true; } } }; @@ -148,10 +145,9 @@ public static void AddEventHandlers() // Add click event for 'Uncheck All' button from sub-categories, regardless of whether they are enabled or disabled selectAllSubCategories.Unchecked += (sender, e) => { - - foreach (var item in subCategories.Items) + foreach (ListViewItem item in subCategories.Items) { - ((CheckBox)((ListViewItem)item).Content).IsChecked = false; + ((CheckBox)(item).Content).IsChecked = false; } }; @@ -312,7 +308,7 @@ public static void AddEventHandlers() string presetName = "preset: recommended"; // Check if the preset exists in the dictionary - if (PresetsIntel.TryGetValue(presetName, out var categoriesAndSubcategories)) + if (PresetsIntel.TryGetValue(presetName, out Dictionary<string, List<string>>? categoriesAndSubcategories)) { // Access the categories and subcategories List<string> categories = categoriesAndSubcategories["Categories"]; @@ -323,13 +319,10 @@ public static void AddEventHandlers() { // Loop over each category in the GUI - foreach (var item in GUIProtectWinSecurity.categories.Items) + foreach (ListViewItem item in GUIProtectWinSecurity.categories.Items) { - // Get the category item list view item - ListViewItem categoryItem = (ListViewItem)item; - // get the name of the list view item as string - string categoryItemName = ((CheckBox)categoryItem.Content).Name.ToString(); + string categoryItemName = ((CheckBox)item.Content).Name.ToString(); // if the category is authorized to be available if (GlobalVars.HardeningCategorieX!.Contains(categoryItemName)) @@ -337,7 +330,7 @@ public static void AddEventHandlers() // If the name of the current checkbox list view item in the loop is the same as the category name in the outer loop, then set the category on the GUI to checked if (string.Equals(categoryItemName, category, StringComparison.OrdinalIgnoreCase)) { - ((CheckBox)categoryItem.Content).IsChecked = true; + ((CheckBox)item.Content).IsChecked = true; } } @@ -348,18 +341,15 @@ public static void AddEventHandlers() { // Loop over each sub-category in the GUI - foreach (var item in subCategories.Items) + foreach (ListViewItem item in subCategories.Items) { - // Get the sub-category item list view item - ListViewItem SubCategoryItem = (ListViewItem)item; - // get the name of the list view item as string - string SubcategoryItemName = ((CheckBox)SubCategoryItem.Content).Name.ToString(); + string SubcategoryItemName = ((CheckBox)item.Content).Name.ToString(); // If the name of the current checkbox list view item in the loop is the same as the sub-category name in the outer loop, then set the sub-category on the GUI to checked if (string.Equals(SubcategoryItemName, subcategory, StringComparison.OrdinalIgnoreCase)) { - ((CheckBox)SubCategoryItem.Content).IsChecked = true; + ((CheckBox)item.Content).IsChecked = true; } } diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Miscellaneous methods.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Miscellaneous methods.cs index d29f4e3b4..6198429d1 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Miscellaneous methods.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Miscellaneous methods.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Collections.Concurrent; using System.Linq; using System.Windows.Controls; @@ -94,12 +96,12 @@ public static void ExecuteButtonPress() { // Clear the categories and sub-categories lists from the saved variables - SelectedCategories = new System.Collections.Concurrent.ConcurrentQueue<string>(); - SelectedSubCategories = new System.Collections.Concurrent.ConcurrentQueue<string>(); + SelectedCategories = new ConcurrentQueue<string>(); + SelectedSubCategories = new ConcurrentQueue<string>(); // Gather the selected categories and sub-categories and store them in the GlobalVars HashTable - System.Collections.IEnumerable categoriesItems = categories!.Items; - System.Collections.IEnumerable subCategoriesItems = subCategories!.Items; + IEnumerable categoriesItems = categories!.Items; + IEnumerable subCategoriesItems = subCategories!.Items; // Get the Categories status and add them to the variables foreach (ListBoxItem categoryItem in categoriesItems) diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Variables.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Variables.cs index 141569e66..deaf0d666 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Variables.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/Variables.cs @@ -1,6 +1,8 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -33,10 +35,10 @@ public static partial class GUIProtectWinSecurity internal static Grid? parentGrid; internal static ToggleButton? mainTabControlToggle; internal static ContentControl? mainContentControl; - internal static System.Windows.Style? mainContentControlStyle; + internal static Style? mainContentControlStyle; // Defining the correlation between Categories and which Sub-Categories they activate - internal static System.Collections.Hashtable correlation = new(StringComparer.OrdinalIgnoreCase) + internal static Hashtable correlation = new(StringComparer.OrdinalIgnoreCase) { { "MicrosoftSecurityBaselines", new string[] { "SecBaselines_NoOverrides" } }, { "MicrosoftDefender", new string[] { "MSFTDefender_SAC", "MSFTDefender_NoDiagData", "MSFTDefender_NoScheduledTask", "MSFTDefender_BetaChannels" } }, diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/View.cs index 93a1b8109..075ef5659 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Protection/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Protection/View.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Markup; @@ -30,11 +31,6 @@ private void ProtectView(object obj) return; } - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path cannot be null."); - } - // Construct the file path for the Protect view XAML string xamlPath = Path.Combine(GlobalVars.path, "Resources", "XAML", "Protect.xaml"); @@ -53,15 +49,11 @@ private void ProtectView(object obj) // Due to using ToggleButton as Tab Control element, this is now considered the parent of all inner elements - GUIProtectWinSecurity.mainContentControlStyle = (System.Windows.Style)GUIProtectWinSecurity.mainContentControl.FindName("MainContentControlStyle"); + GUIProtectWinSecurity.mainContentControlStyle = (Style)GUIProtectWinSecurity.mainContentControl.FindName("MainContentControlStyle"); // Assigning image source paths to the buttons // Need to cast the Style to the INameScope before using FindName method on it // more info: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/explicit-interface-implementation - // in PowerShell this would simply work: - // - // [System.Windows.Style]$MainContentControlStyle = $MainContentControl.FindName('MainContentControlStyle') - // $MainContentControlStyle.FindName('PathIcon1').Source // PathIcon1 BitmapImage PathIcon1Image = new(); @@ -131,7 +123,7 @@ private void ProtectView(object obj) string presetName = "preset: basic"; // Check if the preset exists in the dictionary - if (GUIProtectWinSecurity.PresetsIntel.TryGetValue(presetName, out var categoriesAndSubcategories)) + if (GUIProtectWinSecurity.PresetsIntel.TryGetValue(presetName, out Dictionary<string, List<string>> categoriesAndSubcategories)) { // Access the categories and subcategories List<string> categories = categoriesAndSubcategories["Categories"]; @@ -177,7 +169,6 @@ private void ProtectView(object obj) } - } } else @@ -197,7 +188,7 @@ private void ProtectView(object obj) string presetName = "preset: recommended"; // Check if the preset exists in the dictionary - if (GUIProtectWinSecurity.PresetsIntel.TryGetValue(presetName, out var categoriesAndSubcategories)) + if (GUIProtectWinSecurity.PresetsIntel.TryGetValue(presetName, out Dictionary<string, List<string>> categoriesAndSubcategories)) { // Access the categories and subcategories List<string> categories = categoriesAndSubcategories["Categories"]; @@ -243,7 +234,6 @@ private void ProtectView(object obj) } - } } else @@ -260,7 +250,7 @@ private void ProtectView(object obj) string presetName = "preset: complete"; // Check if the preset exists in the dictionary - if (GUIProtectWinSecurity.PresetsIntel.TryGetValue(presetName, out var categoriesAndSubcategories)) + if (GUIProtectWinSecurity.PresetsIntel.TryGetValue(presetName, out Dictionary<string, List<string>> categoriesAndSubcategories)) { // Access the categories and subcategories List<string> categories = categoriesAndSubcategories["Categories"]; @@ -340,7 +330,7 @@ private void ProtectView(object obj) // Load the Execute button image into memory and set it as the source BitmapImage ExecuteButtonBitmapImage = new(); ExecuteButtonBitmapImage.BeginInit(); - ExecuteButtonBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ExecuteButton.png")); + ExecuteButtonBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "ExecuteButton.png")); ExecuteButtonBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory ExecuteButtonBitmapImage.EndInit(); @@ -438,22 +428,22 @@ private void ProtectView(object obj) // Add a new row definition for the text message RowDefinition offlineModeUnavailableRow = new() { - Height = new System.Windows.GridLength(50) + Height = new GridLength(50) }; GUIProtectWinSecurity.grid2.RowDefinitions.Add(offlineModeUnavailableRow); // Create a new text box TextBox offlineModeUnavailableNoticeBox = new() { - HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, - VerticalAlignment = System.Windows.VerticalAlignment.Stretch, - TextWrapping = System.Windows.TextWrapping.Wrap, + HorizontalAlignment = HorizontalAlignment.Stretch, + VerticalAlignment = VerticalAlignment.Stretch, + TextWrapping = TextWrapping.Wrap, Text = "To enable offline mode, use: Protect-WindowsSecurity -GUI -Offline", - TextAlignment = System.Windows.TextAlignment.Center, + TextAlignment = TextAlignment.Center, Background = Brushes.Transparent, FontSize = 20, - BorderThickness = new System.Windows.Thickness(0), - Margin = new System.Windows.Thickness(10, 20, 10, 0), + BorderThickness = new Thickness(0), + Margin = new Thickness(10, 20, 10, 0), ToolTip = "To enable offline mode, use: Protect-WindowsSecurity -GUI -Offline" }; offlineModeUnavailableNoticeBox.SetValue(Grid.ColumnSpanProperty, 2); diff --git a/Harden-Windows-Security Module/Main files/C#/GUI/Unprotect/View.cs b/Harden-Windows-Security Module/Main files/C#/GUI/Unprotect/View.cs index 1cf1e9160..0c9c76b1a 100644 --- a/Harden-Windows-Security Module/Main files/C#/GUI/Unprotect/View.cs +++ b/Harden-Windows-Security Module/Main files/C#/GUI/Unprotect/View.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Windows; using System.Windows.Controls; -using System.Windows.Controls.Primitives; using System.Windows.Markup; using System.Windows.Media.Imaging; @@ -27,11 +26,6 @@ private void UnprotectView(object obj) return; } - if (GlobalVars.path is null) - { - throw new InvalidOperationException("GlobalVars.path cannot be null."); - } - // if Admin privileges are not available, return and do not proceed any further // Will prevent the page from being loaded since the CurrentView won't be set/changed if (!UserPrivCheck.IsAdmin()) @@ -55,28 +49,6 @@ private void UnprotectView(object obj) // Find the Parent Grid GUIUnprotect.ParentGrid = (Grid)GUIUnprotect.View.FindName("ParentGrid"); - // Finding the Execute Button Grid - Grid? ExecuteButtonGrid = GUIUnprotect.ParentGrid.FindName("ExecuteButtonGrid") as Grid ?? throw new InvalidOperationException("ExecuteButtonGrid is null in the ASRRules View"); - - // Finding the Execute Button - ToggleButton? ExecuteButton = ExecuteButtonGrid.FindName("ExecuteButton") as ToggleButton ?? throw new InvalidOperationException("Couldn't find the ExecuteButton in ASRRules view"); - - // Apply the template to make sure it's available - _ = ExecuteButton.ApplyTemplate(); - - // Access the image within the Execute Button's template - Image? RefreshIconImage = ExecuteButton.Template.FindName("RefreshIconImage", ExecuteButton) as Image ?? throw new InvalidOperationException("RefreshIconImage could not be found in the ASRRules view"); - - // Update the image source for the Refresh button - // Load the Refresh icon image into memory and set it as the source - BitmapImage RefreshIconBitmapImage = new(); - RefreshIconBitmapImage.BeginInit(); - RefreshIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "ExecuteButton.png")); - RefreshIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory - RefreshIconBitmapImage.EndInit(); - - RefreshIconImage.Source = RefreshIconBitmapImage; - if (GUIUnprotect.ParentGrid.FindName("AppControlPolicies") is not ComboBox AppControlPoliciesComboBox) { throw new InvalidOperationException("AppControlPoliciesComboBox is null"); @@ -89,12 +61,13 @@ private void UnprotectView(object obj) Button RefreshDrivesButton = GUIUnprotect.ParentGrid.FindName("RefreshDrivesForSelection") as Button ?? throw new InvalidOperationException("RefreshDrivesForSelection could not be found"); + Button RemoveProtectionsButton = GUIUnprotect.ParentGrid.FindName("RemoveProtectionsButton") as Button ?? throw new InvalidOperationException("RemoveProtectionsButton could not be found"); Image? RefreshDrivesForSelectionButtonIcon = GUIUnprotect.ParentGrid.FindName("RefreshDrivesForSelectionButtonIcon") as Image ?? throw new InvalidOperationException("RefreshDrivesForSelectionButtonIcon could not be found"); // Add image to the BackupButtonIcon BitmapImage BackupButtonIconBitmapImage = new(); BackupButtonIconBitmapImage.BeginInit(); - BackupButtonIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path!, "Resources", "Media", "RefreshButtonIcon.png")); + BackupButtonIconBitmapImage.UriSource = new Uri(Path.Combine(GlobalVars.path, "Resources", "Media", "RefreshButtonIcon.png")); BackupButtonIconBitmapImage.CacheOption = BitmapCacheOption.OnLoad; // Load the image data into memory BackupButtonIconBitmapImage.EndInit(); RefreshDrivesForSelectionButtonIcon.Source = BackupButtonIconBitmapImage; @@ -106,8 +79,8 @@ private void UnprotectView(object obj) #endregion - // Register the ExecuteButton as an element that will be enabled/disabled based on current activity - ActivityTracker.RegisterUIElement(ExecuteButton); + // Register the RemoveProtectionsButton as an element that will be enabled/disabled based on current activity + ActivityTracker.RegisterUIElement(RemoveProtectionsButton); // Add more button to activity tracker ActivityTracker.RegisterUIElement(RefreshDrivesButton); @@ -194,8 +167,8 @@ await System.Threading.Tasks.Task.Run(() => }; - // Set up the Click event handler for the ExecuteButton button - ExecuteButton.Click += async (sender, e) => + // Set up the Click event handler for the RemoveProtectionsButton button + RemoveProtectionsButton.Click += async (sender, e) => { // Only continue if there is no activity other places if (!ActivityTracker.IsActive) @@ -207,7 +180,7 @@ await System.Threading.Tasks.Task.Run(() => // mark as activity started ActivityTracker.IsActive = true; - // Disable the ExecuteButton button while processing + // Disable the RemoveProtectionsButton button while processing Application.Current.Dispatcher.Invoke(() => { // Store the values of the combo boxes in View variables since they need to be acquired through the Application dispatcher since they belong to the UI thread @@ -294,12 +267,6 @@ await System.Threading.Tasks.Task.Run(() => }); - // Update the UI Elements at the end of the run - await Application.Current.Dispatcher.InvokeAsync(() => - { - ExecuteButton.IsChecked = false; // Uncheck the ExecuteButton button to start the reverse animation - }); - // mark as activity completed ActivityTracker.IsActive = false; diff --git a/Harden-Windows-Security Module/Main files/C#/Others/AsyncDownloader.cs b/Harden-Windows-Security Module/Main files/C#/Others/AsyncDownloader.cs index 38fed1d39..306cf451c 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/AsyncDownloader.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/AsyncDownloader.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Net.Http; using System.Threading.Tasks; @@ -235,16 +236,16 @@ public static void PrepDownloadedFiles(string? LGPOPath, string? MSFTSecurityBas Logger.LogMessage("Extracting the downloaded zip files", LogTypeIntel.Information); // Extract MicrosoftSecurityBaseline.zip - System.IO.Compression.ZipFile.ExtractToDirectory(MicrosoftSecurityBaselineZipFilePath, MicrosoftSecurityBaselineDirPath); + ZipFile.ExtractToDirectory(MicrosoftSecurityBaselineZipFilePath, MicrosoftSecurityBaselineDirPath); // Extract Microsoft365SecurityBaseline.zip - System.IO.Compression.ZipFile.ExtractToDirectory(Microsoft365SecurityBaselineZipFilePath, Microsoft365SecurityBaselineDirPath); + ZipFile.ExtractToDirectory(Microsoft365SecurityBaselineZipFilePath, Microsoft365SecurityBaselineDirPath); } // Extract LGPO.zip - System.IO.Compression.ZipFile.ExtractToDirectory(LGPOZipFilePath, GlobalVars.WorkingDir); + ZipFile.ExtractToDirectory(LGPOZipFilePath, GlobalVars.WorkingDir); if (!OnlyLGPO) { diff --git a/Harden-Windows-Security Module/Main files/C#/Others/CSVImporter.cs b/Harden-Windows-Security Module/Main files/C#/Others/CSVImporter.cs index 1adee7fe1..aef5f2b4e 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/CSVImporter.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/CSVImporter.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; @@ -21,14 +20,11 @@ public sealed class CsvRecord // Define a public method to parse the CSV file and save the records to RegistryCSVItems public static void ReadCsv() { - // Ensure GlobalVars.path is not null - string basePath = GlobalVars.path ?? throw new ArgumentNullException(nameof(GlobalVars.path), "GlobalVars.path cannot be null."); - // Ensure RegistryCSVItems is initialized List<CsvRecord> registryCSVItems = GlobalVars.RegistryCSVItems; // Define the path to the CSV file - string path = Path.Combine(basePath, "Resources", "Registry.csv"); + string path = Path.Combine(GlobalVars.path, "Resources", "Registry.csv"); // Open the file and read the contents using StreamReader reader = new(path); diff --git a/Harden-Windows-Security Module/Main files/C#/Others/Categoriex.cs b/Harden-Windows-Security Module/Main files/C#/Others/Categoriex.cs index 8c1b4016f..7abeacba4 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/Categoriex.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/Categoriex.cs @@ -16,7 +16,7 @@ public enum ComplianceCategories UserAccountControl, // 6 DeviceGuard, // 10 WindowsFirewall, // 20 - OptionalWindowsFeatures, // 14 + OptionalWindowsFeatures, // 15 WindowsNetworking, // 17 MiscellaneousConfigurations, // 20 WindowsUpdateConfigurations, // 15 diff --git a/Harden-Windows-Security Module/Main files/C#/Others/CategoryProcessing.cs b/Harden-Windows-Security Module/Main files/C#/Others/CategoryProcessing.cs index b861f5955..138bdd905 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/CategoryProcessing.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/CategoryProcessing.cs @@ -34,11 +34,6 @@ private static List<CsvRecord> ReadCsv() // Create a list to store the records List<CsvRecord> records = []; - if (GlobalVars.path is null) - { - throw new ArgumentNullException("The path to the CSV file is not set."); - } - // Define the path to the CSV file - hardcoded because it doesn't need to change string path = Path.Combine(GlobalVars.path, "Resources", "Registry resources.csv"); diff --git a/Harden-Windows-Security Module/Main files/C#/Others/ConditionalResultAdd.cs b/Harden-Windows-Security Module/Main files/C#/Others/ConditionalResultAdd.cs index 69b1b3db2..c1d4948b8 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/ConditionalResultAdd.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/ConditionalResultAdd.cs @@ -28,8 +28,10 @@ internal static void Add(List<IndividualResult> nestedObjectArray, IndividualRes { // Remove the existing item with Compliant status "False" _ = nestedObjectArray.Remove(existingItem); + // Add the current item with Compliant status "True" nestedObjectArray.Add(result); + Logger.LogMessage($"Item with Name '{existingItem.Name}' and FriendlyName '{existingItem.FriendlyName}' replaced with a compliant item.", LogTypeIntel.Information); } else diff --git a/Harden-Windows-Security Module/Main files/C#/Others/ConfirmSystemComplianceMethods.cs b/Harden-Windows-Security Module/Main files/C#/Others/ConfirmSystemComplianceMethods.cs index 320b5920c..00d06382e 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/ConfirmSystemComplianceMethods.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/ConfirmSystemComplianceMethods.cs @@ -46,8 +46,7 @@ internal static void OrchestrateComplianceChecks(params string[] methodNames) GlobalVars.SystemSecurityPoliciesIniObject = IniFileConverter.ConvertFromIniFile(GlobalVars.securityPolicyInfPath); // Process the SecurityPoliciesVerification.csv and save the output to the global variable GlobalVars.SecurityPolicyRecords - string basePath = GlobalVars.path ?? throw new InvalidOperationException("GlobalVars.path cannot be null."); - string fullPath = Path.Combine(basePath, "Resources", "SecurityPoliciesVerification.csv"); + string fullPath = Path.Combine(GlobalVars.path, "Resources", "SecurityPoliciesVerification.csv"); GlobalVars.SecurityPolicyRecords = SecurityPolicyCsvProcessor.ProcessSecurityPolicyCsvFile(fullPath); @@ -1034,6 +1033,16 @@ private static Task VerifyOptionalWindowsFeatures() Method = Method.DISM }); + nestedObjectArray.Add(new IndividualResult + { + FriendlyName = "VBSCRIPT is not present", + Compliant = string.Equals(FeaturesCheckResults.VBSCRIPT, "Not Present", StringComparison.OrdinalIgnoreCase), + Value = FeaturesCheckResults.VBSCRIPT, + Name = "VBSCRIPT is not present", + Category = CatName, + Method = Method.DISM + }); + _ = GlobalVars.FinalMegaObject.TryAdd(CatName, nestedObjectArray); }); } diff --git a/Harden-Windows-Security Module/Main files/C#/Others/GetLocalUser.cs b/Harden-Windows-Security Module/Main files/C#/Others/GetLocalUser.cs index 78e776cdf..4549e1d98 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/GetLocalUser.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/GetLocalUser.cs @@ -1,8 +1,6 @@ -using System; using System.Collections.Generic; using System.DirectoryServices.AccountManagement; using System.Globalization; -using System.Runtime.InteropServices; namespace HardenWindowsSecurity; @@ -33,10 +31,6 @@ internal sealed class LocalUser /// </summary> internal static class LocalUserRetriever { - // https://learn.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertsidtostringsida - [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - private static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid); /// <summary> /// Retrieves local user accounts on the system and returns them as a list of LocalUser objects diff --git a/Harden-Windows-Security Module/Main files/C#/Others/GlobalVars.cs b/Harden-Windows-Security Module/Main files/C#/Others/GlobalVars.cs index 43122e6ca..b49c9d1ed 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/GlobalVars.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/GlobalVars.cs @@ -21,8 +21,11 @@ public static class GlobalVars // Create full OS build number as seen in Windows Settings internal static string? FullOSBuild; +#pragma warning disable CS8618 // Stores the value of $PSScriptRoot in a global variable to allow the internal functions to use it when navigating the module structure - public static string? path; + // The check for being empty or whitespace is performed in the Initializer class. + public static string path; +#pragma warning restore // Stores the output of Get-MpComputerStatus which happens early on in the root module .psm1 file public static dynamic? MDAVConfigCurrent; diff --git a/Harden-Windows-Security Module/Main files/C#/Others/Initializer.cs b/Harden-Windows-Security Module/Main files/C#/Others/Initializer.cs index 8802c9ac2..8919338c6 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/Initializer.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/Initializer.cs @@ -20,6 +20,13 @@ public static void Initialize(string VerbosePreference = "SilentlyContinue", boo GlobalVars.LogHeaderHasBeenWritten = false; + // This check is only necessary to be performed + // GlobalVars.path is set to non-nullable intentionally with pragma disable + if (string.IsNullOrWhiteSpace(GlobalVars.path)) + { + throw new InvalidOperationException("The PSScriptRoot variable hasn't been set!"); + } + // Set the default culture to InvariantCulture globally CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; @@ -93,7 +100,7 @@ public static void Initialize(string VerbosePreference = "SilentlyContinue", boo GlobalVars.MDAVConfigCurrent = ConfigDefenderHelper.GetMpComputerStatus(); // Total number of Compliant values - GlobalVars.TotalNumberOfTrueCompliantValues = 256; + GlobalVars.TotalNumberOfTrueCompliantValues = 257; // Getting the $VerbosePreference from the calling cmdlet and saving it in the global variable GlobalVars.VerbosePreference = VerbosePreference; diff --git a/Harden-Windows-Security Module/Main files/C#/Others/NativeMethods.cs b/Harden-Windows-Security Module/Main files/C#/Others/NativeMethods.cs new file mode 100644 index 000000000..75b284f05 --- /dev/null +++ b/Harden-Windows-Security Module/Main files/C#/Others/NativeMethods.cs @@ -0,0 +1,41 @@ +using System; +using System.Runtime.InteropServices; +using static HardenWindowsSecurity.FirmwareChecker; +using static HardenWindowsSecurity.SystemInformationClass; + +namespace HardenWindowsSecurity; + +internal static class NativeMethods +{ + + // https://learn.microsoft.com/en-us/windows/win32/api/sddl/nf-sddl-convertsidtostringsida + [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern bool ConvertSidToStringSid(IntPtr pSID, out IntPtr ptrSid); + + [DllImport("TpmCoreProvisioning", CharSet = CharSet.Unicode)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern uint TpmIsEnabled(out byte pfIsEnabled); + + [DllImport("TpmCoreProvisioning", CharSet = CharSet.Unicode)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern uint TpmIsActivated(out byte pfIsActivated); + + [DllImport("ntdll.dll")] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern Int32 NtQuerySystemInformation( + SYSTEM_DMA_GUARD_POLICY_INFORMATION SystemDmaGuardPolicyInformation, + IntPtr SystemInformation, + Int32 SystemInformationLength, + out Int32 ReturnLength); + + // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfirmwaretype + [DllImport(dllName: "kernel32.dll", SetLastError = true)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern bool GetFirmwareType(out FirmwareType firmwareType); + + [DllImport("shell32.dll")] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + internal static extern int SHGetKnownFolderPath( + ref Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath); +} diff --git a/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsApplication.cs b/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsApplication.cs index 29e31e604..eeabdbcd1 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsApplication.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsApplication.cs @@ -1,5 +1,6 @@ using System; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Management.Automation; using Microsoft.Win32; @@ -26,7 +27,7 @@ internal static void Apply() Logger.LogMessage("Removing the existing process mitigations", LogTypeIntel.Information); foreach (IGrouping<string?, ProcessMitigationsParser.ProcessMitigationsRecords> group in groupedMitigations) { - string? fileName = System.IO.Path.GetFileName(group.Key); + string? fileName = Path.GetFileName(group.Key); if (allAvailableMitigations.Contains(fileName)) { diff --git a/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsParser.cs b/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsParser.cs index f14e1ed18..a9008b5ff 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsParser.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/ProcessMitigationsParser.cs @@ -23,15 +23,8 @@ internal static void ReadCsv() // Initializing the path variable for the CSV file string path; - if (GlobalVars.path is not null) - { - // Define the path to the CSV file - path = Path.Combine(GlobalVars.path, "Resources", "ProcessMitigations.csv"); - } - else - { - throw new InvalidOperationException("GlobalVars.path is null."); - } + // Define the path to the CSV file + path = Path.Combine(GlobalVars.path, "Resources", "ProcessMitigations.csv"); // Open the file and read the contents using StreamReader reader = new(path); diff --git a/Harden-Windows-Security Module/Main files/C#/Others/SystemInfoNativeMethods.cs b/Harden-Windows-Security Module/Main files/C#/Others/SystemInfoNativeMethods.cs index 78fcb97ab..f50babe83 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/SystemInfoNativeMethods.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/SystemInfoNativeMethods.cs @@ -15,14 +15,6 @@ internal enum SYSTEM_DMA_GUARD_POLICY_INFORMATION : int SystemDmaGuardPolicyInformation = 202 } - [DllImport("ntdll.dll")] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - internal static extern Int32 NtQuerySystemInformation( - SYSTEM_DMA_GUARD_POLICY_INFORMATION SystemDmaGuardPolicyInformation, - IntPtr SystemInformation, - Int32 SystemInformationLength, - out Int32 ReturnLength); - internal static byte BootDmaCheck() { Int32 result; @@ -30,7 +22,7 @@ internal static byte BootDmaCheck() IntPtr SystemInformation = Marshal.AllocHGlobal(SystemInformationLength); // https://learn.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntquerysysteminformation - result = NtQuerySystemInformation( + result = NativeMethods.NtQuerySystemInformation( SYSTEM_DMA_GUARD_POLICY_INFORMATION.SystemDmaGuardPolicyInformation, SystemInformation, SystemInformationLength, diff --git a/Harden-Windows-Security Module/Main files/C#/Others/ToastNotification.cs b/Harden-Windows-Security Module/Main files/C#/Others/ToastNotification.cs index 4bb20afe4..1e897afdc 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/ToastNotification.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/ToastNotification.cs @@ -32,7 +32,7 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo { // Notifications Icon Override for all of the toast notification styles - string LogoOverride = Path.Combine(GlobalVars.path!, "Resources", "Media", "NotificationIconOverride.png"); + string LogoOverride = Path.Combine(GlobalVars.path, "Resources", "Media", "NotificationIconOverride.png"); // Detect the notification type so we can create the proper notification to be displayed switch (Type) @@ -42,9 +42,9 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo case Type.EndOfProtection: { // Combine paths - // string Hero = Path.Combine(GlobalVars.path!, "Resources", "Media", "Microsoft Defender.png"); - // string DismissButtonImage = Path.Combine(GlobalVars.path!, "Resources", "Media", "notification (1).png"); - string Inline = Path.Combine(GlobalVars.path!, "Resources", "Media", "ProtectToastNotificationImage.png"); + // string Hero = Path.Combine(GlobalVars.path, "Resources", "Media", "Microsoft Defender.png"); + // string DismissButtonImage = Path.Combine(GlobalVars.path, "Resources", "Media", "notification (1).png"); + string Inline = Path.Combine(GlobalVars.path, "Resources", "Media", "ProtectToastNotificationImage.png"); new ToastContentBuilder() @@ -105,7 +105,7 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo { // Combine paths - string Inline = Path.Combine(GlobalVars.path!, "Resources", "Media", "ConfirmToastNotificationImage.png"); + string Inline = Path.Combine(GlobalVars.path, "Resources", "Media", "ConfirmToastNotificationImage.png"); new ToastContentBuilder() @@ -135,8 +135,8 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo { // Combine paths - string Hero = Path.Combine(GlobalVars.path!, "Resources", "Media", "Attack Surface Reduction Notification Hero Image.png"); - string Inline = Path.Combine(GlobalVars.path!, "Resources", "Media", "ASRRulesToastNotificationImage.png"); + string Hero = Path.Combine(GlobalVars.path, "Resources", "Media", "Attack Surface Reduction Notification Hero Image.png"); + string Inline = Path.Combine(GlobalVars.path, "Resources", "Media", "ASRRulesToastNotificationImage.png"); new ToastContentBuilder() @@ -165,7 +165,7 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo case Type.EndOfUnprotection: { // Combine paths - string Inline = Path.Combine(GlobalVars.path!, "Resources", "Media", "UnprotectToastNotificationImage.png"); + string Inline = Path.Combine(GlobalVars.path, "Resources", "Media", "UnprotectToastNotificationImage.png"); new ToastContentBuilder() @@ -190,7 +190,7 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo case Type.EndOfExclusions: { // Combine paths - string Inline = Path.Combine(GlobalVars.path!, "Resources", "Media", "UnprotectToastNotificationImage.png"); + string Inline = Path.Combine(GlobalVars.path, "Resources", "Media", "UnprotectToastNotificationImage.png"); new ToastContentBuilder() @@ -215,7 +215,7 @@ public static void Show(Type Type, string? TotalCompliantValues, string? TotalNo case Type.EndOfBitLocker: { // Combine paths - string Inline = Path.Combine(GlobalVars.path!, "Resources", "Media", "BitLockerToastNotificationImage.png"); + string Inline = Path.Combine(GlobalVars.path, "Resources", "Media", "BitLockerToastNotificationImage.png"); new ToastContentBuilder() diff --git a/Harden-Windows-Security Module/Main files/C#/Others/VolumeWritabilityCheck.cs b/Harden-Windows-Security Module/Main files/C#/Others/VolumeWritabilityCheck.cs index 586394712..86d2949e3 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/VolumeWritabilityCheck.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/VolumeWritabilityCheck.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; namespace HardenWindowsSecurity; @@ -42,7 +43,7 @@ internal static partial class VolumeWritabilityCheck using (FileStream fs = File.Create(testFilePath)) { // Write some data - byte[] testData = new System.Text.UTF8Encoding(true).GetBytes("test"); + byte[] testData = new UTF8Encoding(true).GetBytes("test"); fs.Write(testData, 0, testData.Length); } diff --git a/Harden-Windows-Security Module/Main files/C#/Others/WindowsFeatureChecker.cs b/Harden-Windows-Security Module/Main files/C#/Others/WindowsFeatureChecker.cs index 77fd731ca..61627e88e 100644 --- a/Harden-Windows-Security Module/Main files/C#/Others/WindowsFeatureChecker.cs +++ b/Harden-Windows-Security Module/Main files/C#/Others/WindowsFeatureChecker.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Management; namespace HardenWindowsSecurity; @@ -23,6 +24,7 @@ public sealed class FeatureStatus public string? LegacyWordPad { get; set; } public string? PowerShellISE { get; set; } public string? StepsRecorder { get; set; } + public string? VBSCRIPT { get; set; } } public static FeatureStatus CheckWindowsFeatures() @@ -45,7 +47,8 @@ public static FeatureStatus CheckWindowsFeatures() LegacyNotepad = GetCapabilityState("Microsoft.Windows.Notepad.System"), LegacyWordPad = GetCapabilityState("Microsoft.Windows.WordPad"), PowerShellISE = GetCapabilityState("Microsoft.Windows.PowerShell.ISE"), - StepsRecorder = GetCapabilityState("App.StepsRecorder") + StepsRecorder = GetCapabilityState("App.StepsRecorder"), + VBSCRIPT = GetCapabilityState("VBSCRIPT") }; } @@ -141,8 +144,8 @@ private static string RunDismCommand(string arguments) // Start the DISM process using Process? process = Process.Start(startInfo) ?? throw new InvalidOperationException("Failed to start the process."); - using System.IO.StreamReader outputReader = process.StandardOutput; - using System.IO.StreamReader errorReader = process.StandardError; + using StreamReader outputReader = process.StandardOutput; + using StreamReader errorReader = process.StandardError; string output = outputReader.ReadToEnd(); string error = errorReader.ReadToEnd(); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/AttackSurfaceReductionRules.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/AttackSurfaceReductionRules.cs index fc3eed44a..fa94610f3 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/AttackSurfaceReductionRules.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/AttackSurfaceReductionRules.cs @@ -11,11 +11,6 @@ public static class AttackSurfaceReductionRules /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🪷 ASR Rules"); Logger.LogMessage("Running the Attack Surface Reduction Rules category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/BitLockerSettings.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/BitLockerSettings.cs index 946052038..1e25aa411 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/BitLockerSettings.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/BitLockerSettings.cs @@ -13,11 +13,6 @@ public static class BitLockerSettings /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🔑 BitLocker"); Logger.LogMessage("Running the Bitlocker category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DangerousScriptHostsBlocking.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DangerousScriptHostsBlocking.cs index 5be31aa06..b0b76ad58 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DangerousScriptHostsBlocking.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DangerousScriptHostsBlocking.cs @@ -12,11 +12,6 @@ public static partial class DownloadsDefenseMeasures /// <exception cref="ArgumentNullException"></exception> public static void DangerousScriptHostsBlocking() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Running the Dangerous Script Hosts Blocking section", LogTypeIntel.Information); string CIPPath = Path.Combine(GlobalVars.WorkingDir, "Dangerous-Script-Hosts-Blocking.cip"); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard.cs index ceab555b3..1d64ed66a 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard.cs @@ -13,11 +13,6 @@ public static partial class DeviceGuard public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🖥️ Device Guard"); Logger.LogMessage("Running the Device Guard category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard_MandatoryVBS.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard_MandatoryVBS.cs index deffcf9d8..6831402cb 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard_MandatoryVBS.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DeviceGuard_MandatoryVBS.cs @@ -11,12 +11,6 @@ public partial class DeviceGuard /// <exception cref="ArgumentNullException"></exception> public static void DeviceGuard_MandatoryVBS() { - - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🖥️ Device Guard"); Logger.LogMessage("Setting VBS and Memory Integrity in Mandatory Mode", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DownloadsDefenseMeasures.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DownloadsDefenseMeasures.cs index 6451e7790..fcf6a08a2 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/DownloadsDefenseMeasures.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/DownloadsDefenseMeasures.cs @@ -12,22 +12,12 @@ public static partial class DownloadsDefenseMeasures // GUID for the Downloads folder private static Guid FolderDownloads = new("374DE290-123F-4565-9164-39C4925E467B"); - [DllImport("shell32.dll")] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - private static extern int SHGetKnownFolderPath( - ref Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr ppszPath); - /// <summary> /// Prevents executables originating from the Downloads folder from running, using AppControl policy /// </summary> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🎇 Downloads Defense Measures"); Logger.LogMessage("Running the Downloads Defense Measures category", LogTypeIntel.Information); @@ -65,7 +55,7 @@ public static void Invoke() try { // Get the System Downloads folder path - int result = SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero, out pathPtr); + int result = NativeMethods.SHGetKnownFolderPath(ref FolderDownloads, 0, IntPtr.Zero, out pathPtr); if (result is 0) // S_OK { diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/EdgeBrowserConfigurations.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/EdgeBrowserConfigurations.cs index 47fa4a676..b6fbe5890 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/EdgeBrowserConfigurations.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/EdgeBrowserConfigurations.cs @@ -10,11 +10,6 @@ public static class EdgeBrowserConfigurations /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🦔 Edge"); Logger.LogMessage("Running the Edge Browser category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen.cs index c1cba9146..7c00d859d 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen.cs @@ -11,12 +11,6 @@ public static partial class LockScreen /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("💻 Lock Screen"); Logger.LogMessage("Running the Lock Screen category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_CtrlAltDel.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_CtrlAltDel.cs index 800c65565..4bc4aafdd 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_CtrlAltDel.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_CtrlAltDel.cs @@ -11,11 +11,6 @@ public static partial class LockScreen /// <exception cref="ArgumentNullException"></exception> public static void LockScreen_CtrlAltDel() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Applying the Enable CTRL + ALT + DEL policy", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Lock Screen Policies", "Enable CTRL + ALT + DEL", "GptTmpl.inf"), LGPORunner.FileType.INF); } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_LastSignedIn.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_LastSignedIn.cs index e94c1bfdb..948e47153 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_LastSignedIn.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/LockScreen_LastSignedIn.cs @@ -11,14 +11,7 @@ public static partial class LockScreen /// <exception cref="ArgumentNullException"></exception> public static void LockScreen_LastSignedIn() { - - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Applying the Don't display last signed-in policy", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Lock Screen Policies", "Don't display last signed-in", "GptTmpl.inf"), LGPORunner.FileType.INF); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_BetaChannels.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_BetaChannels.cs index 29615d8ce..581040d1e 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_BetaChannels.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_BetaChannels.cs @@ -10,16 +10,10 @@ public static partial class MicrosoftDefender /// <exception cref="ArgumentNullException"></exception> public static void MSFTDefender_BetaChannels() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Setting Microsoft Defender engine and platform update channel to beta", LogTypeIntel.Information); ConfigDefenderHelper.ManageMpPreference("EngineUpdatesChannel", "2", true); ConfigDefenderHelper.ManageMpPreference("PlatformUpdatesChannel", "2", true); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_EnableDiagData.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_EnableDiagData.cs index 6b2fc573c..fa609ca91 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_EnableDiagData.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MSFTDefender_EnableDiagData.cs @@ -12,14 +12,8 @@ public static partial class MicrosoftDefender public static void MSFTDefender_EnableDiagData() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Enabling Optional Diagnostic Data", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Microsoft Defender Policies", "Optional Diagnostic Data", "registry.pol"), LGPORunner.FileType.POL); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftDefender.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftDefender.cs index 766cfb4f2..04ae2a123 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftDefender.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftDefender.cs @@ -13,11 +13,6 @@ public static partial class MicrosoftDefender public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🍁 MSFT Defender"); Logger.LogMessage("Running the Microsoft Defender category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftSecurityBaselines.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftSecurityBaselines.cs index 2bca18f2e..08bd6b095 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftSecurityBaselines.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MicrosoftSecurityBaselines.cs @@ -16,11 +16,6 @@ public static void Invoke() throw new InvalidOperationException("The path to the Microsoft Security Baselines has not been set."); } - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🔐 Security Baselines"); Logger.LogMessage("Applying the Microsoft Security Baselines", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations.cs index 8186ca51d..af3aabe63 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations.cs @@ -12,11 +12,6 @@ public static partial class MiscellaneousConfigurations /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🥌 Miscellaneous"); Logger.LogMessage("Running the Miscellaneous Configurations category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_LongPathSupport.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_LongPathSupport.cs index 7b068288d..70c7a5605 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_LongPathSupport.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_LongPathSupport.cs @@ -11,14 +11,8 @@ public static partial class MiscellaneousConfigurations /// <exception cref="ArgumentNullException"></exception> public static void MiscellaneousConfigurations_LongPathSupport() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Enabling support for long paths", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Miscellaneous Policies", "Long Path Support", "registry.pol"), LGPORunner.FileType.POL); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_StrongKeyProtection.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_StrongKeyProtection.cs index b5eaeef4c..62fa2b057 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_StrongKeyProtection.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_StrongKeyProtection.cs @@ -11,14 +11,8 @@ public static partial class MiscellaneousConfigurations /// <exception cref="ArgumentNullException"></exception> public static void MiscellaneousConfigurations_StrongKeyProtection() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Enabling force strong key protection policy", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Miscellaneous Policies", "Strong key protection", "GptTmpl.inf"), LGPORunner.FileType.INF); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_WindowsProtectedPrint.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_WindowsProtectedPrint.cs index 563c84637..a0c773564 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_WindowsProtectedPrint.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/MiscellaneousConfigurations_WindowsProtectedPrint.cs @@ -11,14 +11,8 @@ public static partial class MiscellaneousConfigurations /// <exception cref="ArgumentNullException"></exception> public static void MiscellaneousConfigurations_WindowsProtectedPrint() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Enabling Windows Protected Print", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Miscellaneous Policies", "Windows Protected Print", "registry.pol"), LGPORunner.FileType.POL); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/NonAdminCommands.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/NonAdminCommands.cs index 8367499dc..d953fbd1f 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/NonAdminCommands.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/NonAdminCommands.cs @@ -10,11 +10,6 @@ public static partial class NonAdminCommands /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🏷️ Non-Admins"); Logger.LogMessage("Running the Non-Admin category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/OptionalWindowsFeatures.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/OptionalWindowsFeatures.cs index 29fc4d1ff..49890f0ee 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/OptionalWindowsFeatures.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/OptionalWindowsFeatures.cs @@ -5,24 +5,16 @@ namespace HardenWindowsSecurity; public static class OptionalWindowsFeatures { - // Declare the _FeaturesCheckResults as a private static field - private static WindowsFeatureChecker.FeatureStatus? _FeaturesCheckResults; /// <summary> - /// A Private method that removes the capability if it is present + /// A method that removes the capability if it is present /// </summary> /// <param name="CapabilityIdentity">the capability's identity, the one that will be used to query its state and to remove it</param> /// <param name="CapabilityName">The name of the capability, used to display in the log messages</param> - private static void RemoveCapability(string CapabilityIdentity, string CapabilityName) + internal static void RemoveCapability(string CapabilityIdentity, string CapabilityName) { - - ArgumentNullException.ThrowIfNull(CapabilityIdentity); - ArgumentNullException.ThrowIfNull(CapabilityName); - // The queried state of the capability - string CapabilityState; - - CapabilityState = WindowsFeatureChecker.GetCapabilityState(CapabilityIdentity); + string CapabilityState = WindowsFeatureChecker.GetCapabilityState(CapabilityIdentity); if (string.Equals(CapabilityState, "Not Present", StringComparison.OrdinalIgnoreCase)) { @@ -64,7 +56,7 @@ private static void RemoveCapability(string CapabilityIdentity, string Capabilit /// Since the method uses the values in WindowsFeatureChecker.FeatureStatus class /// and they are stored under different names, we need this parameter to create the correct connections /// </param> - private static void ConfigureWindowsOptionalFeature(bool Action, string FeatureNameToActOn, string FriendlyName, string FeatureNameToCheckWith) + internal static void ConfigureWindowsOptionalFeature(bool Action, string FeatureNameToActOn, string FriendlyName, string FeatureNameToCheckWith, WindowsFeatureChecker.FeatureStatus featureResults) { // If the action is to enable a feature, then check if it's disabled and vise versa string ValueToCheckFor = Action ? "Disabled" : "Enabled"; @@ -74,14 +66,14 @@ private static void ConfigureWindowsOptionalFeature(bool Action, string FeatureN string TextToUseForMessages = Action ? "Enabling" : "Disabling"; // Use reflection to get the property value - PropertyInfo? propertyInfo = _FeaturesCheckResults?.GetType().GetProperty(FeatureNameToCheckWith); + PropertyInfo? propertyInfo = featureResults?.GetType().GetProperty(FeatureNameToCheckWith); - // To store the value of the property of the _FeaturesCheckResults + // To store the value of the property of the featureResults string? propertyValue = string.Empty; if (propertyInfo is not null) { - propertyValue = propertyInfo.GetValue(_FeaturesCheckResults)?.ToString(); + propertyValue = propertyInfo.GetValue(featureResults)?.ToString(); } if (string.IsNullOrWhiteSpace(propertyValue)) @@ -112,15 +104,15 @@ public static void Invoke() Logger.LogMessage("Running the Optional Windows Features category", LogTypeIntel.Information); // Get the results of all optional features once and store them in the static variable to be reused later - _FeaturesCheckResults = WindowsFeatureChecker.CheckWindowsFeatures(); - - ConfigureWindowsOptionalFeature(false, "MicrosoftWindowsPowerShellV2", "PowerShell v2", "PowerShellv2"); - ConfigureWindowsOptionalFeature(false, "MicrosoftWindowsPowerShellV2Root", "PowerShell v2 root", "PowerShellv2Engine"); - ConfigureWindowsOptionalFeature(false, "WorkFolders-Client", "Work Folders", "WorkFoldersClient"); - ConfigureWindowsOptionalFeature(false, "Printing-Foundation-InternetPrinting-Client", "Internet Printing Client", "InternetPrintingClient"); - ConfigureWindowsOptionalFeature(false, "Windows-Defender-ApplicationGuard", "Deprecated Microsoft Defender Application Guard (MDAG)", "MDAG"); - ConfigureWindowsOptionalFeature(true, "Containers-DisposableClientVM", "Windows Sandbox", "WindowsSandbox"); - ConfigureWindowsOptionalFeature(true, "Microsoft-Hyper-V", "Hyper-V", "HyperV"); + WindowsFeatureChecker.FeatureStatus FeaturesCheckResults = WindowsFeatureChecker.CheckWindowsFeatures(); + + ConfigureWindowsOptionalFeature(false, "MicrosoftWindowsPowerShellV2", "PowerShell v2", "PowerShellv2", FeaturesCheckResults); + ConfigureWindowsOptionalFeature(false, "MicrosoftWindowsPowerShellV2Root", "PowerShell v2 root", "PowerShellv2Engine", FeaturesCheckResults); + ConfigureWindowsOptionalFeature(false, "WorkFolders-Client", "Work Folders", "WorkFoldersClient", FeaturesCheckResults); + ConfigureWindowsOptionalFeature(false, "Printing-Foundation-InternetPrinting-Client", "Internet Printing Client", "InternetPrintingClient", FeaturesCheckResults); + ConfigureWindowsOptionalFeature(false, "Windows-Defender-ApplicationGuard", "Deprecated Microsoft Defender Application Guard (MDAG)", "MDAG", FeaturesCheckResults); + ConfigureWindowsOptionalFeature(true, "Containers-DisposableClientVM", "Windows Sandbox", "WindowsSandbox", FeaturesCheckResults); + ConfigureWindowsOptionalFeature(true, "Microsoft-Hyper-V", "Hyper-V", "HyperV", FeaturesCheckResults); RemoveCapability("Media.WindowsMediaPlayer", "The old Windows Media Player"); RemoveCapability("WMIC", "Deprecated WMIC"); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/SecBaselines_Overrides.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/SecBaselines_Overrides.cs index 15439cd6d..17971a73c 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/SecBaselines_Overrides.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/SecBaselines_Overrides.cs @@ -19,11 +19,6 @@ public static void SecBaselines_Overrides() throw new InvalidOperationException("The path to the Microsoft Security Baselines has not been set."); } - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - // Sleep for 1 second (1000 milliseconds) Thread.Sleep(1000); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity.cs index ebcd4cc0b..7fb2210a4 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity.cs @@ -8,10 +8,6 @@ public static partial class TLSSecurity { public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } ChangePSConsoleTitle.Set("🛡️ TLS"); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity_BattleNetClient.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity_BattleNetClient.cs index 61a84fc2c..6d1f8d527 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity_BattleNetClient.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/TLSSecurity_BattleNetClient.cs @@ -12,11 +12,6 @@ public static partial class TLSSecurity public static void TLSSecurity_BattleNetClient() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Adding (TLS_RSA_WITH_AES_256_CBC_SHA) cipher suite for the BattleNet Client", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "TLS Security", "For BattleNetClient", "registry.pol"), LGPORunner.FileType.POL); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_NoFastSwitching.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_NoFastSwitching.cs index 46c05fcad..0187f6079 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_NoFastSwitching.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_NoFastSwitching.cs @@ -1,4 +1,5 @@ using System; +using System.IO; namespace HardenWindowsSecurity; @@ -10,12 +11,8 @@ public static partial class UserAccountControl /// <exception cref="ArgumentNullException"></exception> public static void UAC_NoFastSwitching() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } Logger.LogMessage("Applying the Hide the entry points for Fast User Switching policy", LogTypeIntel.Information); - LGPORunner.RunLGPOCommand(System.IO.Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "User Account Control UAC Policies", "Hides the entry points for Fast User Switching", "registry.pol"), LGPORunner.FileType.POL); + LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "User Account Control UAC Policies", "Hides the entry points for Fast User Switching", "registry.pol"), LGPORunner.FileType.POL); } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_OnlyElevateSigned.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_OnlyElevateSigned.cs index 3a4a2c866..a2a243072 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_OnlyElevateSigned.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/UAC_OnlyElevateSigned.cs @@ -11,12 +11,9 @@ public static partial class UserAccountControl /// <exception cref="ArgumentNullException"></exception> public static void UAC_OnlyElevateSigned() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } Logger.LogMessage("Applying the Only elevate executables that are signed and validated policy", LogTypeIntel.Information); + LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "User Account Control UAC Policies", "Only elevate executables that are signed and validated", "GptTmpl.inf"), LGPORunner.FileType.INF); } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/UserAccountControl.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/UserAccountControl.cs index 9e1b12590..d6a6ee620 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/UserAccountControl.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/UserAccountControl.cs @@ -11,10 +11,6 @@ public static partial class UserAccountControl /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } ChangePSConsoleTitle.Set("💎 UAC"); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsFirewall.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsFirewall.cs index a8cf8ab09..f9358c0f4 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsFirewall.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsFirewall.cs @@ -15,10 +15,6 @@ public static class WindowsFirewall /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } ChangePSConsoleTitle.Set("🔥 Firewall"); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking.cs index f7ad40f1e..6c6a9148b 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking.cs @@ -11,10 +11,6 @@ public static partial class WindowsNetworking /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } ChangePSConsoleTitle.Set("📶 Networking"); diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking_BlockNTLM.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking_BlockNTLM.cs index af699e8e1..596a95478 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking_BlockNTLM.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsNetworking_BlockNTLM.cs @@ -12,14 +12,8 @@ public static partial class WindowsNetworking public static void WindowsNetworking_BlockNTLM() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - Logger.LogMessage("Blocking NTLM", LogTypeIntel.Information); LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Security-Baselines-X", "Windows Networking Policies", "Block NTLM", "registry.pol"), LGPORunner.FileType.POL); - } } diff --git a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsUpdateConfigurations.cs b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsUpdateConfigurations.cs index afded4c29..a868310a4 100644 --- a/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsUpdateConfigurations.cs +++ b/Harden-Windows-Security Module/Main files/C#/Protect Methods/WindowsUpdateConfigurations.cs @@ -11,11 +11,6 @@ public static class WindowsUpdateConfigurations /// <exception cref="ArgumentNullException"></exception> public static void Invoke() { - if (GlobalVars.path is null) - { - throw new ArgumentNullException("GlobalVars.path cannot be null."); - } - ChangePSConsoleTitle.Set("🪟 Windows Update"); Logger.LogMessage("Running the Windows Update category", LogTypeIntel.Information); diff --git a/Harden-Windows-Security Module/Main files/C#/Unprotect Methods/UnprotectWindowsSecurity.cs b/Harden-Windows-Security Module/Main files/C#/Unprotect Methods/UnprotectWindowsSecurity.cs index f45f28b15..da7b5d28a 100644 --- a/Harden-Windows-Security Module/Main files/C#/Unprotect Methods/UnprotectWindowsSecurity.cs +++ b/Harden-Windows-Security Module/Main files/C#/Unprotect Methods/UnprotectWindowsSecurity.cs @@ -81,7 +81,7 @@ public static void Unprotect() } // Apply the default security policy on the system - LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path!, "Resources", "Default Security Policy.inf"), LGPORunner.FileType.INF, Path.Combine(GlobalVars.WorkingDir, "LGPO_30", "LGPO.exe")); + LGPORunner.RunLGPOCommand(Path.Combine(GlobalVars.path, "Resources", "Default Security Policy.inf"), LGPORunner.FileType.INF, Path.Combine(GlobalVars.WorkingDir, "LGPO_30", "LGPO.exe")); #endregion diff --git a/Harden-Windows-Security Module/Main files/C#/Windows APIs/FirmwareType.cs b/Harden-Windows-Security Module/Main files/C#/Windows APIs/FirmwareType.cs index 27eb703c7..7ad668047 100644 --- a/Harden-Windows-Security Module/Main files/C#/Windows APIs/FirmwareType.cs +++ b/Harden-Windows-Security Module/Main files/C#/Windows APIs/FirmwareType.cs @@ -1,13 +1,7 @@ -using System.Runtime.InteropServices; - namespace HardenWindowsSecurity; internal static class FirmwareChecker { - // https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfirmwaretype - [DllImport(dllName: "kernel32.dll", SetLastError = true)] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - private static extern bool GetFirmwareType(out FirmwareType firmwareType); // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-firmware_type internal enum FirmwareType @@ -21,7 +15,7 @@ internal enum FirmwareType // Check the firmware type internal static FirmwareType CheckFirmwareType() { - if (GetFirmwareType(out FirmwareType firmwareType)) + if (NativeMethods.GetFirmwareType(out FirmwareType firmwareType)) { return firmwareType; } diff --git a/Harden-Windows-Security Module/Main files/C#/Windows APIs/TPM.cs b/Harden-Windows-Security Module/Main files/C#/Windows APIs/TPM.cs index f261c96f2..30abbfb0e 100644 --- a/Harden-Windows-Security Module/Main files/C#/Windows APIs/TPM.cs +++ b/Harden-Windows-Security Module/Main files/C#/Windows APIs/TPM.cs @@ -2,7 +2,6 @@ using System.Globalization; using System.Linq; using System.Management; -using System.Runtime.InteropServices; namespace HardenWindowsSecurity; @@ -27,7 +26,7 @@ public static TpmResult Get() string? errorMessage = null; // Call TpmIsEnabled and check result - uint result = TpmCoreProvisioningFunctions.TpmIsEnabled(out byte isEnabledByte); + uint result = NativeMethods.TpmIsEnabled(out byte isEnabledByte); if (result == 0) { isEnabled = isEnabledByte != 0; @@ -38,7 +37,7 @@ public static TpmResult Get() } // Call TpmIsActivated and check result - result = TpmCoreProvisioningFunctions.TpmIsActivated(out byte isActivatedByte); + result = NativeMethods.TpmIsActivated(out byte isActivatedByte); if (result == 0) { isActivated = isActivatedByte != 0; @@ -52,20 +51,6 @@ public static TpmResult Get() } - // Class that imports TpmCoreProvisioning.dll and use its exported functions - private static class TpmCoreProvisioningFunctions - { - [DllImport("TpmCoreProvisioning", CharSet = CharSet.Unicode)] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - internal static extern uint TpmIsEnabled(out byte pfIsEnabled); - - [DllImport("TpmCoreProvisioning", CharSet = CharSet.Unicode)] - [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] - internal static extern uint TpmIsActivated(out byte pfIsActivated); - } - - - /// <summary> /// Checks TPM status by invoking WMI methods to determine if it's enabled and activated. /// </summary> diff --git a/Harden-Windows-Security Module/Main files/Harden-Windows-Security-Module.psm1 b/Harden-Windows-Security Module/Main files/Harden-Windows-Security-Module.psm1 index dba9c6885..05346aeb7 100644 --- a/Harden-Windows-Security Module/Main files/Harden-Windows-Security-Module.psm1 +++ b/Harden-Windows-Security Module/Main files/Harden-Windows-Security-Module.psm1 @@ -91,7 +91,7 @@ $ToastNotificationDLLs.Add([System.IO.Path]::Combine($PSScriptRoot, 'DLLs', 'Toa $ToastNotificationDLLs.Add([System.IO.Path]::Combine($PSScriptRoot, 'DLLs', 'Toast Notifications', 'System.Drawing.Common.dll')) $ToastNotificationDLLs.Add([System.IO.Path]::Combine($PSScriptRoot, 'DLLs', 'Toast Notifications', 'WinRT.Runtime.dll')) -# Load all of the C# codes +# Compile all of the C# codes # for some reason it tries to use another version of the WindowsBase.dll unless i define its path explicitly like this # https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/ Add-Type -Path ([System.IO.Directory]::GetFiles("$PSScriptRoot\C#", '*.*', [System.IO.SearchOption]::AllDirectories)) -ReferencedAssemblies @((Get-Content -Path "$PSScriptRoot\.NETAssembliesToLoad.txt") + "$($PSHOME)\WindowsBase.dll" + $ToastNotificationDLLs) -CompilerOptions '/langversion:preview', '/nowarn:1701', '/nullable:enable', '/checked' diff --git a/Harden-Windows-Security Module/Main files/Resources/Media/OptionalFeaturesMenuButtonIcon.png b/Harden-Windows-Security Module/Main files/Resources/Media/OptionalFeaturesMenuButtonIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..4391dc0ca7a880b8a8b157a1b1f006b82a8b3209 GIT binary patch literal 1752 zcmV;}1}FK6P)<h;3K|Lk000e1NJLTq003kF003kN1^@s6aN?Cz00009a7bBm000XU z000XU0RWnu7ytkUib+I4RCt{2om;3?MHt7IoiZymJ8Bo~W_QZyq80ek1$*crsUAua z3XdWpMYjhlDhi3}!3-*uiiDz<ph74zx=>k}6<wh)=vZbqGgC|La*n?knPbb@-&%XE zwP#)STHo*KoV{nw`ey$7n{U3E*=q-Zq9_dp*azqX?gS>3ZBL^C4g{X#e|`W?DBG?^ z0*nLRp_TQ(F=gA=D1g&|bwu+uaCq5v)?xTr2rL6mj43w_*g|_g0mc;Dikbi%1iT&U z%wK_%g>rL%e}v9|30Nw;{;sLJoK|(WXS^YF=J&u+w#+c#?g&qK4A|F}c|v&qHDE;9 z?d%GG1Ay0KhMg}=EC8Mn-WvcGIQ8`a&kAK%7}3gWY4?cnD(%@Jy!IzBJ)++IfmeiU zo;Ep4@h$BFfDsX$W~Q+(wh_qW8fPbnNz#;fi5c30rUA^efjJHD1EXzBF@H;Z3LKfx zhJ%5R$&cTGtAi>7jEorX+woC&ifWU-wL-ZYQ`$2g_>%nC3iJk51UL!!JVT>C1I7yV zO$2@t0{P`B?V14elOK-;RRg#zVY24(6>wNgy{8NHnjk+lrG3ZS*pml?z_~#cu=D@> zV}_xLHb0P(wza?!3GQ(b@RxJ#CMj`jQ_m!Oo$GN|w7G7U?esW4D18QJk~Uy<gn<tO z!>t(0vWhVTa1F4_spFeC?~(w{vE#n$aTi3C?-Rr@|1TEonH`h`a3S!s(9wSYGi;e* zRv4FWv#iDfw?%m2$dvU=wRudKZNQWSo?%3oXWw7$ythe;g}Guod4Y9xDIQD;m3<&$ zX?$V__kT#J(`5R?Q`U2_FbtY$`l(68uw}*yLtt?M-Wu>SGEapU@qk4UVjS0@4L#0= z)DX+lCVaq^!Ut=E^+aiy>J#di@02t3P41+PNsXTzF?BSbvKyST_X_3A@OFyFEI+(5 zJjB8bbzLjO0^&SF*gjt4l>ac-01wOs{uT`V4mi&#YxXl-ei<4Hd||V2lfSrJm!Yof zvxpJ8ev05xvy0BUSGb!$z&%2_jb?YxyK%wp`yFkE7<b5+o}sSi1>418D&l&x1>nY` z-XgN@0lP1;mrDY7MXdEqE?_Hnb0>*ok^r8dj$UEyZb{~bCCs|b&@)Xae~VCdi#v_X z3*h{$iK7oOoT1%c2Hz&@ep5>1fSZJ}TZ>*w0Im``wm<HmgHJI+0e-cY03VZe@3OO| z9^smsh4S0dt~2=}!XA@2j!Kb%_j#C&4s;aY?GR<g`zABksTiUDG@D@A0=%6`x!GpZ z81yBE?bAc->@v*Kq!-^>QYTc27kr7~#HVx_y!8%O$tE%YoR!0x-&?5yJaD^YT~Ko< zXg|YluKnxWXHHb%QBkoYs5wN_m&3i>6@dO!-qCPDHu_xdh{$t(lnRcHn^^_T6(sp= zD4Q7O|Cv(ZJBT5uIplm`A=L_i^^V_EkiBqEIIhVW;A1>Pj!%Mjv}EW(&7qYuh2@U9 zMTjAJN6QiapynX77kI>Z+4R%66m_OwsI=cwb-m+Q--6h~4Lk8qKX8c$`&!y-Hrwp> zLYT*M@r=-xr@N7}&i9aI-9Jw@bYh>iQEacU+%f2GQF{?1W=Bt?!Ga6}-V>JZTecoL z6=O`A<#i7Yz7N<=7Y$iMm^CdSz|Y@Ppi?pI#ZlkQ6A5Y#ZQ5%NyE#S7P=BbmoyM3I zUE?)6%SyJN@uat%Mj@CF39<Vak9tTew&Pt7SR8Q*zAwuGfX!C*JwhaP;krSB_C^GF zkx~q-6C`Y}`C@6rp>h?(CuurVIIy6Clq`rF;9FuysRq^oQnuH8yUON3=20IrR1nW} z+Mz0lXH<}ifqF=_Kn1B5s36q>6{K3Af>aAskZOSnQY}zHss$=YwLk@_7N{Wg5d`6w zQ>6^-M#$J+`!u9=zR!tyGq77BLwoH*70e^cU1nCozy=DkND$+}${5(qkg~nzVab9R ztAPC~VPLmIiuM9$2*+a0bHc_~!oWH}!uHxnE}18vhS{0>Q;t-S$Y(pQ6o#r<LEfk! zB?ocg<~n4R8N^*wkdlMAiwaV55O+~Qf^vhn3bHq)2XPgog>r+q3ev)M;ny3A3*stB zEX4<L6(pA8gSZM3NjX8hogfWmRcS%orR<)l0L5nF?XX|fYAQS0{fukjnCFMspCf7- u>w!zl?tev56h%=KMNt$*Q4~c9D$0Kj;RW<y??!n50000<MNUMnLSTZ0N;`xA literal 0 HcmV?d00001 diff --git a/Harden-Windows-Security Module/Main files/Resources/SafeToRemoveAppsList.json b/Harden-Windows-Security Module/Main files/Resources/SafeToRemoveAppsList.json new file mode 100644 index 000000000..fc5f67a36 --- /dev/null +++ b/Harden-Windows-Security Module/Main files/Resources/SafeToRemoveAppsList.json @@ -0,0 +1,152 @@ +{ + "SafeToRemoveAppsList": [ + { + "Name": "MicrosoftCorporationII.QuickAssist", + "Description": "Quick Assist" + }, + { + "Name": "Microsoft.XboxSpeechToTextOverlay", + "Description": "Speech-to-text overlay for Xbox" + }, + { + "Name": "Microsoft.Windows.DevHome", + "Description": "DevHome App" + }, + { + "Name": "Microsoft.OutlookForWindows", + "Description": "Outlook for Windows" + }, + { + "Name": "Microsoft.Xbox.TCUI", + "Description": "Xbox game connection feature" + }, + { + "Name": "Microsoft.Todos", + "Description": "Microsoft To Do" + }, + { + "Name": "Microsoft.BingNews", + "Description": "News App" + }, + { + "Name": "Clipchamp.Clipchamp", + "Description": "ClipChamp Video Editor" + }, + { + "Name": "Microsoft.GetHelp", + "Description": "Get Help App" + }, + { + "Name": "Microsoft.WindowsTerminal", + "Description": "Windows Terminal" + }, + { + "Name": "Microsoft.BingSearch", + "Description": "Microsoft Bing Search" + }, + { + "Name": "Microsoft.StorePurchaseApp", + "Description": "Microsoft Store Purchase App" + }, + { + "Name": "Microsoft.WindowsFeedbackHub", + "Description": "Feedback Hub" + }, + { + "Name": "Microsoft.XboxGamingOverlay", + "Description": "Xbox Game Overlay" + }, + { + "Name": "Microsoft.WindowsCamera", + "Description": "Camera App" + }, + { + "Name": "Microsoft.WindowsCalculator", + "Description": "Calculator App" + }, + { + "Name": "Microsoft.GamingApp", + "Description": "Xbox App" + }, + { + "Name": "Microsoft.ZuneMusic", + "Description": "Music App" + }, + { + "Name": "Microsoft.WindowsAlarms", + "Description": "Alarm App" + }, + { + "Name": "Microsoft.PowerAutomateDesktop", + "Description": "Power Automate" + }, + { + "Name": "Microsoft.BingWeather", + "Description": "Weather App" + }, + { + "Name": "Microsoft.ScreenSketch", + "Description": "Snipping Tool" + }, + { + "Name": "Microsoft.WindowsNotepad", + "Description": "Notepad" + }, + { + "Name": "Microsoft.XboxIdentityProvider", + "Description": "Xbox Identity Provider" + }, + { + "Name": "Microsoft.Paint", + "Description": "Paint App" + }, + { + "Name": "Microsoft.Windows.Photos", + "Description": "Photos App" + }, + { + "Name": "Microsoft.Copilot", + "Description": "Copilot App" + }, + { + "Name": "Microsoft.MicrosoftStickyNotes", + "Description": "Sticky Notes" + }, + { + "Name": "MicrosoftWindows.WindowsSandbox", + "Description": "Windows Sandbox" + }, + { + "Name": "MSTeams", + "Description": "Microsoft Teams" + }, + { + "Name": "Microsoft.Winget.Source", + "Description": "Winget App" + }, + { + "Name": "MicrosoftWindows.CrossDevice", + "Description": "Cross Device App" + }, + { + "Name": "Microsoft.YourPhone", + "Description": "Your Phone App" + }, + { + "Name": "Microsoft.WindowsSoundRecorder", + "Description": "Sound Recorder App" + }, + { + "Name": "Microsoft.MicrosoftSolitaireCollection", + "Description": "Microsoft Solitaire Collection Game" + }, + { + "Name": "Microsoft.MicrosoftOfficeHub", + "Description": "Office App" + }, + { + "Name": "Microsoft.OneDriveSync", + "Description": "OneDrive Sync" + } + ] +} \ No newline at end of file diff --git a/Harden-Windows-Security Module/Main files/Resources/XAML/ASRRules.xaml b/Harden-Windows-Security Module/Main files/Resources/XAML/ASRRules.xaml index 83811f412..7f6a71915 100644 --- a/Harden-Windows-Security Module/Main files/Resources/XAML/ASRRules.xaml +++ b/Harden-Windows-Security Module/Main files/Resources/XAML/ASRRules.xaml @@ -290,305 +290,21 @@ </ListViewItem> </ListView> - <Button x:Name="RetrieveASRStatus" Style="{StaticResource CustomButtonStyle2}" Margin="12,0,5,0" Grid.Row="1" Grid.ColumnSpan="1" Grid.Column="1" ToolTipService.InitialShowDelay="1000" ToolTip="Using this button will retrieve the latest effective status of each Attack Surface Reduction rule on the system and will populate the combo boxes for you."> - <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> - <TextBlock Text="Retrieve ASR Status" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="Normal"/> - </StackPanel> - </Button> + <StackPanel Orientation="Horizontal" Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Center"> + + <Button x:Name="ApplyASRRulesButton" Style="{StaticResource CustomButtonStyle2}" Margin="15,0,10,0" ToolTipService.InitialShowDelay="1000" ToolTip="Apply the configured Attack Surface Reduction Rules"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Apply ASR Rules" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> + + <Button x:Name="RetrieveASRStatus" Style="{StaticResource CustomButtonStyle2}" Margin="10,0,15,0" ToolTipService.InitialShowDelay="1000" ToolTip="Using this button will retrieve the latest effective status of each Attack Surface Reduction rule on the system and will populate the combo boxes for you."> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Retrieve ASR Status" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> + + </StackPanel> - <!-- Grid containing the Execute Button --> - <Grid x:Name="ExecuteButtonGrid" Height="150" Grid.Row="1" Grid.ColumnSpan="1" Grid.Column="0" Margin="0,0,0,0"> - <!-- First Ellipse (Forward1) - Represents the outermost expanding ellipse when the button is clicked --> - <!-- Initial height and Width of the Ellipse --> - <Ellipse x:Name="EclipseForward1" - Height="50" - Width="50" - HorizontalAlignment="Center" - VerticalAlignment="Center"> - <!-- Ellipse Fill with a gradient from #ED4264 to #cbad6d --> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Second Ellipse (Forward2) - Another expanding ellipse, but starts later than Forward1 --> - <Ellipse x:Name="EclipseForward2" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Third Ellipse (Forward3) - Another expanding ellipse, starts even later --> - <Ellipse x:Name="EclipseForward3" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- First Ellipse (Backward1) - Represents the outermost contracting ellipse when the button is unchecked --> - <Ellipse x:Name="EclipseBackward1" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <!-- Ellipse Fill with a gradient from #ef32d9 to #89fffd --> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Second Ellipse (Backward2) - Another contracting ellipse, starts later than Backward1 --> - <Ellipse x:Name="EclipseBackward2" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Third Ellipse (Backward3) - Another contracting ellipse, starts even later --> - <Ellipse x:Name="EclipseBackward3" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Refresh Toggle Button - The main button in the center --> - <ToggleButton x:Name="ExecuteButton" - Height="55" - Width="55" - HorizontalAlignment="Center" - VerticalAlignment="Center" > - <ToggleButton.Template> - <ControlTemplate TargetType="ToggleButton"> - <!-- Border around the button with rounded corners --> - <Border x:Name="border" - Background="Transparent" - CornerRadius="30"> - <Grid x:Name="RefreshButtonIconImageGrid"> - <!-- Button icon image centered inside the button --> - <Image x:Name="RefreshIconImage" Source="icon.png" - Stretch="None" HorizontalAlignment="Center" VerticalAlignment="Center" /> - </Grid> - </Border> - <!-- Triggers for visual states (hover, checked) --> - <ControlTemplate.Triggers> - <!-- Mouse hover trigger --> - <Trigger Property="IsMouseOver" Value="True"> - <Setter Property="Background" TargetName="border"> - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </Trigger> - <!-- Button checked trigger --> - <Trigger Property="IsChecked" Value="True"> - <Setter Property="Background" TargetName="border"> - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </Trigger> - <!-- MultiTrigger: Hovering while the button is unchecked --> - <MultiTrigger> - <MultiTrigger.Conditions> - <Condition Property="IsMouseOver" Value="True" /> - <Condition Property="IsChecked" Value="False" /> - </MultiTrigger.Conditions> - <Setter Property="Background" TargetName="border"> - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </MultiTrigger> - </ControlTemplate.Triggers> - </ControlTemplate> - </ToggleButton.Template> - <!-- Triggers for button actions (Checked, Unchecked) --> - <ToggleButton.Triggers> - <!-- When the button is checked (clicked) --> - <EventTrigger RoutedEvent="ToggleButton.Checked"> - <EventTrigger.Actions> - <!-- Start the forward expanding animations --> - <BeginStoryboard x:Name="Ellipse_Activated"> - <Storyboard> - <!-- Forward1 Animation (Expanding and fading out) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseForward1" - RepeatBehavior="Forever" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseForward1" - RepeatBehavior="Forever" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseForward1" - From="1.0" - To="0.0" - BeginTime="00:00:00" - Duration="00:00:01.5" - RepeatBehavior="Forever" /> - <!-- Forward2 Animation (Starts 1 second later) --> - <DoubleAnimation BeginTime="00:00:00.5" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseForward2" - RepeatBehavior="Forever" /> - <DoubleAnimation BeginTime="00:00:00.5" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseForward2" - RepeatBehavior="Forever" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseForward2" - From="1.0" - To="0.0" - BeginTime="00:00:00.5" - Duration="00:00:01.5" - RepeatBehavior="Forever" /> - <!-- Forward3 Animation (Starts 2 seconds later) --> - <DoubleAnimation BeginTime="00:00:01" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseForward3" - RepeatBehavior="Forever" /> - <DoubleAnimation BeginTime="00:00:01" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseForward3" - RepeatBehavior="Forever" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseForward3" - From="1.0" - To="0.0" - BeginTime="00:00:01" - Duration="00:00:01.5" - RepeatBehavior="Forever" /> - </Storyboard> - </BeginStoryboard> - </EventTrigger.Actions> - </EventTrigger> - <!-- When the button is unchecked --> - <EventTrigger RoutedEvent="ToggleButton.Unchecked"> - <EventTrigger.Actions> - <!-- Stop the forward animation --> - <RemoveStoryboard BeginStoryboardName="Ellipse_Activated" /> - <!-- Start the backward contracting animations --> - <BeginStoryboard x:Name="Ellipse_Deactivated"> - <Storyboard> - <!-- Backward1 Animation (Contracting and fading in) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="150" - To="50" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseBackward1" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="150" - To="50" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseBackward1" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseBackward1" - From="0.0" - To="1.0" - BeginTime="00:00:00" - Duration="00:00:01.5" /> - <!-- Backward2 Animation (Starts 1 second later) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01" - From="125" - To="50" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseBackward2" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01" - From="125" - To="50" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseBackward2" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseBackward2" - From="0.0" - To="1.0" - BeginTime="00:00:00" - Duration="00:00:01" /> - <!-- Backward3 Animation (Starts 2 seconds later) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:00.5" - From="100" - To="50" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseBackward3" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:00.5" - From="100" - To="50" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseBackward3" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseBackward3" - From="0.0" - To="1.0" - BeginTime="00:00:00" - Duration="00:00:00.5" /> - </Storyboard> - </BeginStoryboard> - </EventTrigger.Actions> - </EventTrigger> - </ToggleButton.Triggers> - </ToggleButton> - </Grid> - <!--End of Refresh Button Grid--> </Grid> </UserControl> \ No newline at end of file diff --git a/Harden-Windows-Security Module/Main files/Resources/XAML/Main.xaml b/Harden-Windows-Security Module/Main files/Resources/XAML/Main.xaml index eb880f698..1d54b3f4f 100644 --- a/Harden-Windows-Security Module/Main files/Resources/XAML/Main.xaml +++ b/Harden-Windows-Security Module/Main files/Resources/XAML/Main.xaml @@ -84,6 +84,13 @@ <TextBlock Text='BitLocker' Style='{StaticResource Text_Style}' /> </Grid> </RadioButton> + <!-- OptionalFeatures --> + <RadioButton Style='{StaticResource BtnStyle}' Command='{Binding OptionalFeaturesCommand}'> + <Grid x:Name="OptionalFeaturesButtonGrid"> + <Image x:Name="OptionalFeaturesButtonIcon" Style="{StaticResource Image_Style}" /> + <TextBlock Text='Apps | Features' Style='{StaticResource Text_Style}' /> + </Grid> + </RadioButton> <!-- Logs --> <RadioButton Style='{StaticResource BtnStyle}' Command='{Binding LogsCommand}'> <Grid x:Name="LogsButtonGrid"> diff --git a/Harden-Windows-Security Module/Main files/Resources/XAML/OptionalFeatures.xaml b/Harden-Windows-Security Module/Main files/Resources/XAML/OptionalFeatures.xaml new file mode 100644 index 000000000..50e930ae8 --- /dev/null +++ b/Harden-Windows-Security Module/Main files/Resources/XAML/OptionalFeatures.xaml @@ -0,0 +1,141 @@ +<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="Trebuchet MS" FontSize="16" Style="{StaticResource Page_Style}"> + <Grid x:Name="ParentGrid"> + <Grid.RowDefinitions> + <RowDefinition Height="3*" /> + <RowDefinition Height="*" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="*" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + + <Grid Grid.Row="0" Margin="10" Grid.Column="0" Grid.ColumnSpan="1"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <CheckBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="1" Content="Select All" VerticalContentAlignment="Center" Margin="7,0,0,2" Padding="10,10,40,10" x:Name="SelectAllOptionalFeatures" Template="{StaticResource CustomCheckBoxTemplate}"/> + <!-- ListViews for Optional Features --> + <ListView x:Name="OptionalFeatures" BorderThickness="0" ToolTip="Select the optional features to add and remove" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" VirtualizingPanel.ScrollUnit="Pixel" ScrollViewer.PanningMode="Both"> + <!-- Background color for the ListView --> + <ListView.Background> + <SolidColorBrush Color="transparent"/> + </ListView.Background> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove PowerShell v2"> + <CheckBox x:Name="RemovePowerShellV2" Content="Remove PowerShell v2" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}" /> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Work Folders"> + <CheckBox x:Name="RemoveWorkFolders" Content="Remove Work Folders" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Internet Printing Client"> + <CheckBox x:Name="RemoveInternetPrintingClient" Content="Remove Internet Printing Client" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Legacy Windows Media Player"> + <CheckBox x:Name="RemoveLegacyWindowsMediaPlayer" Content="Remove Legacy Windows Media Player" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Microsoft Defender Application Guard"> + <CheckBox x:Name="RemoveMicrosoftDefenderApplicationGuard" Content="Remove Microsoft Defender Application Guard" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Legacy Notepad"> + <CheckBox x:Name="RemoveLegacyNotepad" Content="Remove Legacy Notepad" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove VBSCRIPT"> + <CheckBox x:Name="RemoveVBSCRIPT" Content="Remove VBSCRIPT" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Internet Explorer Mode For Edge"> + <CheckBox x:Name="RemoveInternetExplorerModeForEdge" Content="Remove Internet Explorer Mode For Edge" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove WMIC, unsafe and deprecated"> + <CheckBox x:Name="RemoveWMIC" Content="Remove WMIC" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove WordPad, it's deprecated"> + <CheckBox x:Name="RemoveWordPad" Content="Remove WordPad" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove PowerShell ISE"> + <CheckBox x:Name="RemovePowerShellISE" Content="Remove PowerShell ISE" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Steps Recorder"> + <CheckBox x:Name="RemoveStepsRecorder" Content="Remove Steps Recorder" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Math Recognizer if you don't need it"> + <CheckBox x:Name="RemoveMathRecognizer" Content="Remove Math Recognizer" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Print Management if you don't use printers"> + <CheckBox x:Name="RemovePrintManagement" Content="Remove Print Management" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove OpenSSH Client if you don't use SSH"> + <CheckBox x:Name="RemoveOpenSSHClient" Content="Remove OpenSSH Client" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Facial Recognition if your device doesn't have a webcam and you do not use Windows Hello facial recognition for login"> + <CheckBox x:Name="RemoveFacialRecognition" Content="Remove Facial Recognition" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Remove Extended Theme Content"> + <CheckBox x:Name="RemoveExtendedThemeContent" Content="Remove Extended Theme Content" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Enable Windows Sandbox - Great feature for testing unsafe software or temporarily installing a program"> + <CheckBox x:Name="EnableWindowsSandbox" Content="Enable Windows Sandbox" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + <ListViewItem ToolTipService.InitialShowDelay="1000" ToolTip="Enable Hyper-V"> + <CheckBox x:Name="EnableHyperV" Content="Enable Hyper-V" VerticalContentAlignment="Center" Padding="10,10,40,10" Template="{StaticResource CustomCheckBoxTemplate}"/> + </ListViewItem> + </ListView> + </Grid> + + + <StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" HorizontalAlignment="Center"> + + <Button x:Name="RetrieveOptionalFeaturesStatus" Style="{StaticResource CustomButtonStyle2}" Margin="0,0,0,10" ToolTipService.InitialShowDelay="1000" ToolTip="Using this button will retrieve the latest status of the optional features displayed in this page"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Retrieve Optional Features Status" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> + + <Button x:Name="ApplyOptionalFeaturesButton" Style="{StaticResource CustomButtonStyle2}" ToolTipService.InitialShowDelay="1000" ToolTip="Apply the selected optional features"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Apply Optional Features" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> + + </StackPanel> + + + + + <Grid Grid.Row="0" Margin="10" Grid.Column="1" Grid.ColumnSpan="1"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="*"/> + </Grid.RowDefinitions> + <CheckBox Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="1" Content="Select All" VerticalContentAlignment="Center" Margin="7,0,0,2" Padding="10,10,40,10" x:Name="SelectAllApps" Template="{StaticResource CustomCheckBoxTemplate}"/> + <!-- ListViews for Optional Features --> + <ListView x:Name="Apps" BorderThickness="0" ToolTip="Select the optional features to add and remove" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="1" VirtualizingPanel.ScrollUnit="Pixel" ScrollViewer.PanningMode="Both"> + <!-- Background color for the ListView --> + <ListView.Background> + <SolidColorBrush Color="transparent"/> + </ListView.Background> + </ListView> + </Grid> + + + <StackPanel Orientation="Vertical" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1" HorizontalAlignment="Center"> + + <Button x:Name="RetrieveRemovableApps" Style="{StaticResource CustomButtonStyle2}" Margin="0,0,0,10" ToolTipService.InitialShowDelay="1000" ToolTip="Using this button will retrieve the latest status of the optional features displayed in this page"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Retrieve Removable Apps" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> + + <Button x:Name="RemoveApps" Style="{StaticResource CustomButtonStyle2}" ToolTipService.InitialShowDelay="1000" ToolTip="Apply the selected optional features"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Remove Apps For All Users" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> + + </StackPanel> + + + </Grid> +</UserControl> \ No newline at end of file diff --git a/Harden-Windows-Security Module/Main files/Resources/XAML/Protect.xaml b/Harden-Windows-Security Module/Main files/Resources/XAML/Protect.xaml index 6d2a6958d..5bd981505 100644 --- a/Harden-Windows-Security Module/Main files/Resources/XAML/Protect.xaml +++ b/Harden-Windows-Security Module/Main files/Resources/XAML/Protect.xaml @@ -2,7 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - Style="{StaticResource Page_Style}" Background="Transparent" FontFamily="Trebuchet MS" FontSize="16" + Style="{StaticResource Page_Style}" Background="Transparent" FontFamily="Trebuchet MS" FontSize="16" ToolTipService.InitialShowDelay="1000" ToolTipService.ShowDuration="2147483647" ToolTipService.BetweenShowDelay="1000" diff --git a/Harden-Windows-Security Module/Main files/Resources/XAML/Unprotect.xaml b/Harden-Windows-Security Module/Main files/Resources/XAML/Unprotect.xaml index 708254386..3c75b8398 100644 --- a/Harden-Windows-Security Module/Main files/Resources/XAML/Unprotect.xaml +++ b/Harden-Windows-Security Module/Main files/Resources/XAML/Unprotect.xaml @@ -8,15 +8,10 @@ <Grid x:Name="ParentGrid"> <!-- Define the rows for the Grid --> <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - - <RowDefinition Height="150" /> - + <RowDefinition Height="100" /> <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <!-- Define the columns for the middle row --> @@ -55,301 +50,11 @@ ItemContainerStyle="{StaticResource ModernComboBoxItemStyle}" </ComboBox> </StackPanel> - <!-- Grid containing the Execute Button --> - <Grid x:Name="ExecuteButtonGrid" Height="150" Grid.Row="2" Grid.ColumnSpan="2" Margin="0,0,0,0"> - <!-- First Ellipse (Forward1) - Represents the outermost expanding ellipse when the button is clicked --> - <!-- Initial height and Width of the Ellipse --> - <Ellipse x:Name="EclipseForward1" - Height="50" - Width="50" - HorizontalAlignment="Center" - VerticalAlignment="Center"> - <!-- Ellipse Fill with a gradient from #ED4264 to #cbad6d --> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Second Ellipse (Forward2) - Another expanding ellipse, but starts later than Forward1 --> - <Ellipse x:Name="EclipseForward2" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Third Ellipse (Forward3) - Another expanding ellipse, starts even later --> - <Ellipse x:Name="EclipseForward3" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- First Ellipse (Backward1) - Represents the outermost contracting ellipse when the button is unchecked --> - <Ellipse x:Name="EclipseBackward1" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <!-- Ellipse Fill with a gradient from #ef32d9 to #89fffd --> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Second Ellipse (Backward2) - Another contracting ellipse, starts later than Backward1 --> - <Ellipse x:Name="EclipseBackward2" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Third Ellipse (Backward3) - Another contracting ellipse, starts even later --> - <Ellipse x:Name="EclipseBackward3" -Height="50" -Width="50" -HorizontalAlignment="Center" -VerticalAlignment="Center"> - <Ellipse.Fill> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Ellipse.Fill> - </Ellipse> - <!-- Refresh Toggle Button - The main button in the center --> - <ToggleButton x:Name="ExecuteButton" - Height="55" - Width="55" - HorizontalAlignment="Center" - VerticalAlignment="Center" > - <ToggleButton.Template> - <ControlTemplate TargetType="ToggleButton"> - <!-- Border around the button with rounded corners --> - <Border x:Name="border" - Background="Transparent" - CornerRadius="30"> - <Grid x:Name="RefreshButtonIconImageGrid"> - <!-- Button icon image centered inside the button --> - <Image x:Name="RefreshIconImage" Source="icon.png" - Stretch="None" HorizontalAlignment="Center" VerticalAlignment="Center" /> - </Grid> - </Border> - <!-- Triggers for visual states (hover, checked) --> - <ControlTemplate.Triggers> - <!-- Mouse hover trigger --> - <Trigger Property="IsMouseOver" Value="True"> - <Setter Property="Background" TargetName="border"> - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </Trigger> - <!-- Button checked trigger --> - <Trigger Property="IsChecked" Value="True"> - <Setter Property="Background" TargetName="border"> - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ED4264" Offset="0.0" /> - <GradientStop Color="#cbad6d" Offset="1.0" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </Trigger> - <!-- MultiTrigger: Hovering while the button is unchecked --> - <MultiTrigger> - <MultiTrigger.Conditions> - <Condition Property="IsMouseOver" Value="True" /> - <Condition Property="IsChecked" Value="False" /> - </MultiTrigger.Conditions> - <Setter Property="Background" TargetName="border"> - <Setter.Value> - <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> - <GradientStop Color="#ef32d9" Offset="0.0" /> - <GradientStop Color="#89fffd" Offset="1.0" /> - </LinearGradientBrush> - </Setter.Value> - </Setter> - </MultiTrigger> - </ControlTemplate.Triggers> - </ControlTemplate> - </ToggleButton.Template> - <!-- Triggers for button actions (Checked, Unchecked) --> - <ToggleButton.Triggers> - <!-- When the button is checked (clicked) --> - <EventTrigger RoutedEvent="ToggleButton.Checked"> - <EventTrigger.Actions> - <!-- Start the forward expanding animations --> - <BeginStoryboard x:Name="Ellipse_Activated"> - <Storyboard> - <!-- Forward1 Animation (Expanding and fading out) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseForward1" - RepeatBehavior="Forever" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseForward1" - RepeatBehavior="Forever" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseForward1" - From="1.0" - To="0.0" - BeginTime="00:00:00" - Duration="00:00:01.5" - RepeatBehavior="Forever" /> - <!-- Forward2 Animation (Starts 1 second later) --> - <DoubleAnimation BeginTime="00:00:00.5" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseForward2" - RepeatBehavior="Forever" /> - <DoubleAnimation BeginTime="00:00:00.5" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseForward2" - RepeatBehavior="Forever" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseForward2" - From="1.0" - To="0.0" - BeginTime="00:00:00.5" - Duration="00:00:01.5" - RepeatBehavior="Forever" /> - <!-- Forward3 Animation (Starts 2 seconds later) --> - <DoubleAnimation BeginTime="00:00:01" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseForward3" - RepeatBehavior="Forever" /> - <DoubleAnimation BeginTime="00:00:01" - Duration="00:00:01.5" - From="50" - To="150" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseForward3" - RepeatBehavior="Forever" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseForward3" - From="1.0" - To="0.0" - BeginTime="00:00:01" - Duration="00:00:01.5" - RepeatBehavior="Forever" /> - </Storyboard> - </BeginStoryboard> - </EventTrigger.Actions> - </EventTrigger> - <!-- When the button is unchecked --> - <EventTrigger RoutedEvent="ToggleButton.Unchecked"> - <EventTrigger.Actions> - <!-- Stop the forward animation --> - <RemoveStoryboard BeginStoryboardName="Ellipse_Activated" /> - <!-- Start the backward contracting animations --> - <BeginStoryboard x:Name="Ellipse_Deactivated"> - <Storyboard> - <!-- Backward1 Animation (Contracting and fading in) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="150" - To="50" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseBackward1" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01.5" - From="150" - To="50" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseBackward1" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseBackward1" - From="0.0" - To="1.0" - BeginTime="00:00:00" - Duration="00:00:01.5" /> - <!-- Backward2 Animation (Starts 1 second later) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01" - From="125" - To="50" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseBackward2" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:01" - From="125" - To="50" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseBackward2" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseBackward2" - From="0.0" - To="1.0" - BeginTime="00:00:00" - Duration="00:00:01" /> - <!-- Backward3 Animation (Starts 2 seconds later) --> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:00.5" - From="100" - To="50" - Storyboard.TargetProperty="(Ellipse.Width)" - Storyboard.TargetName="EclipseBackward3" /> - <DoubleAnimation BeginTime="00:00:00" - Duration="00:00:00.5" - From="100" - To="50" - Storyboard.TargetProperty="(Ellipse.Height)" - Storyboard.TargetName="EclipseBackward3" /> - <DoubleAnimation Storyboard.TargetProperty="Opacity" - Storyboard.TargetName="EclipseBackward3" - From="0.0" - To="1.0" - BeginTime="00:00:00" - Duration="00:00:00.5" /> - </Storyboard> - </BeginStoryboard> - </EventTrigger.Actions> - </EventTrigger> - </ToggleButton.Triggers> - </ToggleButton> - </Grid> - <!--End of Refresh Button Grid--> - + <Button x:Name="RemoveProtectionsButton" Style="{StaticResource CustomButtonStyle2}" Margin="0,0,0,0" Grid.Row="2" Grid.ColumnSpan="2"> + <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> + <TextBlock Text="Remove Selected Protections Category" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> + </StackPanel> + </Button> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Grid.Row="3" Grid.ColumnSpan="2" > <TextBlock x:Name="TextBlockdCategories" HorizontalAlignment="Center" VerticalAlignment="Center" Text="Select a Drive to Decrypt" Foreground="Black" FontSize="16" FontWeight="Normal" Margin="5,0,5,0" /> @@ -366,10 +71,9 @@ ItemContainerStyle="{StaticResource ModernComboBoxItemStyle}" SelectedIndex="0"></ComboBox> </StackPanel> - <Button x:Name="DecryptButton" Style="{StaticResource CustomButtonStyle2}" Margin="5,15,5,30" Grid.Row="4" Grid.ColumnSpan="2"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> - <TextBlock Text="Decrypt the Selected Drive" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="Normal"/> + <TextBlock Text="Decrypt the Selected Drive" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="8,0,8,0" FontWeight="SemiBold"/> </StackPanel> </Button>