Skip to content

Commit

Permalink
Further modernization of Harden Windows Security (#572)
Browse files Browse the repository at this point in the history
Updated the link to the Microsoft 365 apps security baselines to the latest version, 24H2. Previous version was 2306.

Added a new design for when an error occurs in the app

You no longer need to use PowerShell to copy the logs and no error is propagated there. Complete detail of the error is presented to you in the dialog that you see, and with 1 press of a button you can copy it to clipboard and report it on GitHub if you want. This is of course a rare occurrence, but this feature is there whenever it's necessary.
error screenshot
Added support for running the module in Windows Server. You can use all of the features of the Harden Windows Security module in Windows Server 2025 to harden it. This is the Phase 1 of completing this roadmap item.

Applied more optimizations to the code.

Updated Readme with info regarding the new Edge policeis.

Updated the version number file.

Update the required Microsoft DLLs.

Removed the emoji text arts that appear at the end of the compliance check in the CLI experience.

Improved the text colors in the Protect cmdlet in the CLI experience.
  • Loading branch information
HotCakeX authored Feb 3, 2025
1 parent 8a0a79c commit 2ba0ea6
Show file tree
Hide file tree
Showing 59 changed files with 356 additions and 584 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

namespace HardenWindowsSecurity;


internal partial class BitLocker
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ internal partial class BitLocker
private const uint FVE_E_VOLUME_BOUND_ALREADY = 2150694943;



/// <summary>
/// Removes a key protector of an encrypted volume based on the key protector ID
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace HardenWindowsSecurity;
internal static class FirewallHelper
{
// Method to get firewall rules based on RuleGroup and Direction
public static List<ManagementObject> GetFirewallRules(string ruleGroup, ushort direction)
internal static List<ManagementObject> GetFirewallRules(string ruleGroup, ushort direction)
{
string namespacePath = @"root\standardcimv2";
string className = "MSFT_NetFirewallRule";
Expand Down Expand Up @@ -191,7 +191,7 @@ internal enum FirewallRuleAction
/// <param name="DisplayName">The DisplayName of the Firewall rule</param>
/// <param name="ListDownloadURL">Link to the GitHub file that contains the IP Addresses</param>
/// <param name="ToAdd">If true, the firewall rules will be added. If false, the firewall rules will only be deleted.</param>
public static void BlockIPAddressListsInGroupPolicy(string DisplayName, Uri? ListDownloadURL, bool ToAdd)
internal static void BlockIPAddressListsInGroupPolicy(string DisplayName, Uri? ListDownloadURL, bool ToAdd)
{
// An array to hold the IP Address ranges
string[] ipList = [];
Expand Down
30 changes: 5 additions & 25 deletions Harden-Windows-Security Module/Main files/C#/GUI/ASRRules/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ namespace HardenWindowsSecurity;

public static partial class GUIMain
{

// Partial class definition for handling navigation and view models
public partial class NavigationVM : ViewModelBase
{

// Method to handle the ASRRules view, including loading
private void ASRRulesView(object obj)
private void ASRRulesView(object? obj)
{
// Check if the view is already cached
if (_viewCache.TryGetValue("ASRRulesView", out var cachedView))
Expand All @@ -41,16 +39,12 @@ private void ASRRulesView(object obj)
// Parse the XAML content to create a UserControl
UserControl View = (UserControl)XamlReader.Parse(xamlContent);

// Find the Parent Grid
Grid? ParentGrid = (Grid)View.FindName("ParentGrid");

#region finding elements

// Finding the elements
Grid ParentGrid = (Grid)View.FindName("ParentGrid");
Button RetrieveASRStatusButton = (Button)ParentGrid.FindName("RetrieveASRStatus");
Button ApplyASRRulesButton = (Button)ParentGrid.FindName("ApplyASRRulesButton");

#endregion

ListView ASRRuleSet1 = (ListView)ParentGrid.FindName("ASRRuleSet1");
ListView ASRRuleSet2 = (ListView)ParentGrid.FindName("ASRRuleSet2");

// Register button to be disabled/enabled based on global activity
ActivityTracker.RegisterUIElement(RetrieveASRStatusButton);
Expand Down Expand Up @@ -142,12 +136,6 @@ string GetASRRuleConfig(string ASRRuleName, byte ComboBoxIndex)
// Set text blocks to empty while new data is being generated
Application.Current.Dispatcher.Invoke(() =>
{
// Get the ListViews
if (ParentGrid.FindName("ASRRuleSet1") is not ListView ASRRuleSet1 || ParentGrid.FindName("ASRRuleSet2") is not ListView ASRRuleSet2)
{
throw new InvalidOperationException("One of the ListViews in the ASRRules view XAML is empty.");
}

// Empty the dictionary from previous ComboBox values in order to collect new data
comboBoxDictionary.Clear();

Expand Down Expand Up @@ -239,13 +227,6 @@ await Task.Run(() =>

Application.Current.Dispatcher.Invoke(() =>
{
// Get the ListViews
if (ParentGrid.FindName("ASRRuleSet1") is not ListView ASRRuleSet1 ||
ParentGrid.FindName("ASRRuleSet2") is not ListView ASRRuleSet2)
{
throw new InvalidOperationException("One of the ListViews in the ASRRules view XAML is empty.");
}

// Combine the items of both ListViews
IEnumerable<ListViewItem> combinedItems = ASRRuleSet1.Items.Cast<ListViewItem>()
.Concat(ASRRuleSet2.Items.Cast<ListViewItem>());
Expand Down Expand Up @@ -347,7 +328,6 @@ await Task.Run(() =>
// Cache the view before setting it as the CurrentView
_viewCache["ASRRulesView"] = View;

// Set the CurrentView to the ASRRules view
CurrentView = View;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,11 @@ namespace HardenWindowsSecurity;

public partial class GUIMain
{

// Partial class definition for handling navigation and view models
public partial class NavigationVM : ViewModelBase
{

// Method to handle the AppControlManager view, including loading
private void AppControlManagerView(object obj)
private void AppControlManagerView(object? obj)
{

// Check if the view is already cached
Expand All @@ -54,10 +52,8 @@ private void AppControlManagerView(object obj)
// Parse the XAML content to create a UserControl
GUIAppControlManager.View = (UserControl)XamlReader.Parse(xamlContent);

// Find the Parent Grid
// Find the elements
GUIAppControlManager.ParentGrid = (Grid)GUIAppControlManager.View.FindName("ParentGrid");

// Finding other elements
Button InstallAppControlManagerButton = (Button)GUIAppControlManager.ParentGrid.FindName("InstallAppControlManagerButton");
Button ViewDemoOnYouTubeButton = (Button)GUIAppControlManager.ParentGrid.FindName("ViewDemoOnYouTubeButton");
Button AccessTheGuideOnGitHubButton = (Button)GUIAppControlManager.ParentGrid.FindName("AccessTheGuideOnGitHubButton");
Expand Down Expand Up @@ -369,7 +365,6 @@ await Task.Run(() =>
"with your on-device keys. Please disable the policy. It can be found in Group Policy Editor -> " +
"Computer Configuration -> Windows Settings -> Security Settings -> Local Policies -> Security Options -> " +
"'User Account Control: Only elevate executable files that are signed and validated'", LogTypeIntel.WarningInteractionRequired);

}
}
}
Expand All @@ -380,7 +375,6 @@ await Task.Run(() =>
}
#endregion


});
}

Expand Down Expand Up @@ -413,7 +407,6 @@ await Task.Run(() =>
// Cache the view before setting it as the CurrentView
_viewCache["AppControlManagerView"] = GUIAppControlManager.View;

// Set the CurrentView to the Protect view
CurrentView = GUIAppControlManager.View;
}
}
Expand Down
31 changes: 13 additions & 18 deletions Harden-Windows-Security Module/Main files/C#/GUI/BitLocker/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ namespace HardenWindowsSecurity;

public partial class GUIMain
{

// Partial class definition for handling navigation and view models
public partial class NavigationVM : ViewModelBase
{

// Method to handle the Logs view, including loading
private void BitLockerView(object obj)
// Method to handle the BitLocker view, including loading
private void BitLockerView(object? obj)
{
// Check if the view is already cached
if (_viewCache.TryGetValue("BitLockerView", out var cachedView))
Expand All @@ -35,24 +33,25 @@ private void BitLockerView(object obj)
return;
}

if (!Initializer.BitLockerInfrastructureAvailable)
{
Logger.LogMessage("BitLocker infrastructure is not available or enabled on this system.", LogTypeIntel.ErrorInteractionRequired);
return;
}

// Read the XAML content from the file
string xamlContent = File.ReadAllText(Path.Combine(GlobalVars.path, "Resources", "XAML", "BitLocker.xaml"));

// Parse the XAML content to create a UserControl
GUIBitLocker.View = (UserControl)XamlReader.Parse(xamlContent);

// Find the Parent Grid
// Finding the elements
GUIBitLocker.ParentGrid = (Grid)GUIBitLocker.View.FindName("ParentGrid");

GUIBitLocker.TabControl = (TabControl)GUIBitLocker.ParentGrid.FindName("TabControl");

if (GUIBitLocker.TabControl.FindName("OSDriveGrid") is not Grid OSDriveGrid ||
GUIBitLocker.TabControl.FindName("NonOSDrivesGrid") is not Grid NonOSDrivesGrid ||
GUIBitLocker.TabControl.FindName("RemovableDrivesGrid") is not Grid RemovableDrivesGrid ||
GUIBitLocker.TabControl.FindName("BackupGrid") is not Grid BackupGrid)
{
throw new InvalidOperationException("BitLocker view grids could not be found");
}
Grid OSDriveGrid = (Grid)GUIBitLocker.TabControl.FindName("OSDriveGrid");
Grid NonOSDrivesGrid = (Grid)GUIBitLocker.TabControl.FindName("NonOSDrivesGrid");
Grid RemovableDrivesGrid = (Grid)GUIBitLocker.TabControl.FindName("RemovableDrivesGrid");
Grid BackupGrid = (Grid)GUIBitLocker.TabControl.FindName("BackupGrid");


#region OS Drives
Expand Down Expand Up @@ -133,7 +132,6 @@ static void UpdateEnhancedLevelElements()

#region Non-OS Drives
GUIBitLocker.RefreshNonOSDrives = (Button)NonOSDrivesGrid.FindName("RefreshNonOSDrives");

GUIBitLocker.NonOSDrivesComboBox = (ComboBox)NonOSDrivesGrid.FindName("NonOSDrivesComboBox");
Button NonOSDriveEncryptButton = (Button)NonOSDrivesGrid.FindName("NonOSDriveEncryptButton");

Expand All @@ -159,7 +157,6 @@ await Task.Run(() =>

#region Removable Drives
GUIBitLocker.RefreshRemovableDrivesForRemovableDrivesSection = (Button)RemovableDrivesGrid.FindName("RefreshRemovableDrivesForRemovableDrivesSection");

GUIBitLocker.RemovableDrivesInRemovableDrivesGridComboBox = (ComboBox)RemovableDrivesGrid.FindName("RemovableDrivesInRemovableDrivesGridComboBox");
GUIBitLocker.Password1 = (PasswordBox)RemovableDrivesGrid.FindName("Password1");
GUIBitLocker.Password2 = (PasswordBox)RemovableDrivesGrid.FindName("Password2");
Expand Down Expand Up @@ -218,7 +215,6 @@ await Task.Run(() =>

#endregion


// Event handler to refresh the recovery key info in the DataGrid
GUIBitLocker.RefreshButtonForBackup.Click += async (sender, e) =>
{
Expand Down Expand Up @@ -551,7 +547,6 @@ await Task.Run(() =>
// Cache the view before setting it as the CurrentView
_viewCache["BitLockerView"] = GUIBitLocker.View;

// Set the CurrentView to the Protect view
CurrentView = GUIBitLocker.View;
}
}
Expand Down
36 changes: 4 additions & 32 deletions Harden-Windows-Security Module/Main files/C#/GUI/Confirm/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Markup;
using System.Windows.Media.Imaging;

namespace HardenWindowsSecurity;

public partial class GUIMain
{

// Partial class definition for handling navigation and view models
public partial class NavigationVM : ViewModelBase
{
// Method to handle the "Confirm" view, including loading and modifying it
private void ConfirmView(object obj)
private void ConfirmView(object? obj)
{
// Check if the Confirm view is already cached
if (_viewCache.TryGetValue("ConfirmView", out var cachedView))
Expand All @@ -46,7 +43,7 @@ private void ConfirmView(object obj)
// Parse the XAML content to create a UserControl object
UserControl View = (UserControl)XamlReader.Parse(xamlContent);

// Finding elements
// Finding the elements
DataGrid SecOpsDataGrid = (DataGrid)View.FindName("SecOpsDataGrid");
TextBlock TotalCurrentlyDisplayedSecOpsTextBlock = (TextBlock)View.FindName("TotalCurrentlyDisplayedSecOps");
ToggleButton CompliantItemsToggleButton = (ToggleButton)View.FindName("CompliantItemsToggleButton");
Expand All @@ -55,6 +52,7 @@ private void ConfirmView(object obj)
TextBox textBoxFilter = (TextBox)View.FindName("textBoxFilter");
TextBlock TotalCountTextBlock = (TextBlock)View.FindName("TotalCountTextBlock");
ComboBox ComplianceCategoriesSelectionComboBox = (ComboBox)View.FindName("ComplianceCategoriesSelectionComboBox");
ToggleButton RefreshButton = (ToggleButton)View.FindName("RefreshButton");

// Initialize an empty security options collection
ObservableCollection<SecOp> SecOpsObservableCollection = [];
Expand Down Expand Up @@ -117,32 +115,6 @@ void ApplyFilters(string filterText, bool includeCompliant, bool includeNonCompl
NonCompliantItemsToggleButton.Unchecked += (sender, e) => ApplyFilters(textBoxFilter.Text, CompliantItemsToggleButton.IsChecked ?? false, NonCompliantItemsToggleButton.IsChecked ?? false);
#endregion

#region RefreshButton
// Find the Refresh button and attach the Click event handler

// Access the grid containing the Refresh Button
Grid RefreshButtonGrid = (Grid)View.FindName("RefreshButtonGrid");

// Access the Refresh Button
ToggleButton RefreshButton = (ToggleButton)RefreshButtonGrid.FindName("RefreshButton");

// Apply the template to make sure it's available
_ = RefreshButton.ApplyTemplate();

// Access the image within the Refresh Button's template
Image RefreshIconImage = (Image)RefreshButton.Template.FindName("RefreshIconImage", RefreshButton);

// 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;

#endregion

#region ComboBox

// Get the valid compliance category names
Expand Down Expand Up @@ -326,6 +298,7 @@ await Task.Run(() =>
catch (Exception ex)
{
Logger.LogMessage($"Failed to export the results to the file: {ex.Message}", LogTypeIntel.ErrorInteractionRequired);
return;
}

Logger.LogMessage($"Compliance check results have been successfully exported.", LogTypeIntel.InformationInteractionRequired);
Expand Down Expand Up @@ -380,7 +353,6 @@ string EscapeForCsv(string? value)
// Cache the Confirm view for future use
_viewCache["ConfirmView"] = View;

// Set the CurrentView to the modified Confirm view
CurrentView = View;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
using System.Windows.Controls;

namespace HardenWindowsSecurity;
namespace HardenWindowsSecurity;

internal static class GUIExclusions
{
internal static UserControl? View;

internal static Grid? ParentGrid;

// Stores the file paths selected by the user after using the browse button
internal static string[]? selectedFiles;

Expand Down
32 changes: 12 additions & 20 deletions Harden-Windows-Security Module/Main files/C#/GUI/Exclusions/View.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ namespace HardenWindowsSecurity;

public partial class GUIMain
{

// Partial class definition for handling navigation and view models
public partial class NavigationVM : ViewModelBase
{

// Method to handle the Exclusions view, including loading
private void ExclusionsView(object obj)
private void ExclusionsView(object? obj)
{
// Check if the view is already cached
if (_viewCache.TryGetValue("ExclusionsView", out var cachedView))
Expand All @@ -39,21 +37,16 @@ private void ExclusionsView(object obj)
string xamlContent = File.ReadAllText(Path.Combine(GlobalVars.path, "Resources", "XAML", "Exclusions.xaml"));

// Parse the XAML content to create a UserControl
GUIExclusions.View = (UserControl)XamlReader.Parse(xamlContent);

// Find the Parent Grid
GUIExclusions.ParentGrid = (Grid)GUIExclusions.View.FindName("ParentGrid");

#region Finding other elements

ToggleButton MicrosoftDefenderToggleButton = (ToggleButton)GUIExclusions.ParentGrid.FindName("MicrosoftDefenderToggleButton");
ToggleButton ControlledFolderAccessToggleButton = (ToggleButton)GUIExclusions.ParentGrid.FindName("ControlledFolderAccessToggleButton");
ToggleButton AttackSurfaceReductionRulesToggleButton = (ToggleButton)GUIExclusions.ParentGrid.FindName("AttackSurfaceReductionRulesToggleButton");
TextBox? SelectedFilePaths = (TextBox)GUIExclusions.ParentGrid.FindName("SelectedFilePaths");
Button? BrowseForFilesButton = (Button)GUIExclusions.ParentGrid.FindName("BrowseForFilesButton");
Button ApplyExclusionsButton = (Button)GUIExclusions.ParentGrid.FindName("ApplyExclusionsButton");
UserControl View = (UserControl)XamlReader.Parse(xamlContent);

#endregion
// Find the elements
Grid ParentGrid = (Grid)View.FindName("ParentGrid");
ToggleButton MicrosoftDefenderToggleButton = (ToggleButton)ParentGrid.FindName("MicrosoftDefenderToggleButton");
ToggleButton ControlledFolderAccessToggleButton = (ToggleButton)ParentGrid.FindName("ControlledFolderAccessToggleButton");
ToggleButton AttackSurfaceReductionRulesToggleButton = (ToggleButton)ParentGrid.FindName("AttackSurfaceReductionRulesToggleButton");
TextBox SelectedFilePaths = (TextBox)ParentGrid.FindName("SelectedFilePaths");
Button BrowseForFilesButton = (Button)ParentGrid.FindName("BrowseForFilesButton");
Button ApplyExclusionsButton = (Button)ParentGrid.FindName("ApplyExclusionsButton");

// Event handler for Browse Button
BrowseForFilesButton.Click += (sender, e) =>
Expand Down Expand Up @@ -265,10 +258,9 @@ await Task.Run(() =>
};

// Cache the view before setting it as the CurrentView
_viewCache["ExclusionsView"] = GUIExclusions.View;
_viewCache["ExclusionsView"] = View;

// Set the CurrentView to the Exclusions view
CurrentView = GUIExclusions.View;
CurrentView = View;
}
}
}
Loading

0 comments on commit 2ba0ea6

Please sign in to comment.