diff --git a/404.html b/404.html index 8b73399..288ea40 100644 --- a/404.html +++ b/404.html @@ -14,7 +14,7 @@ - + diff --git a/Azure/Clean Source principle, Azure and Privileged Access Workstations/index.html b/Azure/Clean Source principle, Azure and Privileged Access Workstations/index.html index c589ade..a375fed 100644 --- a/Azure/Clean Source principle, Azure and Privileged Access Workstations/index.html +++ b/Azure/Clean Source principle, Azure and Privileged Access Workstations/index.html @@ -20,7 +20,7 @@ - + diff --git a/Azure/How to Securely Connect to Azure VMs and Use RDP/index.html b/Azure/How to Securely Connect to Azure VMs and Use RDP/index.html index ef12d87..333be03 100644 --- a/Azure/How to Securely Connect to Azure VMs and Use RDP/index.html +++ b/Azure/How to Securely Connect to Azure VMs and Use RDP/index.html @@ -20,7 +20,7 @@ - + diff --git a/GitHub/Cloning Personal and Enterprise Repositories Using GitHub Desktop/index.html b/GitHub/Cloning Personal and Enterprise Repositories Using GitHub Desktop/index.html index 2012cc8..ec1a991 100644 --- a/GitHub/Cloning Personal and Enterprise Repositories Using GitHub Desktop/index.html +++ b/GitHub/Cloning Personal and Enterprise Repositories Using GitHub Desktop/index.html @@ -20,7 +20,7 @@ - + diff --git a/GitHub/Git GitHub Desktop and Mandatory ASLR/index.html b/GitHub/Git GitHub Desktop and Mandatory ASLR/index.html index f1bf055..219261d 100644 --- a/GitHub/Git GitHub Desktop and Mandatory ASLR/index.html +++ b/GitHub/Git GitHub Desktop and Mandatory ASLR/index.html @@ -20,7 +20,7 @@ - + diff --git a/GitHub/Signed and Verified commits with GitHub desktop/index.html b/GitHub/Signed and Verified commits with GitHub desktop/index.html index f76d7c4..a5761cd 100644 --- a/GitHub/Signed and Verified commits with GitHub desktop/index.html +++ b/GitHub/Signed and Verified commits with GitHub desktop/index.html @@ -20,7 +20,7 @@ - + diff --git a/Harden-Windows-Security-Module/Harden-Windows-Security-Module/index.html b/Harden-Windows-Security-Module/Harden-Windows-Security-Module/index.html index 03d5d56..50a9d94 100644 --- a/Harden-Windows-Security-Module/Harden-Windows-Security-Module/index.html +++ b/Harden-Windows-Security-Module/Harden-Windows-Security-Module/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/About TLS, DNS, Encryption and OPSEC concepts/index.html b/Miscellaneous/About TLS, DNS, Encryption and OPSEC concepts/index.html index 5a82584..2e6b96a 100644 --- a/Miscellaneous/About TLS, DNS, Encryption and OPSEC concepts/index.html +++ b/Miscellaneous/About TLS, DNS, Encryption and OPSEC concepts/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/BitLocker, TPM and Pluton What Are They and How Do They Work/index.html b/Miscellaneous/BitLocker, TPM and Pluton What Are They and How Do They Work/index.html index 2e0ead3..3bfd777 100644 --- a/Miscellaneous/BitLocker, TPM and Pluton What Are They and How Do They Work/index.html +++ b/Miscellaneous/BitLocker, TPM and Pluton What Are They and How Do They Work/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Comparison of Security Benchmarks/index.html b/Miscellaneous/Comparison of Security Benchmarks/index.html index 4b6f0b6..63519bd 100644 --- a/Miscellaneous/Comparison of Security Benchmarks/index.html +++ b/Miscellaneous/Comparison of Security Benchmarks/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Create Bootable USB flash drive with no 3rd party tools/index.html b/Miscellaneous/Create Bootable USB flash drive with no 3rd party tools/index.html index 6398db9..932ec68 100644 --- a/Miscellaneous/Create Bootable USB flash drive with no 3rd party tools/index.html +++ b/Miscellaneous/Create Bootable USB flash drive with no 3rd party tools/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Device Guard and Virtualization Based Security in Windows/index.html b/Miscellaneous/Device Guard and Virtualization Based Security in Windows/index.html index aa7b68e..7f1212a 100644 --- a/Miscellaneous/Device Guard and Virtualization Based Security in Windows/index.html +++ b/Miscellaneous/Device Guard and Virtualization Based Security in Windows/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Event Viewer/index.html b/Miscellaneous/Event Viewer/index.html index d91a2e6..7847c19 100644 --- a/Miscellaneous/Event Viewer/index.html +++ b/Miscellaneous/Event Viewer/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Group Policy/index.html b/Miscellaneous/Group Policy/index.html index 8c889ff..c21c687 100644 --- a/Miscellaneous/Group Policy/index.html +++ b/Miscellaneous/Group Policy/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell/index.html b/Miscellaneous/How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell/index.html index 7681337..9188ff1 100644 --- a/Miscellaneous/How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell/index.html +++ b/Miscellaneous/How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/How to compact your OS and free up extra space/index.html b/Miscellaneous/How to compact your OS and free up extra space/index.html index 53231c3..9c29d64 100644 --- a/Miscellaneous/How to compact your OS and free up extra space/index.html +++ b/Miscellaneous/How to compact your OS and free up extra space/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Hyper V/index.html b/Miscellaneous/Hyper V/index.html index 041d7fd..d909a0c 100644 --- a/Miscellaneous/Hyper V/index.html +++ b/Miscellaneous/Hyper V/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Only a Small Portion of The Windows OS Security Apparatus/index.html b/Miscellaneous/Only a Small Portion of The Windows OS Security Apparatus/index.html index cb1b04b..7025631 100644 --- a/Miscellaneous/Only a Small Portion of The Windows OS Security Apparatus/index.html +++ b/Miscellaneous/Only a Small Portion of The Windows OS Security Apparatus/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Overrides for Microsoft Security Baseline/index.html b/Miscellaneous/Overrides for Microsoft Security Baseline/index.html index c76a8f3..1fba58e 100644 --- a/Miscellaneous/Overrides for Microsoft Security Baseline/index.html +++ b/Miscellaneous/Overrides for Microsoft Security Baseline/index.html @@ -20,7 +20,7 @@ - + diff --git a/Miscellaneous/Things to do for clean installing Windows/index.html b/Miscellaneous/Things to do for clean installing Windows/index.html index e9df24d..73f5828 100644 --- a/Miscellaneous/Things to do for clean installing Windows/index.html +++ b/Miscellaneous/Things to do for clean installing Windows/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/Basic PowerShell tricks and notes Part 2/index.html b/PowerShell/Basic PowerShell tricks and notes Part 2/index.html index 2889185..b71978d 100644 --- a/PowerShell/Basic PowerShell tricks and notes Part 2/index.html +++ b/PowerShell/Basic PowerShell tricks and notes Part 2/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/Basic PowerShell tricks and notes Part 3/index.html b/PowerShell/Basic PowerShell tricks and notes Part 3/index.html index 1f724f9..541f5f6 100644 --- a/PowerShell/Basic PowerShell tricks and notes Part 3/index.html +++ b/PowerShell/Basic PowerShell tricks and notes Part 3/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/Basic PowerShell tricks and notes Part 4/index.html b/PowerShell/Basic PowerShell tricks and notes Part 4/index.html index bea3609..c3e2c40 100644 --- a/PowerShell/Basic PowerShell tricks and notes Part 4/index.html +++ b/PowerShell/Basic PowerShell tricks and notes Part 4/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/Basic PowerShell tricks and notes/index.html b/PowerShell/Basic PowerShell tricks and notes/index.html index 71c2ecc..7bae80f 100644 --- a/PowerShell/Basic PowerShell tricks and notes/index.html +++ b/PowerShell/Basic PowerShell tricks and notes/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time/index.html b/PowerShell/How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time/index.html index e09622e..6313835 100644 --- a/PowerShell/How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time/index.html +++ b/PowerShell/How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell/index.html b/PowerShell/How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell/index.html index c0eb3bb..431d4da 100644 --- a/PowerShell/How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell/index.html +++ b/PowerShell/How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/PowerShell Best Practices/index.html b/PowerShell/PowerShell Best Practices/index.html index 4467936..04a182f 100644 --- a/PowerShell/PowerShell Best Practices/index.html +++ b/PowerShell/PowerShell Best Practices/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/Powershell Dynamic Parameters and How to Add Them to the Get-Help Syntax/index.html b/PowerShell/Powershell Dynamic Parameters and How to Add Them to the Get-Help Syntax/index.html index 951dbb9..f58a613 100644 --- a/PowerShell/Powershell Dynamic Parameters and How to Add Them to the Get-Help Syntax/index.html +++ b/PowerShell/Powershell Dynamic Parameters and How to Add Them to the Get-Help Syntax/index.html @@ -20,7 +20,7 @@ - + diff --git a/PowerShell/RunSpaces In PowerShell/index.html b/PowerShell/RunSpaces In PowerShell/index.html index ae2b0c8..82c982f 100644 --- a/PowerShell/RunSpaces In PowerShell/index.html +++ b/PowerShell/RunSpaces In PowerShell/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/Application Control WDAC Frequently Asked Questions FAQs/index.html b/WDAC/Application Control WDAC Frequently Asked Questions FAQs/index.html index 6440090..015d189 100644 --- a/WDAC/Application Control WDAC Frequently Asked Questions FAQs/index.html +++ b/WDAC/Application Control WDAC Frequently Asked Questions FAQs/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/EKUs in WDAC, App Control for Business, Policies/index.html b/WDAC/EKUs in WDAC, App Control for Business, Policies/index.html index 2875e93..594d24d 100644 --- a/WDAC/EKUs in WDAC, App Control for Business, Policies/index.html +++ b/WDAC/EKUs in WDAC, App Control for Business, Policies/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/Fast and Automatic Microsoft Recommended Driver Block Rules updates/index.html b/WDAC/Fast and Automatic Microsoft Recommended Driver Block Rules updates/index.html index 0afdde5..ef9d230 100644 --- a/WDAC/Fast and Automatic Microsoft Recommended Driver Block Rules updates/index.html +++ b/WDAC/Fast and Automatic Microsoft Recommended Driver Block Rules updates/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/How to Create and Deploy a Signed WDAC Policy Windows Defender Application Control/index.html b/WDAC/How to Create and Deploy a Signed WDAC Policy Windows Defender Application Control/index.html index 3950256..1866df4 100644 --- a/WDAC/How to Create and Deploy a Signed WDAC Policy Windows Defender Application Control/index.html +++ b/WDAC/How to Create and Deploy a Signed WDAC Policy Windows Defender Application Control/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/How to Use Microsoft Defender for Endpoint Advanced Hunting With WDAC App Control/index.html b/WDAC/How to Use Microsoft Defender for Endpoint Advanced Hunting With WDAC App Control/index.html index 7b578aa..ee56d68 100644 --- a/WDAC/How to Use Microsoft Defender for Endpoint Advanced Hunting With WDAC App Control/index.html +++ b/WDAC/How to Use Microsoft Defender for Endpoint Advanced Hunting With WDAC App Control/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/Introduction/index.html b/WDAC/Introduction/index.html index 1e6b80f..58835e8 100644 --- a/WDAC/Introduction/index.html +++ b/WDAC/Introduction/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/Script Enforcement and PowerShell Constrained Language Mode in WDAC App Control Policies/index.html b/WDAC/Script Enforcement and PowerShell Constrained Language Mode in WDAC App Control Policies/index.html index f96b7eb..d3b7f61 100644 --- a/WDAC/Script Enforcement and PowerShell Constrained Language Mode in WDAC App Control Policies/index.html +++ b/WDAC/Script Enforcement and PowerShell Constrained Language Mode in WDAC App Control Policies/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC Notes/index.html b/WDAC/WDAC Notes/index.html index 92e0789..4791fb4 100644 --- a/WDAC/WDAC Notes/index.html +++ b/WDAC/WDAC Notes/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC for Fully Managed Devices (2nd variant)/index.html b/WDAC/WDAC for Fully Managed Devices (2nd variant)/index.html index 644e05b..103ea3c 100644 --- a/WDAC/WDAC for Fully Managed Devices (2nd variant)/index.html +++ b/WDAC/WDAC for Fully Managed Devices (2nd variant)/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC for Fully Managed Devices Variant 3/index.html b/WDAC/WDAC for Fully Managed Devices Variant 3/index.html index 636a50d..4ca4fa1 100644 --- a/WDAC/WDAC for Fully Managed Devices Variant 3/index.html +++ b/WDAC/WDAC for Fully Managed Devices Variant 3/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC for Fully Managed Devices Variant 4/index.html b/WDAC/WDAC for Fully Managed Devices Variant 4/index.html index 224959a..2d43dbb 100644 --- a/WDAC/WDAC for Fully Managed Devices Variant 4/index.html +++ b/WDAC/WDAC for Fully Managed Devices Variant 4/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC for Fully Managed Devices/index.html b/WDAC/WDAC for Fully Managed Devices/index.html index 4e81562..3b1a5d5 100644 --- a/WDAC/WDAC for Fully Managed Devices/index.html +++ b/WDAC/WDAC for Fully Managed Devices/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC for Lightly Managed Devices/index.html b/WDAC/WDAC for Lightly Managed Devices/index.html index 33d0572..5f3ca63 100644 --- a/WDAC/WDAC for Lightly Managed Devices/index.html +++ b/WDAC/WDAC for Lightly Managed Devices/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDAC/WDAC policy for BYOVD Kernel mode only protection/index.html b/WDAC/WDAC policy for BYOVD Kernel mode only protection/index.html index f6237c5..9fb0a3e 100644 --- a/WDAC/WDAC policy for BYOVD Kernel mode only protection/index.html +++ b/WDAC/WDAC policy for BYOVD Kernel mode only protection/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Assert-WDACConfigIntegrity/index.html b/WDACConfig Module/Assert-WDACConfigIntegrity/index.html index c0f13e6..9b3386b 100644 --- a/WDACConfig Module/Assert-WDACConfigIntegrity/index.html +++ b/WDACConfig Module/Assert-WDACConfigIntegrity/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Build-WDACCertificate/index.html b/WDACConfig Module/Build-WDACCertificate/index.html index 414699a..a07defa 100644 --- a/WDACConfig Module/Build-WDACCertificate/index.html +++ b/WDACConfig Module/Build-WDACCertificate/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Confirm-WDACConfig/index.html b/WDACConfig Module/Confirm-WDACConfig/index.html index 9402881..4221e49 100644 --- a/WDACConfig Module/Confirm-WDACConfig/index.html +++ b/WDACConfig Module/Confirm-WDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/ConvertTo-WDACPolicy/index.html b/WDACConfig Module/ConvertTo-WDACPolicy/index.html index c50c110..300601f 100644 --- a/WDACConfig Module/ConvertTo-WDACPolicy/index.html +++ b/WDACConfig Module/ConvertTo-WDACPolicy/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Deploy-SignedWDACConfig/index.html b/WDACConfig Module/Deploy-SignedWDACConfig/index.html index 36346e1..e93f17f 100644 --- a/WDACConfig Module/Deploy-SignedWDACConfig/index.html +++ b/WDACConfig Module/Deploy-SignedWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Edit-SignedWDACConfig/index.html b/WDACConfig Module/Edit-SignedWDACConfig/index.html index 9687beb..6ae9bb8 100644 --- a/WDACConfig Module/Edit-SignedWDACConfig/index.html +++ b/WDACConfig Module/Edit-SignedWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Edit-WDACConfig/index.html b/WDACConfig Module/Edit-WDACConfig/index.html index 56771c7..2549f02 100644 --- a/WDACConfig Module/Edit-WDACConfig/index.html +++ b/WDACConfig Module/Edit-WDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Get-CIPolicySetting/index.html b/WDACConfig Module/Get-CIPolicySetting/index.html index 8631206..dcc23b9 100644 --- a/WDACConfig Module/Get-CIPolicySetting/index.html +++ b/WDACConfig Module/Get-CIPolicySetting/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Get-CiFileHashes/index.html b/WDACConfig Module/Get-CiFileHashes/index.html index c971198..32d1dc6 100644 --- a/WDACConfig Module/Get-CiFileHashes/index.html +++ b/WDACConfig Module/Get-CiFileHashes/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Get-CommonWDACConfig/index.html b/WDACConfig Module/Get-CommonWDACConfig/index.html index 82c0d9b..4bf936a 100644 --- a/WDACConfig Module/Get-CommonWDACConfig/index.html +++ b/WDACConfig Module/Get-CommonWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Invoke-WDACSimulation/index.html b/WDACConfig Module/Invoke-WDACSimulation/index.html index a0dd09f..2cdbb85 100644 --- a/WDACConfig Module/Invoke-WDACSimulation/index.html +++ b/WDACConfig Module/Invoke-WDACSimulation/index.html @@ -20,7 +20,7 @@ - + @@ -2240,15 +2240,6 @@ - - -
  • - - - Notes - - -
  • @@ -2643,15 +2634,6 @@ - - -
  • - - - Notes - - -
  • @@ -2969,13 +2951,6 @@

    -CSVOutputhorizontal super thin rainbow RGB line

    -


    -

    Notes

    - -


    @@ -2998,7 +2973,7 @@

    Notes& - 2024-03-02 + 2024-06-20 diff --git a/WDACConfig Module/New-DenyWDACConfig/index.html b/WDACConfig Module/New-DenyWDACConfig/index.html index 43dbd84..27a576f 100644 --- a/WDACConfig Module/New-DenyWDACConfig/index.html +++ b/WDACConfig Module/New-DenyWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/New-KernelModeWDACConfig/index.html b/WDACConfig Module/New-KernelModeWDACConfig/index.html index b786701..0f899ca 100644 --- a/WDACConfig Module/New-KernelModeWDACConfig/index.html +++ b/WDACConfig Module/New-KernelModeWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/New-SupplementalWDACConfig/index.html b/WDACConfig Module/New-SupplementalWDACConfig/index.html index 7ba711d..a85f48d 100644 --- a/WDACConfig Module/New-SupplementalWDACConfig/index.html +++ b/WDACConfig Module/New-SupplementalWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/New-WDACConfig/index.html b/WDACConfig Module/New-WDACConfig/index.html index 55e2a5f..c0c99f4 100644 --- a/WDACConfig Module/New-WDACConfig/index.html +++ b/WDACConfig Module/New-WDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Remove-CommonWDACConfig/index.html b/WDACConfig Module/Remove-CommonWDACConfig/index.html index 7ac3c30..ba0ed42 100644 --- a/WDACConfig Module/Remove-CommonWDACConfig/index.html +++ b/WDACConfig Module/Remove-CommonWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Remove-WDACConfig/index.html b/WDACConfig Module/Remove-WDACConfig/index.html index 5cb664d..df60069 100644 --- a/WDACConfig Module/Remove-WDACConfig/index.html +++ b/WDACConfig Module/Remove-WDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Set-CiRuleOptions/index.html b/WDACConfig Module/Set-CiRuleOptions/index.html index 03dbd05..6d05c0d 100644 --- a/WDACConfig Module/Set-CiRuleOptions/index.html +++ b/WDACConfig Module/Set-CiRuleOptions/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Set-CommonWDACConfig/index.html b/WDACConfig Module/Set-CommonWDACConfig/index.html index ed9cbd8..90fb441 100644 --- a/WDACConfig Module/Set-CommonWDACConfig/index.html +++ b/WDACConfig Module/Set-CommonWDACConfig/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/Test-CiPolicy/index.html b/WDACConfig Module/Test-CiPolicy/index.html index b1c44a9..05c1403 100644 --- a/WDACConfig Module/Test-CiPolicy/index.html +++ b/WDACConfig Module/Test-CiPolicy/index.html @@ -20,7 +20,7 @@ - + diff --git a/WDACConfig Module/WDACConfig/index.html b/WDACConfig Module/WDACConfig/index.html index 3f34291..e8ff4d7 100644 --- a/WDACConfig Module/WDACConfig/index.html +++ b/WDACConfig Module/WDACConfig/index.html @@ -18,7 +18,7 @@ - + diff --git a/index.html b/index.html index ec16169..de9cf6b 100644 --- a/index.html +++ b/index.html @@ -18,7 +18,7 @@ - + diff --git a/search/search_index.json b/search/search_index.json index 5ca3c41..dbf3a05 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to SpyNetGirl Blog","text":""},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/","title":"Clean Source principle, Azure and Privileged Access","text":""},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#clean-source-principle","title":"Clean Source principle","text":"

    The clean source principle states that all security dependencies must be as trustworthy as the object being secured. The source of the control and/or trust must have an equal or higher level of trustworthiness and/or security than the destination.

    This article reveals the significance of the clean source principle, common short comings, and how it radically transforms the security architecture paradigm.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#a-case-study-of-using-bitlocker-and-tpm-with-nested-vms-in-azure","title":"A Case Study of Using BitLocker and TPM with Nested VMs in Azure","text":"

    Now that you are generally aware of the Clean Source principle, you might want to try to make an architecture that is resistant to tamper/compromise from upstream systems or identities.

    We will examine a scenario that may appear very secure and advanced but is still susceptible to side channel attacks because of not adhering to the clean source principle. In this hypothetical scenario, the Global Admin account is compromised, and we want to safeguard our data from admin abuse.

    Let us assume that you create an Azure VM, which we will refer to as the \u201cHost VM\u201d. We will also create another virtual machine inside of the Host VM using Hyper-V. We will refer to this new guest VM as the \u201cNested VM\u201d. The nested VM\u2019s operating system volume is encrypted with BitLocker. You configure the Key Protectors to be Startup PIN, TPM and a recovery password. Only you have access to the PIN and recovery password of the BitLocker encrypted drive.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#how-to-use-bitlocker-in-azure","title":"How to Use BitLocker in Azure","text":"

    You can utilize Bitlocker in Azure to encrypt the disks of the virtual machines. The service is called Azure Disk Encryption, and it employs Key Vault to store the key instead of a TPM.

    Key Vaults are extremely economical, and disk encryption does not incur any licensing fees, only Key Vault hosting, which is negligible.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#flaws-of-the-above-mentioned-scenario","title":"Flaws of the Above-Mentioned Scenario","text":"

    None of the protections mentioned in the scenario can defend against a compromised admin which has gotten Host VM admin permissions. They can install Command and Control (C2) software using the Azure VM guest agent.

    Once the host VM is compromised, the C2 software can be used as a key logger to steal the startup PIN and authentication credentials of the Nested VM. After the PIN and/or the credentials are stolen, the threat actor can use \u202fPowerShell Direct\u202f to access the virtual machine through the host's hypervisor if it is already booted, or they can boot the Nested VM themselves using the PIN they skimmed.

    At this point, the nested virtual machine can be booted up, and no brute forcing is needed.

    Another attack path is if they download the Nested VM\u2019s disks, they can offline attack the VM once they gain access to the recovery key or the key that is stored in the vTPM of the Nested VM\u2019s hypervisor which is on the disk of the host VM. All software based KSPs just get decoded at runtime and there are tools to skim the decoded value.

    When the nested VM is running, the system sees the disk as plain text, not encrypted. BitLocker encryption is transparent drive encryption, not encryption in use. (For encryption in use, I recommend something like Microsoft Purview\u202fon the data itself.)

    BitLocker is not easy to brute force if the right algorithms are configured (XTS-AES-256) so they would not want to go that direction in most cases.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#what-if-you-deploy-a-signed-wdac-policy-on-the-host-vm","title":"What if You Deploy a Signed WDAC Policy on the Host VM?","text":"

    You could, but what would prevent the threat actor from disabling it on the host? The host is controlled by the threat actor in this scenario and not having the private keys of the deployed signed policy won't matter.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#so-what-alternative-will-the-threat-actor-pursue","title":"So, What Alternative Will the Threat Actor Pursue?","text":"

    They could simply download the VHDX of the main host (Azure virtual machine), extract the nested VHDX that pertains to the guest operating system, construct a new operating system with your data in it but devoid of security, upload that and await your login. You would remain oblivious to the tampering since the operating system is identical but bereft of security, or the threat actor can even deploy their own signed policy on the new operating system.

    Bear in mind, host compromise entails all security dependencies are also compromised. So, you must presume through some black magic that your guest is compromised. What happens if they alter Hyper-V's binaries to perform custom stuff?

    You can technically insert custom guest firmware. Custom firmware is not officially supported and is usually used by pirates to get ACPI tables altered to activate Windows for free.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#clean-source-and-assume-breach-principle-a-match-made-in-heaven","title":"Clean Source and Assume Breach Principle, a Match Made in Heaven","text":"

    It is not only virtual machines that are mistaken to be secure, but also jump boxes (RDP) and session manager apps (PAM) are insufficiently secure. The problem with RDP and PAMs is session hijacking. You can use keyboard and mouse takeover capabilities to control anything downstream without having to install any malware, because the system that is running the RDP client / session manager app is technically in charge of the secure system.

    The control and/or trust that is being originated from hardware is insecure and propagated downstream through the remote-control apps. So, all insecure states can be transmitted onto the secure systems, and you do not even have to install anything on the remote systems to compromise them.

    Clean source done right will prevent session takeovers, because the system hosting the session will be as secure as the upstream system requires.

    However, on Azure, things are much superior. Azure is a hosting fabric that receives commands from an admin. The admin must be hosted on a secure system, which is where the PAW comes in. Azure fabric itself is more secure than anything you can provide.

    The guest has to abide by the rules of its host, and the host has to conform to the rules of Azure, and Azure adheres to the rules of the admins, so by proxy, the guest complies with the rules of the admins, because the chain of control/trust flows through the host virtual machine. Any type of direct guest guarding is futile.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#so-what-is-the-solution","title":"So, What Is the Solution?","text":"

    What you desire is to create something that can remain protected in most hostile environment and preserve its integrity.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#introducing-privileged-access-workstations-paw","title":"Introducing Privileged Access Workstations (PAW)","text":"

    PAW is the highest security configuration designed for extremely sensitive roles that would have a significant or material impact on the organization if their account was compromised. The PAW configuration includes security controls and policies that restrict local administrative access and productivity tools to minimize the attack surface to only what is absolutely needed for performing sensitive jobs or tasks.

    Often, the servers are considerably less secure than the PAW itself. Likewise with intermediaries, they are usually less secure than the PAW itself. Consequently, the session host and/or client is not the weakest chain link. Which also implies that the clean source principle is kept at least on the start of the chain.

    For more of a do-it-your-self experience, check out my harden windows security repository over at GitHub.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#azure-confidential-compute","title":"Azure Confidential Compute","text":"

    Confidential computing is an industry term defined by the Confidential Computing Consortium (CCC) - a foundation dedicated to defining and accelerating the adoption of confidential computing. The CCC defines confidential computing as: The protection of data in use by performing computations in a hardware-based Trusted Execution Environment (TEE).

    Unlike Guarded hosts, Azure confidential compute VMs use Intel SGX or AMD's Secure Encrypted Virtualization-Secure Nested Paging, or SEV-SNP.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#conclusion","title":"Conclusion","text":"

    In this article, we have explored the clean source principle, which states that all security dependencies must be as trustworthy as the object being secured. We have seen how this principle can help us design more secure architectures and avoid common pitfalls that can compromise our data and systems.

    We have also learned about some of the solutions that Microsoft offers to help us achieve clean source, such as Privileged Access Workstations (PAW) and Azure Confidential Compute. These solutions leverage advanced technologies such as Intel SGX and AMD SEV-SNP to protect our sensitive workloads from upstream attacks and side channel threats.

    By following the clean source principle and using these solutions, we can enhance our security posture and reduce our risk exposure in the cloud and beyond.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/","title":"How to Securely Connect to Azure VMs and Use RDP","text":""},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#what-are-azure-vms","title":"What Are Azure VMs","text":"

    Azure Virtual Machines (VMs) run on Microsoft\u2019s cloud computing platform, Azure. They allow users to create, manage, and scale their own virtualized infrastructure in the cloud, without having to invest in physical hardware or deal with maintenance issues.

    To establish a secure connection to your Azure VM, you need to make some preparations. You can avoid exposing your VM\u2019s RDP port to the Internet, which reduces the risk of port scanning and brute force attacks.

    None of the methods described below require you to assign a public IP address or open inbound ports in your Azure VM. They only need a virtual network with a private IP address assigned to the Azure VM.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#bastion","title":"Bastion","text":"

    Azure Bastion uses TLS encryption and firewall traversal for RDP connections, which means your traffic is more secure and less vulnerable to attacks. You also don\u2019t need to manage network security groups (NSGs) for your VM, as you can configure them to allow RDP only from Azure Bastion

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#there-are-many-ways-to-use-bastion-to-connect-to-your-azure-vm","title":"There Are Many Ways to Use Bastion to Connect to Your Azure VM","text":"

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#lets-get-started-with-using-bastion-with-native-client","title":"Let's Get Started With Using Bastion with Native Client","text":"
    1. First get the Bastion ready by Configuring it for native client connections
    Screenshots
    1. Install Azure CLI on your computer. There are many ways to do that but the easiest way is using Winget:
    winget install -e --id Microsoft.AzureCLI\n
    1. Log in to your Azure account, a web page will open.
    az login\n
    1. Gather the following details needed for the next command

      • Bastion name, you can find it by going to your Azure VM and search for \"Bastion\"
      • Azure Resource Group name
      • The VM's Resource ID. The Resource ID can be easily located in the Azure portal. Go to the Overview page for your VM and select the JSON View link to open the Resource JSON. Copy the Resource ID at the top of the page.
    2. Log into RDP, paste this in PowerShell

    az network bastion rdp --name \"<BastionName>\" --resource-group \"<ResourceGroupName>\" --target-resource-id \"<VMResourceId>\"\n

    You now have a secure connection to your Azure VM using Bastion Native Client.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#using-azure-vpn-gui-method","title":"Using Azure VPN - GUI Method","text":"

    Azure VPN Gateway connects your on-premises networks to Azure, or connects Azure virtual networks together, through VPN setups such as Site-to-Site, Point-to-Site etc. The connectivity is secure and uses the industry-standard protocols such as SSTP, IKEv2, OpenVPN etc.

    We need a resource group first because we're going to need a few components: Azure Virtual Network, Azure Public IP address, Azure VPN Gateway. We can either install everything in a separate group or install them in the same resource group as Azure VMs. It will work either way. For this guide, all of the resources reside in the same location, which is UK South.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-resource-group","title":"Create a Resource Group","text":""},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-virtual-network-with-subnets","title":"Create a Virtual Network With Subnets","text":" Screenshots

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-vm-skip-if-you-already-have-one","title":"Create a VM - Skip if You Already Have One","text":"

    Create a VM in Azure and do not allow any open ports from Internet. Do not assign any public IP to the VM.

    In the Virtual Network section, choose the VirtualNetwork1 for the VM and set its Default Subnet accordingly.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-virtual-network-gateway","title":"Create a Virtual Network Gateway","text":" Screenshot

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-point-to-site-vpn-connection","title":"Create a Point-To-Site VPN Connection","text":" Screenshot

    You can connect to other VMs (using RDP) on the same subnet using their private IPs from inside a VM.

    When you don't assign a public IP to a VM, it will only have a private IP address; You can verify this from Control Panel inside the OS.

    Screenshots

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#using-azure-vpn-cloud-powershell-method","title":"Using Azure VPN - Cloud PowerShell Method","text":""},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#run-on-azure-cloud-powershell","title":"Run on Azure Cloud PowerShell","text":"
    # get all of the available location for Azure resources\nGet-AzLocation | Format-Table -Property Location, DisplayName\n\n# Create a new Resource Group\nNew-AzResourceGroup -Name 'ResourceGroup1' -Location uksouth\n\n# Create a new Virtual Network\nNew-AzVirtualNetwork -ResourceGroupName 'ResourceGroup1' -Location 'uksouth' -Name 'VirtualNetwork1' -AddressPrefix '10.0.0.0/14'\n\n# Get the virtual network we created\n$VirtualNetwork1 = Get-AzVirtualNetwork -ResourceGroupName 'ResourceGroup1' -Name 'VirtualNetwork1'\n\n# Add a new subnet to the virtual network named default\nAdd-AzVirtualNetworkSubnetConfig -Name 'Default' -AddressPrefix '10.0.0.0/24' -VirtualNetwork $VirtualNetwork1\n\n# Add the GateWay subnet to the virtual network\nAdd-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -AddressPrefix '10.0.1.0/24' -VirtualNetwork $VirtualNetwork1\n\n# Apply the configurations to the virtual network\n$VirtualNetwork1 | Set-AzVirtualNetwork\n\n# Create a public IP address\nNew-AzPublicIpAddress -Name 'PublicIP1' `\n    -ResourceGroupName 'ResourceGroup1' `\n    -Location 'uksouth' `\n    -AllocationMethod 'Static'\n\n# Get the Public IP address\n$PublicIP1 = Get-AzPublicIpAddress -Name 'PublicIP1' -ResourceGroupName 'ResourceGroup1'\n\n# Get the virtual network\n$VirtualNetwork1 = Get-AzVirtualNetwork -ResourceGroupName 'ResourceGroup1' -Name 'VirtualNetwork1'\n\n# Get the subnet that belongs to Virtual network Gateway from our Virtual Network\n$VN1GatewaySubnet = Get-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -VirtualNetwork $VirtualNetwork1\n\n# Specify the details of the IP Config for the Virtual Network Gateway\n$IpConfigurations1 = New-AzVirtualNetworkGatewayIpConfig -Name 'IpConfigurations1' -Subnet $VN1GatewaySubnet -PublicIpAddress $PublicIP1\n\n# Create the Virtual Network Gateway - This can take a few minutes to complete\nNew-AzVirtualNetworkGateway -Name 'VNGateWay1' `\n    -ResourceGroupName 'ResourceGroup1' `\n    -Location 'uksouth' `\n    -IpConfigurations $IpConfigurations1  `\n    -GatewayType 'Vpn' `\n    -VpnType 'RouteBased' `\n    -GatewaySku 'VpnGw2' `\n    -VpnGatewayGeneration 'Generation2'\n
    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#run-on-your-local-computer","title":"Run on Your Local Computer","text":"
    # Create Root Certificate\n$RootCert = New-SelfSignedCertificate -Type Custom -KeySpec Signature `\n    -Subject 'CN=AzureVirtualGateway1RootCert' -KeyExportPolicy Exportable `\n    -HashAlgorithm sha512 -KeyLength 4096 `\n    -CertStoreLocation 'Cert:\\CurrentUser\\My' -KeyUsageProperty Sign -KeyUsage CertSign `\n    -NotAfter (Get-Date).AddYears(10)\n\n# Create Client Certificate\n$ClientCert = New-SelfSignedCertificate -Type Custom -DnsName 'AzureVirtualGateway' -KeySpec Signature `\n    -Subject 'CN=AzureVirtualGateway1ClientCert' -KeyExportPolicy Exportable `\n    -HashAlgorithm sha512 -KeyLength 4096 `\n    -CertStoreLocation 'Cert:\\CurrentUser\\My' `\n    -Signer $RootCert -TextExtension @('2.5.29.37={text}1.3.6.1.5.5.7.3.2') `\n    -NotAfter (Get-Date).AddYears(10)\n\n# Get the RAW content of the Root certificate for upload to Azure - will be copied to your clipboard\n[System.Convert]::ToBase64String($RootCert.RawData) | clip\n\n# Export the Client certificate with private keys as PFX file\nExport-PfxCertificate -Cert $ClientCert `\n-FilePath \".\\P2SClientCert.pfx\" `\n-Password $(ConvertTo-SecureString -String \"123\" -Force -AsPlainText) -CryptoAlgorithmOption AES256_SHA256 -Force\n
    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#run-on-azure-cloud-powershell_1","title":"Run on Azure Cloud PowerShell","text":"
    $p2srootcert = \"<Root certificate's .cer file's content that is between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----->\"\n\n$RootCertificateAzure = New-AzVpnClientRootCertificate -PublicCertData $p2srootcert -Name 'VPNRootCertificate'\n\n$Gateway = Get-AzVirtualNetworkGateway -ResourceGroupName 'ResourceGroup1' -Name 'VNGateWay1'\n\nSet-AzVirtualNetworkGateway -VirtualNetworkGateway $Gateway `\n    -VpnClientRootCertificate $RootCertificateAzure `\n    -VpnClientAddressPool '20.20.0.0/16' `\n    -VpnAuthenticationType 'Certificate' `\n    -VpnClientProtocol 'SSTP', 'IkeV2'\n\n# Download the VPN client using Azure CLI command\naz network vnet-gateway vpn-client generate --resource-group ResourceGroup1 --name VNGateWay1\n
    \u26a1 Click/Tap here for info about Cmdlets used in the PowerShell commands \u26a1

    "},{"location":"GitHub/Cloning%20Personal%20and%20Enterprise%20Repositories%20Using%20GitHub%20Desktop/","title":"Cloning Personal and Enterprise Repositories Using GitHub Desktop","text":"

    GitHub Desktop enables you to effortlessly clone and manage repositories using a user-friendly graphical interface. GitHub offers various types of repositories, such as personal, Enterprise Cloud and Enterprise Server (Self-Hosted). All of them can either be configured as public or private.

    Cloning a GitHub Enterprise Cloud repository differs from cloning a personal repository. GitHub personal repositories necessitate you to provide the clone URL or simply authenticate with your personal GitHub account credentials.

    GitHub Enterprise Cloud repositories, however, require SSO (Single Sign-On) claim to be added to GitHub Desktop before you can access those repositories. GitHub Desktop runs a loopback token collection server when you sign in.

    If you attempt to sign in without SSO claim, it will be absent from the GitHub Desktop app and you will not be able to clone GitHub Enterprise Cloud repositories.

    At this point, you have to:

    1. Sign out of GitHub Desktop
    2. Go to GitHub.com
    3. Use the \"Single Sign-on\" link at the top to sign in to your Enterprise Cloud
    4. Now go back again to GitHub Desktop -> Options
    5. Use the Sign in button; The browser will be opened and this time when you sign in to GitHub Desktop, the SSO claim to your existing account that grants you access to Enterprise Cloud repositories will be appended as well.

    "},{"location":"GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/","title":"Git GitHub Desktop and Mandatory ASLR","text":"

    Git executables are among few poorly written programs that have problem with Mandatory ASLR (Address Space Layout Randomization) Exploit protection feature. When you turn on Mandatory ASLR in Microsoft Defender (which is off by default), those executables fail to run.

    The same Git executables are bundled with GitHub desktop app. In order to use Git in Visual Studio Code or use GitHub desktop app, we need to exclude Git executables from Mandatory ASLR and let them bypass it. Executables can be excluded from Mandatory ASLR rebootlessly.

    You can use the following PowerShell commands to automatically add all Git executables bundled with GitHub desktop or Git itself, to the exclusion for Mandatory ASLR

    "},{"location":"GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/#for-github-desktop-git-binaries","title":"For GitHub desktop Git binaries","text":"
    Get-ChildItem -Recurse -Path \"C:\\Users\\$env:username\\AppData\\Local\\GitHubDesktop\\*\\resources\\app\\git\\*.exe\" | ForEach-Object -Process { Set-ProcessMitigation -Name $_.Name -Disable ForceRelocateImages }\n
    "},{"location":"GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/#for-git-binaries-installed-using-standalone-installer","title":"For Git binaries installed using standalone installer","text":"
    Get-ChildItem -Recurse -File -Path 'C:\\Program Files\\Git\\*.exe' | ForEach-Object -Process { Set-ProcessMitigation -Name $_.Name -Disable ForceRelocateImages }\n
    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/","title":"Signed and Verified commits with GitHub desktop","text":"

    Web commits, the commits you perform using GitHub website, are automatically verified, but the ones you do from GitHub desktop need to be manually signed.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#signing-using-gpg-key","title":"Signing using GPG key","text":""},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#setting-up-gpg","title":"Setting up GPG","text":"

    Download gpg4win from their official website

    (suggested by GitHub too)

    Begin the installation, choose to only install GnuPG and Kleopatra, don't need any other component.

    After installation, open Kleopatra and create a new GPG key pair by selecting \"New Key Pair\"

    Enter your real name and the email address that is added as one your verified email addresses in your GitHub account settings.

    Select advanced settings and here you can optionally check the box next to \"Authentication\" and also increase the validity period of your GPG key.

    Choosing a passphrase is not mandatory.

    Export the public key by right-clicking on the GPG key and selecting Export. Open the exported file in Notepad or VS code, copy its content and paste it in your GitHub profile's GPG key section so it can be added as a new GPG key to your GitHub account.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#configuring-gitconfig-file","title":"Configuring .gitconfig file","text":"

    Assuming GitHub desktop is installed and logged in on your system, open the .gitconfig file, usually located in User's folder, and add the following items to it.

    Add this section to the end of the file

    [commit]\n  gpgsign = true\n

    And then add this to the [user] section

    signingkey = YourGPGSigningkeyID\n

    Replace YourGPGSigningkeyID with your actual GPG key ID. You can get it from Kleopatra GUI in Key-ID column (enter them without spaces in the .gitconfig file) or you can get it from your GPG keys section in GitHub account settings, Key ID will be visible for you after adding your GPG public key.

    You can set the validity period of your GPG certificate to unlimited, set/change/remove its passphrase and other modifications. You can publish it on the GPG server too so others can look it up and verify it.

    Make sure you backup your secret key using Kleopatra and store it in a safe place, you can import it again on another machine to continue signing your GitHub commits. Public key doesn't need to be backed up as you can regenerate it again by importing the secret GPG key on a different machine.

    Now every time you commit using GitHub desktop, your commits will be signed. If your GPG key has a passphrase, you will be asked to enter it before committing and pushing in GitHub desktop, otherwise signing will happen automatically. Your repository commit history on GitHub website will show verified badge next to them.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#how-to-restore-gpg-for-commit-signing-using-your-current-key-on-a-new-environment","title":"How to restore GPG for commit signing using your current key on a new environment","text":"
    1. Install GitHub desktop and log in with your GitHub account
    2. Configure the .gitconfig file as explained above
    3. install gpg4win as explained above
    4. Open Kleopatra GUI and use the Import button to import your GPG secret key backup to the program. You can also double-click on your GPG secret key backup file and add it to the program that way.
    5. Start committing and pushing changes to your repository using GitHub desktop app, your commits will have a verified badge on GitHub website commit history.
    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#official-resources","title":"Official resources","text":"

    Telling Git about your signing key

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#signing-using-ssh-key","title":"Signing using SSH key","text":""},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#generating-the-key-pair","title":"Generating the key pair","text":"

    Run this command to create a new SSH key pair, using the provided email as a label. It should be one of the emails added to your account as a verified emails.

    ssh-keygen -t ed25519 -C \"spynetgirl@outlook.com\"\n

    Replace spynetgirl@outlook.com with your own email address

    When asked, enter a file name, don't need to specify a file extension (such as .txt). 2 files will be created in User folder. The one with .pub extension contains your public key, the other one contains your private keys. Both of them must be backed up and stored in a safe place.

    Set a passphrase when asked, not mandatory so you can just press enter when asked for a passphrase.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#configuring-ssh-windows-service","title":"Configuring SSH Windows service","text":"
    Set-Service -Name ssh-agent -StartupType Automatic\nSet-Service -Name ssh-agent -Status Running\n

    First make sure you've moved the generated SSH key pair from the default User folder location and stored them somewhere else, can be OneDrive's personal vault, and then run the following command to add the private key of your SSH key pair to the SSH agent.

    ssh-add \"Path/To/SSH/Privatekey\"\n

    If you set a passphrase for your private key from previous steps then you'll be asked to enter it, otherwise you will see the successful message saying \"Identity added\".

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#add-your-ssh-public-key-to-github-account","title":"Add your SSH public key to GitHub account","text":"

    Open the file containing your SSH public key, which has a .pub extension, using a text editor such as Notepad or VS code, copy its content and paste it in your GitHub account settings and save.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#configuring-gitconfig-file_1","title":"Configuring .gitconfig file","text":"

    Add these new sections to the end of your .gitconfig file. It's usually located in User folder C:\\Users\\YourUserName

    [gpg]\n    format = ssh\n[commit]\n    gpgsign = true\n

    and add this to the [user] section to define your SSH public key, it's a direct path to that file.

    signingkey = \"Path/To/SSH/SSHKey.pub\"\n

    You must replace all of the normal backward slashes \\ to forward slash / in your path, otherwise GitHub desktop throws an error.

    Now every time you commit using GitHub desktop, your commits will be signed. If your SSH key has a passphrase, you will be asked to enter it before committing and pushing in GitHub desktop, otherwise signing will happen automatically. Your repository commit history on GitHub website will show verified badge next to them.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#how-to-restore-ssh-for-commit-signing-using-your-current-key-on-a-new-environment","title":"How to restore SSH for commit signing using your current key on a new environment","text":"
    1. Install GitHub desktop and log in with your GitHub account
    2. Configure the .gitconfig file as explained above
    3. Turn on the ssh-agent Windows service
    4. Add your SSH private key to ssh-agent using ssh-add \"Path/To/SSH/Privatekey\" command
    5. Start committing and pushing changes to your repository, your commits will have a verified badge on GitHub website commit history.
    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#official-resources_1","title":"Official resources","text":"

    Telling Git about your SSH key

    Key-based authentication in OpenSSH for Windows

    About commit signature verification

    Adding a new SSH key to your GitHub account

    Generating a new SSH key and adding it to the ssh-agent

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/","title":"Harden Windows Security Module","text":"

    It is a PowerShell module that can apply all of the hardening measures described in the readme. It also offers rigorous compliance verification and security assessment. It enables you to evaluate the conformity of your system based on the security standards and recommendations of this repository. The module employs various techniques such as Security Policy, PowerShell cmdlet and Registry keys to conduct the checks.

    It is also useful for security researchers and penetration testers who want to assess their system security posture. The module works with any system locale and language.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#automatic-updates","title":"Automatic Updates","text":"

    The module checks for updates every time you run it and updates itself if there is a new version available, so you don't have to manually do anything.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#how-to-install-and-use","title":"How to Install and Use","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#install-the-harden-windows-security-module-from-powershell-gallery","title":"Install the Harden Windows Security Module from PowerShell Gallery","text":"
    Install-Module -Name 'Harden-Windows-Security-Module' -Force\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#use-the-gui-graphical-user-interface","title":"Use the GUI (Graphical User Interface)","text":"
    Protect-WindowsSecurity -GUI\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#apply-the-hardening-measures-described-in-the-readme","title":"Apply the Hardening measures described in the Readme","text":"
    Protect-WindowsSecurity\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#perform-compliance-check","title":"Perform Compliance Check","text":"
    Confirm-SystemCompliance\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#remove-the-hardening-measures-described-in-the-readme","title":"Remove the Hardening Measures Described in The Readme","text":"
    Unprotect-WindowsSecurity\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#uninstall-the-harden-windows-security-module","title":"Uninstall the Harden Windows Security Module","text":"
    Uninstall-Module -Name 'Harden-Windows-Security-Module' -Force -AllVersions\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#quick-demo","title":"Quick Demo","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#youtube-demo-of-the-modules-gui","title":"YouTube demo of the Module's GUI","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#protect-windowssecurity","title":"Protect-WindowsSecurity","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#syntax","title":"Syntax","text":"
    Protect-WindowsSecurity\n    [-GUI]\n    [-Categories <String[]>]\n    [-Log]\n    [-Offline]\n    [<CommonParameters>]\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#description","title":"Description","text":"

    The Protect-WindowsSecurity cmdlet's hybrid design allows it to operate as a standalone script and as a module component. It allows it to operate with and without administrator privileges. You can use this cmdlet in both interactive and non-interactive modes.

    In Interactive mode, the cmdlet will ask you to confirm the changes before applying them. In non-interactive mode, you can pre-configure the hardening categories you want to apply and the cmdlet will apply them without asking for confirmation.

    It possesses the ability to operate entirely in isolation, useful for systems or servers that are disconnected from the Internet.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#parameters","title":"Parameters","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-gui","title":"-GUI","text":"

    Shows a graphical user interface (GUI) that allows you to select the hardening categories you want to apply.

    Tip

    In the GUI experience:

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-categories","title":"-Categories","text":"

    Specify the hardening categories that you want to apply. This will tell the module to operate in non-interactive or headless/silent mode which won't ask for confirmation before running each selected categories.

    You can specify multiple categories by separating them with a comma. If you don't specify any category, the cmdlet will run in interactive mode. Use this parameter for deployments at a large scale.

    If a selected category requires Administrator privileges and the module is running with Standard privileges, that category is skipped.

    This parameter has automatic tab completion. You can press the Tab key to see the available categories.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-verbose","title":"-Verbose","text":"

    Shows verbose messages on the console about what the cmdlet is doing.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-log","title":"-Log","text":"

    Activates comprehensive logging by recording all the information shown on the screen and some additional data to a text file. It is strongly advised to use the -Verbose parameter when you want to enable logging.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-logpath","title":"-LogPath","text":"

    The path to save the log file to. If not specified, the log file will be saved in the current working directory.

    Note

    Only available if the -Log switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-offline","title":"-Offline","text":"

    Indicates that the module is being run in offline mode. Will not download any files from the internet. Will not check for updates. Using this parameter will make the following 3 parameters available and mandatory: PathToLGPO, PathToMSFTSecurityBaselines and PathToMSFT365AppsSecurityBaselines.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-pathtolgpo","title":"-PathToLGPO","text":"

    The path to the 'LGPO.zip'. Make sure it's in the zip format just like it's downloaded from the Microsoft servers. File name can be anything. The parameter has argument completer so you can press tab and use the file picker GUI to select the zip file.

    Note

    Only available if the -Offline switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-pathtomsftsecuritybaselines","title":"-PathToMSFTSecurityBaselines","text":"

    The path to the 'Windows Security Baseline.zip'. Make sure it's in the zip format just like it's downloaded from the Microsoft servers. File name can be anything. The parameter has argument completer so you can press tab and use the file picker GUI to select the zip file.

    Note

    Only available if the -Offline switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-pathtomsft365appssecuritybaselines","title":"-PathToMSFT365AppsSecurityBaselines","text":"

    The path to the 'Microsoft 365 Apps for Enterprise zip'. Make sure it's in the zip format just like it's downloaded from the Microsoft servers. File name can be anything. The parameter has argument completer so you can press tab and use the file picker GUI to select the zip file.

    Note

    Only available if the -Offline switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    Note

    You can further control the sub-categories of each category by using the following switch parameters. Pay attention to the naming convention of them. They are named after the category they belong to. For example, the switch parameter -MSFTDefender_SAC belongs to the MicrosoftDefender category. The switch parameters are dynamic and will only appear if you specify the corresponding category in the -Categories parameter. For example, if you don't specify the MicrosoftDefender category in the -Categories parameter, the switch parameters related to it won't appear. The following table shows the available switch parameters and their corresponding categories.

    Parameter Name Description Required Category -SecBaselines_NoOverrides Applies the Microsoft Security Baselines without the optional overrides MicrosoftSecurityBaselines -MSFTDefender_SAC Enables Smart App Control MicrosoftDefender -MSFTDefender_NoDiagData Will not enable optional diagnostics data required for Smart App Control (Does not have any effect if Smart App Control is already turned on) MicrosoftDefender -MSFTDefender_NoScheduledTask Will not create scheduled task for fast MSFT driver block rules MicrosoftDefender -MSFTDefender_BetaChannels Set Defender Engine and Intelligence update channels to beta MicrosoftDefender -LockScreen_CtrlAltDel Require CTRL + ALT + Delete at lock screen LockScreen -LockScreen_NoLastSignedIn Will not display the last signed in user at the lock screen LockScreen -UAC_NoFastSwitching Hide entry points for fast user switching UserAccountControl -UAC_OnlyElevateSigned Only elevate signed and validated executables UserAccountControl -CountryIPBlocking_OFAC Include the IP ranges of OFAC Sanctioned Countries in the firewall block rules CountryIPBlocking

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#what-if-you-dont-configure-the-sub-categories","title":"What if You Don\u2019t Configure the Sub-Categories?","text":"

    If you do not specify any sub-categories using the switch parameters above, the following sub-category configuration will be applied when the corresponding category exists in the -Categories parameter.

    Indicator Sub-Category Status Is Applied Is Not Applied

    Important

    It is highly recommended to always include the Microsoft Security Baselines category and place it first as it forms the foundation of all subsequent categories.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#examples","title":"Examples","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-1","title":"Example 1","text":"

    If you run the module like this without specifying any categories, the module will run in interactive mode and the usual beautiful prompts will be displayed to the user.

    Protect-WindowsSecurity\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-2","title":"Example 2","text":"

    If you run the module like this, the 2 categories will be executed automatically without requiring any user input. The results will be displayed on the console.

    Protect-WindowsSecurity -Categories MicrosoftDefender, AttackSurfaceReductionRules\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-3","title":"Example 3","text":"

    This example will apply the Microsoft Defender category with the Smart App Control sub-category, without the need for user interaction, and will show verbose messages.

    Protect-WindowsSecurity -Categories MicrosoftDefender -MSFTDefender_SAC -Verbose\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-4","title":"Example 4","text":"

    This example will apply the Microsoft Security Baselines, BitLocker, User Account Control, Lock Screen and Downloads Defense Measures categories. It will also apply the \"Only Elevate Signed and Validated Executables\" sub-category of the User Account Control category, and the \"Require CTRL + ALT + DEL on Lock Screen\" sub-category of the Lock Screen category.

    Protect-WindowsSecurity -Categories MicrosoftSecurityBaselines,BitLockerSettings,UserAccountControl,LockScreen,DownloadsDefenseMeasures -UAC_OnlyElevateSigned -LockScreen_CtrlAltDel\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-5","title":"Example 5","text":"

    This example instructs the cmdlet to run in offline mode and will not download any files from the internet. It also runs it in headless/silent mode by specifying which categories to automatically run. -MSFTDefender_SAC switch is used so the Smart App Control sub-category is also applied in the headless/silent mode. -Log switch is mentioned which will save the output of the cmdlet to a text file in the current working directory.

    Protect-WindowsSecurity -Verbose -Offline -PathToLGPO 'C:\\Users\\Admin\\Desktop\\LGPO.zip' -PathToMSFTSecurityBaselines 'C:\\Users\\Admin\\Desktop\\Baselines.zip' -PathToMSFT365AppsSecurityBaselines 'C:\\Users\\Admin\\Desktop\\M365Baselines.zip' -Log -Categories MicrosoftSecurityBaselines,MicrosoftDefender -MSFTDefender_SAC\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-6","title":"Example 6","text":"

    This will display a GUI (Graphical UI) allowing you to easily select various options and categories to apply.

    Protect-WindowsSecurity -GUI\n

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#confirm-systemcompliance","title":"Confirm-SystemCompliance","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#syntax_1","title":"Syntax","text":"
    Confirm-SystemCompliance\n    [-Categories]\n    [-ExportToCSV]\n    [-ShowAsObjectsOnly]\n    [-DetailedDisplay]\n    [-Offline]\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#description_1","title":"Description","text":"

    This cmdlet verifies and validates all of the applied security measures. It checks registry keys if the module uses Group Policy or registry, PowerShell cmdlets if the module invokes them and Security Group Policy if the module applies them.

    Compliance checking strictly follows the guidelines and security measures of this GitHub repository. Any minor deviation from them will result in a false value for the corresponding check.

    Note

    Based on the score that you get you will see a different ASCII art!

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#parameters_1","title":"Parameters","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-categories_1","title":"-Categories","text":"

    Specify the categories to check compliance for. If not specified, all categories will be checked.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-exporttocsv","title":"-ExportToCSV","text":"

    In addition to displaying the results on the screen, also exports them in a nicely formatted CSV for easier viewing. The CSV is fully compatible with GitHub too so you can upload it to GitHub and view it.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-showasobjectsonly","title":"-ShowAsObjectsOnly","text":"

    Instead of displaying strings on the console, outputs actionable objects and properties. You can use this parameter for when you need to store the output of the function in a variable and use it that way. This provides a very detailed nested object and suppresses the normal string output on the console.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-detaileddisplay","title":"-DetailedDisplay","text":"

    Shows the output on the PowerShell console with more details and in the list format instead of table format

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-offline_1","title":"-Offline","text":"

    Skips the online update check and allows you to run the cmdlet in completely offline mode.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#unprotect-windowssecurity-cmdlet","title":"Unprotect-WindowsSecurity Cmdlet","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#syntax_2","title":"Syntax","text":"
    Unprotect-WindowsSecurity\n    [-OnlyProcessMitigations]\n    [-OnlyDownloadsDefenseMeasures]\n    [-OnlyCountryIPBlockingFirewallRules]\n    [-Force]\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#description_2","title":"Description","text":"

    You can use this cmdlet to remove all of the applied hardening measures, with the following exceptions:

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#parameters_2","title":"Parameters","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-onlyprocessmitigations","title":"-OnlyProcessMitigations","text":"

    Indicates that the cmdlet will only remove Process Mitigations (Exploit Protection) settings and doesn't change anything else.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-onlydownloadsdefensemeasures","title":"-OnlyDownloadsDefenseMeasures","text":"

    Indicates that the cmdlet will only remove the Downloads Defense Measures WDAC policy from the system and doesn't change anything else.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-onlycountryipblockingfirewallrules","title":"-OnlyCountryIPBlockingFirewallRules","text":"

    Indicates that the cmdlet will only remove the country IP blocking firewall rules and doesn't change anything else.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    Any feedback or suggestions? Please use GitHub issues or discussions

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/","title":"About TLS, DNS, Encryption and OPSEC concepts","text":"

    The contents here are for beginners, to learn the basics of TLS, encrypted connections and some preliminary OPSEC (Operational security) concepts.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns","title":"DNS","text":"

    Let's talk about DNS first. Whether you are using Secure DNS such as DNS over HTTPS or using plain text DNS (Default port: 53), the domain name is the only piece of information that the DNS server provider will see. DNS does not deal with URLs, only domain names.

    E.g., in this URL, anything after the first / is inaccessible to the DNS server.

    Github.com/HotCakeX/Harden-Windows-Security\n

    The DNS provider will know that you are accessing GitHub.com but won't know which repository on GitHub.com you are visiting.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#about-dns-leak-in-plain-text-dns","title":"About DNS Leak in plain text DNS","text":"

    When you are using VPN or proxies, it's important to make sure there is no DNS leakage. Properly implemented and configured VPNs/Proxies don't have this problem.

    The most practical way to see if you have DNS leak while using a VPN/Proxy is to use Wireshark to monitor your outbound connections on the edge of your network. Simply type dns in the Wireshark's display filter bar and observe the results. If you are using a proper VPN/Proxy or if you are using Secure DNS such as DoH or DoT, then you shouldn't see any results because that keyword only displays plain text DNS over the default port 53.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns-security","title":"DNS Security","text":"

    DNSSEC by itself without using DoH/DoT can be downgraded. If you're using DoH or DoT you must be safe as long as you are using a trusted DNS provider and your certificate authority storage is not poisoned/compromised.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#certificates-and-tls","title":"Certificates and TLS","text":"

    Certain countries with dictatorship or theocracy governments make people install their own root certificate to perform TLS-termination and view their data in plain-text even when HTTPS is being used. One example is what happened in Kazakhstan.

    Certain applications install root certificates, such as 3rd party antiviruses. They are all equally dangerous and must be avoided.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns-privacy","title":"DNS Privacy","text":"

    Using DNS-over-TLS or DNS-over-HTTPS mitigates some privacy leaks, because now the ISP won't have the domain you are visiting, but only the IP address. It's possible that more than one site uses the same IP address, so in some cases, it's not possible to say for sure that you are visiting SiteA.com when SiteB.com shares the same IP (Unless you are using TLS v1.2 which leaks Certificate's common name, more on that later), and high-traffic sites usually employ a CDN (content delivery network) to distribute traffic, and the IP they use are not the site's IP, but an IP belonging to the CDN (like CloudFlare or Akamai).

    Website owners use CDNs like Cloudflare for two purposes:

    1. Best user response time by using the nearest server.

    2. Load-balancing in case of the nearest server being overloaded (DDoS and more) and then pointing to the next-nearest server.

    Browsers such as Microsoft Edge only support DNS over HTTPS. Windows supports DNS over HTTPS and DNS over TLS.

    DNS over HTTPS is preferred because by default it uses the same port 443 as the rest of the HTTPS traffic on the Internet, that makes it harder to be detected and blocked. DNS over TLS on the other hand uses TCP port 853 by default and a filter on that port would block DNS over TLS entirely, whereas blocking port 443 is impractical as it essentially cripples the entire Internet.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns-caching","title":"DNS Caching","text":"

    DNS caches, just like DNS itself, only map domain names to values ('A' records), never the other way around.

    Both the DNS cache, and the DNS system as a whole, only care that bing.com points to 1.2.3.4, not that the address \"points\" back.

    Entries in the DNS cache look exactly like entries in authoritative DNS servers, with domain name as the lookup key.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#tls-security-in-windows","title":"TLS Security in Windows","text":"

    Windows components (Tested on Windows 11 22H2) rely on TLS 1.2, and that makes them dependent on ECC Curves. So, when enforcing TLS 1.3 only for Schannel, Windows components stop working.

    TLS 1.3 cipher suites don't require ECC curves.

    NistP256 ECC curve is a must have, otherwise Windows update won't work.

    nistP521 is the best ECC curve in terms of security, but curve25519 is also the best non-Nist one, which is also secure and popular.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#certificates","title":"Certificates","text":"

    Handshake messages contain the certificates (both from server and client), and they are encrypted in TLS 1.3, which means that you cannot see these without breaking the encryption.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#sni","title":"SNI","text":"

    SNI, which is part of the handshake, is still unencrypted even in TLS v1.3. The only way to encrypt SNI is to use ECH (Encrypted Client Hello).

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#opsec","title":"OPSEC","text":"

    Assuming you are operating in a hostile country (E.g, China, Russia, Iran), you must be aware of the following information to keep your digital footprint minimal.

    There are 4 pieces of information that can reveal which websites/apps/services you use, to the ISP/government.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns_1","title":"DNS","text":"

    Avoid using plain text DNS as much as you can. Use DNS over HTTPS for security and anonymity. Governments can block well-known servers quickly, you can however self-host on a private cloud or use a serverless DNS to have access to a new endpoint for DoH over a newly setup domain.

    If plain text DNS over port 53 is used, and you are not using a proper VPN like OpenVPN or WireGuard, or you are using proxy, then eavesdropper can see the website domain/sub-domain you are visiting. If you use secure DNS like DNS over HTTPS, then DNS becomes fully encrypted and all they can see is the domain name of the Secure DNS server as well as the IP addresses of the websites you connect to.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#certificate-common-name-etc","title":"Certificate (common name etc.)","text":"

    Use TLS v1.3. When using TLS v1.3, the certificate part of the HTTPS connection is encrypted and none of its details are visible to the eavesdropper. TLS v1.2 handshakes do not encrypt the certificates, resulting in the common name and the website you are visiting to be revealed to the eavesdropper.

    Read more

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#url","title":"URL","text":"

    The full path to a web page or web resource is sent over HTTP protocol, so if website uses HTTPS, it's all encrypted.

    When using\u202fHTTPS, the path and query string (everything after TLD and slash /) is encrypted and not available to anybody but the client and server, the answer is encrypted as well.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#sni-server-name-indication-or-client-hello","title":"SNI (Server Name Indication or Client Hello)","text":"

    This is the most important part. Even after using:

    1. HTTPS to encrypt the full URL path

    2. DoH to encrypt the DNS

    3. TLS v1.3 to encrypt the certificate

    If you don't use a proper VPN, SNI can still reveal the domain and sub-domain of the website you are visiting to the eavesdropper. To secure that, the browser and the website must support ECH (Encrypted Client Hello) or use proper VPN like OpenVPN or WireGuard.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#wireshark","title":"Wireshark","text":"

    Interesting and useful columns to add to the Wireshark GUI for better visibility into your network connections:

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/","title":"BitLocker, TPM and Pluton","text":""},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#introduction","title":"Introduction","text":"

    The optimal kind of security measure is imperceptible to the user during deployment and usage. Whenever there is a potential delay or difficulty due to a security feature, there is a high probability that users will attempt to circumvent security. This situation is particularly prevalent for data protection, and that is a scenario that organizations need to prevent. Whether intending to encrypt entire volumes, removable devices, or individual files, Windows satisfies these requirements by providing streamlined, usable solutions. BitLocker Device Encryption safeguards the system by seamlessly implementing device-wide data encryption.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#bitlocker-and-virtual-hard-disks-such-as-vhdx","title":"BitLocker and Virtual Hard Disks such as VHDX","text":"

    When using VHDX native boot, you can employ BitLocker to encrypt the drives that reside in it, they will be equally secure. In the native VHDX boot scenario, the decryption keys are still retained in the TPM, precluding an offline attack against the stored data. BitLocker still operates the same as it does on a normal installed system.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#a-discourse-on-the-modes-and-methods-of-protection-from-physical-intrusions","title":"A Discourse on the Modes and Methods of Protection from Physical Intrusions","text":""},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#bitlocker-with-tpm","title":"BitLocker With TPM","text":"

    BitLocker with TPM only, uses PCRs, if the hashes are the same the decryption key is released. With TPM only mode, a threat actor can access the secret data when it is released and can obtain the decryption key when the TPM releases it automatically.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#bitlocker-with-tpm-and-startup-key","title":"BitLocker With TPM and Startup Key","text":"

    With a Startup PIN, a PIN is required before the secret material is released. This thwarts a jumper cable attack where a threat actor can directly access the secret material from the TPM. Therefore, the only security benefit a PIN would provide during the boot sequence is a physical attack prevention.

    If you are a threat actor and the system lacks a Startup PIN, the disk remains encrypted even when you boot it to the logon screen where authentication is required via Windows Hello credential providers. Conversely, when you use a Startup PIN and enter it correctly, the disk stays encrypted until you authenticate at the logon screen.

    When BitLocker is activated, the disk is constantly encrypted. It is irrelevant whether you utilize a Startup PIN, or you operate in TPM only mode or you employ a smart card to unlock it. However, a Startup PIN is invariably recommended as a deterrent mechanism against physical attacks.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#the-power-of-bitlocker-and-tpm-against-offline-and-side-channel-attacks","title":"The Power of BitLocker and TPM Against Offline and Side Channel Attacks","text":"

    Now there is the in-band versus out of band security system paradigm we need to discuss. For instance, Windows login screen is in-band and TPM is out of band.

    The TPM is used to deter side channel attacks while login screen is to deter brute force/cryptographic attacks. Windows Hello, which is a very robust system, is TPM backed just like BitLocker.

    BitLocker is to prevent offline attacks primarily, secondarily it is to prevent data loss. If you can alter the Windows operating system files while it is offline, it has no means to protect itself. That is why BitLocker exists to impede tampering while the system is offline. Most people assume it is used for data loss prevention; in reality the primary defense capability is tampering with OS files.

    I can guarantee breach into any operating system that has an unencrypted disk, and I don\u2019t have to use any zero days or exploit code.

    BitLocker is a transparent drive encryption technology operating below the file system level and BitLocker encrypted disks always remain encrypted even after Windows Hello authentication and unlocking the OS.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#how-do-the-bitlocker-key-protectors-work","title":"How Do The BitLocker Key Protectors Work?","text":"

    BitLocker key protectors safeguard the encryption key, which encrypts and decrypts the data on the disk. BitLocker provides various key protectors and allows using multiple key protectors simultaneously. However, some key protectors must be combined with other key protectors to attain the required level of security.

    Suppose you want your BitLocker encrypted drive to demand a PIN at Startup, need TPM for verification, and also necessitate a USB flash drive to be plugged in. In this document, you can see there is a -StartupKeyProtector option for the USB flash drive, -TPMProtector option for TPM, and a -Pin option for the PIN.

    Using those parameters individually will not mandate all 3 key protectors to be used concurrently. It will only oblige one of them to be used. So you will have to either enter the PIN, have the disk connected to the same computer (TPM) or have the USB flash drive plugged in, but all 3 of them are not enforced.

    If you want to enforce a multifactor authentication, you need to use the following command

    Add-BitLockerKeyProtector -MountPoint C: -TpmAndPinAndStartupKeyProtector\n

    This time, all 3 key protectors are essential to unlock the drive. You will have to enter the PIN, have the disk connected to the same computer (TPM), and have the USB flash drive plugged in.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#pluton-the-ultimate-security-chip","title":"Pluton, The Ultimate Security Chip","text":"

    One of the most formidable technologies that is impervious to tampering, jumper cable or other vulnerabilities is the Pluton chip. The same technology that has been employed in Xbox to stop even the most sophisticated physical attacks.

    Pluton is a dedicated physical chip that runs on Azure sphere architecture. It is very much out of band and is technically physically on the same die as the CPU, but the CPU has no control over it at all because it has its own dedicated self-maintaining operating system.

    A firmware based TPM is reliant on the CPU to emulate it, Pluton is not dependent on the CPU to emulate it or run it. Pluton is completely self-sufficient which implies that it is out of band. dTPM (discrete TPMs) are usually more susceptible than fTPMs (Firmware based TPMs).

    Pluton addresses security needs like booting an operating system securely even against firmware threats and storing sensitive data safely even against physical attacks.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#conclusion","title":"Conclusion","text":"

    We learned how important it is to use BitLocker and protect our data at rest. The Harden Windows Security repository employs BitLocker to encrypt the operation system drive and optionally any other drives that user chooses to. It utilizes the most secure configuration and military grade encryption algorithm, XTS-AES-256, TPM 2.0 and Start-up PIN.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#continue-reading","title":"Continue Reading","text":""},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/","title":"Comparison of security benchmarks","text":"

    I conducted a thorough analysis of some of the prominent security benchmarks/guidelines for my GitHub repository and I discovered some fascinating insights. By analysis, I mean that I examined every single recommendation in them and compared them with my own suggestions and Microsoft Security Baselines.

    The majority of the recommendations in the security benchmarks align with the Microsoft Security Baselines, which are a set of best practices for securing various products and services. Only a small fraction of the recommendations deviate from the baselines, and they are either additional enhancements (rarely), redundant suggestions or erroneous advice that undermine security!

    For my reviews I used the latest available version of each benchmark.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#some-of-the-pitfalls-of-relying-on-third-party-benchmarks","title":"Some of the Pitfalls of Relying on Third-Party Benchmarks","text":""},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#clipboard-sharing-from-guest-to-host","title":"Clipboard sharing from guest to host !","text":"

    CIS 18.10.44.5 (L1) recommends allowing clipboard operation from an isolated session to the host, i.e. guest to host redirection, which is a highly insecure and irrational suggestion!

    These are their precise official words:

    Rationale: The primary purpose of Microsoft Defender Application Guard is to present a \"sandboxed container\" for visiting untrusted websites. If the host clipboard is made available to Microsoft Defender Application Guard, a compromised Microsoft Defender Application Guard session will have access to its content, potentially exposing sensitive information to a malicious website or application. However, the risk is reduced if the Microsoft Defender Application Guard clipboard is made accessible to the host, and indeed that functionality may often be necessary from an operational standpoint

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#renaming-built-in-administrator-and-guest-accounts","title":"Renaming built-in administrator and guest accounts !","text":"

    Both CIS and STIG suggest altering the name of the built-in administrator and guest accounts as a security measure.

    This is futile as those built-in accounts can be readily identified by PowerShell, regardless of any modifications to its name or description (which I have done).

    For example, the BUILTIN\\Administrator account always has a relative identifier (RID) of 500.

    Get-LocalUser | Where-Object -FilterScript {$_.SID -like 'S-1-5-*-500'}\n

    Thanks Elliot Huffman for suggesting the shorter command!

    Add-Type -AssemblyName System.DirectoryServices.AccountManagement\n$principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)\n$userPrincipal = New-Object System.DirectoryServices.AccountManagement.UserPrincipal($principalContext)\n$searcher = New-Object System.DirectoryServices.AccountManagement.PrincipalSearcher\n$searcher.QueryFilter = $userPrincipal\n$searcher.FindAll() | Where-Object { $_.Sid -Like \"*-500\" } | Select-Object SamAccountName</details>\n

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#disabling-windows-hello-pin-and-using-traditional-passwords-instead","title":"Disabling Windows Hello PIN and using traditional passwords instead !","text":"

    These benchmarks recommend disabling Windows Hello PIN and opting for passwords instead. Stig V-253423 and CIS 18.9.27.4.

    They argue that this is for domain accounts

    Their rationale, which is very wrong, is

    A PIN is created from a much smaller selection of characters than a password, so in most cases a PIN will be much less robust than a password.

    It is a grave security lapse to propose such a policy and then label the benchmark/guideline as \u201cCIS Microsoft Windows 11 Stand-alone Benchmark\u201d, highlighting that it is intended for stand-alone computers, while simultaneously suggesting to disable PIN for domain-joined devices. This is a glaring inconsistency and a perilous practice.

    The guideline/benchmark is fundamentally flawed if it presupposes that the computer is domain-joined, despite the label indicating that it is stand-alone. It also neglects to consider that some users may actually be stand-alone (home users that account for the majority of the users) or use Microsoft Entra ID, and this policy is nonsensical for them.

    STIG commits the same error, as it only provides a generic Windows 11 guideline/benchmark and recommends disabling Windows Hello PIN, without taking into account the factors mentioned above.

    You can read this Microsoft document to find out why a PIN is better than an online password

    There are proper policies regarding anti-hammering features that can enhance the security of PINs over passwords. I utilize them in my module and you can find them here.

    The benchmarks/guidelines seem to be uninformed of the fact that Windows allows multi-factor unlock, which can enforce a combination of PIN and biometric factors (plus more), to enforce PIN + Facial recognition OR PIN + Fingerprint etc.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#bad-configuration-for-early-launch-anti-malware","title":"Bad configuration for Early Launch Anti Malware","text":"

    CIS in 18.9.13.1

    The recommended state for this setting is: Enabled: Good, unknown and bad but critical

    That's not even a recommendation, that's the default value! If you use Harden Windows Security module it sets it to Good Only, which is the correct recommendation for a secure environment.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#disabling-windows-error-reporting","title":"Disabling Windows Error reporting !","text":"

    Their rationale is:

    ...There is no benefit to the corporation to report these errors directly to Microsoft...

    Indeed, the corporation that uses the software benefits from it by reporting the problems. This exact way of thinking that leads to making such a policy is the reason why problems remain unsolved, because they are not reported to Microsoft and the IT staff of the companies are simply unable to resolve the problem themselves, since they are not the ones developing the OS.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#disabling-cloud-protection","title":"Disabling Cloud Protection!","text":"

    CIS 18.10.43.5.2 (L2), suggests disabling Cloud Protection of Microsoft Defender. This is precisely the kind of security measure that Threat Actors and advanced persistent threats (APTs) seek to disable and then CIS is suggesting to disable it, astonishing.

    This is an extremely important security feature that should never be disabled and there is no rationale that justifies disabling it. This feature also uses the Intelligent Security Graph (ISG).

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#not-enabling-important-attack-surface-reduction-rules","title":"Not enabling important Attack Surface Reduction rules","text":"

    CIS in 18.10.43.6.1.2 (L1) intentionally leaves out very important ASR rules

    1. Use advanced protection against ransomware
    2. Block executable files from running unless they meet a prevalence, age, or trusted list criterion
    3. Block process creations originating from PSExec and WMI commands

    Rule #2 has the potential to prevent zero-days!

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#to-be-continued","title":"To be continued...","text":"

    These benchmarks or guidelines have numerous flaws and I have only examined two of them. There are many other benchmarks, standards, guidelines, etc. that may also contain errors or inconsistencies and are totally unsafe to implement them.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#aspects-that-are-lacking","title":"Aspects that are lacking","text":"

    The benchmarks omit many new security features that the Harden Windows Security module implements.

    Everything in the repository is carefully researched, evaluated and tested. The module ensures that nothing is redundant or incompatible with the latest version of Windows. Older versions of the OS are obsolete and insecure, and should be avoided in any environment that requires protection. Threat actors can exploit vulnerabilities and use PoCs even on the same day that an update is released, this applies to any OS.

    The security measures in the Harden Windows Security repository are also perfectly suitable for regular home users.

    There are many security measures that are missing from the benchmarks/guidelines, such as the ones I use in:

    The benchmarks/guidelines suggest using application control or whitelisting, but that's just it, a suggestion, no comprehensive guide about how to do it.

    "},{"location":"Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/","title":"Create Bootable flash drive no 3rd party tools","text":""},{"location":"Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/#create-bootable-usb-flash-drive-with-no-3rd-party-tools","title":"Create Bootable USB flash drive with no 3rd party tools","text":""},{"location":"Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/#steps-to-create-bootable-usb-flash-drive-with-no-3rd-party-tools","title":"Steps to create Bootable USB flash drive with no 3rd party tools","text":"
    1. Plug in a USB flash drive that has at least 8GB capacity.

    2. Delete all partitions on the USB flash drive either using Disk Management \u00b9 \u00b2 or using Windows Settings => System => Storage => Advanced Storage Settings => Disks & Volumes

    3. Using either of the methods above, create a 1GB FAT32 partition, let's name it BOOT\ud83d\udfe8

    4. Create a 2nd partition on the USB flash drive with the rest of the remaining unused space, formatted as NTFS, let's name this one DATA\ud83d\udfe9

    5. Mount your Windows ISO file by double clicking on it.

    6. Select all and Copy everything from Windows ISO file to the NTFS partition (DATA partition\ud83d\udfe9)

    7. Copy everything from Windows ISO file, except for the \"sources\" folder, to the FAT32 partition (BOOT partition\ud83d\udfe8)

    8. Create a new folder in the FAT32 partition (BOOT partition\ud83d\udfe8), and name it sources

    9. copy the boot.wim from the \"sources\" folder inside the Windows ISO file to the newly created \"sources\" folder in the FAT32 partition (BOOT partition\ud83d\udfe8).

    10. That's it, your USB flash drive is ready and bootable.

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/","title":"Device Guards","text":""},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-guards","title":"Device Guards","text":""},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-guard","title":"Device Guard","text":"

    Most of the Device Guard and Virtualization-Based Security features are Automatically enabled by default on capable and modern hardware. The rest of them will be enabled and configured to the most secure state after you apply the Microsoft Security Baselines 23H2 or later.

    The Harden Windows Security Module has a feature that is accessible through confirm-SystemCompliance cmdlet. It will let you scan your system and verify the implementations of the Device Guard policies.

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#about-uefi-lock","title":"About UEFI Lock","text":"

    UEFI locked security measures are rooted in Proof of Physical Presence and they can't be disabled by modifying Group Policy, registry keys or other Administrative tasks.

    The only way to disable UEFI locked security measures is to have physical access to the computer, reboot and access the UEFI settings, supply the credentials to access the UEFI, turn off Secure Boot, reboot the system and then you will be able to disable those security measures with Administrator privileges.

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-guard-controls-and-policies","title":"Device Guard Controls and Policies","text":"

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-protection-in-windows-security-gives-you-one-of-these-4-hardware-scores","title":"Device Protection in Windows Security Gives You One of These 4 Hardware Scores","text":"
    1. Standard hardware security not supported
      • This means that your device does not meet at least one of the requirements of Standard Hardware Security.
    2. Your device meets the requirements for Standard Hardware Security.
      • TPM 2.0
      • Secure boot
      • DEP
      • UEFI MAT
    3. Your device meets the requirements for Enhanced Hardware Security
      • TPM 2.0
      • Secure boot
      • DEP
      • UEFI MAT
      • Memory Integrity
    4. Your device has all Secured-core PC features enabled
      • TPM 2.0
      • Secure boot
      • DEP
      • UEFI MAT
      • Memory Integrity
      • System Management Mode (SMM)
    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#additional-resources","title":"Additional Resources","text":""},{"location":"Miscellaneous/Event%20Viewer/","title":"Event Viewer","text":""},{"location":"Miscellaneous/Event%20Viewer/#event-viewer","title":"Event Viewer","text":""},{"location":"Miscellaneous/Event%20Viewer/#windows-event-viewer","title":"Windows Event Viewer","text":"

    This document is dedicated to offering various ways to use Event logs to achieve different purposes.

    "},{"location":"Miscellaneous/Event%20Viewer/#how-to-identify-which-windows-firewall-rule-is-responsible-for-a-blocked-packet","title":"How to identify which Windows Firewall rule is responsible for a blocked packet","text":"

    I've mostly considered this for the Country IP Blocking category, but you can use it for any purpose.

    Before doing this, you need to activate one of the system Audits.

    I suggest doing it using GUI because it will have a permanent effect:

    Or you can activate that Audit using this command, but it will only temporarily activate it and it'll be disabled again after you restart Windows.

    "},{"location":"Miscellaneous/Event%20Viewer/#for-systems-with-english-locale-only","title":"For Systems With English Locale Only","text":"
    Auditpol /set /category:\"System\" /SubCategory:\"Filtering Platform Packet Drop\" /success:enable /failure:enable\n
    "},{"location":"Miscellaneous/Event%20Viewer/#for-systems-with-any-locale","title":"For Systems With Any Locale","text":"
    Auditpol /set /category:\"{69979848-797A-11D9-BED3-505054503030}\" /SubCategory:\"{0CCE9225-69AE-11D9-BED3-505054503030}\" /success:enable /failure:enable\n

    After the Audit is activated, running this PowerShell code will generate an output showing you blocked packets (if any).

    For example, if you visit a website or access a server that is hosted in one of the countries you blocked, or a connection was made from one of those countries to your device, it will generate an event log that will be visible to you once you run this code.

    "},{"location":"Miscellaneous/Event%20Viewer/#link-to-the-get-blockedpackets-function","title":"\u27a1\ufe0f Link to the Get-BlockedPackets Function","text":""},{"location":"Miscellaneous/Event%20Viewer/#how-to-get-event-logs-in-real-time-in-powershell","title":"How to Get Event Logs in Real Time in PowerShell","text":"

    This code assumes you've already used the Harden Windows Security Module and the event logs custom views exist on your machine.

    In this example, any logs generated for Exploit Protection is displayed in real time on PowerShell console. You can modify and improve the displayed output more according to your needs.

    "},{"location":"Miscellaneous/Event%20Viewer/#link-to-the-get-eventdata-function","title":"\u27a1\ufe0f Link to the Get-EventData Function","text":"

    If you don't want the real time mode and just want to get the logs one time, you can use the following code

    # Load the XML content from a file or a string\n$xml = [xml](Get-Content -Path 'C:\\ProgramData\\Microsoft\\Event Viewer\\Views\\Hardening Script\\Exploit Protection Events.xml')\n\n# Get the QueryList element using XPath\n$queryList = $xml.SelectSingleNode(\"//QueryList\")\n\n# Convert the QueryList element to a string\n$queryListString = $queryList.OuterXml\n\n$Events = Get-WinEvent -FilterXml $queryListString -Oldest\n$Events | Format-Table -AutoSize\n

    "},{"location":"Miscellaneous/Group%20Policy/","title":"Group Policy usage in this GitHub repository","text":""},{"location":"Miscellaneous/Group%20Policy/#microsoft-security-compliance-toolkit","title":"Microsoft Security Compliance Toolkit","text":"

    This set of tools allows enterprise security administrators to download, analyze, test, edit and store Microsoft-recommended security configuration baselines for Windows and other Microsoft products, while comparing them against other security configurations.

    Microsoft Security Compliance Toolkit includes multiple files and useful programs that are required for the Harden Windows Security Module to operate.

    "},{"location":"Miscellaneous/Group%20Policy/#microsoft-security-baseline","title":"Microsoft Security Baseline","text":"

    Microsoft is dedicated to providing its customers with secure operating systems, such as Windows and Windows Server, and secure apps, such as Microsoft 365 apps for enterprise and Microsoft Edge. In addition to the security assurance of its products, Microsoft also enables you to have fine control over your environments by providing various configuration capabilities.

    Even though Windows and Windows Server are designed to be secure out-of-the-box, many organizations still want more granular control over their security configurations. Continue reading more in the Microsoft website

    When you unzip the Microsoft Security Baseline file, you will find this folder structure:

    1. Documentation - contains PDF and Excel files describing the differences between the previous baseline release and the new settings that were added. contains the default policyrules file, which is used with the Security Compliance Toolkit, you can view it using Policy Analyzer program.
    2. GP Reports - contains reports in HTML format, describes the GPO settings that can be applied for each category.
    3. GPOs \u2013 contains GPO objects for different scenarios, these are the actual policies that will be applied.
    4. Scripts - contains multiple PowerShell scripts for different scenarios and helps us easily import GPO settings to our system. The most important PowerShell script here is Baseline-LocalInstall.ps1.
    5. Templates \u2013 contains additional Group Policy Object templates that are not available by default on Windows, such as MSS-legacy.admx, these are in ADMX and ADML formats. They will be copied to C:\\Windows\\PolicyDefinitions, where they belong, so that the new Security Baselines GPOs can be interpreted.

    "},{"location":"Miscellaneous/Group%20Policy/#lgpo","title":"LGPO","text":"

    Quoting from the PDF file supplied by LGPO:

    LGPO.exe is a command-line utility that is designed to help automate management of Local Group Policy. It can import and apply settings from Registry Policy (Registry.pol) files, security templates, Advanced Auditing backup files, as well as from formatted \"LGPO text\" files and Policy Analyzer '.PolicyRules' XML files.

    It can export local policy to a GPO backup. It can export the contents of a Registry Policy file to the 'LGPO textformat' that can then be edited, and can build a Registry Policy file from an LGPO text file. (The syntax for LGPO text files is described later in this document.)

    LGPO.exe has four command-line forms: for importing and applying settings to local policy \u2013 including to Multiple Local Group Policy Objects (MLGPO)1 ; for creating a GPO backup; for parsing a Registry Policy file and outputting \"LGPO\" text; for producing a Registry Policy file from an LGPO text file.

    All output is written to LGPO.exe's standard output, and all diagnostic and error information is written to its standard error. Both can be redirected to files using standard command shell operations. To support batch file use, LGPO.exe's exit code is 0 on success and non-zero on any error.

    LGPO is the most crucial program for our workflow, it is part of the Security Compliance Toolkit (SCT)

    What is the Local Group Policy Object (LGPO) tool?

    LGPO.exe - Local Group Policy Object Utility

    "},{"location":"Miscellaneous/Group%20Policy/#how-to-manually-back-up-group-policy-objects-from-a-system-using-lgpoexe","title":"How to Manually Back up Group Policy Objects From a System Using LGPO.exe","text":"

    Use this command to back up the currently set local group policies to drive C

    .\\LGPO.exe /b C:\n
    "},{"location":"Miscellaneous/Group%20Policy/#how-to-import-group-policy-objects-from-a-backup-created-using-lgpoexe-to-the-local-system","title":"How to Import Group Policy Objects From a Backup, Created Using LGPO.exe, to the Local System","text":"
    .\\LGPO.exe /g 'Path to the backup'\n

    Example:

    .\\LGPO.exe /g 'C:\\{841474E6-33EC-418C-B884-EA0F7C8195DB}'\n
    "},{"location":"Miscellaneous/Group%20Policy/#how-to-import-only-the-settings-from-a-registry-policy-file-into-computer-machine-configuration","title":"How to Import Only the Settings From a Registry Policy File Into Computer (Machine) Configuration","text":"

    (This only contains everything in Computer (Machine) Configuration -> Administrative Templates and some policies in Computer Configuration -> Windows Settings)

    Registry Policy File Format

    .\\LGPO.exe /m <Path to registry.pol file>\n
    "},{"location":"Miscellaneous/Group%20Policy/#how-to-import-only-the-security-policies-file-into-computer-machine-configuration","title":"How to Import only the Security policies file into Computer (Machine) Configuration","text":"

    (This only contains everything in Computer (Machine) Configuration -> Windows Settings => Security Settings => everything in the subfolders except for the Advanced Audit Policy Configuration)

    Security policy settings

    .\\LGPO.exe /s \".\\GPOX\\DomainSysvol\\GPO\\Machine\\microsoft\\windows nt\\SecEdit\\GptTmpl.inf\"\n

    "},{"location":"Miscellaneous/Group%20Policy/#policy-analyzer","title":"Policy Analyzer","text":"

    Quoting from the PDF file supplied by Policy Analyzer:

    Policy Analyzer is a lightweight utility for analyzing and comparing sets of Group Policy Objects (GPOs). It can highlight when a set of Group Policies has redundant settings or internal inconsistencies and can highlight the differences between versions or sets of Group Policies.

    It can also compare one or more GPOs against local effective state. You can export all its findings to a Microsoft Excel spreadsheet.

    Policy Analyzer lets you treat a set of GPOs as a single unit, and represents all settings in one or more GPOs in a single \".PolicyRules\" XML file. You can also use .PolicyRules files with LGPO.exe v3.0 to apply those GPOs to a computer's local policy, instead of having to copy GPO backups around.

    What is the Policy Analyzer tool?

    Policy Analyzer Tool

    "},{"location":"Miscellaneous/Group%20Policy/#about-compare-to-effective-state","title":"About Compare to Effective State","text":"

    In Policy Analyzer, there is an option called Compare to Effective State. Quoting from the PDF file that ships with Policy Analyzer program regarding that option:

    Enable one or more of the Policy Rule sets' checkboxes and click \"Compare to Effective State\" to compare the selected baselines against the local computer's current configured state. The operation will require UAC elevation if any of the selected baselines include security template or advanced auditing settings that require elevation to retrieve.

    The Policy Viewer will show the combined settings from all the selected Policy Rule sets in one column under the heading \"Baseline(s),\" and the corresponding current settings on the local computer and the logged-on user in a separate column under the heading \"Effective state.\"

    The effective state settings are also saved to a new .PolicyRules file with a name combining \"EffectiveState_,\" the current computer name, and the current date and time in the format \"yyyyMMdd- HHmmss.\" For example, \"EffectiveState_WKS51279_20200210-183947.PolicyRules.\"

    "},{"location":"Miscellaneous/Group%20Policy/#how-are-group-policies-used-by-the-harden-windows-security-module","title":"How Are Group Policies Used by the Harden Windows Security Module?","text":"
    1. The module downloads the official Microsoft Security Baselines from Microsoft servers and applies them to the system.

    2. It then downloads Group Policies from this GitHub repository, which represent the configurations explained in the main Readme page, and applies them to the system, on top of Microsoft Security Baselines, so where there is a conflict of policy, the module will replace the configurations set by Microsoft Security Baselines.

    3. When applying the Microsoft Security Baselines, you have the option to apply the optional overrides too, you can find the details of those overrides in here,, they are required to be applied if you are using Harden Windows Security Module in Azure VMs and highly recommended in general.

    "},{"location":"Miscellaneous/Group%20Policy/#how-are-group-policies-for-the-module-created-and-maintained","title":"How Are Group Policies for the Module Created and Maintained?","text":""},{"location":"Miscellaneous/Group%20Policy/#how-i-created-them-for-the-first-time","title":"How I Created Them for the First Time","text":"
    1. Installed the newest available Windows build on a fresh Hyper-V VM, fully updated it, created a standard checkpoint.

    2. Opened Group Policy editor and started applying security measures described in the Readme page.

    3. After completing each category, used LGPO.exe /b C: to backup Group Policies of the system by creating a full GPO.

    4. Then I took only files needed from the backup, registry.pol and GptTmpl.inf and put them in a zip file, renamed it to Security-Baselines-X.zip

    "},{"location":"Miscellaneous/Group%20Policy/#how-i-maintain-them","title":"How I Maintain Them","text":"
    1. As long as the VM is still using the latest available build of Windows, I use the standard checkpoint I had created to revert the VM back to that new state. If there is a newer build of Windows available, I delete that old VM, download the new Windows ISO file from Microsoft servers, then I create a fresh Hyper-V VM using it.

    2. I copy the Group Policy files, registry.pol or GptTmpl.inf to the VM, import them by using .\\LGPO.exe /m \"path\" for registry.pol files or .\\LGPO.exe /s \"path\" for GptTmpl.inf files.

    3. Open Group Policy editor and change anything that is needed, once I'm done, I create a full backup of the Group Policies of the system using LGPO.exe /b C: command, again take out the modified file, either registry.pol or GptTmpl.inf.

    4. Use PolicyAnalyzer to double check everything by comparing the old file with the new one and making sure the correct changes are applied.

    5. Replace the old Group Policy file with the new file and create a new Security-Baselines-X to upload to the GitHub repository.

    "},{"location":"Miscellaneous/Group%20Policy/#we-can-use-policy-analyzer-for-verification-and-comparison","title":"We Can Use Policy Analyzer for Verification and Comparison","text":""},{"location":"Miscellaneous/Group%20Policy/#to-verify-the-settings-are-applied-correctly-by-the-module","title":"To Verify the Settings Are Applied Correctly by The Module","text":"
    1. Use folder options in Control Panel or File Explorer to show hidden files and folder.

    2. Open Policy Analyzer program, Navigate to Add -> File -> Add files from GPO(s)... -> Browser for this folder \"C:\\Windows\\System32\\GroupPolicy\", Select the folder -> Import -> save the Policy Rules file in \\Documents\\PolicyAnalyzer\\

    3. Back at the main window, use View/Compare button to view applied Group Policies. The result that you will see is all of the Group Policies that are applied to your system.

    Another way to verify the applied Group Policies is to perform the 3 tasks above; What it will give you is the Policy Rules file which is generated from Group Policy state after using the module. If we take this policy rules file to a different machine where we just clean installed Windows and use Policy Analyzer to compare it to the Effective State of the system, we will see what Group Policy settings have changed as a result of using the module.

    Note: At first, when we clean install Windows, the Group Policy folder C:\\Windows\\System32\\GroupPolicy is empty, it will get populated with empty folders and a 1kb file that contains only 1 word when we first open the local Group Policy editor. It will get more populated with actual policies once we start modifying any group policies.

    "},{"location":"Miscellaneous/Group%20Policy/#how-to-verify-security-baselines-xzip-file-and-100-trust-it","title":"How to verify security-baselines-x.zip file and 100% trust it?","text":"
    1. Download the security-baselines-x.zip file, extract it.
    2. Open Policy Analyzer, Navigate to Add -> File -> Select either Add User Configuration (registry.pol) or Add Security Template (*.inf) -> Browser for the folder that was extracted from the security-baselines-x.zip, navigate to the category you want.
    3. Select either .pol or .inf file, Import it, give it a name, save it in \\Documents\\PolicyAnalyzer\\

    4. Back at the main window, use \"Compare to Effective State\" button to view what policies are included in the file.

    5. As you will see, everything is according to what has been explicitly stated in the GitHub's Readme page.

    You can also use Virus Total website to scan security-baselines-x.zip without downloading it first

    "},{"location":"Miscellaneous/Group%20Policy/#using-configuration-service-providers-csps-and-provisioning-packages-work-in-progress","title":"Using Configuration Service Providers (CSPs) and Provisioning Packages (Work in Progress)","text":"

    This command gets the information about all installed provisioning packages on your system.

    Get-ProvisioningPackage -AllInstalledPackages\n

    Configuration service providers for IT pros

    Settings changed when you uninstall a provisioning package

    Why Intune and CSPs are the future of Windows management instead of Group Policy

    Link to Microsoft Employee's comment

    Download Windows Configuration Designer from Microsoft Store or from Windows ADK or from Windows insiders ADK, to easily create provisioning packages for your device(s)

    You can use gpresult to see more info about Group Policies on your computer

    # What policies are applied to your computer:\ngpresult /z\n# or\ngpresult /v\n\n# What policies are applied to the current user:\ngpresult /scope user /v\n

    We can manually backup and restore Group Policy settings by copying this folder and all of its content:

    C:\\Windows\\System32\\GroupPolicy

    "},{"location":"Miscellaneous/How%20to%20Detect%20Changes%20in%20User%20and%20Local%20Machine%20Certificate%20Stores%20in%20Real%20Time%20Using%20PowerShell/","title":"How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell","text":"

    Here is a PowerShell script that can display the changes in User and Local Machine Certificate Stores in Real Time. It performs the check every 3 seconds. The script is published to PowerShell Gallery and you can easily install it using the following command:

    Install-Script -Name Certificates-Change-Detection -Force\n

    "},{"location":"Miscellaneous/How%20to%20Detect%20Changes%20in%20User%20and%20Local%20Machine%20Certificate%20Stores%20in%20Real%20Time%20Using%20PowerShell/#the-code-used-in-the-script","title":"The Code used in the script","text":"
    #Requires -RunAsAdministrator\n#Requires -Version 7.3\n\n# Custom colors\n[scriptblock]$WritePink = { Write-Output \"$($PSStyle.Foreground.FromRGB(255,192,203))$($PSStyle.Blink)$($args[0])$($PSStyle.Reset)\" }\n[scriptblock]$WriteMintGreen = { Write-Output \"$($PSStyle.Foreground.FromRGB(152,255,152))$($PSStyle.Blink)$($args[0])$($PSStyle.Reset)\" }\n\n# Create variables to store the initial certificates for both locations\n$InitialLocal = Get-ChildItem Cert:\\LocalMachine\\* -Recurse\n$InitialUser = Get-ChildItem Cert:\\CurrentUser\\* -Recurse\n\n# Create a loop that runs indefinitely\nwhile ($true) {\n    # Create variables to store the current certificates for both locations\n    $CurrentLocal = Get-ChildItem Cert:\\LocalMachine\\* -Recurse\n    $CurrentUser = Get-ChildItem Cert:\\CurrentUser\\* -Recurse\n\n    # Compare the variables and check if there is any difference in certificates for LocalMachine\n    $DifferenceLocal = Compare-Object $InitialLocal $CurrentLocal\n\n    # Compare the variables and check if there is any difference in certificates for CurrentUser\n    $DifferenceUser = Compare-Object $InitialUser $CurrentUser\n\n    # If there is any difference in certificates for LocalMachine, display it and update the initial variable\n    if ($DifferenceLocal) {\n        foreach ($Diff in $DifferenceLocal) {\n            # Check if the change is an addition or a removal based on the side indicator\n            if ($Diff.SideIndicator -eq '=>') {\n                &$WritePink \"Certificate Added to LocalMachine at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(255,192,203))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n            elseif ($Diff.SideIndicator -eq '<=') {\n                &$WriteMintGreen \"Certificate Removed from LocalMachine at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(152,255,152))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n        }\n        $InitialLocal = $CurrentLocal\n    }\n\n    # If there is any difference in certificates for CurrentUser, display it and update the initial variable\n    if ($DifferenceUser) {\n        foreach ($Diff in $DifferenceUser) {\n            # Check if the change is an addition or a removal based on the side indicator\n            if ($Diff.SideIndicator -eq '=>') {\n                &$WritePink \"Certificate Added to CurrentUser at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(255,192,203))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n            elseif ($Diff.SideIndicator -eq '<=') {\n                &$WriteMintGreen \"Certificate Removed from CurrentUser at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(152,255,152))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n        }\n        $InitialUser = $CurrentUser\n    }\n\n    # Wait for 3 seconds before repeating the loop\n    Start-Sleep -Seconds 3\n}\n
    "},{"location":"Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/","title":"How to compact your OS and free up extra space","text":""},{"location":"Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/#how-to-compact-your-os-and-free-up-extra-space","title":"How to compact your OS and free up extra space","text":""},{"location":"Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/#run-the-following-commands-in-an-elevated-powershell","title":"Run the following commands in an elevated PowerShell","text":"

    To turn on CompactOS:

    Compact.exe /CompactOS:always\n

    To turn off CompactOS:

    Compact.exe /CompactOS:never\n

    To Query whether CompactOS is on or off:

    Compact.exe /CompactOS:Query\n

    Source

    "},{"location":"Miscellaneous/Hyper%20V/","title":"Hyper-V Tips and Tricks","text":""},{"location":"Miscellaneous/Hyper%20V/#how-to-import-and-export-tpm-enabled-hyper-v-vm-certificates-with-powershell","title":"How to Import and Export TPM-enabled Hyper-V VM certificates with PowerShell","text":"

    TPM requirement, which is a great security feature, was added to Windows 11. On the host, it is managed by the OS and UEFI, but when you create a Virtual Machine (VM) that runs an OS like Windows 11, you have to know how to manage it properly so that your VM will stay secure everywhere and you will maintain your access to your VM even if you import/export it to a different Hyper-V host or reinstall your host OS.

    Here is a screenshot of my Hyper-V VM on Windows 11 with the following security features enabled:

    1. Secure Boot
    2. Trusted Platform Module (TPM)

    When a VM uses TPM, Windows creates 2 certificates in the Local Machine Certificate Store => Shielded VM Local Certificates => Certificates

    One of them is for encryption and the other one is for signing. They both contain private keys. If these 2 certificates don't exist in that folder in the Local Machine Certificate store of a Hyper-V host, your VM won't be able to start

    What you need to do is to export those 2 certificates (with private keys) and store them in a safe place (such as OneDrive's personal Vault) as a backup.

    If you completely reinstall Windows or move the VMs to a different Hyper-V host and Import the certificates, you will be able to continue using your VMs, but when you create new TPM enabled VMs on the new host, 2 more certificates will be added to the Local Machine Certificate Store => Shielded VM Local Certificates => Certificates, so you will have 4 certificates in total, 2 of which are tied to your old VMs and the other 2 are tied to the new VMs. Each generated certificate has 10 years expiry date from the time it was created.

    You can Import/Export the certificates using GUI, but here I'm going to show how to automate it using PowerShell:

    "},{"location":"Miscellaneous/Hyper%20V/#export-all-the-available-host-guardian-service-certificates-with-private-keys-and-extended-properties","title":"Export all the available Host Guardian service certificates with private keys and extended properties","text":"
    $CertificatePassword = ConvertTo-SecureString -String \"hotcakex\" -Force -AsPlainText\nGet-Item \"Cert:\\LocalMachine\\Shielded VM Local Certificates\\*\" | ForEach-Object {\nExport-PfxCertificate -Cert $_ -FilePath \".\\$($_.Issuer)-$($_.Thumbprint).pfx\" -Password $CertificatePassword -CryptoAlgorithmOption AES256_SHA256}\n
    "},{"location":"Miscellaneous/Hyper%20V/#import-the-certificates-with-private-keys","title":"Import the certificates with private keys","text":"
    $ShieldedCertsPath = 'Cert:\\LocalMachine\\Shielded VM Local Certificates'\nif (-NOT (Test-Path $ShieldedCertsPath)) { New-Item -Path $ShieldedCertsPath -Force }\n$CertificatePassword = 'hotcakex' | ConvertTo-SecureString -AsPlainText -Force\nGet-Item \"C:\\Users\\$($env:USERNAME)\\OneDrive\\Desktop\\Hyper-V Guardian certificates\\*.pfx\" | Import-PfxCertificate -CertStoreLocation $ShieldedCertsPath -Password $CertificatePassword -Exportable\n

    You should change the values for $CertificateLocation and $CertificatePassword varaibles according to your own needs and environment.

    "},{"location":"Miscellaneous/Hyper%20V/#how-to-enable-nested-virtualization-for-all-the-vms-on-the-hyper-v-host","title":"How to Enable Nested Virtualization for All the VMs on the Hyper-V Host","text":"

    Use the following command to enable Nested Virtualization for a single VM

    Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true\n

    Use the following command to automatically enable Nested Virtualization for all VMs

    (Get-VM).name | ForEach-Object {Set-VMProcessor -VMName $_ -ExposeVirtualizationExtensions $true}\n

    All of the VMs must be in Off state when enabling nested virtualization for them

    This is how to verify Nested Virtualization is enabled for all of your VMs

    (Get-VM).name | ForEach-Object {get-VMProcessor -VMName $_} | Select-Object -Property VMName,ExposeVirtualizationExtensions\n

    "},{"location":"Miscellaneous/Hyper%20V/#confidential-computing-on-azure","title":"Confidential Computing on Azure","text":"

    Azure confidential computing makes it easier to trust the cloud provider, by reducing the need for trust across various aspects of the compute cloud infrastructure. Azure confidential computing minimizes trust for the host OS kernel, the hypervisor, the VM admin, and the host admin.

    "},{"location":"Miscellaneous/Hyper%20V/#continue-reading","title":"Continue reading","text":"

    "},{"location":"Miscellaneous/Hyper%20V/#shielded-vms-are-deprecated-concepts","title":"Shielded VMs are deprecated concepts","text":"

    They are deprecated starting with Windows Server 2022. They were prone to modern attacks such as side-channel.

    The following details about Shielded VMs are old and no longer valid
    HgsClientConfiguration\n

    Note that this configuration is for standalone systems. an actual shielded virtual machine is a lot more secure because the host's security and health is properly attested in a Guarded Fabric, using Host Guardian Service (HGS) on a Windows Server.

    "},{"location":"Miscellaneous/Hyper%20V/#scenario-hyper-v-enhanced-session-mode-no-authentication-in-the-vms-os","title":"Scenario: Hyper-V, Enhanced session mode, no authentication in the VM's OS","text":"

    When you create a VM in Hyper-V that doesn't have any authentication method for login such as Password or PIN, and use Enhanced session-mode to connect to it, there might be an issue where the RDP disconnects once after each restart of the VM and Hyper-V virtual machine connection asks you to connect to the VM again by clicking/tapping on the connect button. To fix this, set a local password for the user account of the OS in VM.

    "},{"location":"Miscellaneous/Hyper%20V/#native-boot-hyper-v-vms-vhdx","title":"Native boot Hyper-V VMs, VHDX","text":"

    There are guides for native booting a VHDX and it's very easy to do. If you already have a Hyper-V VM, you can add it to the Windows boot manager so that during a reboot you will have the option to boot the VHDX.

    "},{"location":"Miscellaneous/Hyper%20V/#you-need-to-pay-attention-to-a-few-things-though","title":"You need to pay attention to a few things though:","text":"
    1. The VHDX should be on a drive that is NTFS formatted, for now booting from ReFS is not supported.

    2. The drive that hosts the VHDX file must have more free space than the assigned size of the VHDX. The size you see in the file explorer is not the same as the size of the disk you assigned to the VHDX when creating it. It's easier if you have a fixed size VHDX instead of a dynamically expanding one. To find the real size of the VHDX, you can boot it in Hyper-V and check the drives inside it.

    3. Merge all checkpoints and delete them before attempting to native boot VHDX.

    "},{"location":"Miscellaneous/Hyper%20V/#vhdx-native-booting-is-very-easy-and-flexible-you-can-do-it-even-if","title":"VHDX native booting is very easy and flexible, you can do it even if:","text":"
    1. Your host has Secure boot enabled

    2. You use Signed WDAC policies

    3. Your VM wasn't SysPrepped before natively booting it on physical machine

    4. VM has secure boot and TPM

    "},{"location":"Miscellaneous/Hyper%20V/#how-to-make-the-vhdx-bootable","title":"How to make the VHDX bootable:","text":"
    1. Double-click/tap on the VHDX file to mount it
    2. Run this in CMD or PowerShell
    bcdboot D:\\Windows /d\n

    Bcdboot

    Use the /d option to preserve the existing boot order.

    "},{"location":"Miscellaneous/Hyper%20V/#verify-the-change-by-running-this-command","title":"Verify the change by running this command","text":"
    bcdedit /enum\n

    Bcdedit

    The description of the boot entry is the same one you see during OS selection menu. You can change it with this command in PowerShell:

    bcdedit /set '{default}' description 'VHDX Boot'\n

    or in CMD:

    bcdedit /set {default} description 'VHDX Boot'\n

    If {default} is not the correct identifier, then change it according to the result of the bcdedit /enum

    There are three different identifiers: The chosen default OS has identifier {default}, the current OS you are signed in at the moment is {current}. All other entries have a long hexadecimal identifier.

    "},{"location":"Miscellaneous/Hyper%20V/#some-hyper-v-nested-virtualization-screenshots","title":"Some Hyper-v Nested Virtualization Screenshots","text":"

    To display how optimized and powerful Hyper-V hypervisor is (including any feature that runs on it such as Windows Sandbox, WSL, WSA, MDAG and more), here are some screenshots taken on a very old hardware, hardware that is not even officially supported by Windows 11, yet you can virtualize 5 operation systems nested in each other, and the last nested virtualized OS still has full functionality including direct file copy from host to guest, full Internet connectivity, ability to listen to music, do tasks and so on.

    "},{"location":"Miscellaneous/Hyper%20V/#hardware-specs-all-from-2016-2017-couldnt-find-any-older-to-test","title":"Hardware specs - All from 2016-2017, couldn't find any older to test","text":"
    1. CPU: Intel Core I7 7700k
    2. RAM: 16GB
    3. GPU: N/A (Intel IGPU)
    4. SSD: 256 GB M.2
    Click/Tap here to see the screenshots"},{"location":"Miscellaneous/Hyper%20V/#important-hyper-v-related-documents","title":"Important Hyper-V Related Documents","text":"

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/","title":"Only a Small Portion of The Windows OS Security Apparatus","text":"

    Tip

    Many of the features mentioned in the map above can be automatically deployed and configured via the Harden Windows Security repository's offerings.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#superiority","title":"SUPERIORITY","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#intelligent-security-graph-isg","title":"Intelligent Security Graph (ISG)","text":"

    This cloud-based AI is based on trillions of signals collected from Windows endpoints and other data sources, and processed every 24 hours. As a result, the decision from the cloud can change.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#no-0-dayunknown-file-allowed-asr","title":"No 0-day/Unknown File Allowed (ASR)","text":"

    This rule blocks untrusted or unknown executable files such as .exe, .dll, or .scr, from launching that can be risky, as it might not be initially clear if the files are malicious.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#rigorous-custom-exploit-protections","title":"Rigorous Custom Exploit Protections","text":"

    Exploit protection helps protect devices from malware that uses exploits to spread and infect other devices. Mitigation can be applied to either the operating system or to an individual app.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#network-protection","title":"Network Protection","text":"

    Network protection helps protect devices from Internet-based events. Network protection is an attack surface reduction capability. It helps prevent employees from accessing dangerous domains through applications. Domains that host phishing scams, exploits, and other malicious content on the Internet are considered dangerous.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#cloud-protection","title":"Cloud Protection","text":"

    Next-generation technologies in Microsoft Defender Antivirus provide near-instant, automated protection against new and emerging threats. To identify new threats dynamically, next-generation technologies work with large sets of interconnected data in the Microsoft Intelligent Security Graph and powerful artificial intelligence (AI) systems driven by advanced machine learning models. Cloud protection works together with Microsoft Defender Antivirus to deliver accurate, real-time, and intelligent protection.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#cloud-based-remote-detonation-and-analysis","title":"Cloud-Based Remote Detonation And Analysis","text":"

    Advanced cloud-based protection is provided for cases when Microsoft Defender Antivirus running on the endpoint needs more intelligence to verify the intent of a suspicious file.

    After files are submitted to cloud protection, the submitted files can be scanned, detonated, and processed through big data analysis machine-learning models to reach a verdict.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#block-at-first-sight","title":"Block At First Sight","text":"

    Block at first sight is a threat protection feature of next-generation protection that detects new malware and blocks it within seconds.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#intel-threat-detection-technology-tdt","title":"Intel Threat Detection Technology (TDT)","text":"

    Intel TDT is a detection approach that can augment traditional file-based or behavior-based detection. This technology integration focuses on the CPU execution patterns that are characteristic of ransomware attacks. Intel TDT is available in a broad range of Intel hardware over multiple generations and will be available for consumers through Microsoft Defender Antivirus.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#remote-encryption-protection","title":"Remote Encryption Protection","text":"

    Remote Encryption Protection in Microsoft Defender Antivirus detects and blocks attempts to replace local files with encrypted versions from another device.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#brute-force-protection","title":"Brute Force Protection","text":"

    Brute-Force Protection in Microsoft Defender Antivirus detects and blocks attempts to forcibly sign in and initiate sessions.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#windows-updates-installed-within-24-hours-of-release","title":"Windows Updates Installed Within 24 Hours Of Release","text":"

    Windows updates are extremely important. They always should be installed as fast as possible to stay secure and if a reboot is required, it should be done immediately. Threat actors can weaponize publicly disclosed vulnerabilities the same day their POC (Proof-Of-Concept) is released.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#microsoft-defender-updates-installed-every-3-hours","title":"Microsoft Defender Updates Installed Every 3 Hours","text":"

    Regularly updating Microsoft Defender Antivirus is crucial for maintaining robust security on your Windows OS. These updates ensure that your system has the latest security intelligence, which is vital for identifying and mitigating the most recent threats. Cyber threats evolve rapidly, and outdated antivirus signatures leave your system vulnerable to new malware, viruses, and other security risks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#ultimatum","title":"ULTIMATUM","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#application-control-for-business-wdac","title":"Application Control For Business (WDAC)","text":"

    Application control is a crucial line of defense for protecting computer systems given today's threat landscape, and it has an inherent advantage over traditional antivirus solutions. Specifically, application control moves away from an application trust model where all applications are assumed trustworthy to one where applications must earn trust in order to run.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#complete-byovd-protection","title":"Complete BYOVD Protection","text":"

    This scenario involves removing the trust to any Kernel mode driver, whether they are vulnerable or not. It does not affect User-mode binaries or drivers. Any 3rd party software/hardware Kernel mode driver will need to be explicitly allowed. This scenario protects against all BYOVD scenarios and much more.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#application-cross-dependency-usage-control","title":"Application Cross-Dependency Usage Control","text":"

    Implements Sandboxing-like restrictions around the program's dependencies so that only the main executable(s) of the program can use its dependencies and any other executable will be blocked from using them.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#controlled-folder-access","title":"Controlled Folder Access","text":"

    Controlled folder access helps you protect valuable data from malicious apps and threats, such as ransomware.

    Controlled folder access applies to many system folders and default locations, including folders such as Documents, Pictures, and Movies. You can add other folders to be protected, but you cannot remove the default folders in the default list.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#smart-app-control","title":"Smart App Control","text":"

    Smart App Control is a new app execution control feature that combines Microsoft\u2019s app intelligence services and Windows' code integrity features to protect users from untrusted or potentially dangerous code. Smart App Control selectively allows apps and binaries to run only if they're likely to be safe. Microsoft's app intelligence services provide safety predictions for many popular apps. If the app intelligence service is unable to make a prediction, then Smart App Control will still allow an app to run if it is signed with a certificate issued by a certificate authority (CA) within the Trusted Root Program.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#hyper-v-windows-sandbox-untrusted-software-usage","title":"Hyper-V & Windows Sandbox (Untrusted Software Usage)","text":"

    Hyper-V is the most secure and one of the best, if not the best Type-1 hypervisor. It's available in Windows and can virtualize an OS.

    Windows Sandbox provides a lightweight desktop environment to safely run applications in isolation. Software installed inside the Windows Sandbox environment remains \"sandboxed\" and runs separately from the host machine.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#windows-defender-firewall-rule-based","title":"Windows Defender Firewall (Rule Based)","text":"

    Windows Firewall is a Stateful Firewall. It is a security feature that helps to protect your device by filtering network traffic that enters and exits your device. This traffic can be filtered based on several criteria, including source and destination IP address, IP protocol, or source and destination port number.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#automated-firewall-with-appid-tagging","title":"Automated Firewall With AppID Tagging","text":"

    Windows Firewall supports the use of Windows Defender Application Control (WDAC) Application ID (AppID) tags. With this capability, you'll be able to scope your firewall rules to an application or a group of applications and rely on WDAC policies to define those applications. The WDAC AppID functionality adds an administrator defined tag to the given process token.

    For example, you can easily use a policy that allows only files that come with Windows by default to be allowed to access the Internet while everything else will be blocked.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#win32-app-isolation","title":"Win32 App Isolation","text":"

    Win32 app isolation is a new security feature designed to be the default isolation standard on Windows clients. It is built on AppContainers and offers several added security features to help windows platform defend against attacks that leverage vulnerabilities in the application (this could be 3P libraries as well). To isolate their apps, application developers can update their applications using the tools provided by Microsoft.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#vbs-enclaves","title":"VBS Enclaves","text":"

    A Virtualization-based security (VBS) Enclave is a software-based trusted execution environment inside the address space of a host application. VBS Enclaves leverage underlying VBS technology to isolate the sensitive portion of an application in a secure partition of memory. VBS Enclaves enable isolation of sensitive workloads from both the host application and the rest of the system.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#uefi-locked-settings-to-require-proof-of-physical-presence","title":"UEFI Locked Settings (To Require Proof Of Physical Presence)","text":"

    UEFI locked security measures are rooted in Proof of Physical Presence and they can't be disabled by modifying Group Policy, registry keys or other Administrative tasks.

    The only way to disable UEFI locked security measures is to have physical access to the computer, reboot and access the UEFI settings, supply the credentials to access the UEFI, turn off Secure Boot, reboot the system and then you will be able to disable those security measures with Administrator privileges.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#early-launch-antimalware-elam","title":"Early Launch AntiMalware (ELAM)","text":"

    A security model in the kernel to better defend against malicious attacks on system-critical components. This security model extends the protected process infrastructure into a general-purpose model that can be used by 3rd party anti-malware vendors. The protected process infrastructure only allows trusted, signed code to load and has built-in defense against code injection attacks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#physical-security","title":"Physical Security","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#bitlocker","title":"BitLocker","text":"

    BitLocker is a Windows security feature that provides encryption for entire volumes, addressing the threats of data theft or exposure from lost, stolen, or inappropriately decommissioned devices.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#startup-key-usb-flash-drive","title":"Startup Key (USB Flash Drive)","text":"

    Requires a USB flash drive to be inserted into the computer to start the computer. The USB flash drive must contain the startup key for the encrypted drive. This key is only a portion of the complete key required to perform a successful authentication. The other portion of of the key is provided by the Startup PIN.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-boot-pcr7-binding","title":"Secure Boot (PCR7 Binding)","text":"

    Secure Boot blocks untrusted firmware and bootloaders (signed or unsigned) from being able to start on the system. By default, BitLocker provides integrity protection for Secure Boot by utilizing the TPM PCR 7 measurement. An unauthorized EFI firmware, EFI boot application, or bootloader can't run and acquire the BitLocker key.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#tpm","title":"TPM","text":"

    A TPM is a microchip designed to provide basic security-related functions, primarily involving encryption keys. The TPM is installed on the motherboard of a computer, and it communicates with the rest of the system by using a hardware bus.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#startup-pin","title":"Startup PIN","text":"

    In addition to the protection that the TPM provides, part of the encryption key is stored on a USB flash drive, and a PIN is required to authenticate the user to the TPM. This configuration provides multifactor authentication so that if the USB key is lost or stolen, it can't be used for access to the drive, because the PIN is also required. Preboot authentication with a PIN can mitigate an attack vector for devices that use a bootable eDrive because an exposed eDrive bus can allow an attacker to capture the BitLocker encryption key during startup.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#firmware-security","title":"Firmware Security","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#system-management-mode-smm-protection","title":"System Management Mode (SMM) Protection","text":"

    SMM code executes in the highest privilege level and is invisible to the OS. SMM protection is built on top of the Secure Launch technology and requires it to function. A hardware-enforced processor feature known as a supervisor SMI handler can monitor the SMM and make sure it doesn't access any part of the address space that it isn't supposed to. Windows measures SMI Handler's behavior and attest that no OS-owned memory has been tampered with.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#static-root-of-trust-for-measurement-srtm","title":"Static Root of Trust for Measurement (SRTM)","text":"

    It is a hardware-based root of trust that helps ensure no unauthorized firmware or software (such as a bootkit) can start before the Windows bootloader. This hardware-based root of trust comes from the device's Secure Boot feature, which is part of the Unified Extensible Firmware Interface (UEFI). This technique of measuring the static early boot UEFI components is called the Static Root of Trust for Measurement (SRTM).

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-launch-drtm","title":"Secure Launch (DRTM)","text":"

    The Dynamic Root of Trust for Measurement (DRTM) lets the system freely boot into untrusted code initially, but shortly after launches the system into a trusted state by taking control of all CPUs and forcing them down a well-known and measured code path. This has the benefit of allowing untrusted early UEFI code to boot the system, but then being able to securely transition into a trusted and measured state.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-memory-overwrite","title":"Secure Memory Overwrite","text":"

    Secure MOR protects the MOR lock setting using a UEFI secure variable. This helps guard against advanced memory attacks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#tcg-storage-security-drive-password","title":"TCG Storage Security Drive Password","text":"

    This is a password for modern SSDs that can be set in the UEFI firmware. User is asked for this password during the boot process before the OS is loaded. The SSD itself can be encrypted by BitLocker and still require this additional password before the Startup PIN.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#mode-based-execution-control","title":"Mode Based Execution Control","text":"

    MBEC virtualization provides an extra layer of protection from malware attacks. It enables hypervisors to more reliably and efficiently verify and enforce the integrity of kernel-level code.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#uefi-password","title":"UEFI Password","text":"

    It's a password that is set in the UEFI firmware. It is required to access the UEFI settings. This password can be used to prevent unauthorized changes to the UEFI settings.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#uefi-code-readonly","title":"UEFI Code ReadOnly","text":"

    All UEFI memory that is marked executable is set to be read only. Memory marked writable must not be executable. Entries may not be left with neither of the attributes set, indicating memory that is both executable and writable.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#kernel-dma-protection","title":"Kernel DMA Protection","text":"

    Kernel Direct Memory Access (DMA) Protection is a Windows security feature that protects against external peripherals from gaining unauthorized access to memory. Windows uses the system Input/Output Memory Management Unit (IOMMU) to block external peripherals from starting and performing DMA, unless the drivers for these peripherals support memory isolation (such as DMA-remapping).

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#pluton","title":"Pluton","text":"

    Microsoft Pluton security processor is a chip-to-cloud security technology built with Zero Trust principles at the core. Microsoft Pluton provides hardware-based root of trust, secure identity, secure attestation, and cryptographic services. Pluton technology is a combination of a secure subsystem, which is part of the System on Chip (SoC) and Microsoft authored software that runs on this integrated secure subsystem.

    It addresses security needs like booting an operating system securely even against firmware threats and storing sensitive data safely even against physical attacks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#apic-virtualization","title":"APIC Virtualization","text":"

    APIC virtualization is a collection of features that can be used to support the virtualization of interrupts and the Advanced Programmable Interrupt Controller (APIC). When APIC virtualization is enabled, the processor emulates many accesses to the APIC, tracks the state of the virtual APIC, and delivers virtual interrupts \u2014 all in VMX non-root operation without a VM exit.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-boot","title":"Secure Boot","text":"

    Secure Boot is a security standard developed by members of the PC industry to help ensure that a device boots using only software that's trusted by the original equipment manufacturer (OEM).

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#identity-in-the-abstract-sense","title":"IDENTITY (In the Abstract Sense)","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#smart-screen","title":"Smart Screen","text":"

    Microsoft Defender SmartScreen protects against phishing or malware websites and applications, and the downloading of potentially malicious files.

    Microsoft Defender SmartScreen provide an early warning system against websites that might engage in phishing attacks or attempt to distribute malware through a socially engineered attack.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#potentially-unwanted-application-pua-protection","title":"Potentially Unwanted Application (PUA) Protection","text":"

    Potentially unwanted applications (PUA) are a category of software that can cause your machine to run slowly, display unexpected ads, or at worst, install other software that might be unexpected or unwanted. PUA isn't considered a virus, malware, or other type of threat, but it might perform actions on endpoints that adversely affect endpoint performance or use. The term PUA can also refer to an application that has a poor reputation, as assessed by Microsoft Defender for Endpoint, due to certain kinds of undesirable behavior.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#valid-signature-required-for-elevation","title":"Valid Signature Required For Elevation","text":"

    Only elevate executable files that are signed and validated. This setting enforces public key infrastructure (PKI) signature checks for any interactive applications that request elevation of privilege. Enterprise administrators can control which applications are allowed to run by adding certificates to the Trusted Publishers certificate store on local computers.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#behavioral-analysis","title":"Behavioral Analysis","text":"

    Behavior monitoring (Analysis) is a critical detection and protection functionality of Microsoft Defender Antivirus.

    Monitors process behavior to detect and analyze potential threats based on the behavior of applications, services, and files. Rather than relying solely on signature-based detection (which identifies known malware patterns), behavior monitoring focuses on observing how software behaves in real-time

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#static-signature-analysis","title":"Static Signature Analysis","text":"

    Microsoft Defender's security definition updates are a critical component of the cybersecurity infrastructure, designed to continuously enhance protection against new malware and sophisticated attack techniques. These updates regularly refresh the definition files that are crucial for identifying spyware, viruses, and other potentially unwanted software.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#personal-data-encryption-pde","title":"Personal Data Encryption (PDE)","text":"

    PDE utilizes Windows Hello for Business to link data encryption keys with user credentials. When a user signs in to a device using Windows Hello for Business, decryption keys are released, and encrypted data is accessible to the user. When a user logs off, decryption keys are discarded and data is inaccessible, even if another user signs into the device.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#enhanced-sign-in-security-ess","title":"Enhanced Sign-in Security (ESS)","text":"

    Windows Hello enables a user to authenticate using their biometrics or a PIN eliminating the need for a password. Biometric authentication uses facial recognition or fingerprint to prove a user's identity in a way that is secure, personal, and convenient. Enhanced Sign-in Security provides an additional level of security to biometric data by leveraging specialized hardware and software components, such as Virtualization Based Security (VBS) and Trusted Platform Module 2.0 to isolate and protect a user's authentication data and secure the channel by which that data is communicated.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#credential-guard","title":"Credential Guard","text":"

    Credential Guard prevents credential theft attacks by protecting NTLM password hashes, Kerberos Ticket Granting Tickets (TGTs), and credentials stored by applications as domain credentials.

    Credential Guard uses Virtualization-based security (VBS) to isolate secrets so that only privileged system software can access them. Unauthorized access to these secrets can lead to credential theft attacks like pass the hash and pass the ticket.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#admin-less","title":"Admin-less","text":"

    Most people run as full admins on their devices, which means apps and services have the same access to the kernel and other critical services as users. And the problem is that these apps and services can access critical resources without the user knowing. This is why Windows requires just in time administrative access to the kernel and other critical services as needed, not all the time, and certainly not by default. This makes it harder for an app to unexpectedly abuse admin privileges and secretly put malware or malicious code on Windows. When this feature is enabled, such as when an app needs special permissions like admin rights, you'll be asked for approval.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#windows-hello-multi-factor-authentication","title":"Windows Hello Multi-Factor Authentication","text":"

    Windows Hello for Business supports the use of a single credential (PIN and biometrics) for unlocking a device. Therefore, if any of those credentials are compromised (shoulder surfed), an attacker could gain access to the system.

    Windows Hello for Business can be configured with multi-factor unlock, by extending Windows Hello with trusted signals. Administrators can configure devices to request a combination of factors and trusted signals to unlock them.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#zero-trust-dns-ztdns","title":"Zero Trust DNS (ZTDNS)","text":"

    ZTDNS integrates the Windows DNS client and the Windows Filtering Platform (WFP) to enable this domain-name-based lockdown. First, Windows is provisioned with a set of DoH or DoT capable Protective DNS servers; these are expected to only resolve allowed domain names. This provisioning may also contain a list of IP address subnets that should always be allowed (for endpoints without domain names), expected Protective DNS server certificate identities to properly validate the connection is to the expected server, or certificates to be used for client authentication.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#advanced-intelligence-based-phishing-protection","title":"Advanced Intelligence-Based Phishing Protection","text":"

    This feature is constantly learning from phishing attacks seen throughout the entire Microsoft security stack. It works alongside other Microsoft security products, to provide a layered approach to password security, especially for organizations early in their password-less authentication journey.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#continue-reading","title":"Continue Reading","text":"

    Head over to the main page of the GitHub repository to learn more about Windows Security and how to automate a lot of the features talked about in this page.

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/","title":"Optional overrides for Microsoft Security Baseline","text":"

    Since Microsoft Security Baselines are geared towards Enterprise level security, some functionalities that home users might require are disabled. Use the following overrides in the Harden Windows Security module to bring back those functionalities. Some of these are necessary when using the module in Azure VMs.

    Tip

    All of the features and functionalities listed below are enabled by default in Windows.

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#1-windows-game-recording-and-broadcasting","title":"1. Windows Game Recording and Broadcasting","text":"

    This setting enables or disables the Windows Game Recording and Broadcasting features. If you disable this setting, Windows Game Recording will not be allowed. If the setting is enabled or not configured, then Recording and Broadcasting (streaming) will be allowed.

    Policy path:

    Computer Configuration\\Administrative Templates\\Windows Components\\Windows Game Recording and Broadcasting\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#2-prohibit-use-of-internet-connection-sharing-on-your-dns-domain-network","title":"2. Prohibit use of Internet Connection Sharing on your DNS domain network","text":"

    Determines whether administrators can enable and configure the Internet Connection Sharing (ICS) feature of an Internet connection and if the ICS service can run on the computer.

    ICS lets administrators configure their system as an Internet gateway for a small network and provides network services, such as name resolution and addressing through DHCP, to the local private network.

    If you enable this setting, ICS cannot be enabled or configured by administrators, and the ICS service cannot run on the computer. The Advanced tab in the Properties dialog box for a LAN or remote access connection is removed. The Internet Connection Sharing page is removed from the New Connection Wizard. The Network Setup Wizard is disabled.

    If you disable this setting or do not configure it and have two or more connections, administrators can enable ICS. The Advanced tab in the properties dialog box for a LAN or remote access connection is available. In addition, the user is presented with the option to enable Internet Connection Sharing in the Network Setup Wizard and Make New Connection Wizard. (The Network Setup Wizard is available only in Windows XP Professional.)

    By default, ICS is disabled when you create a remote access connection, but administrators can use the Advanced tab to enable it. When running the New Connection Wizard or Network Setup Wizard, administrators can choose to enable ICS.

    Note: Internet Connection Sharing is only available when two or more network connections are present.

    Note: When the \"Prohibit access to properties of a LAN connection,\" \"Ability to change properties of an all user remote access connection,\" or \"Prohibit changing properties of a private remote access connection\" settings are set to deny access to the Connection Properties dialog box, the Advanced tab for the connection is blocked.

    Note: Non-administrators are already prohibited from configuring Internet Connection Sharing, regardless of this setting.

    Note: Disabling this setting does not prevent Wireless Hosted Networking from using the ICS service for DHCP services. To prevent the ICS service from running, on the Network Permissions tab in the network's policy properties, select the \"Don't use hosted networks\" check box.

    Policy path:

    Computer Configuration\\Administrative Templates\\Network\\Network Connections\\Prohibit use of Internet Connection Sharing on your DNS domain network\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#3-firewall-local-rule-merging","title":"3. Firewall local rule merging","text":"

    This can prevent Hyper-V default switch from working properly, please see this forum post on Microsoft Tech Community for more info.

    The Group policies that we change back to default values are located in:

    Computer Configuration\\Windows Settings\\Security Settings\\Windows Defender Firewall with Advanced Security\\\n

    From there you need to select properties and then in each relevant profile tab, you need to select Customize and change the 2 settings for Rule merging to Yes (Default) and also set Display a notification to Yes, which is the default value in Windows.

    Here is an screenshot of the settings for the Public Profile tab:

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#4-deny-write-access-to-removable-drives-not-protected-by-bitlocker","title":"4. Deny write access to removable drives not protected by BitLocker","text":"

    Disabling this policy because it can cause inconvenience and if your flash drive is BitLocker encrypted, it can't be used as a bootable Windows installation USB flash drive.

    Policy path:

    Computer Configuration\\Administrative Templates\\Windows Components\\BitLocker Drive Encryption\\Removable Data Drives\\Deny write access to removable drives not protected by BitLocker\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#5-set-the-status-of-these-4-xbox-services-back-to-their-default-states","title":"5. Set the status of these 4 Xbox services back to their default states","text":"

    XboxGipSvc, XblAuthManager,XblGameSave,XboxNetApiSvc

    Microsoft Security Baseline sets their status to disabled.

    Policy path:

    Computer Configuration\\Windows Settings\\\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#6-enable-clipboard-and-drive-redirection-when-using-remote-desktop-connection","title":"6. Enable Clipboard and Drive redirection when using Remote Desktop connection","text":"

    It is necessary when using Hyper-V VM Enhanced session mode and you want to copy items between guest and host OS.

    Policy path:

    Computer Configuration\\Administrative Templates\\Windows Components\\Remote Desktop Services\\Remote Desktop Session Host\\Device and Resource Redirection\\\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#7-enable-the-xblgamesave-standby-task","title":"7. Enable the XblGameSave Standby Task","text":"

    The scheduled task is disabled as a result of applying the Microsoft Security Baselines. Using the optional overrides, it will be enabled and its status will be set back to the default state. The task syncs Xbox game saves on PC.

    PowerShell command

    SCHTASKS.EXE /Change /TN \\Microsoft\\XblGameSave\\XblGameSaveTask /Enable\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#8-enable-microsoft-defender-exclusion-lists-to-be-visible-to-local-admins","title":"8. Enable Microsoft Defender exclusion lists to be visible to Local Admins","text":"

    This policy is located in the following Group Policy path

    Computer Configuration\\Administrative Templates\\Windows Components\\Microsoft Defender Antivirus\\Control whether or not exclusions are visible to Local Admins\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#9-disabled-turn-off-microsoft-consumer-experiences","title":"9. Disabled \"Turn off Microsoft Consumer Experiences\"","text":"

    It disables some important features in Windows Settings -> Bluetooth & Devices -> Mobile Devices

    More info in this PR

    Computer Configuration\\Administrative Templates\\Windows Components\\Cloud Content\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#10-disabled-configure-password-backup-directory","title":"10. Disabled \"Configure password backup directory\"","text":"

    Microsoft Security Baselines set its value to \"Active Directory\", but since the Harden Windows Security module does not apply to computers managed by domain controllers or Entra ID, there is no need for this policy to be active.

    Computer Configuration\\Administrative Templates\\System\\LAPS\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#11-enabled-apply-uac-restrictions-to-local-accounts-on-network-logons","title":"11. Enabled \"Apply UAC restrictions to local accounts on network logons\"","text":"

    A Security feature that is enabled by default and should stay enabled.

    Computer Configuration\\Administrative Templates\\MS Security Guide\n

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/","title":"Things to do when clean installing Windows","text":"

    There are certain tasks that need to be performed for a proper Windows clean installation. Not all of the items below apply to all hardware.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#bitlocker","title":"BitLocker","text":"

    Suspend the protection of the OS drive and make sure you have the recovery password of all other non-OS drives so that you will be able to unlock them after clean installation of the OS.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#intel-vmd-drivers-varies-by-device","title":"Intel VMD Drivers (Varies by device)","text":"

    If you use a modern hardware that uses Intel\u00ae Volume Management Device (Intel\u00ae VMD) technology, you will need to download the VMD drivers on a flash drive and load them during Windows OS installation so that the OS installer will be able to detect the internal SSD and its partitions. You can download the VMD drivers from your hardware manufacturer's website.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#clear-the-tpm-varies-by-device","title":"Clear the TPM (Varies by device)","text":"

    Not all devices have this capability in the UEFI. If your UEFI has the option to clear the TPM, use it prior to clean installation of the OS.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#formatdelete-the-following-partitions","title":"Format/Delete the following partitions","text":"

    Let Windows recreate them during clean installation process

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#how-to-create-a-bootable-usb-drive-without-3rd-party-tools","title":"How to create a bootable USB drive without 3rd party tools","text":"

    Refer to this Wiki post

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/","title":"Basic PowerShell Tricks and Notes Part 2","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 2 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#view-all-predictive-intellisense-suggestions-based-on-past-history","title":"View All Predictive Intellisense Suggestions Based on Past History","text":"

    Press F2 to see the complete list of the Predictive IntelliSense suggestions as you type on the PowerShell console.

    More info

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#where-is-the-powershell-command-history-stored","title":"Where Is the Powershell Command History Stored?","text":"

    In this directory

    $env:USERPROFILE\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\n

    There is a file called ConsoleHost_history.txt and it contains the history of all the commands you've ever typed in PowerShell on your device. If you want to clear it, open the file, delete all of its content. If PowerShell is already open, close and reopen it to see the change.

    You can open the file with this command

    Invoke-Item -Path \"$env:USERPROFILE\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt\"\n

    You can use the following command to set the maximum remembered history to 1

    Set-PSReadLineOption -MaximumHistoryCount 1\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-clear-the-automatic-error-variable-in-powershell","title":"How to Clear the Automatic Error Variable in Powershell","text":"
    $error.clear()\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-last-error-type-in-powershell","title":"How to Get the Last Error Type in Powershell","text":"
    $Error[0].Exception.GetType().FullName\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-display-all-environment-variables-and-their-values-in-powershell","title":"How to Display All Environment Variables and Their Values in Powershell","text":"
    gci env:\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#list-all-mscs-and-cpls-for-microsoft-management-console-and-control-panels-in-powershell","title":"List All MSCs and CPLs for Microsoft Management Console and Control Panels in Powershell","text":"
    Get-ChildItem -Path C:\\Windows\\system32\\* -Include *.msc, *.cpl | Sort-Object -Property Extension | Select-Object -Property Name | Format-Wide -Column 2\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-mount-the-efi-system-partition","title":"How to Mount the EFI System Partition?","text":"
    mountvol u: /s\n

    This isn't a native PowerShell cmdlet, it uses mountvol CLI.

    With that command you can mount the EFI partition and assign the letter U to it, it will appear in This PC. You can browse it in PowerShell as admin.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-check-if-a-file-is-in-use-in-powershell","title":"How to Check if a File Is in Use in Powershell?","text":"

    Here is an example function that tries to rename files given to it with the same names and if it was successful, it will consider that file not in use.

    function IsFileAccessible {\n    param ([System.String]$FullFileName)\n    [System.Boolean]$IsAccessible = $false\n    try {\n        Rename-Item $FullFileName $FullFileName -ErrorVariable LockError -ErrorAction Stop\n        $IsAccessible = $true\n    }\n    catch {\n        $IsAccessible = $false\n    }\n    return $IsAccessible, $FullFileName\n}\n

    You can use it like this:

    (Get-ChildItem -Path 'C:\\Program Files\\Windows Defender' -Filter '*.exe*').FullName | ForEach-Object { IsFileAccessible -FullFileName $_ }\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#choosing-between-powershell-and-powershell-preview","title":"Choosing Between Powershell and Powershell Preview","text":"

    Use PowerShell Preview if you want to test new features and don't need to call PowerShell with its alias, pwsh, from CMD. If you do need to call it like that, use PowerShell stable.

    Use cases for it are when you need to use pwsh.exe in Windows Task Scheduler.

    PowerShell Preview by default doesn't set its pwsh.exe available system wide, the path to that file isn't added to the system environment variables, only PowerShell stable does that, but of course if you want to use PowerShell preview you can manually modify the PATH environment variable to have pwsh.exe of PowerShell Preview be available system wide.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#variable-types-in-powershell","title":"Variable Types in Powershell","text":"

    PowerShell variables can have types and type accelerator. The following command lists all of the types and their equivalent type accelerators. The fully qualified type names replace implicit with explicit.

    [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#success-codes-and-error-codes","title":"Success Codes and Error Codes","text":"

    In PowerShell, or for programming languages in general, 0 = success, 1 or anything else means failure/error.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-names-and-appids-of-installed-apps-of-the-current-user-in-powershell","title":"How to Get the Names and AppIDs of Installed Apps of the Current User in Powershell?","text":"
    Get-StartApps\n

    More info

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#difference-between-async-and-sync","title":"Difference Between Async and Sync","text":"

    Async is faster than Sync

    PowerShell supports sync/async commands workflows, also known as parallel.

    Note

    A comment under this answer:

    Oddly enough \"Synchronously\" means \"using the same clock\" so when two instructions are synchronous they use the same clock and must happen one after the other. \"Asynchronous\" means \"not using the same clock\" so the instructions are not concerned with being in step with each other. That's why it looks backwards, the term is not referring to the instructions relationship to each other. It's referring to each instructions relationship to the clock.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-enable-a-disabled-event-log-using-powershell","title":"How to Enable a Disabled Event Log Using Powershell","text":"

    First we create a new\u202fEventLogConfiguration\u202fobject and pass it the name of the log we want to configure, then we set it to enabled and save the changes.

    $LogName = 'Microsoft-Windows-DNS-Client/Operational'\n$Log = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogConfiguration -ArgumentList $LogName\n$Log.IsEnabled = $true\n$Log.SaveChanges()\n

    We can confirm the change by running this command:

    Get-WinEvent -ListLog Microsoft-Windows-DNS-Client/Operational | Format-List -Property *\n

    Using the same method we can configure many other options of the log file, just take a look at the\u202fEventLogConfiguration Class\u202ffor a list of configurable properties.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#find-the-current-users-username-in-powershell","title":"Find the Current User\u2019s Username in Powershell","text":"
    [Environment]::UserName\n
    $env:username\n
    whoami\n
    [System.Security.Principal.WindowsIdentity]::GetCurrent().Name\n

    Most secure way

    Example

    $UserSID = [System.Security.Principal.WindowsIdentity]::GetCurrent().user.value\n(Get-LocalUser | Where-Object -FilterScript { $_.SID -eq $UserSID }).name\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-access-properties-of-an-object-in-powershell","title":"How to Access Properties of an Object in Powershell","text":"

    For example, you can first assign the entire object to a variable:

    $Preferences = Get-MpPreference\n

    Then call properties of that variable

    $Preferences.PUAProtection\n

    Another method is this:

    $(Get-MpPreference).puaprotection\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#dot-sourcing","title":"Dot-Sourcing","text":"

    To dot-source a PowerShell function in the same script file, you can use the dot operator . followed by the path of the script file containing the function. The path can be relative or absolute. Here's an example:

    # Contents of MyFunctions.ps1\nfunction New-Function {\n    Write-Host \"Hello World!\"\n}\n\n# Contents of Main.ps1\n. .\\MyFunctions.ps1\n\nNew-Function\n

    In this example, Main.ps1 dot-sources MyFunctions.ps1 using the dot operator and then calls MyFunction. When you run Main.ps1, it will output Hello World! to the console.

    The dot operator tells PowerShell to execute the script file in the current scope instead of a new scope. This means that any functions or variables defined in the script file will be available in the current scope.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#a-custom-script-to-generate-random-words-in-powershell","title":"A Custom Script to Generate Random Words in Powershell","text":"
    # Generate four variables with random names\n$TotallyRandomNamesArray = @() # Create an empty array to store the names\nfor ($i = 0; $i -lt 4; $i++) {\n    # Loop four times\n    $Chars = [CHAR[]](Get-Random -Minimum 97 -Maximum 123 -Count 11) # Generate random English letters\n    $Chars[0] = [CHAR]::ToUpper($Chars[0]) # Change the first character to upper-case\n    $TotallyRandomNamesArray += -join $Chars # Add the name to the array\n}\n# Assign the names from the Names array to the individual variables\n$TotallyRandomName1, $TotallyRandomName2, $TotallyRandomName3, $TotallyRandomName4 = $TotallyRandomNamesArray\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-see-all-the-shared-folders-and-drives","title":"How to See All the Shared Folders and Drives","text":"
    Get-CimInstance -Class Win32_Share\n

    There are other ways that are not native PowerShell cmdlets, such as

    net view \\\\$env:computername /all\n

    And

    net share\n

    Also visible from Computer => System Tools => Shared Folders => Shares

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#an-example-of-using-f-format-operator","title":"An Example of Using -F Format Operator","text":"
    Write-output(\"The drivername {0} is vulnerable with a matching SHA256 hash of {1}\" -f $Filename, $SHA256)\n

    More info

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-list-all-of-the-positional-parameters-of-a-cmdlet","title":"How to List All of the Positional Parameters of a Cmdlet","text":"

    In this example we use the

    Get-Help -Name 'Get-ChildItem' -Parameter * |\nSort-Object -Property position |\nSelect-Object -Property name, position\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-number-of-fans-and-details-about-them-in-powershell","title":"How to Get the Number of Fans and Details About Them in Powershell","text":"
    (Get-CimInstance -Namespace root/CIMV2 -ClassName Win32_Fan).count\nGet-CimInstance -Namespace root/CIMV2 -ClassName Win32_Fan\n

    P.S VMs don't have fans.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-last-reboot-time-in-powershell","title":"How to Get the Last Reboot Time in Powershell","text":"
    [System.DateTime](Get-CimInstance -ClassName win32_operatingsystem -ComputerName $_.Name).LastBootUpTime\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-add-a-ps-custom-object-to-another-ps-custom-object","title":"How to Add a PS Custom Object to Another PS Custom Object","text":"

    You can use the Add-Member cmdlet with the -InputObject parameter. The -InputObject parameter specifies the custom object that you want to add a property to, and the -Value parameter specifies the custom object that you want to add as a property. For example, you can use this code to add the $CustomObject to another custom object called $ParentObject:

    $HashTable = @{\n    Name = 'Alice'\n    Age = 25\n    Occupation = 'Teacher'\n}\n$CustomObject = [PSCustomObject]$HashTable\n\n# Create another custom object\n$ParentObject = [PSCustomObject]@{\n    ID = 123\n    Location = 'London'\n}\n\n# Add the $CustomObject as a property to the $ParentObject\nAdd-Member -InputObject $ParentObject -MemberType NoteProperty -Name Child -Value $CustomObject\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#use-crlf-instead-of-lf-for-end-of-line-characters","title":"Use CRLF Instead of LF for End of Line Characters","text":"

    In Visual Studio Code for example, you can see at the bottom right corner whether your end of line sequence is set to CRLF or LF, Windows uses CRLF.

    When you upload a PowerShell script to GitHub you need to make sure it's set to CRLF. PowerShell codes that are signed have big signature blocks at the end of them. PowerShell expects CRLF when doing authenticode signatures. You can also add those scripts to a .gitattribute config to your repo so that PowerShell files are uploaded with CRLF and not with LF.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-securely-get-the-temp-directorys-path","title":"How to Securely Get the Temp Directory's Path","text":"
    [System.IO.Path]::GetTempPath()\n

    A less secure way is this

    $env:Temp\n

    The problem with the 2nd method is that if the path is long, contains too many spaces or contains non-English characters, it might lead to pattern matching using ~1.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-securely-get-the-user-directorys-path","title":"How to Securely Get the User Directory's Path","text":"

    The Get-CimInstance cmdlet can query the Win32_UserProfile class and filter by the current user's SID to get the LocalPath property, which is the path of the current user's profile directory. This method is more accurate than using the environment variable.

    (Get-CimInstance Win32_UserProfile -Filter \"SID = '$([System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value)'\").LocalPath\n

    A less secure or accurate way is this

    $env:USERPROFILE\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-run-multiple-kernel-drivers-in-powershell","title":"How to Run Multiple Kernel Drivers In PowerShell","text":"

    If you have a folder full of .bin driver files, you can use the following command to create a kernel service and run them one by one.

    This can be useful for testing drivers against a deployed WDAC policy.

    (Get-ChildItem \"C:\\drivers\").FullName | ForEach-Object -begin {$global:i=1} -Process {\n    sc create \"DriverTest$global:i\" type=kernel binpath=\"$_\"\n    Start-Sleep -Seconds 1\n    Start-Service -Name \"DriverTest$global:i\" -ErrorAction SilentlyContinue\n    $global:i++\n}\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-run-powershell-code-in-cmdbatch","title":"How to Run PowerShell Code in CMD/Batch","text":"

    Example, the code has no double quotes inside it

    powershell.exe -Command \"$UserSID = [System.Security.Principal.WindowsIdentity]::GetCurrent().user.value;(Get-LocalUser | where-object {$_.SID -eq $UserSID}).name\"\n

    Example, the code has double quotes inside it. We have to escape double quotes with \\\"

    powershell.exe -Command \"$UserSID = [System.Security.Principal.WindowsIdentity]::GetCurrent().user.value;$UserName = (Get-LocalUser | where-object {$_.SID -eq $UserSID}).name;Get-Process | where-object {$_.path -eq \"\\\"C:\\Users\\$UserName\\AppData\\Local\\Microsoft\\Edge SxS\\Application\\msedge.exe\\\"\"} | ForEach-Object {Stop-Process -Id $_.id -Force -ErrorAction SilentlyContinue}\"\n

    A good related answer from StackOverflow

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/","title":"Basic PowerShell Tricks and Notes Part 3","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 3 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-get-unique-items-from-a-list-of-objects-based-on-a-specific-property-only","title":"How to Get Unique Items From a List of Objects Based on a Specific Property Only","text":"

    Let's create some dummy data first

    # Create an array of 10 objects with 4 properties each\n$Objects = @()\nfor ($i = 1; $i -le 10; $i++) {\n    $Object = New-Object -TypeName PSObject -Property @{\n        'Name'         = \"Person$i\"\n        'Age'          = Get-Random -Minimum 20 -Maximum 40\n        'Gender'       = Get-Random -InputObject @('Male', 'Female')\n        'Occupation'   = Get-Random -InputObject @('Teacher', 'Engineer', 'Doctor', 'Lawyer', 'Journalist', 'Chef', 'Artist', 'Writer', 'Student', 'Manager')\n        'RandomNumber' = Get-Random -InputObject @('694646152', '9846152', '3153546')\n    }\n    $Objects += $Object\n}\n

    Then we can display that data like this in a table

    $objects | Format-Table -AutoSize\n

    Now we want to filter the result to get the unique values, but the uniqueness should be based on a specific property, which here is \"RandomNumber\". We don't want more than 1 object with the same \"RandomNumber\" property.

    To do that, we use this method in PowerShell

    $Objects | Group-Object -Property RandomNumber | ForEach-Object -Process { $_.Group[0] } | Format-Table -AutoSize\n

    You can use the Group-Object cmdlet to group the objects by the property you want to filter, and then select the first object from each group. This way, you will get one object for each \"RandomNumber\" property with all the properties intact. Using other methods such as Get-Unique or Select-Object -Unique won't work in this particular case.

    You can find more information about the Group-Object cmdlet and its parameters in this article.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#install-big-powershell-modules-system-wide","title":"Install Big Powershell Modules System Wide","text":"

    Modules such as Az or Microsoft.Graph.Beta are big, can have thousands of files and take more than 1GB space after installation.

    By default modules are installed in the Documents directory and when you use OneDrive, everything in there is synced automatically.

    You can install such modules system wide so that they won't be stored in the Documents\\PowerShell directory and instead will be stored in C:\\Program Files\\PowerShell\\Modules (for PowerShell core). This will also improve security since Administrator privileges will be required to change module files in that directory.

    To do this, you need to use the -Scope AllUsers parameter.

    Install-Module Az -Scope AllUsers\n\nInstall-Module Microsoft.Graph.Beta -Scope AllUsers\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#variable-scopes-in-foreach-object-parallel","title":"Variable Scopes in ForEach-Object -Parallel","text":"

    When using ForEach-Object -Parallel, the variables from the parent scope are read-only within the parallel script block when accessed with the $using: scope modifier. You cannot write to them or modify them inside the parallel script block. If you do not use the $using: scope modifier, they won't be available in the parallel script block at all.

    If you need to collect or aggregate results from each parallel run, you should output the results to the pipeline, and then collect them after the parallel execution. Here's an example of how you can do that:

    [System.String[]]$AnimalsList = @()\n$AnimalsList = 'Cat', 'Dog', 'Zebra', 'Horse', 'Mouse' | ForEach-Object -Parallel {\n    $_\n}\n

    In that example, the count of the $AnimalsList will be 5 and it will contain the animals in the input array.

    This example however would not work:

    [System.String[]]$AnimalsList = @()\n'Cat', 'Dog', 'Zebra', 'Horse', 'Mouse' | ForEach-Object -Parallel {\n    $AnimalsList += $_\n}\n
    Because the $AnimalsList variable is read-only in the parallel script block and only available in the local scriptblock's scope.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-get-the-sid-of-all-of-the-accounts-on-the-system","title":"How to Get the SID of All of the Accounts on the System","text":"

    SID stands for Security Identifier. It is a unique value of variable length that is used to identify a security principal or security group in Windows operating systems. SIDs are used in access control lists (ACLs) and in the user manager database (SAM) in Windows operating systems.

    You can get the SID of all the accounts on the system using the following PowerShell script:

    (Get-CimInstance -Class Win32_UserAccount -Namespace 'root\\cimv2').Name | ForEach-Object -Process {\n    [System.Security.Principal.NTAccount]$ObjSID = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $_\n    [System.Security.Principal.SecurityIdentifier]$ObjUser = $ObjSID.Translate([System.Security.Principal.SecurityIdentifier])\n    [PSCustomObject]@{\n        User = $_\n        SID  = $ObjUser.Value\n    }\n}\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-convert-a-sid-to-user-name","title":"How To Convert a SID to User Name","text":"
    [System.String]$SID = 'S-1-5-21-348961611-2991266383-1085979528-1004'\n$ObjSID = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $SID\n$ObjUser = $ObjSID.Translate([System.Security.Principal.NTAccount])\nWrite-Host -Object 'Resolved user name: ' $ObjUser.Value -ForegroundColor Magenta\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-convert-a-user-name-to-sid","title":"How To Convert a User Name to SID","text":"
    [System.String]$UserName = 'HotCakeX'\n$ObjUser = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $UserName\n$ObjSID = $ObjUser.Translate([System.Security.Principal.SecurityIdentifier])\nWrite-Host -Object \"Resolved User's SID: \" $ObjSID.Value -ForegroundColor Magenta\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-block-edge-traversal-for-all-of-the-firewall-rules","title":"How To Block Edge Traversal For All of the Firewall Rules","text":"
    Get-NetFirewallRule | Where-Object -FilterScript { $_.EdgeTraversalPolicy -ne 'Block' } | ForEach-Object -Process {\n    Set-NetFirewallRule -Name $_.Name -EdgeTraversalPolicy Block\n}\n

    Edge Traversal controls whether an application or service the firewall rule applies to can receive unsolicited traffic from the internet. Unsolicited traffic is traffic that is not a response to a request from the computer or user and is originated from the Internet. Solicited traffic is initiated by the computer or user.

    You can read more about it here

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#function-manipulation-with-variables-and-scriptblocks","title":"Function Manipulation With Variables And ScriptBlocks","text":"

    Suppose you have this function

    Function Write-Text {\n    [CmdletBinding()]\n    Param(\n        [Parameter(Mandatory = $true)][System.String]$InputText\n    )\n    Write-Output -InputObject $InputText\n}\n

    You can store the function in a variable like this

    [System.Management.Automation.FunctionInfo]$Function = Get-Item -Path 'Function:Write-Text'\n

    Or do it in bulk like this. In this example, $SyncHash is a synchronized hashtable used for communications between runspaces and ExportedFunctions is a nested hashtable that stores the functions inside of it.

    'Function-1', 'Function-2', 'Function-3' | ForEach-Object -Process {\n  $SyncHash['ExportedFunctions'][\"$_\"] = Get-Item -Path \"Function:$_\"\n}\n

    You can redefine the function using the same name or a different name like this. This is useful for passing the function to a different RunSpace or session.

    New-Item -Path 'Function:\\Write-TextAlt' -Value $Function -Force\n

    Redefining the functions in bulk just like the previous bulk operation above.

    Tip

    This is the recommended method of redefining the function in a different RunSpace because it completely strips its ScriptBlock of its affinity to the original RunSpace, so it'll just run on whatever the current RunSpace is without attempting to marshal.

    The affinity is about which RunSpace the script block was created in (rather than is allowed to run on).

    Basically when a scriptblock is created in a RunSpace, it knows where it came from, and when invoked outside of that RunSpace, the engine tries to send it back. This often fails because the main RunSpace is busy. So after a ~200ms time out, it will sometimes just run it on the current thread against the busy RunSpace, that causes a lot of issues, one of which is the inability to see it's parent scope. So it just forgets all commands exist and the result will be unexpected.

    Thanks to SeeminglyScience for providing this additional info.

    New-Item -Path \"Function:\\$($_.Key)\" -Value $_.Value.ScriptBlock.Ast.Body.GetScriptBlock() -Force | Out-Null\n

    Tip

    This method isn't recommended as it will maintain the ScriptBlock's affinity to the original RunSpace.

    $SyncHash.ExportedFunctions.GetEnumerator() | ForEach-Object -Process {\n    New-Item -Path \"Function:\\$($_.Key)\" -Value $_.Value.ScriptBlock -Force | Out-Null\n}\n

    Invoke the function using its new name, just as you would with the original function.

    Write-Text -InputText 'Hello from the original function!'\nWrite-TextAlt -InputText 'Hello from the new function!'\n

    You can also create a scriptblock from the function using the following approach

    $ScriptBlock = [System.Management.Automation.ScriptBlock]::Create($Function.Definition)\n

    And then call the scriptblock like this

    &$ScriptBlock 'Hello from the ScriptBlock! (direct call)'\n. $ScriptBlock 'Hello from the ScriptBlock! (dot sourced)'\nInvoke-Command -ScriptBlock $ScriptBlock -ArgumentList 'Hello from the ScriptBlock! (Invoke-Command)'\n

    Tip

    When orchestrating tasks across multiple RunSpaces with synchronized Hashtables, it's crucial to ensure seamless function transfer. Follow these steps for optimal results:

    1. Convert the desired function into a ScriptBlock.
    2. Store the ScriptBlock in the synchronized Hashtable.
    3. Redefine the ScriptBlock in the target RunSpace.

    This approach is necessary because simply saving the function to a variable, redefining it as a function in the destination RunSpace, and executing it won't replicate the original function's behavior outside the RunSpace context.

    Alternatively, you can define your code as ScriptBlocks instead of functions from the beginning.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-achieve-pseudo-lexical-variable-scoping-in-powershell","title":"How To Achieve Pseudo-Lexical Variable Scoping in PowerShell","text":"

    Lexical Scoping means:

    PowerShell does not have true lexical scoping, but you can achieve pseudo-lexical scoping using C# types. Here's an example where we define a C# class with static members to store variables.

    # A path defined in the parent scope\n$SomePath = 'C:\\FolderName\\FolderName2'\n\nAdd-Type -TypeDefinition @\"\nnamespace NameSpace\n{\n    public static class ClassName\n    {\n        public static int SomeNumber = 456;\n        public static string path = $(\"`\"$($SomePath -replace '\\\\', '\\\\')`\"\");\n    }\n}\n\"@ -Language CSharp\n

    The benefit of this approach is that you can access the variables from any scope across the PowerShell App Domain. That means any RunSpace you create, or any job started by either Start-ThreadJob or Start-Job cmdlets, without having to pass them as arguments.

    Another great feature of this approach is that you don't need to set the value of the variables in the C# code, you can simply define the variable in C# and then assign the values in PowerShell side.

    In this example, I'm only defining the variables:

    Add-Type -TypeDefinition @\"\nnamespace NameSpace\n{\n    public static class ClassName\n    {\n        public static int SomeNumber;\n        public static string path;\n        public static object MDAVConfigCurrent;\n    }\n}\n\"@ -Language CSharp\n

    And now I can set any value to the variables in PowerShell side

    [NameSpace.ClassName]::SomeNumber = 123\n[NameSpace.ClassName]::path = 'C:\\FolderName\\FolderName2'\n[NameSpace.ClassName]::MDAVConfigCurrent = Get-MpPreference\n

    You can now use the variables anywhere by accessing them

    Write-Host -Object ([NameSpace.ClassName]::SomeNumber)\nWrite-Host -Object ([NameSpace.ClassName]::path)\nWrite-OutPut -InputObject ([NameSpace.ClassName]::MDAVConfigCurrent)\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/","title":"Basic PowerShell Tricks and Notes Part 4","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 4 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/#how-to-bypass-powershell-constant-variables-and-how-to-prevent-the-bypass","title":"How To Bypass PowerShell Constant Variables And How To Prevent The Bypass","text":"

    When using Set-Variable cmdlet to create a constant variable, you can't change the value of that variable later in the script by simple assignments, but there is a way to bypass this limitation using reflection.

    Set-Variable -Name 'MyConstantVariable' -Value 'Hello World' -Option 'Constant'\n$MyConstantVariable\n\n$PSVar = Get-Variable -Name 'MyConstantVariable'\n$PSVar.GetType().GetField('_value', [System.Reflection.BindingFlags] 'NonPublic, Instance').SetValue($PSVar, 'Wut')\n$MyConstantVariable\n\n$PSVar.GetType().GetField('_options', [System.Reflection.BindingFlags] 'NonPublic, Instance').SetValue($PSVar, [System.Management.Automation.ScopedItemOptions]::None)\n$MyConstantVariable = 'Lolz'\n$MyConstantVariable\n

    Shout out to Santiago Squarzon for this trick.

    The way you can prevent this bypass is by defining constant variables in C# code in PowerShell. The reflection method demonstrated above won't work on this type of constant variables.

    Add-Type -TypeDefinition @'\nnamespace NS\n{\n    public static class Const\n    {\n        public const int myConst = 66;\n    }\n}\n'@ -Language CSharp\n\n([NS.Const]::myConst)\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/#how-to-prevent-powershell-optimization-from-being-disabled","title":"How To Prevent PowerShell Optimization From Being Disabled","text":"

    In PowerShell, the presence of the following commands in a ScriptBlock will completely disable optimizations in that ScriptBlock:

    New-Variable\nRemove-Variable\nSet-Variable\nSet-PSBreakpoint\n# Also Dot-Sourcing\n. .\\file.ps1\n# Also if any type of breakpoint is already set\n

    Also usage of any AllScope variable in a ScriptBlock will disable optimization in there.

    You can view those commands in here too.

    Shout out to SeeminglyScience for this info.

    Any PowerShell code at some point will run and be in a ScriptBlock. Functions are their own ScriptBlock, modules (.psm1 files) are their own ScriptBlock, script files (.ps1 files) are their own ScriptBlock, ScriptBlocks themselves are their own ScriptBlock and so on.

    So the presence of the above methods and commands inside a ScriptBlock in the context explained above will disable optimization in that ScriptBlock, you can however use them outside of the ScriptBlock and then utilize them inside which will not disable optimization in that ScriptBlock.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/#the-fastest-way-to-enumerate-all-files-in-directories-based-on-specific-extensions","title":"The Fastest Way To Enumerate All Files In Directories Based On Specific Extensions","text":"

    This example will enumerate all files in an array of directories based on specific extensions and return an array of FileInfo objects. This is potentially the fastest and most optimized way to do this. This command takes ~9 seconds to complete on my system.

    # Define a HashSet of file extensions to filter by\n$Extensions = [System.Collections.Generic.HashSet[System.String]]@('.sys', '.exe', '.com', '.dll', '.rll', '.ocx', '.msp', '.mst', '.msi', '.js', '.vbs', '.ps1', '.appx', '.bin', '.bat', '.hxs', '.mui', '.lex', '.mof')\n# Define an array of directory paths to scan through\n[System.IO.DirectoryInfo[]]$Paths = 'C:\\ProgramData\\Microsoft', 'C:\\Program Files\\Windows Defender', 'C:\\Program Files\\Hyper-V'\n# Define a HashSet to store the initial output\n$Output = [System.Collections.Generic.HashSet[System.IO.FileInfo]]@()\n# Define the GetFiles parameters\n$Options = [System.IO.EnumerationOptions]@{\n    IgnoreInaccessible    = $true\n    # This is equal to -Recurse parameter in Get-ChildItem cmdlet\n    RecurseSubdirectories = $true\n    # By default is skips hidden and system files, here we just skip the System files\n    # https://learn.microsoft.com/en-us/dotnet/api/system.io.fileattributes\n    # https://learn.microsoft.com/en-us/dotnet/api/system.io.enumerationoptions.attributestoskip\n    AttributesToSkip      = 'System'\n}\n\n# Loop over each path and add the files to the output HashSet using UnionWith\nforeach ($Path in $Paths) {\n    $Output.UnionWith((Get-Item -LiteralPath $Path).GetFiles('*', $Options))\n}\n# Define a HashSet to store the filtered output - Making sure the comparison is case-insensitive since \"Get-ChildItem -Include\" is case-insensitive as well and we don't want to miss files with \".DLL\" extension and so on\n$OutputAfterFiltering = [System.Collections.Generic.HashSet[System.IO.FileInfo]]@( $Output.Where({ $Extensions.Contains($_.Extension.ToLower()) }))\n

    This is an improved variation of the script above that handles inaccessible directories better but takes a few seconds (~3) more to complete.

    # Define a HashSet of file extensions to filter by\n$Extensions = [System.Collections.Generic.HashSet[System.String]]::new(\n    [System.String[]] ('.sys', '.exe', '.com', '.dll', '.rll', '.ocx', '.msp', '.mst', '.msi', '.js', '.vbs', '.ps1', '.appx', '.bin', '.bat', '.hxs', '.mui', '.lex', '.mof'),\n    # Make it case-insensitive\n    [System.StringComparer]::InvariantCultureIgnoreCase\n)\n# Define an array of directory paths to scan through\n[System.IO.DirectoryInfo[]]$Paths = 'C:\\ProgramData\\Microsoft', 'C:\\Program Files\\Windows Defender', 'C:\\Program Files\\Hyper-V'\n# Define a HashSet to store the initial output\n$Output = [System.Collections.Generic.HashSet[System.IO.FileInfo]]@()\n# Define the GetFiles parameters\n$Options = [System.IO.EnumerationOptions]@{\n    IgnoreInaccessible    = $true\n    # This is equal to -Recurse parameter in Get-ChildItem cmdlet\n    RecurseSubdirectories = $true\n    # This is equal to -Force parameter in Get-ChildItem cmdlet\n    AttributesToSkip      = 'None'\n}\n\n$Output = foreach ($Path in $Paths) {\n    [System.IO.Enumeration.FileSystemEnumerator[System.IO.FileInfo]]$Enum = $Path.EnumerateFiles('*', $Options).GetEnumerator()\n    while ($true) {\n        try {\n            # Move to the next file\n            if (-not $Enum.MoveNext()) {\n                # If we reach the end of the enumeration, we break out of the loop\n                break\n            }\n            # Check if the file extension is in the Extensions HashSet\n            if ($Extensions.Contains($Enum.Current.Extension)) {\n                # Pass the file to the output\n                $Enum.Current\n            }\n        }\n        catch {}\n    }\n}\n

    Shout out to Santiago Squarzon for providing this method.

    For comparison, the following command takes ~20 minutes to complete on my system and produces the same exact output as the scripts above but it's 100x times slower.

    [System.IO.DirectoryInfo[]]$Paths = 'C:\\ProgramData\\Microsoft', 'C:\\Program Files\\Windows Defender', 'C:\\Program Files\\Hyper-V'\n[System.String[]]$Extensions = @('*.sys', '*.exe', '*.com', '*.dll', '*.rll', '*.ocx', '*.msp', '*.mst', '*.msi', '*.js', '*.vbs', '*.ps1', '*.appx', '*.bin', '*.bat', '*.hxs', '*.mui', '*.lex', '*.mof')\n[System.IO.FileInfo[]]$Output = Get-ChildItem -Recurse -File -LiteralPath $Paths -Include $Extensions -Force -ErrorAction SilentlyContinue\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/","title":"Basic PowerShell Tricks and Notes","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 1 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#pipeline-variable","title":"Pipeline Variable","text":"

    $_ is the variable for the current value in the pipeline.

    Examples

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#filtering-data-with-where-object","title":"Filtering Data With Where-Object","text":"

    ? which is an alias for Where-Object, is used to filter all the data given to it.

    Where-Object

    Example

    Get-PSDrive | ?{$_.free -gt 1}\n

    Example

    Get-PSDrive | Where-Object {$_.free -gt 1}\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#show-the-properties-of-an-object-selectively","title":"Show the Properties of an Object Selectively","text":"

    Select or Select-Object show the properties that we want to see from an object

    If we use * then all of the properties will be shown and from there we can choose which properties to add.

    Example:

    Get-PSDrive | Where-Object {$_.free -gt 1} | Select-Object -Property *\n\nGet-PSDrive | Where-Object {$_.free -gt 1} | Select-Object -Property root, used, free\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#looping-using-foreach-object","title":"Looping Using Foreach-Object","text":"

    The ForEach-Object cmdlet performs an operation on each item in a collection of input objects. The input objects can be piped to the cmdlet or specified using the InputObject parameter.

    In other words: for every item in the pipe, run this line.

    Examples:

    Get-PSDrive | Where-Object { $_.free -gt 1 } | Select-Object -Property root, used, free | ForEach-Object { 'zebra' }\n
    Get-PSDrive | Where-Object { $_.free -gt 1 } | Select-Object -Property root, used, free | ForEach-Object { Write-Host 'Free Space for ' $_.Root 'is' ($_.free / 1gb ) }\n

    The parenthesis, ($_.free/1gb ) must be there if we want to modify one of the output strings.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#to-get-online-help-about-any-cmdlet","title":"To Get Online Help About Any Cmdlet","text":"

    These commands open the webpage for the specified cmdlet or command

    Get-help <cmdlet> \u2013online\n
    Get-Help dir \u2013online\n
    Get-Help ForEach-Object \u2013online\n

    This shows the full help on the PowerShell console

    Get-help Get-Service -full\n

    This opens a new window showing the full help content and offers other options such as Find

    Get-help Get-Service -ShowWindow\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#to-query-windows-services","title":"To Query Windows Services","text":"

    This gets any Windows service that has the word \"Xbox\" in it.

    Get-Service \"*xbox*\"\n

    This gets any Windows service that has the word \"x\" in it.

    Get-Service \"*x*\"\n

    Putting * around the word or letter finds anything that contains it.

    Get-Service \"*x*\" | Sort-Object status\n

    Example syntax:

    Get-Service [[-Name] <System.String[]>] [-ComputerName <System.String[]>] [-DependentServices] [-Exclude <System.String[]>] [-Include <System.String[]>] [-RequiredServices] [<CommonParameters>]\n

    In this part

    Get-Service [[-Name] <System.String[]>]\n

    The -Name Parameter accepts <System.String[]>, which is a StringList, and when [] is included, that means there can be multiple inputs/strings, separated by comma ,.

    So [[-Name] <System.String[]>] can be used like this:

    Get-Service -Name WinRM,BITS,*Xbox*\n

    Also in another similar example syntax:

    Get-Service [-ComputerName <System.String[]>] [-DependentServices] -DisplayName <System.String[]> [-Exclude <System.String[]>] [-Include <System.String[]>] [-RequiredServices] [<CommonParameters>]\n

    Everything is inside a bracket except for -DisplayName, that means it is mandatory. If a parameter is inside a bracket, that means it is optional.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-suppress-errors-in-powershell","title":"How to Suppress Errors in Powershell","text":"
    -ErrorAction SilentlyContinue\n

    Everything you wanted to know about exceptions

    Try/Catch will only 'trigger' on a terminating exception. Most cmdlets in PowerShell, by default, won't throw terminating exceptions. You can set the error action with the\u202f-ErrorAction\u202for -ea parameters:

    Do-Thing 'Stuff' -ErrorAction Stop\n

    Be careful when using -ErrorAction Stop. If using it in loops like with ForEach-Object, it will stop the entire loop after the first encounter of error.

    Handling Errors the PowerShell Way

    Tip: If you set

    $ErrorActionPreference = 'Stop'\n

    In your PowerShell code, either locally or globally for the entire script, Write-Error will cause the script to stop because it will be like throwing an error.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#get-file-signature-of-all-of-the-files-in-a-folder","title":"Get File Signature of All of the Files in a Folder","text":"

    This will check all of the files' signatures in the current directory

    Get-ChildItem -File | ForEach-Object -Process {Get-AuthenticodeSignature -FilePath $_}\n

    More info about Get-ChildItem cmdlet

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#write-output-to-a-file-or-string","title":"Write Output to a File or String","text":"
    > output.txt\n

    Example:

    ipconfig /all > mynetworksettings.txt\n

    about_Redirection

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-add-delaypause-to-the-execution-of-powershell-script","title":"How to Add Delay/Pause to the Execution of Powershell Script","text":"

    To sleep a PowerShell script for 5 seconds, you can run the following command

    Start-Sleep -Seconds 5\n

    You can also use the -milliseconds parameter to specify how long the resource sleeps in milliseconds.

    Start-Sleep -Milliseconds 25\n

    Start-Sleep

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-stopkill-a-a-process-or-exe-executable-in-powershell","title":"How to Stop/Kill a a Process or (.exe) Executable in Powershell","text":"

    Using native PowerShell cmdlet

    Stop-Process -Name \"Photoshop\"\n

    Stop-Process

    Using taskkill.exe

    taskkill /IM \"photoshop app.exe\" /F\n

    taskkill

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#automatically-answer-yes-to-a-prompt-in-powershell","title":"Automatically Answer \u201cYes\u201d to a Prompt in Powershell","text":"

    Use \u2013force at the end of the command

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#displays-all-information-in-the-current-access-token","title":"Displays All Information in the Current Access Token","text":"

    The command below displays all information in the current access token, including the current user name, security identifiers (SID), privileges, and groups that the current user belongs to.

    whoami /all\n

    whoami

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#display-all-the-tcp-and-udp-ports-on-which-the-computer-is-listening","title":"Display All the Tcp and Udp Ports on Which the Computer Is Listening","text":"
    netstat -a\n

    netstat

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#copy-the-result-of-a-command-to-clipboard-automatically","title":"Copy the Result of a Command to Clipboard Automatically","text":"

    Add | clip at the end the command

    Example:

    Get-TimeZone | clip\n

    Example:

    rg -i -F URL: | clip\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-scan-2-text-files-for-differences-and-pipe-the-difference-to-a-third-file","title":"How to Scan 2 Text Files for Differences and Pipe the Difference to a Third File","text":"
    $File1 = \"C:\\Scripts\\Txt1.txt\"\n$File2 = \"C:\\Scripts\\Txt2.txt\"\n$Location = \"C:\\Scripts\\Txt3.txt\"\n\nCompare-Object -ReferenceObject (Get-Content -Path $File1) -DifferenceObject (Get-Content -Path $File2) | Format-List | Out-File -FilePath $Location\n

    Compare-Object

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#difference-between-strings-and-stringlists","title":"Difference Between Strings and StringLists","text":"

    This is Stringlist in PowerShell:

    [String[]]

    And this is a string

    [String]

    When we define Stringlist in a parameter, then the argument will keep asking for multiple values instead of 1, if we want to stop adding arguments for the parameter, we have to enter twice.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-run-a-powershell-ps1-script","title":"How to Run a Powershell (.PS1) Script ?","text":"
    &\"Path\\To\\PS\\Script.ps1\"\n

    Using the & Call operator

    Set-Location 'Path\\To\\Folder\\OfThe\\Script'\n.\\Script.ps1\n
    pwsh.exe -File 'Path\\To\\Folder\\OfThe\\Script.ps1'\n

    This example uses PowerShell Core

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#enclosing-strings-that-have-a-lot-of-single-and-double-quotation-marks","title":"Enclosing Strings That Have a Lot of Single and Double Quotation Marks","text":"
    $string =@\"\n\nSome string text\n\n\"@\n\n$string\n

    the markers @\" and \"@ indicating the beginning and end of the string must be on separate lines.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-find-the-type-of-the-output-of-a-command-in-powershell","title":"How to Find the Type of the Output of a Command in Powershell","text":"

    Using GetType()

    Examples:

    (Get-BitlockerVolume -MountPoint \"C:\").KeyProtector.keyprotectortype.GetType()\n
    (Get-NetTCPConnection).GetType()\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#make-sure-to-use-pascal-case-for-variable-names","title":"Make Sure to Use Pascal Case for Variable Names","text":"

    Pascal Case requires variables made from compound words and have the first letter of each appended word written with an uppercase letter.

    Example: $Get-CurrentTime

    This will make your code readable and more understandable.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#some-popular-resources-and-cmdlets","title":"Some Popular Resources and Cmdlets","text":"

    "},{"location":"PowerShell/How%20To%20Access%20All%20Stream%20Outputs%20From%20Thread%20Jobs%20In%20PowerShell%20In%20Real%20Time/","title":"How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time","text":"

    The following code snippet demonstrates how to access all stream outputs from thread jobs in PowerShell in real time. It uses the Start-ThreadJob cmdlet to start the thread jobs and the Receive-Job cmdlet to access the job output streams. The code snippet also demonstrates how to access the warning, debug, verbose, output, host, and information streams from the thread jobs.

    It is properly commented to explain each part of the code.

    [System.String[]]$JobNames = 'cat', 'dog', 'Zebra', 'kangaroo'\n\n# A hashtable to store the jobs\n[System.Collections.Hashtable]$Jobs = @{}\n\n# Start a job for each animal in the list\nforeach ($JobName in $JobNames) {\n\n    [System.Management.Automation.Job2]$CurrentJob = Start-ThreadJob -Name \"Animals $JobName\" -ScriptBlock {\n        Param ($JobNameInput)\n        #   $ErrorActionPreference = 'Stop'\n\n        Write-Output -InputObject \"Job started for $JobNameInput\"\n\n        # Simulate some real work\n        Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 10)\n\n        Throw 1 / 0\n\n        Write-Error -Message \"Error message for $JobNameInput\"\n\n        Write-Warning -Message \"Warning message for $JobNameInput\"\n        Write-Debug -Message \"Debug Message for $JobNameInput\" -Debug\n        Write-Verbose -Message \"Verbose message for $JobNameInput\" -Verbose\n        Write-Output -InputObject \"Output message for $JobNameInput\"\n        Write-Host -Object \"Host message for $JobNameInput\"\n        Write-Information -MessageData \"Information message for $JobNameInput\"\n\n    } -ArgumentList $JobName\n\n    # Add the job to the hashtable with the job object as the key and its name as the value\n    $Jobs[$CurrentJob] = $JobName\n}\n\n# Continuously check for job output\nwhile ($Jobs.Count -ne 0) {\n\n    # An array of the jobs to remove\n    [System.Management.Automation.Job2[]]$JobsToRemove = @()\n\n    foreach ($Job in $Jobs.Keys) {\n\n        # Accessing individual output streams from the job that Receive-Job does not display\n        # $Job.Warning - not required - Receive-Job shows it\n        $Job.Debug\n        $Job.Progress\n        # $Job.Error - not required - Receive-Job shows it\n        $Job.Information # Also displays the Write-Host message\n\n        # Gets the success, error, warning and host stream from Write-Host\n        Receive-Job -Job $Job\n\n        if ($Job.State -eq 'Completed' -or $Job.State -eq 'Failed') {\n\n            #  if ($Job.State -eq 'Failed') {\n            #      Write-Output \"Job $($Job.Id) failed with reason: $($Job.JobStateInfo.Reason)\"\n            #  }\n\n            # Remove the job\n            Remove-Job -Job $Job -Force\n\n            # Add the job to the list of jobs to remove\n            $JobsToRemove += $Job\n        }\n    }\n\n    # Remove the jobs from the hashtable\n    foreach ($Job in $JobsToRemove) {\n        $Jobs.Remove($Job)\n    }\n\n    # Define the interval for checking the jobs\n    Start-Sleep -Milliseconds 500\n}\n\n# Getting all of the jobs to make sure nothing is left\nGet-Job\n

    "},{"location":"PowerShell/How%20To%20Access%20All%20Stream%20Outputs%20From%20Thread%20Jobs%20In%20PowerShell%20In%20Real%20Time/#highly-recommended-to-read-the-following-related-articles","title":"Highly recommended to read the following related articles:","text":""},{"location":"PowerShell/How%20To%20Asynchronously%20Access%20All%20Stream%20Outputs%20From%20Background%20Jobs%20In%20PowerShell/","title":"How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell","text":"

    In this article, we will learn how to asynchronously access all stream outputs from background jobs in PowerShell. We will use the Start-Job cmdlet to start a job for each animal in the list. We will then use the Register-ObjectEvent cmdlet to create an event subscriber for the job to automatically receive the job output for all streams and discard itself and the job. We will also use the Unregister-Event cmdlet to remove the event itself and the Remove-Job cmdlet to remove the event subscriber's job.

    We will also properly communicate any terminating or non-terminating error that ocurred inside of each job to the console.

    [System.String[]]$JobNames = 'cat', 'dog', 'Zebra', 'kangaroo'\n\n# Start a job for each animal in the list\nforeach ($JobName in $JobNames) {\n\n    $CurrentJob = Start-Job -Name \"Animals $JobName\" -ScriptBlock {\n        Param ($JobNameInput)\n\n        Start-Sleep -Seconds 2\n\n        Write-Output -InputObject \"Job started for $JobNameInput\"\n\n        # Simulate some real work\n        Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 10)\n\n        # Generate terminating error\n        # Throw \"Error message for $JobNameInput\"\n\n        # Generate Non-terminating error\n        Write-Error -Message \"Error message 1 for $JobNameInput\"\n\n        Write-Warning -Message \"Warning message for $JobNameInput\"\n        Write-Debug -Message \"Debug Message for $JobNameInput\" -Debug\n        Write-Verbose -Message \"Verbose message for $JobNameInput\" -Verbose\n        Write-Error -Message \"Error message 2 for $JobNameInput\"\n        Write-Output -InputObject \"Output message for $JobNameInput\"\n        Write-Host -Object \"Host message for $JobNameInput\"\n        Write-Information -MessageData \"Information message for $JobNameInput\"\n\n    } -ArgumentList $JobName\n\n    # Create an event subscriber for the job to automatically receive the job output for all streams and discard itself and the job\n    Register-ObjectEvent -InputObject $CurrentJob -EventName StateChanged -Action {\n\n        # Receive the Write-Output stream for success stream\n        # Write-Host is needed to display the error message on the console\n        # We need to use loop because all of the Write-Output messages are stored in the ChildJobs.Output property\n        # And without a loop, they would all be written as a single string on in one line\n        if ($null -ne $EventSubscriber.SourceObject.ChildJobs.Output) {\n            $EventSubscriber.SourceObject.ChildJobs.Output | ForEach-Object -Process {\n                Write-Host -Object $_\n            }\n        }\n\n        # Check if a terminating error ocurred in the job\n        if ($EventSubscriber.SourceObject.State -eq 'Failed') {\n            Write-Host -Object \"The Job $($EventSubscriber.SourceObject.Name) Failed\" -ForegroundColor Red\n        }\n\n        # Receive the Terminating error stream - Write-Host is needed to display the error message on the console\n        if ($null -ne $EventSubscriber.SourceObject.ChildJobs.JobStateInfo.Reason.Message) {\n            $EventSubscriber.SourceObject.ChildJobs.JobStateInfo.Reason.Message | ForEach-Object -Process {\n                Write-Host -Object $_ -ForegroundColor Red\n            }\n        }\n\n        # Receive the Non-Terminating error stream - Write-Host is needed to display the error message on the console\n        if ($null -ne $EventSubscriber.SourceObject.ChildJobs.Error) {\n            $EventSubscriber.SourceObject.ChildJobs.Error | ForEach-Object -Process {\n                Write-Host -Object $_ -ForegroundColor DarkRed\n            }\n        }\n\n        # Receive the job output except for Wire-Output and error stream\n        Receive-Job -Job $EventSubscriber.SourceObject\n\n        # Unregister the event itself\n        Unregister-Event -SourceIdentifier $EventSubscriber.SourceIdentifier -Force\n        # Remove the event subscriber's job, it is the same as the event subscriber's SourceIdentifier\n        Remove-Job -Name $EventSubscriber.SourceIdentifier -Force\n        # Remove the input job initiated by Start-Job\n        Remove-Job -Id $EventSubscriber.SourceObject.Id -Force\n\n    } | Out-Null\n}\n\n# Get all of the jobs at the end to make sure there is no leftover\n# Get-Job\n\n# Make sure all of the event subscriptions have been properly removed at the end\n# (Get-EventSubscriber).SourceIdentifier\n\n# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables#eventsubscriber\n# $EventSubscriber inside of the action block is the same as the following objects\n# (Get-EventSubscriber)[0].SourceObject.ChildJobs.JobStateInfo.Reason.Message\n# (Get-EventSubscriber).SourceObject.ChildJobs.output\n

    "},{"location":"PowerShell/How%20To%20Asynchronously%20Access%20All%20Stream%20Outputs%20From%20Background%20Jobs%20In%20PowerShell/#note-about-why-we-needed-to-access-childjobs-property","title":"Note About Why We Needed To Access ChildJobs Property","text":"

    when you use Start-Job to initiate a background job, it executes the provided script block in a separate, child job. This is because Start-Job is designed to run tasks asynchronously, allowing the main PowerShell session to continue without waiting for the task to complete.

    The child job is essentially a separate PowerShell process that runs in the background. It's isolated from the parent job, which means it has its own scope and doesn't share variables or RunSpaces with the parent. This isolation ensures that the main session remains responsive and that the background task doesn't interfere with the ongoing tasks in the main session.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/","title":"PowerShell Best Practices To Follow When Coding","text":"

    It is important to follow best practices when coding in PowerShell to ensure that your codes are efficient, maintainable, and secure.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#specify-the-variable-types-explicitly","title":"Specify The Variable Types Explicitly","text":"

    \ud83d\udeab Don't do this

    $Var = 5\n

    \u2705 Do this instead

    [System.Int32]$Var = 5\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-full-type-names-instead-of-type-accelerators","title":"Use Full Type Names Instead of Type Accelerators","text":"

    \ud83d\udeab Don't do this

    [String]$Var = 'Hello'\n

    \u2705 Do this instead

    [System.String]$Var = 'Hello'\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-single-quotes-instead-of-double-quotes-unless-absolutely-necessary","title":"Use Single Quotes Instead of Double Quotes Unless Absolutely Necessary","text":"

    \ud83d\udeab Don't do this

    $Var = \"Hello\"\n

    \u2705 Do this instead

    $Var = 'Hello'\n

    This is because double quotes allow for string interpolation, which can be a security risk if the string is not sanitized properly and also slightly slower than single quotes.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-full-cmdlet-names-instead-of-aliases","title":"Use Full Cmdlet Names Instead of Aliases","text":"

    \ud83d\udeab Don't do this

    Gci\ncls\n

    \u2705 Do this instead

    Get-ChildItem\nClear-Host\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-pascal-casing-for-everything","title":"Use Pascal Casing for Everything","text":"

    \ud83d\udeab Don't do this

    $myvariable\nget-childitem\nnew-item\n

    \ud83d\udeab or this (camelCase)

    $myVariable\nget-ChildItem\nnew-Item\n

    \u2705 Do this instead

    $MyVariable\nGet-ChildItem\nNew-Item\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-regions-to-organize-your-code","title":"Use Regions to Organize Your Code","text":"

    \u2705 Using regions like this allows you to collapse and expand sections of your code for better readability.

    #Region Functions\nfunction Get-MyFunction1 {\n    # Function code here\n}\nfunction Get-MyFunction2 {\n    # Function code here\n}\nfunction Get-MyFunction3 {\n    # Function code here\n}\n#EndRegion\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-visual-studio-code-powershell-extension-for-automatic-best-practice-formatting","title":"Use Visual Studio Code PowerShell Extension For Automatic Best Practice Formatting","text":"

    You can access the settings page of PowerShell extension in VS Code and enable options that automatically apply some of the aforementioned best practices when you format your code with (CTRL + Shift + F) shortcut.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#refrain-from-defining-and-using-global-variables-as-much-as-possible","title":"Refrain From Defining and Using Global Variables as Much as Possible","text":"

    Global variables are not recommended in general because of security implications. They can be overwritten by the user on console as well.

    If you need to define global variables, make sure you set them as constants or read-only so that they cannot be overwritten once they are defined.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#more-resources-from-microsoft-that-you-should-check-out","title":"More Resources From Microsoft That You Should Check Out","text":""},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/","title":"Powershell Dynamic Parameters and How to Add Them to the Get-Help Syntax","text":"

    PowerShell has a feature called dynamic parameters that allows you to add parameters to a cmdlet based on the value of another parameter. This is useful when you have a parameter that can take multiple values and you want to add additional parameters based on the value of the first parameter.

    Dynamic parameters also allow you to make a parameter conditionally mandatory based on different criteria.

    They are very powerful but have a downside: since they are runtime-defined, they are not displayed in the Get-Help output. This can be a problem if you want to provide help to users of your cmdlet and inform them of all of the available parameters that your cmdlet supports, including the dynamic ones.

    Usually, PowerShell developers use comment-based help inside of the cmdlet's function to provide help content to the user, however that approach doesn't allow us to control all aspects of the help content, such as the syntax. If you want to add the dynamic parameters to the Get-Help output's syntax, you will need to switch to XML-based help.

    "},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/#platyps","title":"PlatyPS","text":"

    PlatyPS is a module that allows you to generate XML-based help for your cmdlets. It can be used to add dynamic parameters to the Get-Help output's syntax. You will be editing a Markdown file which is convenient and the module will automatically generate the XML help file for you.

    "},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/#create-a-markdown-file-based-on-your-cmdlet","title":"Create a Markdown file Based on your Cmdlet","text":"
    New-MarkdownHelp -Command 'YourCmdletName' -OutputFolder \".\\docs\"\n

    After you've created a markdown file based on your current cmdlet's parameters and details, you can start adding the dynamic parameters to it and modify the syntax, because dynamic parameters are not automatically added to it. Once you are done, you can run the following command to generate the XML help file.

    "},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/#generate-the-xml-help-file-from-the-markdown-file","title":"Generate the XML Help File from the Markdown file","text":"
    New-ExternalHelp -Path \"Path-To-Markdown-File.md\" -OutputPath \"Path-To-XML-File.xml\" -Force\n

    After creating your XML-based help file, you will then have to reference it in your cmdlet's function like this

    .EXTERNALHELP .\\Help\\Cmdlet-Name.xml\n

    The path doesn't accept variables but it can be either relative or full path to the XML help file. Once you reference that, you can either remove all of the comment-based help from the function or keep them, the XML-based help takes precedence over the comment-based help when both types of help content are present.

    "},{"location":"PowerShell/RunSpaces%20In%20PowerShell/","title":"RunSpaces In PowerShell","text":"

    The concept of Runspaces is built upon the .NET threading model, which allows PowerShell to execute multiple scripts or commands in parallel. This is achieved by creating separate instances of the PowerShell engine, each running in its own thread, thus not interfering with the primary PowerShell session or other Runspaces.

    Utilizing Runspaces effectively requires an understanding of threading and synchronization, as data sharing between threads must be handled carefully to avoid race conditions and ensure thread safety. The synchronized hashtable, as demonstrated in the provided script, is a prime example of a thread-safe data structure that facilitates communication between Runspaces.

    "},{"location":"PowerShell/RunSpaces%20In%20PowerShell/#how-to-create-runspace-and-powershell-instance-and-reuse-them","title":"How To Create RunSpace and PowerShell Instance and Reuse Them","text":"
    # Display the number of the runspaces before operation\n(Get-Runspace).count\n\n# Create a synchronized hashtable for inter-runspace communication\n$SyncHash = [System.Collections.Hashtable]::Synchronized(@{})\n\n# Create a new runspace\n$GUIRunSpace = [System.Management.Automation.RunSpaces.RunSpaceFactory]::CreateRunSpace()\n$GUIRunSpace.ApartmentState = 'STA'\n$GUIRunSpace.ThreadOptions = 'ReuseThread'\n\n# Create a new PowerShell object\n$GUIPowerShell = [System.Management.Automation.PowerShell]::Create()\n# Assign the runspace to the PowerShell object's Runspace property\n$GUIPowerShell.RunSpace = $GUIRunSpace\n# Open the runspace\n$GUIRunSpace.Open()\n\n# Make the synchronized hashtable available in the runspace\n$GUIRunSpace.SessionStateProxy.SetVariable('SyncHash', $SyncHash)\n\n# Add a script to the PowerShell object so that it can run inside the runspace\n[System.Void]$GUIPowerShell.AddScript({\n        Write-Output -InputObject '1st output'\n    })\n\n# Invoke the PowerShell object asynchronously and store the resulting handle in a variable\n$GUIAsyncObject = $GUIPowerShell.BeginInvoke()\n\n# End the asynchronous operation and display the output\n$GUIPowerShell.EndInvoke($GUIAsyncObject)\n\n# Add another script to the PowerShell object to run, replacing the previous script added to the object.\n# The runspace is still open\n[System.Void]$GUIPowerShell.AddScript({\n        Write-Output -InputObject '2nd output'\n    })\n\n# Again invoke the PowerShell object asynchronously and store the resulting handle in a variable\n$GUIAsyncObject = $GUIPowerShell.BeginInvoke()\n\n# End the asynchronous operation and display the output\n$GUIPowerShell.EndInvoke($GUIAsyncObject)\n\n# Close and dispose of the runspace and PowerShell object\n$GUIPowerShell.Dispose()\n$GUIRunSpace.Close()\n$GUIRunSpace.Dispose()\n\n# Display the number of the runspaces after operation\n(Get-Runspace).count\n
    "},{"location":"PowerShell/RunSpaces%20In%20PowerShell/#how-to-handle-runspace-events-asynchronously-from-the-parent-runspace","title":"How To Handle RunSpace Events Asynchronously From The Parent RunSpace","text":"

    This example demonstrates how to create a runspace that runs a GUI thread asynchronously and based on the events happening in the GUI thread, different actions are taken in the parent thread. The parent thread is responsible for handling the events generated by the GUI thread, such as button clicks, window closures, and errors. At the end of the operation, the runspace is closed and disposed of, ensuring no leftover runspaces or jobs.

    # Get the count of the RunSpaces before the operation to compare it with the count after the operation\n(Get-Runspace).count\n\n# Creating a synchronized hashtable to store shared data between the two runspaces\n$SyncedHashtable = [System.Collections.Hashtable]::Synchronized(@{})\n\n# Define the XAML code for WPF GUI\n$SyncedHashtable.XAML = [System.Xml.XmlDocument]@'\n<Window xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\nMaxWidth=\"600\" WindowStartupLocation=\"CenterScreen\" SizeToContent=\"WidthAndHeight\">\n<Button Name=\"Button1\" Content=\"Press Me\"/>\n</Window>\n'@\n\n# Assigning the parent runspace's host to the $SyncedHashtable.Host property.\n# It will be used to detect or rather, refer back to the parent runspace from inside of the GUI runspace.\n# This is crucial for the event communication between the two runspaces.\n$SyncedHashtable.Host = $Host\n\n$RunSpace = [System.Management.Automation.RunSpaces.RunSpaceFactory]::CreateRunspace()\n$RunSpace.ApartmentState = 'STA'\n$RunSpace.ThreadOptions = 'ReuseThread'\n\n$RunSpace.Open()\n$RunSpace.SessionStateProxy.SetVariable('SyncedHashtable', $SyncedHashtable)\n\n$PowerShell = [System.Management.Automation.PowerShell]::Create()\n$PowerShell.Runspace = $RunSpace\n\n[System.Void]$PowerShell.AddScript({\n\n        try {\n            # Add the required assembly for WPF\n            Add-Type -AssemblyName PresentationFramework\n\n            $Reader = New-Object -TypeName 'System.Xml.XmlNodeReader' -ArgumentList $SyncedHashtable.XAML\n            $SyncedHashtable.Window = [System.Windows.Markup.XamlReader]::Load( $Reader )\n\n            # Find the button object in the XAML\n            [System.Windows.Controls.Button]$SyncedHashtable.Button1 = $SyncedHashtable.Window.FindName('Button1')\n\n            # Add a click event to the button\n            $SyncedHashtable.Button1.Add_Click({\n                    $SyncedHashtable.Host.Runspace.Events.GenerateEvent('Button1Clicked', $null, 'Button Click Event', $null)\n                })\n\n            # Add a closed event to the window\n            $SyncedHashtable.Window.Add_Closed({\n                    $SyncedHashtable.Host.Runspace.Events.GenerateEvent('WindowClosed', $null, 'Sender', $null)\n                })\n\n            # Throw a dummy error to test the async error handling\n            # throw 'Test Error'\n\n            # Show the GUI\n            $SyncedHashtable.Window.ShowDialog()\n        }\n        catch {\n            $SyncedHashtable.ErrorMessage = $_.Exception.Message\n            $SyncedHashtable.Host.Runspace.Events.GenerateEvent('ErrorsOccurred', $null, $null, $null)\n        }\n    })\n\n# Start the GUI PowerShell instance asynchronously\n$AsyncHandle = $PowerShell.BeginInvoke()\n\n# You can inspect the events that the 'Register-EngineEvent' cmdlet receives here\n# $Button1ClickedEvent = Get-Event -SourceIdentifier 'Button1Clicked'\n# $WindowClosedEvent = Get-Event -SourceIdentifier 'WindowClosed'\n# $ErrorsOccurredEvent = Get-Event -SourceIdentifier 'ErrorsOccurred'\n\n# Register an event for the button click\n$Button1ClickedSub = Register-EngineEvent -SourceIdentifier 'Button1Clicked' -Action {\n    param (\n        $Sender\n    )\n    Write-Host -Object $Sender\n}\n\n# Register an event for the window closure\n$WindowClosedSub = Register-EngineEvent -SourceIdentifier 'WindowClosed' -Action {\n    param (\n        $Sender\n    )\n    Write-Host -Object 'The GUI has been closed.'\n\n    # Remove the event subscription and the job for the button click event since the GUI Windows was closed\n    Unregister-Event -SubscriptionId $Button1ClickedSub.Id\n    Remove-Job -InstanceId $Button1ClickedSub.InstanceId\n\n    # Remove the event subscription and the job for the errors occurred event since the GUI Windows was closed\n    Unregister-Event -SubscriptionId $ErrorsOccurredSub.Id\n    Remove-Job -InstanceId $ErrorsOccurredSub.InstanceId\n\n    # Close the runspace and dispose of it\n    $RunSpace.Close()\n    $RunSpace.dispose()\n\n    # Remove the event subscription and the job of the current event subscription\n    Unregister-Event -SubscriptionId $WindowClosedSub.Id\n    Remove-Job -InstanceId $WindowClosedSub.InstanceId\n}\n\n# Register an event for the errors occurred in the GUI RunSpace\n$ErrorsOccurredSub = Register-EngineEvent -SourceIdentifier 'ErrorsOccurred' -Action {\n    Write-Host -Object \"Errors Occurred: $($SyncedHashtable.errorMessage)\"\n}\n\n# Get the count of the runspaces after the operation to see there is no leftover runspace\n(Get-Runspace).count\n\n# There won't be any leftover jobs or event subscriptions once the GUI window is closed\n# Get-EventSubscriber\n# Get-Job\n
    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/","title":"Application Control (WDAC) Frequently Asked Questions (FAQs)","text":""},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#whats-the-difference-between-application-control-policies-and-an-antivirus","title":"What's The Difference Between Application Control Policies And An Antivirus?","text":"

    Application Control policies are based on whitelisting strategy, meaning everything is blocked by default unless explicitly allowed. Antiviruses on the other hand are based on blacklisting strategy, meaning everything is allowed by default unless explicitly blocked.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-does-wdac-in-the-os-compare-to-3rd-party-solutions","title":"How Does WDAC In The OS Compare To 3rd Party Solutions?","text":"

    WDAC which is built deep inside of the OS kernel doesn\u2019t need any \u201cagents\u201d to be installed, that means it can\u2019t be killed using techniques used against 3rd party solutions, it also doesn\u2019t increase the attack surface of the system. It\u2019s native and exceedingly fast which makes it transparent to the user.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#can-i-use-microsoft-defender-for-endpoint-mde-to-collect-wdac-logs","title":"Can I Use Microsoft Defender For Endpoint (MDE) To Collect WDAC Logs?","text":"

    Yes. MDE Should definitely be used to manage your endpoints and collect Code Integrity logs used to create WDAC policies. They provide very detailed CI info at scale for your entire fleet of machines. Then Intune can be used for at scale deployment of the policies after creation.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#can-supplemental-policies-have-deny-rules","title":"Can Supplemental Policies Have Deny Rules?","text":"

    No, Supplemental policies are only used to expand a base policy by allowing more files.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-can-i-make-my-wdac-policy-tamper-proof","title":"How Can I Make My WDAC Policy Tamper Proof?","text":"

    If you cryptographically sign and deploy your WDAC policy, it will be tamper-proof and even the system administrator won't be able to remove it without the certificate's private keys \ud83d\udd11.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-do-enterprises-and-businesses-use-application-control-wdac","title":"How Do Enterprises And Businesses Use Application Control (WDAC)?","text":"

    Businesses and Enterprises have a variety of options. They can set Intune as Managed Installer so any application pushed by the administrator to the endpoints will be trusted and installed but the users won't be able to install new applications on their own.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-many-wdac-policies-can-be-deployed-on-a-system","title":"How Many WDAC Policies Can Be Deployed On a System?","text":"

    There is no limit on how many Application Control (WDAC) policies you can deploy on a system.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-are-the-tools-i-need-to-get-started-with-application-control-wdac-policies","title":"What Are The Tools I Need To Get Started With Application Control (WDAC) Policies?","text":"

    WDACConfig PowerShell module and WDAC Wizard are all you need to begin your Application Control journey and create a robust security policy for your environment. They provide many advanced features that you can explore further when you're ready.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-is-isg-and-how-can-i-use-it-in-an-application-control-wdac-policy","title":"What Is ISG And How Can I Use It In An Application Control (WDAC) Policy?","text":"

    ISG stands for The Intelligent Security Graph. It's a very powerful AI-based system that processes Trillions of signals from all kinds of data sources every day. You can utilize it as the arbiter in WDAC policies so it can help you allow trusted apps and block unknown or malicious apps automatically.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-is-smart-app-control","title":"What Is Smart App Control?","text":"

    Smart App Control is an automated AI-based Application Control mechanism that uses the same underlying components as WDAC (Windows Defender Application Control). It can be used in all Windows editions and provides great level of security by default for all systems it's enabled on.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-is-the-most-secure-level-to-use-for-authorizing-files","title":"What Is The Most Secure Level To Use For Authorizing Files?","text":"

    For signed files, you should always use WHQLFilePublisher as main level and FilePublisher as fallback. For unsigned files, use Hash level.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#is-there-a-more-automated-way-to-use-application-control-at-scale","title":"Is There A More Automated Way To Use Application Control At Scale?","text":"

    Yes. Microsoft Defender for Cloud's adaptive application controls enhance your security with this data-driven, intelligent automated solution that defines allowlists of known-safe applications for your machines. It uses Machine Learning models and is based on the collected telemetry data.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/","title":"EKUs in WDAC, App Control for Business, Policies","text":""},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#introduction","title":"Introduction","text":"

    EKU stands for Extended Key Usage, which is an extension of X.509 certificates that delineates the functions for which the public key of the certificate can be employed. EKUs are designated by Object Identifiers (OIDs), which are sequences of digits that distinctly characterize a kind of usage.

    The EKUs extension can be either critical or non-critical. If the extension is critical, it implies that the certificate must be utilized solely for the functions indicated by the EKUs. If the extension is non-critical, it implies that the certificate can be employed for other functions as well, provided that they are not prohibited by other extensions or policies.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#a-detailed-analysis-of-object-identifiers-and-their-usage","title":"A Detailed Analysis of Object Identifiers and Their Usage","text":"

    Let's consider 1.3.6.1.4.1.311.61.4.1 as an example which is an OID accountable for ELAM EKU. An Object Identifier (OID) is a method of denominating distinguishing objects in a hierarchical fashion. OIDs are frequently employed in cryptography, security, and networking protocols to indicate various kinds of data or algorithms.

    Each cluster of digits in an OID is termed an arc. The arcs are separated by dots and constitute a tree structure. The first arc is the root of the tree, and the last arc is the leaf. The arcs in between are denoted as nodes. Each arc has a designation and a numeral, which are allocated by different authorities or standards organizations.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#ekus-in-wdac-policies","title":"EKUs in WDAC Policies","text":"

    EKUs are employed in WDAC policies to indicate the functions for which a certificate can be employed. Consider EKUs as a whitelist of permitted functions. If a certificate does not encompass any of the EKUs indicated in the WDAC policy, it will be discarded. They can be employed to confine the range of a certificate to a specific function.

    For instance, if a certificate is issued to an individual or an organization solely for code signing functions, it cannot be employed for high-value operations such as Early Launch AntiMalware (ELAM) driver signing. To have the capacity to sign ELAM drivers, the certificate must encompass the ELAM EKU which is only attained by fulfilling specific requirements demonstrated by Microsoft.

    We can readily verify this in the subsequent example. Let's assume you have deployed the DefaultWindows template policy on a machine, and now you want to enable a 3rd party application such as OBS to be allowed to run. You create a supplemental policy by scanning the components of the OBS software. If we now open the generated XML file, we can observe that there are signer rules in there.

    And if we open the properties of one of those signed files, we can observe that they are signed by a certificate that was issued to an individual for Code Signing function only.

    If we append an EKU that is not supported by this certificate, such as ELAM, to one of the signer rules in the supplemental policy, the OBS software will no longer be permitted by the Code Integrity to run because the certificate the components of the OBS software are signed with does not encompass the ELAM EKU.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-to-obtain-the-oid-of-an-eku-by-knowing-its-friendly-name-and-vice-versa","title":"How to Obtain the OID of an EKU by Knowing Its Friendly Name and Vice Versa","text":"

    If you know the OID or the friendly name of an EKU, you can readily obtain the other one by using the following PowerShell command

    [Security.Cryptography.Oid]::new($OIDOrFriendlyName)\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-to-convert-an-oid-to-hexadecimal-format-for-wdac-policies","title":"How to Convert an OID to Hexadecimal Format for WDAC Policies","text":"

    In a WDAC Policy XML file, each EKU must be defined in the EKUs node. For each EKU, there are 3 available attributes, 2 of which are mandatory and 1 is optional. The mandatory attributes are ID and Value, and the optional attribute is FriendlyName.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#we-can-convert-the-oid-of-an-eku-to-its-hexadecimal-representation-by-using-the-following-powershell-function","title":"We can convert the OID of an EKU to its hexadecimal representation by using the following PowerShell function:","text":"
    # Import the System.Formats.Asn1 namespaces\nusing namespace System.Formats.Asn1\nFunction Convert-OIDToHex {\n  [CmdletBinding()]\n  Param (\n    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]\n    [ValidateNotNullOrEmpty()][System.String]$OID\n  )\n  <#\n.SYNOPSIS\n  Converts an OID to a hexadecimal string\n.PARAMETER OID\n  The OID to convert\n.EXAMPLE\n  Convert-OIDToHex -OID '1.3.6.1.4.1.311.10.3.5'\n.INPUTS\n  System.String\n.OUTPUTS\n  System.String\n  #>\n\n  # Create an AsnWriter object with the default encoding rules\n  [AsnWriter]$AsnWriter = New-Object -TypeName AsnWriter -ArgumentList ([AsnEncodingRules]::BER)\n  # Write the OID as an ObjectIdentifier\n  $AsnWriter.WriteObjectIdentifier(\"$OID\")\n  # Get the encoded bytes as an array\n  [System.Byte[]]$NumArray = $AsnWriter.Encode()\n  # Check if the first byte is 6, otherwise throw an exception\n  if ($NumArray[0] -ne 6) {\n    throw 'Invalid OID encoding'\n  }\n  # Change the first byte to 1\n  $NumArray[0] = 1\n  # Create a StringBuilder to store the hexadecimal value\n  [System.Text.StringBuilder]$StringBuilder = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($NumArray.Length * 2)\n\n  # Loop through the bytes and append them as hex strings\n  for ($Index = 0; $Index -lt $NumArray.Length; $Index++) {\n    # Convert each byte to a two-digit hexadecimal string using the invariant culture\n    # The invariant culture is a culture that is culture-insensitive and independent of the system settings\n    # This ensures that the hexadecimal string is consistent across different locales and platforms\n    # The 'X2' format specifier indicates that the byte should be padded with a leading zero if necessary\n    # The ToString method returns the hexadecimal string representation of the byte\n    [System.String]$Hex = $NumArray[$Index].ToString('X2', [System.Globalization.CultureInfo]::InvariantCulture)\n    # Append the hexadecimal string to the StringBuilder object\n    # The StringBuilder class provides a mutable string buffer that can efficiently concatenate strings\n    # The Out-Null cmdlet suppresses the output of the Append method, which returns the StringBuilder object itself\n    $StringBuilder.Append($Hex) | Out-Null\n  }\n\n  # Return the hexadecimal value as string\n  return [System.String]$StringBuilder.ToString().Trim()\n}\n
    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-to-convert-the-hexadecimal-format-to-an-oid-for-wdac-policies","title":"How to Convert the Hexadecimal Format to an OID for WDAC Policies","text":"

    The following PowerShell function does the exact opposite of the previous function. It converts the hexadecimal representation of an OID to the OID itself.

    # Import the System.Formats.Asn1 namespaces\n# This allows you to use the AsnReader and AsnWriter classes\nusing namespace System.Formats.Asn1\n\nFunction Convert-HexToOID {\n  [CmdletBinding()]\n  [OutputType([System.String])]\n  Param (\n    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]\n    [ValidateNotNullOrEmpty()][System.String]$Hex\n  )\n  <#\n.SYNOPSIS\n  Converts a hexadecimal string to an OID\n.DESCRIPTION\n  Used for converting hexadecimal values found in the EKU sections of the WDAC policies to their respective OIDs.\n.PARAMETER Hex\n  The hexadecimal string to convert to an OID\n.EXAMPLE\n  Convert-HexToOID -Hex '010a2b0601040182374c0301'\n\n  Returns '1.3.6.1.4.1.311.76.3.1'\n.INPUTS\n  System.String\n.OUTPUTS\n  System.String\n  #>\n\n  begin {\n    # Convert the hexadecimal string to a byte array by looping through the string in pairs of two characters\n    # and converting each pair to a byte using the base 16 (hexadecimal) system\n    [System.Byte[]]$NumArray = for ($Index = 0; $Index -lt $Hex.Length; $Index += 2) {\n      [System.Convert]::ToByte($Hex.Substring($Index, 2), 16)\n    }\n  }\n\n  process {\n    # Change the first byte from 1 to 6 because the hexadecimal string is missing the tag and length bytes\n    # that are required for the ASN.1 encoding of an OID\n    # The tag byte indicates the type of the data, and for an OID it is 6\n    # The length byte indicates the number of bytes that follow the tag byte\n    # and for this example it is 10 (0A in hexadecimal)\n    $NumArray[0] = 6\n\n    # Create an AsnReader object with the default encoding rules\n    # This is a class that can read the ASN.1 BER, CER, and DER data formats\n    # BER (Basic Encoding Rules) is the most flexible and widely used encoding rule\n    # CER (Canonical Encoding Rules) is a subset of BER that ensures a unique encoding\n    # DER (Distinguished Encoding Rules) is a subset of CER that ensures a deterministic encoding\n    # The AsnReader object takes the byte array as input and the encoding rule as an argument\n    [AsnReader]$AsnReader = New-Object -TypeName AsnReader -ArgumentList ($NumArray, [AsnEncodingRules]::BER)\n\n    # Read the OID as an ObjectIdentifier\n    # This is a method of the AsnReader class that returns the OID as a string\n    # The first two numbers are derived from the first byte of the encoded data\n    # The rest of the numbers are derived from the subsequent bytes using a base 128 (variable-length) system\n    [System.String]$OID = $AsnReader.ReadObjectIdentifier()\n  }\n\n  End {\n    # Return the OID value as string\n    return $OID\n  }\n}\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#common-ekus-in-wdac-policies","title":"Common EKUs in WDAC Policies","text":"
    <EKU ID=\"ID_EKU_WINDOWS\" FriendlyName=\"Windows System Component Verification - 1.3.6.1.4.1.311.10.3.6\" Value=\"010A2B0601040182370A0306\" />\n<EKU ID=\"ID_EKU_WHQL\" FriendlyName=\"Windows Hardware Quality Labs (WHQL) - 1.3.6.1.4.1.311.10.3.5\" Value=\"010A2B0601040182370A0305\" />\n<EKU ID=\"ID_EKU_ELAM\" FriendlyName=\"Early Launch Anti Malware - 1.3.6.1.4.1.311.61.4.1\" Value=\"010A2B0601040182373D0401\" />\n<EKU ID=\"ID_EKU_HAL_EXT\" FriendlyName=\"HAL Extension - 1.3.6.1.4.1.311.61.5.1\" Value=\"010A2B0601040182373D0501\" />\n<EKU ID=\"ID_EKU_RT_EXT\" FriendlyName=\"Windows RT - 1.3.6.1.4.1.311.10.3.21\" Value=\"010a2b0601040182370a0315\" />\n<EKU ID=\"ID_EKU_STORE\" FriendlyName=\"Windows Store - 1.3.6.1.4.1.311.76.3.1\" Value=\"010a2b0601040182374c0301\" />\n<EKU ID=\"ID_EKU_DCODEGEN\" FriendlyName=\"Dynamic Code Generation - 1.3.6.1.4.1.311.76.5.1\" Value=\"010A2B0601040182374C0501\" />\n<EKU ID=\"ID_EKU_AM\" FriendlyName=\"AntiMalware - 1.3.6.1.4.1.311.76.11.1\" Value=\"010a2b0601040182374c0b01\" />\n
    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#oids-for-common-microsoft-ekus","title":"OIDs for Common Microsoft EKUs","text":""},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-ekus-are-used-by-the-wdac-engine-for-validation","title":"How EKUs Are Used by the WDAC Engine for Validation","text":"

    Regarding the incorporation of EKUs in file validation, WDAC verifies that the file's leaf certificate (File's signer) possesses identical EKUs as the signer element's EKUs. Regardless of whether the Signer's CertRoot (TBS value) and name (CN of the certificate) match with file's root, intermediate or leaf certificates, the EKUs only need to match with the leaf certificate.

    For example, in the Default Windows template policy, the Kernel32.dll is authorized by the following signer:

    <Signer ID=\"ID_SIGNER_WINDOWS_PRODUCTION\" Name=\"Microsoft Product Root 2010 Windows EKU\">\n  <CertRoot Type=\"Wellknown\" Value=\"06\" />\n  <CertEKU ID=\"ID_EKU_WINDOWS\" />\n</Signer>\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#you-can-see-the-details-in-the-screenshots-below","title":"You can see the details in the screenshots below","text":""},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#the-placement-of-the-certeku-elements","title":"The Placement of the CertEKU Elements","text":"

    In every Signer, the CertEKU node should only be placed directly after CertRoot. It is against the Code Integrity schema for any other nodes to exist between them. Below is a example of such configuration

    <Signer ID=\"ID_SIGNER_F_1\" Name=\"Microsoft Windows Production PCA 2011\">\n  <CertRoot Type=\"TBS\" Value=\"TBS Hash\" />\n  <CertEKU ID=\"ID_EKU_WINDOWS\" />\n  <CertEKU ID=\"ID_EKU_RT_EXT\" />\n  <CertEKU ID=\"ID_EKU_ELAM\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n  <CertPublisher Value=\"Microsoft Windows\" />\n  <FileAttribRef RuleID=\"ID_FILEATTRIB_F_1\" />\n</Signer>\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#continue-reading","title":"Continue Reading","text":""},{"location":"WDAC/Fast%20and%20Automatic%20Microsoft%20Recommended%20Driver%20Block%20Rules%20updates/","title":"Fast and Automatic Microsoft Recommended Driver Block Rules updates","text":"

    The blocklist is updated with each new major release of Windows, typically 1-2 times per year, but you can deploy the recommended driver block rules policy more frequently.

    This is the GitHub source for the XML content shown on the Microsoft document website. You can see when the last time it was changed was, read the change history and commit messages. The script below automates the required steps explained on the document to download and deploy the recommended driver block rules. Make sure you are using the latest version of Windows.

    "},{"location":"WDAC/Fast%20and%20Automatic%20Microsoft%20Recommended%20Driver%20Block%20Rules%20updates/#use-the-wdacconfig-module","title":"Use the WDACConfig Module","text":"

    You can use the WDACConfig Module to create a scheduled task in Windows that will automatically run the script below every 7 days.

    Install-Module -Name WDACConfig -Force\nNew-WDACConfig -GetDriverBlockRules -AutoUpdate\n
    The script
    try {\n    Invoke-WebRequest -Uri 'https://aka.ms/VulnerableDriverBlockList' -OutFile VulnerableDriverBlockList.zip -ErrorAction Stop\n}\ncatch {\n    exit 1\n}\nExpand-Archive -Path .\\VulnerableDriverBlockList.zip -DestinationPath 'VulnerableDriverBlockList' -Force\nRename-Item -Path .\\VulnerableDriverBlockList\\SiPolicy_Enforced.p7b -NewName 'SiPolicy.p7b' -Force\nCopy-Item -Path .\\VulnerableDriverBlockList\\SiPolicy.p7b -Destination \"$env:SystemDrive\\Windows\\System32\\CodeIntegrity\"\ncitool --refresh -json\nRemove-Item -Path .\\VulnerableDriverBlockList -Recurse -Force\nRemove-Item -Path .\\VulnerableDriverBlockList.zip -Force\nexit 0\n

    Microsoft recommended driver block rules that are enforced as a result of using either memory integrity (also known as hypervisor-protected code integrity or HVCI), Smart App Control, or S mode, are saved in a file called driversipolicy.p7b in the %windir%\\system32\\CodeIntegrity directory. The file you will be downloading from Microsoft document is called SiPolicy.p7b and it won't overwrite the driversipolicy.p7b but it will take precedence over the driversipolicy.p7b when deployed, because it has newer version and you can verify it after using CiTool by observing the Code Integrity event logs as described in the document.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/","title":"Create and Deploy Signed Application Control (WDAC) Policies","text":"

    Important

    WDACConfig module can easily and quickly generate a Code Signing certificate to be used for signing Application Control (WDAC) policies.

    This guide is only for those who want to learn how to setup a Windows Server with Active Directory and Certification Authority roles and create their own CA.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#introduction","title":"Introduction","text":"

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#video-guide","title":"Video Guide","text":""},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#tldr-short-version","title":"TL;DR (Short version)","text":"
    1. Install the latest Windows Server, Install AD/DS and AD/CS roles on it. (\u224815 mins depending on hardware and if downloaded ISO or VHDX)
    2. Use the Enterprise CA's code signing template to create a customized certificate template for WDAC Signing (\u22485 minutes)
    3. Generate the certificate and use it to sign the WDAC Policy (\u22483 minutes)

    That's essentially everything we have to do. So, if you are already familiar with the concepts, you can go straight to the bottom of this page and use the resources section to refer to Microsoft guides to create and deploy the Signed WDAC policy.

    But if you aren't familiar, keep reading as I've thoroughly explained every step to set up Windows Server, generate signing certificate and sign the WDAC policy. It takes about 20 minutes for me (as you can see in the video) and depending on the hardware, it can even take less time.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#prerequisites","title":"Prerequisites","text":"

    Latest Windows Server, it's free for 180 days for evaluation and comes in ISO and VHDX formats. Preferably use Windows Server insider vNext because it has the newest features and visual upgrades.

    Once we have our Windows installation media (ISO or VHDX), we need to set up a Hyper-V VM on our host. For this guide, our host is a Windows 11 pro for workstations machine.

    Create a Hyper-V VM with these specifications:

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#windows-server-vm-setup","title":"Windows Server VM setup","text":"

    After Windows Server installation has finished, you can create a Hyper-V standard checkpoint so you'll be able to restore the VM's state to this point in time if you misconfigure something later on.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#rename-the-server","title":"Rename the server","text":"

    Choose a meaningful name, like CAServer. Use this PowerShell cmdlet to easily do that, it will restart the server to apply the new name.

    Rename-Computer CAServer -Restart\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-gui-install-active-directory-domain-services","title":"Using GUI: Install Active Directory Domain Services","text":"

    From Server Manager => Add Roles and Features => Role-based or feature-based installation => Select the current server you are on => Select Active Directory Domain Services from the list => Select \"Add Features\" => Continue the rest of the steps by selecting Next.

    After installation is over, open the notifications in the Server Manager, (there will probably be a yellow icon on it), Select \"Promote this server to a domain controller\".

    In the Deployment Configuration window that will be opened, select \"Add a new forest\" and in the Root domain name, enter a domain name.

    It can be anything, even Bing.com, but for our usage let's use CAServer.com. On the next step, set a password for DSRM (Directory Services Restore Mode), It needs to have uppercase, lowercase and numbers (e.g., Bing6969), write this password down somewhere, like in Sticky notes app on your host.

    Next, choose a NetBIOS domain name, the default one will be OK. Confirm and proceed with the rest of the steps by selecting Next and at the end select Install. Wait for the installation to finish. It will restart the Server once the Installation is finished.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-powershell-install-active-directory-domain-services","title":"Using PowerShell: Install Active Directory Domain Services","text":"

    Install (AD DS) role

    Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools\n

    Install a forest and set a forest password

    $password = ConvertTo-SecureString 'Bing6969' -AsPlainText -Force\n\nInstall-ADDSForest -DomainName CAServer.com -DomainNetbiosName CASERVER0 -SafeModeAdministratorPassword $password -InstallDNS:$false -Force\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-gui-install-active-directory-certification-service-and-set-up-an-enterprise-root-ca-certificate-authority","title":"Using GUI: Install Active Directory Certification Service and set up an Enterprise root CA (Certificate Authority)","text":"

    From Server Manager => Add Roles and Features => Role-based or feature-based installation => Select the current server we are on => Select Active Directory Certification Service => Select Next for the rest of the steps and finally select install.

    After installation is over, open the notifications in the Server Manager, (there will probably be a yellow icon on it), Select \"Configure Active Directory Certificate Service on the destination server\".

    On the newly opened configuration window, on credentials section select next, on the Role services section check the box for Certification Authority and select next.

    Select Enterprise CA (because Standalone CA does not support certificate templates that we are going to use) and select Next. On the CA Type section select Root CA. On the Private Key section select Create a new private key.

    On the Cryptography section, for Cryptographic Provider choose RSA#Microsoft Software Key Storage Provider, for Key length choose 4096, for Hash Algorithm choose SHA512 and select Next. On the CA name section select next. On the Validity Period section set validity period to something like 50 Years. Select next for the rest of the sections and finally select Configure.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-powershell-install-active-directory-certification-services-and-set-up-an-enterprise-root-ca","title":"Using PowerShell: Install Active Directory Certification Services and set up an Enterprise root CA","text":"

    Install Active Directory Certificate Services

    Install-WindowsFeature Adcs-Cert-Authority -IncludeAllSubFeature\n

    Install a new Enterprise CA

    Install-AdcsCertificationAuthority -CAType EnterpriseRootCa -CryptoProviderName \"RSA#Microsoft Software Key Storage Provider\" -KeyLength 4096 -HashAlgorithmName SHA512 -ValidityPeriod Years -ValidityPeriodUnits 50 -Force\n

    Restart the server because it is required, and Server Manager says it too

    Restart-Computer\n

    Lastly do this so that Certification Authority option will be added to Server Manager => Tools and its GUI will become accessible and visible

    Add-WindowsFeature Adcs-Cert-Authority -IncludeManagementTools\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#configure-the-validity-period-of-the-issued-certificates-on-the-server","title":"Configure the Validity period of the issued certificates on the server","text":"

    Microsoft guide for this

    We Increase the validity period of the certificates issued by the CA to 30 years:

    certutil -setreg ca\\ValidityPeriod \"Years\"\ncertutil -setreg ca\\ValidityPeriodUnits \"30\"\n

    Restart the Server after this step.

    You can verify and confirm the results using these commands:

    certutil -getreg ca\\ValidityPeriod\ncertutil -getreg ca\\ValidityPeriodUnits\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#follow-the-official-guide-to-create-certificate-template-and-generate-the-signing-certificate","title":"Follow the official guide to create certificate template and generate the signing certificate","text":"

    Now open Certification Authority, you can do so by searching for it in Windows search or from Server Manager => Tools. Once you open it, you can follow the guide from Microsoft to create the certificate template for WDAC policy signing and then request and create a certificate.

    Note that If the Server doesn't have at least 1 network adapter connected to it, then Certificate Templates don't load,

    Screenshot

    That's why our Hyper-V VM Server needs at least one Virtual Network Adapter.

    The guide suggests using a client computer to request and create the certificate but since we are going to use the certificate for non-domain-joined computers and don't need to use the Active Directory, we can perform all of the steps on the same Windows Server VM.

    These are some optional deviations from the official guide that result in creating a successful and more secure certificate for our WDAC policy signing:

    As the Microsoft's guide suggests, you need to go to security tab to verify account access of the user(s) requesting the certificate, but since we are requesting and creating our certificate on the same CA server, we don't need to change anything there.

    If we want to use a 2nd PC to do this, as described in Microsoft document (Totally Unnecessary) Additional steps to perform on Windows Server If you are going to create a new user account in \"Active Directory Users and Computers\" for use on the client VM, in Certification Authority when duplicating the certificate template, go to Security Tab and set the correct permissions for that user account so that it will be able to request and enroll the certificate. For instance, since you are the only person who is going to use the Active Directory, you can even give `Full Control` permission to `Authenticated Users` group. Alternatively, you can use the same administrator account that you are currently using on Windows Server, which exists by default in the Active Directory, to log into the other client computer. One can log into multiple computers with the same user account across an Active Directory domain. There is no limit by default to how many concurrent logins an active directory user can have. Make sure the Windows Server and Windows client VMs both use the same Hyper-V Private Virtual switch network adapter. The VMs need to have static IP addresses on the same subnet in order to communicate with each other. Go to Windows Settings => Network & Internet => Ethernet => in \"IP Assignment\" select \"Edit\" => Set it to \"Manual\" => Toggle the IPv4 => in IP Address Enter `10.10.10.1` and in Subnet Mask enter `255.0.0.0`. Without configuring anything else, save it. Use the Edit button for DNS server assignment, set it to Manual, toggle the IPv4 button and in the Preferred DNS field enter `127.0.0.1`. Save everything and exit settings. Steps to perform on Client VM Make sure the client VM is running the latest version of Windows, and it follows the same prerequisites explained above. Go to Windows Settings => Network & Internet => Ethernet => in \"IP Assignment\" select \"Edit\" => Set it to \"Manual\" => Toggle the IPv4 => in IP Address Enter `10.10.10.2` and in Subnet Mask enter `255.0.0.0`. Without configuring anything else, save it. Now use the Edit button for DNS server assignment, set it to Manual, toggle the IPv4 button and in the Preferred DNS field enter the static IP address of the Windows Server VM, which was `10.10.10.1`. Save everything and exit settings. Open an elevated PowerShell and enter this to join the Active Directory domain:
    Add-Computer -DomainName <Domain> -Restart\n
    You will be asked for credentials. If you are going to use the same Administrator account from Windows Server, use `Administrator` for username and enter the password of the Windows Server in the password field, otherwise use the password you set when creating the new user account in Active Directory Users and Computers. After the client machine restarted, use `Other user` option on the lock screen and this time you will be using the Active Directory credentials to log into the machine. If using the built-in Administrator account, the password will be the same as the password on Windows Server account, but the username will be in the format, so in this case, it will be `Administrator@CAServer.com`. Since you are using Administrator account, you can by default use Enhanced session in Hyper-V too. To request the certificate and enroll it, you can follow the Microsoft guide.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#create-a-signed-wdac-policy","title":"Create a Signed WDAC policy","text":"

    Once we have the certificate in the User Certificates store of either the Windows Server or a client machine, Right-click on it => All tasks => Export. Export the Private key and export all the Extended Properties, set a password for the certificate and set Encryption to AES256-SHA256. Select a location to export and it will create a .pfx file.

    You also need to export the certificate without private key, in DER encoded binary X.509 format which will create a .cer certificate file. We need this certificate to sign the WDAC policy.

    It is important to keep these 2 files, specially .pfx that contains the private key, in a safe place, such as Azure Key Vault Managed HSM or OneDrive Personal Vault, so that if you delete all the VMs you created, you will be able to continue using the same certificate to sign further WDAC policies and supplemental policies, at least for the next 22 years, before it needs a renewal. As you can see, all of that setup must be done just once every few decades.

    The Personal Information Exchange (.pfx) file has great importance because it contains the Public key and Private key of the certificate so anyone who has access to this file can disable the deployed Signed WDAC policy. It should never be shared with anyone outside your circle of trust. It is a password-protected file by nature.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#use-wdacconfig-module-to-sign-and-deploy-wdac-policies","title":"Use WDACConfig module to sign and deploy WDAC policies","text":"

    WDACConfig module with the Deploy-SignedWDACConfig cmdlet can automate the entire process of signing and deploying a signed WDAC policy.

    Deploy-SignedWDACConfig -CertPath <String> -PolicyPaths <String[]> -CertCN <String>\n

    Cmdlet Info

    Note

    The Deploy-SignedWDACConfig cmdlet will offer to automatically download the SignTool.exe from the Microsoft server if it cannot find it on your system.

    If you want to manually download it, here are the steps:

    Run it and only select Windows SDK Signing Tools for Desktop Apps to install. After that signtool.exe will be placed at C:\\Program Files (x86)\\Windows Kits\\10\\bin and the WDACConfig module will automatically detect and use it for signing. You can even copy the executable to another location for later usage on another system where SDK is not installed and then use the optional -SignToolPath <String> parameter of WDACConfig module to browse for executable.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#system-behavior-after-deploying-a-signed-application-control-policy","title":"System Behavior After Deploying a Signed Application Control Policy","text":""},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#activation-process","title":"Activation Process","text":"

    After the signed Application Control (WDAC) policy binary .cip is copied to the EFI partition as part of the deployment process, and system is restarted once, we can see in System Information that Application Control User-Mode is being enforced and when you try to install an application not permitted by the deployed policy, it will be successfully blocked.

    At this point, since we are using UEFI Secure Boot, the Anti Tampering protection of the Signed policy kicks in and starts protecting WDAC policy against any tampering. We need to reboot the system one more time, to verify everything and make sure there is no boot failure.

    Deploying a Signed WDAC policy without restarting is the same as deploying Unsigned policies, because the Signed policy can be easily removed just like an Unsigned policy. So always make sure you restart at least once after deploying a Signed WDAC policy.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#if-someone-forcefully-deletes-the-deployed-wdac-policy-file","title":"If Someone forcefully deletes the deployed WDAC policy file","text":" Screenshot of a message after forcefully deleting a Signed WDAC policy from the EFI partition

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#what-happens-when-we-turn-on-smart-app-control","title":"What Happens When We Turn On Smart App Control","text":"

    Smart App Control works side-by-side any signed or unsigned Application Control policy (WDAC) because it is itself a special type of WDAC policy. It will be in enforced mode and continue to do its job.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#dual-boot-os-configurations","title":"Dual boot OS configurations","text":"

    When you deploy a Signed WDAC policy on a system that uses Secure Boot, it will be enforced on all of the OSes that boot on the physical machine, because the policy resides on the EFI partition and is not tied to any specific OS. That means if you perform a clean install of a second Windows OS or natively boot a VHDX (Hyper-V VM), the policy will apply to them as well.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#extras","title":"Extras","text":""},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#how-to-interact-with-the-hidden-efi-partition","title":"How to interact with the hidden EFI partition","text":"

    Using Diskpart, Open an elevated PowerShell console and run these commands one by one:

    diskpart\nlist disk\n# double check to make sure it's the correct disk if you have more than 1\nselect disk 0\nlist part\n# The EFI partitions type is System, and its size is approximately 100MB, make sure you choose the correct one\nselect part 1\nassign letter=z\n

    The EFI partition will be available in This PC with letter Z, but you can't access it without modifying permissions. There is however an easier way to access it and manually copy the Signed WDAC policy binary to it. Open Task Manager as admin, select Run New Task, select Browse and now you can access drive Z (EFI partition) and copy the Signed .cip file in Z:\\EFI\\Microsoft\\Boot\\CIPolicies\\Active.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#how-to-find-the-fqdn-fully-qualified-domain-name-of-the-windows-server","title":"How to find the FQDN (Fully Qualified Domain Name) of the Windows Server","text":"

    Using PowerShell

    (Get-ADComputer $(hostname)).DNSHostName\n

    or

    \"$env:computername.$env:userdnsdomain\"\n

    You can also use GUI of Server Manager => Local Server

    The syntax is: Computer_Name.Domain

    So, if:

    then FQDN is: CAServer.CAServer.com

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#resources","title":"Resources","text":""},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/","title":"How to Use Microsoft Defender for Endpoint Advanced Hunting With WDAC App Control","text":"

    Windows Defender Application Control (WDAC), also referred to as Application Control for Business, is a highly effective security feature that empowers you to manage the execution of applications on your endpoints.

    The application whitelisting approach serves as a potent defense against emerging and unknown threats. By emphasizing the identification of trusted applications, it automatically blocks any software that falls outside this trusted realm.

    Microsoft Defender for Endpoint (MDE) is one of the tools that can be used by enterprises and organizations to develop the trusted applications policy and mange it at scale. MDE provides the intelligence and insights needed to create and maintain a robust application control policy through its Advanced Hunting feature. This feature uses KQL (Kusto Query Language) to query the data collected by MDE and using the WDACConfig module, we can turn this actionable data into WDAC policies. We can then use Intune to deploy these policies to our endpoints. All of these tools are built for scalability.

    Note

    You can access Intune portal by navigating to: https://intune.microsoft.com

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#preparing-the-code-integrity-and-applocker-data","title":"Preparing the Code Integrity and AppLocker Data","text":"

    To start, we need our endpoints to be generating data and intelligence we can work with. These data points are the Code Integrity and AppLocker events. These events are generated when an application or file is blocked or audited by WDAC, or when a script or MSI file is blocked or audited by AppLocker. We can trigger the data generation by deploying WDAC policies to our endpoints in Audit mode. This mode will not block any applications, instead it will generate data points for any application, file, script, MSI file and so on that would have been blocked if the policy was in Enforce mode.

    You can create Audit mode policies using the WDACConfig module based on different levels of trust.

    For instance, the following command will create an Audit mode policy that once deployed on an endpoint, starts generating Audit logs for any file that runs but is not part of the Windows by default.

    New-WDACConfig -PrepDefaultWindowsAudit\n

    Another option would be the following command, which will create an Audit mode policy that once deployed, starts generating Audit logs for any file that runs but is not signed by Microsoft certificates.

    New-WDACConfig -PrepMSFTOnlyAudit\n

    Please refer to this document for further info about the commands.

    You will then use Intune to deploy the generated policies to as many endpoints as you want.

    Tip

    Deploy WDAC policies using Mobile Device Management (MDM)

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#collecting-the-data-from-mde-advanced-hunting","title":"Collecting the Data from MDE Advanced Hunting","text":"

    Now we need to collect the data from MDE Advanced Hunting. We can customize this query to be more specific to our environment, for instance by targeting specific devices and so on, but the following query will give us a good starting point by collecting all of the Code Integrity and AppLocker events:

    DeviceEvents\n| where ActionType startswith \"AppControlCodeIntegrity\"\n   or ActionType startswith \"AppControlCIScriptBlocked\"\n   or ActionType startswith \"AppControlCIScriptAudited\"\n

    Note

    You can access Microsoft Defender for Endpoint's portal by navigating to: https://security.microsoft.com

    That query generates a standard output of the data in CSV file format which is compatible with what the WDACConfig module requires in order to generate WDAC policies. If you want to customize the query further, make sure the subsequent filters are applied after the initial query to ensure correct data format.

    Tip

    Proactively hunt for threats with advanced hunting in Microsoft Defender XDR

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#generating-the-wdac-policies","title":"Generating the WDAC Policies","text":"

    After exporting the data from MDE Advanced Hunting, we can use the WDACConfig module to generate WDAC policies. We need to feed the CSV file(s) we collected MDE Advanced Hunting data into the module like so:

    ConvertTo-WDACPolicy -Source MDEAdvancedHunting -MDEAHLogs <Path to one or more CSV files> -BasePolicyGUID <Base policy GUID>\n

    It is only one example of how you can utilize the WDACConfig for policy generation based on MDE AH data, for more information about the cmdlet please refer to its documentations available here.

    The command we used above will process the CSV file(s) and open a GUI window where you can filter the logs based on many criteria, and then either select all or only select some of the logs to be included in the WDAC policy.

    Note that the generated policy will be a Supplemental policy.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#wdacconfig-features-for-mde-advanced-hunting","title":"WDACConfig Features For MDE Advanced Hunting","text":""},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#the-module-can-create-3-types-of-rules-for-files","title":"The Module Can Create 3 Types of Rules for Files:","text":"

    These levels are selected based on their security. You can read more about the levels security comparison in this article.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#video-demonstration","title":"Video Demonstration","text":"

    The following video demonstrates the process of collecting the data from MDE Advanced Hunting and generating WDAC policies using the WDACConfig module

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#deploying-the-wdac-policies","title":"Deploying the WDAC Policies","text":"

    After generating the Supplemental policies based off of the MDE Advanced Hunting data, you need to remove the Audit mode policies you deployed to your endpoints initially and replace them with Enforced mode policies.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#generate-allow-microsoft-base-policy-enforced-mode","title":"Generate Allow Microsoft Base Policy (Enforced Mode)","text":"
    New-WDACConfig -MakeAllowMSFTWithBlockRules\n
    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#generate-default-windows-base-policy-enforced-mode","title":"Generate Default Windows Base Policy (Enforced Mode)","text":"
    New-WDACConfig -MakeDefaultWindowsWithBlockRules\n

    Important

    Ensure that the Enforced mode policies align with the type of policies set during Audit mode. For example, if you utilized an Audit mode policy that permits Microsoft-signed files, it is crucial to employ an Enforced mode policy that also allows such files. Conversely, when dealing with the default Windows policy, consistency is key. Mixing these policies can result in files that were allowed during Audit mode being unexpectedly blocked during Enforce mode.

    You can deploy the policies using Intune, SCCM, or any other MDM solution you are using.

    After deploying the base policies, you will then deploy the Supplemental policies generated from MDE AH data, these policies are responsible for allowing any 3rd party apps or files that your endpoints need to use.

    You can put your endpoints into different groups and each group can receive different Supplemental policy based on their needs.

    Note

    ApplicationControl CSP

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#strict-kernel-mode-code-integrity-policy-scenario","title":"Strict Kernel Mode Code Integrity Policy Scenario","text":"

    I've created a scenario where you can strictly control what is allowed to run in Kernel mode, without blocking any user mode applications. You can read all about this scenario in here. Using the WDACConfig module and MDE Advanced Hunting intel, you can deploy this scenario across your entire fleet of endpoints.

    This approach demands very minimal upkeep as it exclusively manages Kernel-mode activities, yet it offers an exceptional degree of security. A significant benefit of this method is the safeguarding of your endpoints from all Bring Your Own Vulnerable Driver (BYOVD) threats.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#feedback-and-support","title":"Feedback and Support","text":"

    If you have any questions, feature requests or feedback regarding this guide or the WDACConfig module, please feel free to reach out to me on GitHub by opening a new issue or discussion.

    "},{"location":"WDAC/Introduction/","title":"Introduction","text":""},{"location":"WDAC/Introduction/#introduction","title":"Introduction","text":""},{"location":"WDAC/Introduction/#what-is-windows-defender-application-control","title":"What is Windows Defender Application Control?","text":"

    Application control is a crucial line of defense for protecting computer systems given today's threat landscape, and it has an inherent advantage over traditional antivirus solutions. Specifically, application control moves away from an application trust model where all applications are assumed trustworthy to one where applications must earn trust in order to run.

    Devices where Windows Defender Application control (WDAC) policies are deployed on can either be centrally managed via MDM, Intune etc. or they can be home devices, devices that are private and don't belong to any organization, the computer of someone that you want to keep very much safe and secure so that even the device's owner can't willingly or forcefully compromise themselves, the possibilities are endless.

    Important

    The WDACConfig module is a one-stop shop for all your Application Control (WDAC) needs. It is scalable, easy to use, enterprise-ready, Azure VM ready and more importantly, it is free and always will be. Check it out here

    "},{"location":"WDAC/Introduction/#windows-defender-application-control-wdac-wiki-posts","title":"Windows Defender Application Control (WDAC) wiki posts","text":""},{"location":"WDAC/Introduction/#wdacconfig-module","title":"WDACConfig Module","text":"

    WDACConfig is an advanced PowerShell module designed with the aim of automating Application and File whitelisting in Windows using Windows Defender Application Control. It is available in PowerShell gallery.

    "},{"location":"WDAC/Introduction/#application-control-usage-levels","title":"Application Control Usage Levels","text":"

    There are many ways you can utilize Application Control features and here they are sorted by the level of restriction and protection they provide; From top (having the least restriction and protection) to bottom (having the most restriction and protection).

    1. Use Microsoft recommended driver block rules.

      • No user action required; The vulnerable driver blocklist is enabled by default for all devices using HVCI or Memory Integrity.
      • The built-in driver blocklist is updated with each new major release of Windows, typically 1-2 times per year.
    2. Update Microsoft recommended driver block rules outside of the twice a year schedule.

      • The drivers block list itself is updated more frequently than twice a year schedule, use the WDACConfig Module to setup a scheduled task that keeps the list up-to-date.
    3. Use Microsoft recommended block rules + Recommended driver block rules
      • Use the WDACConfig Module to easily deploy the User-Mode Microsoft recommended block rules on your system.
    4. Create WDAC policy for Lightly managed devices
      • Microsoft's guide: Create a WDAC policy for lightly managed devices
      • My guide: WDAC for Lightly Managed Devices
    5. Use Smart App Control
      • It's just a toggle in Windows Security under App & Browser control. It uses a special kind of WDAC policy that provides more protection than a lightly managed workstation but less protection than a fully managed workstation.
      • It uses both of Microsoft's recommended block rules.
    6. Use Smart App Control + Strict Kernel-Mode WDAC Policy
    7. Create WDAC policy for Fully managed devices
      • The following scenarios provide the highest protection against any threats from any sources when cryptographically signed and deployed and properly configured.
      • WDAC for Fully managed device - Variant 1
      • WDAC for Fully managed device - Variant 2
      • WDAC for Fully managed device - Variant 3
      • WDAC for Fully managed device - Variant 4
      • Microsoft's guide: Create a WDAC policy for fully managed devices
      • Microsoft's guide: Create a WDAC policy for fixed-workload devices (reference computer)
      • Microsoft's guide: Use audit events to create WDAC policy rules

    "},{"location":"WDAC/Introduction/#methods-we-can-use-to-create-an-application-control-policy-wdac","title":"Methods we can use to create an Application Control policy (WDAC)","text":""},{"location":"WDAC/Introduction/#plan-for-windows-defender-application-control-lifecycle-policy-management","title":"Plan for Windows Defender Application Control lifecycle policy management","text":"

    Microsoft provides the following official document to understand the decisions you need to make to establish the processes for managing and maintaining Windows Defender Application Control (WDAC) policies. The rest of them are mentioned below at the Resources section.

    "},{"location":"WDAC/Introduction/#resources","title":"Resources","text":"

    There are a lot more WDAC resources and cmdlets available on Microsoft's websites.

    "},{"location":"WDAC/Introduction/#cmdlets","title":"Cmdlets","text":""},{"location":"WDAC/Introduction/#documents","title":"Documents","text":""},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/","title":"Script Enforcement and PowerShell Constrained Language Mode in WDAC App Control Policies","text":""},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#introduction","title":"Introduction","text":"

    This article explores some of the technical details of how to deploy a WDAC (Application Control) policy that uses Script Enforcement and forces PowerShell to run in Constrained Language Mode. It expands aspects of this topic that are not covered enough in the official docs.

    Tip

    Check out these 2 documents from Microsoft for more info and basics:

    Below are the required steps to enable Script Enforcement and allow a PowerShell module to run in Constrained Language Mode, if its code meets the requirements of it.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#signing-the-powershell-module-files","title":"Signing the PowerShell Module files","text":"

    The PowerShell module that you intend to use in Constrained Language Mode must be completely signed, that means all of its .psm1 and .psd1 files must be signed by a code signing certificate.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#type-of-certificate-to-use-to-sign-the-powershell-module-files","title":"Type of Certificate to Use to Sign the PowerShell Module Files","text":"

    The Code Signing certificate you're going to use to sign the PowerShell module files with can be a self-signed certificate or a certificate from a trusted certification authority (CA).

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#making-the-system-trust-the-certificate","title":"Making the System Trust the Certificate","text":"

    If the certificate you used to sign the PowerShell module files with is from a trusted certification authority (CA) and the root certificate of that CA exists in the \"Trusted Root Certification Authorities\" store of either the Local Machine or Current User certificate store, then you're good to go, but if the certificate is self-signed, you need to add the certificate's root certificate to either of those locations.

    For instance, if you generated a Code Signing certificate from Windows Server Active Directory Certificate Services, and you used that certificate to sign the PowerShell module files, you need to export the root certificate containing the public key, to a .cer file and then add it to one of the locations mentioned earlier. Adding the leaf certificate, which is the one you used to sign the module files with, to those locations, will not count and won't allow the signed PowerShell module to run in Constrained Language Mode.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#base-policy-requirements","title":"Base Policy Requirements","text":"

    The WDAC (Application Control) base policy you're going to deploy must have 0 Enabled:UMCI and it must not have the 11 Disabled:Script Enforcement rule options.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#how-to-create-a-supplemental-policy-to-allow-the-certificates","title":"How to Create a Supplemental Policy to Allow the Certificate(s)","text":"

    The root certificate's details must be added as a Signer rule in a WDAC policy in the User-Mode Signing Scenario.

    Adding the Certificate's Signer rule to the Kernel-mode Signing Scenario does not allow the modules signed by that certificate to run, which is expected.

    For better management, you should allow the certificate in a new supplemental policy.

    Here is an example of a valid Supplemental policy that allows a root certificate as a signer.

    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SiPolicy xmlns=\"urn:schemas-microsoft-com:sipolicy\" PolicyType=\"Supplemental Policy\">\n  <VersionEx>1.0.0.0</VersionEx>\n  <PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID>\n  <Rules>\n    <Rule>\n      <Option>Enabled:Unsigned System Integrity Policy</Option>\n    </Rule>\n  </Rules>\n  <EKUs />\n  <FileRules />\n  <Signers>\n    <Signer ID=\"ID_SIGNER_S_1_1\" Name=\"Root Certificate\">\n      <CertRoot Type=\"TBS\" Value=\"e3fbf9a3dc3022eab22b5e961bc6fee45782ae8aaed1d8402f2101a5f393db876444ef1d0e302f03b64463bae816f701cc5cda41068a8bf1954a0cd262eb9d6f\" />\n    </Signer>\n  </Signers>\n  <SigningScenarios>\n    <SigningScenario Value=\"131\" ID=\"ID_SIGNINGSCENARIO_DRIVERS_1\" FriendlyName=\"Auto generated policy on 04-26-2024\">\n      <ProductSigners />\n    </SigningScenario>\n    <SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_WINDOWS\" FriendlyName=\"Auto generated policy on 04-26-2024\">\n      <ProductSigners>\n        <AllowedSigners>\n          <AllowedSigner SignerId=\"ID_SIGNER_S_1_1\" />\n        </AllowedSigners>\n      </ProductSigners>\n    </SigningScenario>\n  </SigningScenarios>\n  <UpdatePolicySigners />\n    <CiSigners>\n  <CiSigner SignerId=\"ID_SIGNER_S_1_1\" />\n  </CiSigners>\n  <HvciOptions>2</HvciOptions>\n  <BasePolicyID>{7558D4BF-69E3-45CA-9C52-915E48A7C50E}</BasePolicyID>\n  <PolicyID>{32C551AF-C243-477A-9955-D37EDF435414}</PolicyID>\n  <Settings>\n    <Setting Provider=\"PolicyInfo\" Key=\"Information\" ValueName=\"Name\">\n      <Value>\n        <String>Supplemental Policy</String>\n      </Value>\n    </Setting>\n  </Settings>\n</SiPolicy>\n

    As you can see, we need the TBS Hash value of the root certificate.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#use-the-wdacconfig-module-to-automatically-allow-certificates","title":"Use the WDACConfig Module to Automatically Allow Certificates","text":"

    You can use the WDACConfig module to create a supplemental policy that allows the certificates you select to be allowed by WDAC. To do that, you can use the following command:

    New-SupplementalWDACConfig -Certificates -CertificatePaths \"certificate.cer\" -SuppPolicyName '<Certificate Name>' -PolicyPath \"<Path to Base policy XML file>\"\n

    More info regarding the cmdlet is available here

    A manual way to get the TBS Hash value of a certificate is using the following command, which also works for signed files and will show the details of the certificates in the chain as well.

    certutil.exe \u2013v <Path To .cer file>\n

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#powershell-engine-behavior","title":"PowerShell Engine Behavior","text":"

    When a WDAC policy with script enforcement is deployed and you try to import an unauthorized module, you might see different errors. For instance, you might see an error about classes not being allowed or other reasons for a module not being able to load, but in essence, the PowerShell engine is trying to load the module in Constrained Language Mode and the module is failing to meet the requirements, most likely because:

    Important

    WDACConfig module is currently not compatible with constrained language mode due to using advanced PowerShell features that are not allowed in that mode.

    "},{"location":"WDAC/WDAC%20Notes/","title":"Important Notes and Tips about WDAC policies","text":""},{"location":"WDAC/WDAC%20Notes/#supplemental-wdac-policy-considerations","title":"Supplemental WDAC Policy Considerations","text":""},{"location":"WDAC/WDAC%20Notes/#verify-policy-type","title":"Verify Policy type","text":"

    We have to make sure the WDAC policy that we are going to use as a supplemental policy has PolicyType=\"Supplemental Policy\" in the SiPolicy element of the XML file. If it doesn't, then we have to use this command to change it from base policy to supplemental policy of our base policy.

    That will also change/create the <BasePolicyID>GUID</BasePolicyID> element in the supplemental policy XML file. The GUID will be the PolicyID of the base policy specified in the command.

    "},{"location":"WDAC/WDAC%20Notes/#verify-policy-rule-options","title":"Verify Policy Rule options","text":"

    We have to make sure that the supplemental policy does not contain any policy rule options that only work with a base policy. This chart shows which ones can be used in a supplemental policy.

    You can use this PowerShell code to automatically make sure non-supplemental policy rule options don't exist in a supplemental policy XML file:

    [System.String]$SupplementalPolicyPath = \"<Path to SupplementalPolicy.xml>\"\n@(0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 15, 16, 17, 19, 20) | ForEach-Object -Process {\n    Set-RuleOption -FilePath $SupplementalPolicyPath -Option $_ -Delete\n}\n

    A supplemental policy can only have these policy rule options:

    "},{"location":"WDAC/WDAC%20Notes/#deny-rules-in-supplemental-policy-are-invalid","title":"Deny Rules in Supplemental Policy Are Invalid","text":"

    Deny rules are ignored in supplemental policies by the WDAC engine. Supplemental policies are only meant to expand what the base policy trusts, that's why only allow rules are supported in supplemental policies, and that's also the reason why we don't need to merge Microsoft recommended block rules or driver block rules with a supplemental policy.

    "},{"location":"WDAC/WDAC%20Notes/#rule-precedence","title":"Rule Precedence","text":"

    When the base policy has a deny rule for a file and we allow the same file in a supplemental policy, the file will still be blocked, because explicit deny rules have the highest priority.

    More info

    "},{"location":"WDAC/WDAC%20Notes/#signing-a-supplemental-policy","title":"Signing a Supplemental Policy","text":"

    Suppose you have a base policy which will subsequently have supplemental policies. To add the details of the code signing certificate to the base policy, ensuring its readiness for signing, you need to use the -Supplemental switch parameter with the Add-SignerRule cmdlet. Failing to do so would render the signed base policy, post-deployment, incapable of accepting any signed supplemental policies. Note that the -Supplemental parameter is exclusively applicable to base policies.

    Important

    Using -Supplemental parameter with Add-SignerRule cmdlet on a Supplemental policy will cause boot failure after deploying it, because that parameter should only be used when adding signer rules to a base policy.

    "},{"location":"WDAC/WDAC%20Notes/#removing-supplemental-policies","title":"Removing Supplemental Policies","text":"

    Whether the deployed supplemental policy is unsigned or signed, you can remove it just like any unsigned policy using CITool.

    "},{"location":"WDAC/WDAC%20Notes/#what-if-you-deployed-an-unsigned-supplemental-policy-for-a-signed-base-policy","title":"What if You Deployed an Unsigned Supplemental Policy for a Signed Base Policy?","text":"

    If you deploy an unsigned supplemental policy on a system where all policies including base and supplemental, are signed, the deployed unsigned supplemental policy will be ignored.

    "},{"location":"WDAC/WDAC%20Notes/#how-deny-rules-for-files-and-certificatessigners-are-specified","title":"How Deny Rules for Files and Certificates/Signers Are Specified","text":""},{"location":"WDAC/WDAC%20Notes/#denied-file-rules","title":"Denied File Rules","text":"

    First, Block/Deny File rules are specified in the <FileRules> node which is directly under the <SiPolicy> node in the XML file. Deny rules are created by having <Deny ID=\"ID_DENY_\" at the beginning of their lines. For example:

    <Deny ID=\"ID_DENY_AGENT64_SHA1\" FriendlyName=<Textual Description/Name> Hash=<Hash Numbers> />\n

    Second, there are File Reference rules for each Deny rule that only mentions them by ID, and these are exactly the same as Allow rules because only Rule IDs are mentioned and nothing about the nature of the rule itself. These are in:

    <SiPolicy>\n    <SigningScenarios>\n        <SigningScenario>\n            <ProductSigners>\n                <FileRulesRef>\n                    <FileRuleRef RuleID=\"<The same ID of the Deny File rule mentioned earlier>\" />\n                </FileRulesRef>\n            </ProductSigners>\n        </SigningScenario>\n    </SigningScenarios>\n</SiPolicy>\n ```\n\n<br>\n\n### Denied Certificates/Signer\n\nDenied certificates/signers are first mentioned in `<SiPolicy` => `<Signers>` with the following syntax:\n\n```xml\n<Signer ID=\"ID_SIGNER_VERISIGN_2010\" Name=\"VeriSign Class 3 Code Signing 2010 CA\">\n... Other possible elements ...\n</Signer>\n

    Unlike file rules, this first part doesn't specify whether the certificate/signer must be allowed or blocked by the WDAC policy.

    In order to specify whether a certificate/signer should be denied/allowed, the ID of each signer must be specified in the second part of the XML policy file in <DeniedSigners> element:

    <SigningScenarios>\n    <SigningScenario Value=\"131\" ID=\"ID_SIGNINGSCENARIO_<Some generic String>\" FriendlyName=\"<Name>\">\n        <ProductSigners>\n            <DeniedSigners>\n                <DeniedSigner SignerId=\"<ID of the Signer mentioned above in the <Signers> section>\" />\n            </DeniedSigners>\n        </ProductSigners>\n    </SigningScenario>\n</SigningScenarios>\n
    "},{"location":"WDAC/WDAC%20Notes/#guidance-on-creating-wdac-deny-policies","title":"Guidance on Creating WDAC Deny Policies","text":""},{"location":"WDAC/WDAC%20Notes/#how-to-verify-the-status-of-user-mode-and-kernel-mode-application-control-on-the-system","title":"How to Verify the Status of User-Mode and Kernel-Mode Application Control on the System","text":""},{"location":"WDAC/WDAC%20Notes/#using-powershell","title":"Using PowerShell","text":"
    Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\\Microsoft\\Windows\\DeviceGuard | select -Property *codeintegrity* | fl\n

    2 means Enforced, 1 means Audit mode, 0 means Disabled/Not running.

    "},{"location":"WDAC/WDAC%20Notes/#using-system-information","title":"Using System Information","text":"

    "},{"location":"WDAC/WDAC%20Notes/#refreshing-wdac-policies","title":"Refreshing WDAC Policies","text":""},{"location":"WDAC/WDAC%20Notes/#using-the-built-in-citool","title":"Using the built-in CiTool","text":"
    CITool --refresh\n

    Old Method: using RefreshPolicy(AMD64).exe

    Note

    When a Supplemental policy is removed from the system and you refresh the policies, that doesn't instantly block the apps that were allowed by the removed policy, simply because those apps might be still running on the system, either in the background or foreground. To properly stop them, a system restart is required.

    "},{"location":"WDAC/WDAC%20Notes/#about-signingscenarios-node-in-the-wdac-policy-xml","title":"About <SigningScenarios> Node in the WDAC Policy XML","text":"

    It consists of 2 elements:

    This one contains the Certificates/Signers of the Kernel-mode drivers

    <SigningScenario Value=\"131\" ID=\"ID_SIGNINGSCENARIO_DRIVERS_1\" FriendlyName=\"Driver Signing Scenarios\">\n

    And this one contains the Certificates/Signers of the User-mode binaries

    <SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_WINDOWS\" FriendlyName=\"User Mode Signing Scenarios\">\n

    Only the Value needs to stay the same. So, for Kernel-mode drivers it should always be 131 and for User-mode binaries it should always be 12, anything else can be customized, this is according to the CI policy schema.

    "},{"location":"WDAC/WDAC%20Notes/#merging-policies","title":"Merging Policies","text":"

    Merge-cipolicy cmdlet does not include duplicates, neither duplicate rules nor rules with duplicate file hashes.

    "},{"location":"WDAC/WDAC%20Notes/#wdac-forces-allow-list-architecture-by-nature","title":"WDAC Forces Allow-list Architecture by Nature","text":"

    WDAC forces Allow-list architecture by nature, not deny-list architecture. An empty deployed policy allows nothing to run and leads to system failure. This is why Microsoft recommended blocklists include 2 Allow All rules with the Deny rules, that changes the WDAC policy's nature from being an Allow-list to being a Deny-list.

    "},{"location":"WDAC/WDAC%20Notes/#about-microsoft-recommended-block-rules","title":"About Microsoft Recommended Block Rules","text":""},{"location":"WDAC/WDAC%20Notes/#how-to-manually-consume-the-microsoft-recommended-block-rules","title":"How to Manually Consume the Microsoft Recommended Block Rules","text":"

    From Microsoft recommended block rules document, copy the WDAC policy XML at the end (you might need to expand that section to view it), use a text editor like VS Code to edit it as recommended:

    The blocklist policy includes \"Allow all\" rules for both kernel and user mode files that make it safe to deploy as a standalone WDAC policy or side-by-side any other policy by keeping its allow all rules in place. Refer to this document about how multiple base policies work.

    "},{"location":"WDAC/WDAC%20Notes/#how-do-the-allow-all-rules-work","title":"How Do the Allow All Rules Work","text":"

    Only applications allowed by all Base policies run without generating block events, that means even though the Microsoft recommended block rules have 2 allow all rules, they don't actually allow everything to run, because for instance in a realistic scenario, the same allow all rules don't exist in other base policies such as AllowMicrosoft or DefaultWindows base policy, they would only contain explicit allow rules.

    The policy must be in multiple policy format, which can be achieved by using the Set-CiPolicyIdInfo cmdlet with the -ResetPolicyId switch.

    Important

    If merging into an existing policy that includes an explicit allowlist, you should first remove the two \"Allow all\" rules and their corresponding FileRuleRefs:

    <Allow ID=\"ID_ALLOW_A_1\" FriendlyName=\"Allow Kernel Drivers\" FileName=\"*\" />\n<Allow ID=\"ID_ALLOW_A_2\" FriendlyName=\"Allow User mode components\" FileName=\"*\" />\n
    <FileRuleRef RuleID=\"ID_ALLOW_A_1\" />\n<FileRuleRef RuleID=\"ID_ALLOW_A_2\" />\n

    "},{"location":"WDAC/WDAC%20Notes/#microsoft-recommended-driver-block-rules","title":"Microsoft Recommended Driver Block Rules","text":"

    Citation: If you only manage Windows 11 22H2 systems (and above), then you don't need the recommended driver block rules in your WDAC policy. Otherwise, you should have the driver block rules in your policy. In either scenario, you should have the recommended user mode rules.

    Citation: ISG does not include the recommended blocklist(s).

    "},{"location":"WDAC/WDAC%20Notes/#miscellaneous","title":"Miscellaneous","text":"

    "},{"location":"WDAC/WDAC%20Notes/#blocking-individual-windows-components","title":"Blocking Individual Windows components","text":""},{"location":"WDAC/WDAC%20Notes/#blocking-microsoft-store","title":"Blocking Microsoft Store","text":"
    $Package = Get-AppXPackage -Name \"Microsoft.WindowsStore\"\n$Rules += New-CIPolicyRule -Package $Package -Deny\nNew-CIPolicy -FilePath \".\\store.xml\" -Rules $Rules\n
    "},{"location":"WDAC/WDAC%20Notes/#how-to-remove-flight-signing-certificates-from-default-example-policies","title":"How to Remove Flight Signing Certificates From Default Example Policies","text":"

    Removing these do not cause any problem as long as your Windows build is in the Stable, Release Preview or Beta channel.

    # Flight root Certs removal\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_STORE_FLIGHT_ROOT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WINDOWS_FLIGHT_ROOT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_ELAM_FLIGHT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_HAL_FLIGHT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WHQL_FLIGHT_SHA2\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WINDOWS_FLIGHT_ROOT_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_ELAM_FLIGHT_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_HAL_FLIGHT_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WHQL_FLIGHT_SHA2_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_RT_FLIGHT\"\n

    "},{"location":"WDAC/WDAC%20Notes/#how-to-remove-wdac-policy-refresh-tool-certificates-from-default-example-policies","title":"How to Remove WDAC Policy Refresh Tool Certificates From Default Example Policies","text":"

    Starting with Windows 11 22H2, CITool is available in Windows by default and Refresh tool is no longer needed, so use the commands below to remove the certificates that allow that tool to be executed, their order of execution is important.

    Remove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_MICROSOFT_REFRESH_POLICY\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_FILEATTRIB_REFRESH_POLICY\"\n

    "},{"location":"WDAC/WDAC%20Notes/#allowing-questionable-software-in-a-wdac-policy","title":"Allowing Questionable Software in a WDAC Policy","text":"

    Questionable software such as pirated software are never recommended to be allowed in the WDAC policy because they are tampered with. Pirated software can have signed files too, but they are modified and as a result there is a mismatch between the file hash and the hash of the file saved in their digital signature. When such a mismatch exists for signed files, Authenticode reports the mismatch, and the file can't be allowed in a WDAC policy.

    If you want to go through many files and see which ones have a mismatch between their file hash and signature hash, you can use the following PowerShell command, it searches through a folder and all of its sub-folders quickly.

    Foreach ($File in (Get-ChildItem -Path 'Path\\To\\a\\Folder' -File -Recurse)) {\n    $Signature = Get-AuthenticodeSignature -FilePath $File.FullName\n    if ($Signature.Status -eq 'HashMismatch') {\n        Write-Output -InputObject $File.FullName\n    }\n}\n

    "},{"location":"WDAC/WDAC%20Notes/#performing-system-reset-while-signed-wdac-policy-is-deployed","title":"Performing System Reset While Signed WDAC Policy Is Deployed","text":"

    If you've deployed a Signed WDAC policy on a system and then decide to reset it, either using local install or cloud download, it will fail during the reset process. You must remove the signed WDAC policy prior to performing the reset.

    Unsigned WDAC policies don't have this behavior. Since they are neither cryptographically signed nor tamper-proof, they will be removed during the reset process and after reset the system will not have the WDAC policy.

    This behavior is true for Lightly managed, Allow Microsoft and Default Windows WDAC policy types.

    "},{"location":"WDAC/WDAC%20Notes/#the-cip-binary-file-can-have-any-name-or-no-name-at-all","title":"The .CIP Binary File Can Have Any Name or No Name at All","text":"

    Using CiTool in Windows 11 build 22621 and above, .CIP binary files can be deployed with any name, even without a name, and lead to a successful WDAC policy deployment.

    "},{"location":"WDAC/WDAC%20Notes/#policies-with-requiredev-signers-rule-option","title":"Policies with Required:EV Signers rule option","text":"

    If a base policy has rule option number 8, Required:EV Signers, it will require all kernel-mode drivers to have EV signer certificates.

    "},{"location":"WDAC/WDAC%20Notes/#the-following-policy-rule-options-only-apply-to-user-mode-binariesdrivers","title":"The Following Policy Rule Options Only Apply to User Mode Binaries/Drivers","text":"

    When we remove the SigningScenario Value=\"12\" completely which is responsible for User Mode code integrity in the xml policy and also remove any signers that belong to User mode section, such as those that have _user in their ID, the Merge-CIPolicy cmdlet automatically removes EKUs that belong to the policy rule options mentioned above during a merge.

    Removing the User mode signers, rules and Enabled:UMCI rule option allows us to create a Kernel-only WDAC policy that doesn't touch User mode binaries/drivers.

    For a Kernel-mode only WDAC policy, only the following EKUs are necessary

    <EKUs>\n    <EKU ID=\"ID_EKU_WINDOWS\" Value=\"010A2B0601040182370A0306\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_ELAM\" Value=\"010A2B0601040182373D0401\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_HAL_EXT\" Value=\"010a2b0601040182373d0501\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_WHQL\" Value=\"010A2B0601040182370A0305\" FriendlyName=\"\" />\n</EKUs>\n

    Important

    Refer to this document for complete info about Kernel-Mode policies

    "},{"location":"WDAC/WDAC%20Notes/#you-can-merge-the-same-policy-xml-file-with-itself","title":"You Can Merge the Same Policy XML File With Itself","text":"

    In order to automatically remove unnecessary things from a policy file, such as the EKUs mentioned earlier, you can run a command like this:

    Merge-CIPolicy .\\Policy.xml -OutputFilePath .\\Policy1.xml\n

    It essentially merges a policy with itself, adding _0 to each ID and SignerID of the xml nodes which is easily removable using WDACConfig module, although it's not necessary to remove them at all, they are perfectly fine.

    "},{"location":"WDAC/WDAC%20Notes/#-audit-parameter-of-the-configci-cmdlets","title":"-Audit Parameter of the ConfigCi Cmdlets","text":"

    When you use -Audit parameter of ConfigCI cmdlets such as Get-SystemDriver and New-CIPolicy, these 2 event logs are scanned

    1. AppLocker \u2013 MSI and Script event log
    2. CodeIntegrity - Operational

    Explained more in here

    "},{"location":"WDAC/WDAC%20Notes/#about-double-signed-files-and-filepublisher-level","title":"About Double-Signed Files and Filepublisher Level","text":"

    Sometimes there are files that are signed by 2 or more certificates, aka double signed files.

    When a level such as FilePublisher is used, ConfigCI cmdlets create signer rules for one of the intermediate certificates of each of the signers of those files.

    Depending on Kernel or use mode, 2 Allowed Signers are created for the file in either UMCI or KMCI Signing scenario sections.

    However, if the file is a kernel mode driver and user mode driver, then 4 signers are created for it, 2 Allowed Signers in the UMCI Signing Scenario and 2 in the KMCI Signing scenario.

    "},{"location":"WDAC/WDAC%20Notes/#an-example","title":"An example","text":"

    In the signer below

    <Signer ID=\"ID_SIGNER_F_2\" Name=\"Microsoft Windows Third Party Component CA 2014\">\n    <CertRoot Type=\"TBS\" Value=\"D8BE9E4D9074088EF818BC6F6FB64955E90378B2754155126FEEBBBD969CF0AE\" />\n    <CertPublisher Value=\"Microsoft Windows Hardware Compatibility Publisher\" />\n    <FileAttribRef RuleID=\"ID_FILEATTRIB_F_46\" />\n</Signer>\n

    "},{"location":"WDAC/WDAC%20Notes/#some-notes","title":"Some Notes","text":"
    1. If 2 files have the same Leaf certificate CN and also have an Intermediate Certificate in common (that has the same TBS and CN) then they should be listed under the same Signer.

    2. Any Intermediate certificate in the certificate chain/path of a file can be used to allow a file using FilePublisher level.

    3. In case of a multi-certificate signed file, such as the Office installer which is triple-signed, any of the certificates can be used to allow the file in a Supplemental policy or Deny it in a base policy.

    "},{"location":"WDAC/WDAC%20Notes/#what-does-hvci-option-set-to-strict-mean","title":"What Does HVCI option Set to Strict Mean?","text":"

    HVCI stands for Hypervisor-protected Code Integrity and it is a feature that uses virtualization-based security (VBS) to protect the Windows kernel from memory attacks. HVCI can be set to different options in a WDAC policy, such as Enabled, DebugMode, or Strict.

    Setting HVCI to Strict in a WDAC policy provides the highest level of protection for kernel mode code integrity, as it enforces these additional restrictions:

    "},{"location":"WDAC/WDAC%20Notes/#about-certificates-and-certificate-chains","title":"About Certificates and Certificate Chains","text":"

    "},{"location":"WDAC/WDAC%20Notes/#msi-files-and-their-applicable-rule-levels","title":"MSI Files and Their Applicable Rule Levels","text":"

    MSI files cannot be allowed using FilePublisher rule level because they are not PEs and do not have the necessary attributes (Such as file version, original file name, product name, file description and so on) of the PEs (Portable Executable) in order to create FilePublisher/SignedVersion rules for them, so they need to be allowed by other levels such as Publisher or Hash.

    "},{"location":"WDAC/WDAC%20Notes/#the-length-of-the-ids-in-the-policy-xml-file-has-no-effect-on-the-size-of-the-generated-cip-file","title":"The Length of the IDs in the policy XML file has no effect on the size of the generated CIP file","text":"

    It doesn't matter how long or short the IDs are in the policy XML file, such as Signer IDs, Allowed Signer IDs, CiSigner IDs and so on, you can even use GUIDs as IDs to make sure they stay unique, the size of the generated CIP file will not change. In fact, even the hash of the generated CIP file stays the same when you change the length of the IDs in the policy XML file.

    "},{"location":"WDAC/WDAC%20Notes/#continue-reading-about-byovd-protection-with-wdac","title":"Continue reading about BYOVD protection with WDAC","text":""},{"location":"WDAC/WDAC%20Notes/#wdac-policy-for-byovd-kernel-mode-only-protection","title":"WDAC policy for BYOVD Kernel mode only protection","text":""},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/","title":"WDAC policy for Fully managed device - Variant 2","text":"Base policy type Method used Signed Protection score 1-5 Default Windows WDACConfig module No 4
    flowchart TD\n    A(Deploy Default Windows base policy) -->B(Identify Important apps that need Supplemental policy)\n    B --> C[Create Supplemental policy based on App's directory]\n    C --> D[Want to allow an entire directory?]\n    D --> E[New-SupplementalWDACConfig -FilePathWildCards]\n    C --> F[Want to Scan the app's install directory?]\n    F --> G[New-SupplementalWDACConfig -Normal]\n    B --> H[Is it a game Installed using Xbox app?]\n    H --> I[Or Is it an app that installs drivers outside app's directory?]\n    I --> J[Edit-WDACConfig -AllowNewApps]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically, any software that you can run.

    This scenario provides a very high protection level. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#deploy-the-default-windows-base-policy-on-the-system","title":"Deploy the Default Windows Base Policy on the System","text":"

    Start by deploying the Default Windows base policy on the system, which allows only files and apps that come pre-installed in Windows to run and anything else is blocked.

    Since this is an unsigned policy, no reboot is required but it's better to perform a reboot if you want the currently running non-Windows apps to stop running.

    New-WDACConfig -PolicyType DefaultWindows -Deploy\n

    After deploying the base policy, you can create Supplemental policies to allow other apps that don't come by default with Windows to run. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    If you deployed the Default Windows base policy on a system that already had apps installed, you can create Supplemental policy for them using the following syntaxes:

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\DefaultWindowsPlusBlockRules.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the Default Windows base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-apps-install-directory-and-other-signals","title":"Based on App\u2019s Install Directory and Other Signals","text":"
    Edit-WDACConfig -AllowNewApps -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/","title":"WDAC policy for Fully managed device - Variant 3","text":"Base policy type Method used Signed Protection score 1-5 Allow Microsoft WDACConfig module Yes 4.5
    flowchart TD\n    A(Deploy Allow Microsoft Signed base policy) -->B(Identify Important apps that need Supplemental policy)\n    B --> C[Create Supplemental policy based on App's directory]\n    C --> D[Want to allow an entire directory?]\n    D --> E[New-SupplementalWDACConfig -FilePathWildCards]\n    E --> AA[Deploy-SignedWDACConfig]\n    C --> F[Want to Scan the app's install directory?]\n    F --> G[New-SupplementalWDACConfig -Normal]\n    G --> AB[Deploy-SignedWDACConfig]\n    B --> H[Is it a game Installed using Xbox app?]\n    H --> I[Or Is it an app that installs drivers outside app's directory?]\n    I --> J[Edit-SignedWDACConfig -AllowNewApps]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically, any software that you can run.

    This scenario provides a very high protection level. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#deploy-the-allow-microsoft-base-policy-on-the-system","title":"Deploy the Allow Microsoft Base Policy on the System","text":"

    Start by creating the Allow Microsoft base policy xml file, which allows only files and apps that are signed by Microsoft's trusted root certificate.

    New-WDACConfig -PolicyType AllowMicrosoft\n

    Now what we have the policy xml file for the Allow Microsoft base policy, we need to sign and deploy it.

    Deploy-SignedWDACConfig -CertPath \"C:\\Certificate.cer\" -PolicyPaths \"C:\\AllowMicrosoftPlusBlockRules.xml\" -CertCN \"WDAC Certificate\" -Deploy\n

    Since this is a signed base policy, you need to perform a reboot after deployment so that the anti-tamper protection of a signed base policy will start.

    After deploying the base policy, you can create Supplemental policies to allow other apps that aren't signed by Microsoft's trusted root certificate to run. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    If you deployed the Allow Microsoft base policy on a system that already had apps installed, you can create Supplemental policy for them using the following syntaxes. After creating each Supplemental policy, you need to sign and deploy it using the same Cmdlet we used above.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\AllowMicrosoftPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\AllowMicrosoftPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\AllowMicrosoftPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the Allow Microsoft base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-apps-install-directory-and-other-signals","title":"Based on App\u2019s Install Directory and Other Signals","text":"
    Edit-SignedWDACConfig -AllowNewApps -CertPath \"C:\\Certificate.cer\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\AllowMicrosoftPlusBlockRules.xml\" -CertCN \"WDAC Certificate\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/","title":"WDAC policy for Fully managed device - Variant 4","text":"Base policy type Method used Signed Protection score 1-5 Default Windows WDACConfig module Yes 5
    flowchart TD\n    A(Deploy Default Windows Signed base policy) -->B(Identify Important apps that need Supplemental policy)\n    B --> C[Create Supplemental policy based on App's directory]\n    C --> D[Want to allow an entire directory?]\n    D --> E[New-SupplementalWDACConfig -FilePathWildCards]\n    E --> AA[Deploy-SignedWDACConfig]\n    C --> F[Want to Scan the app's install directory?]\n    F --> G[New-SupplementalWDACConfig -Normal]\n    G --> AB[Deploy-SignedWDACConfig]\n    B --> H[Is it a game Installed using Xbox app?]\n    H --> I[Or Is it an app that installs drivers outside app's directory?]\n    I --> J[Edit-SignedWDACConfig -AllowNewApps]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically, any software that you can run.

    This scenario provides the ultimate protection level. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#deploy-the-default-windows-base-policy-on-the-system","title":"Deploy the Default Windows Base Policy on the System","text":"

    Start by creating the Default Windows base policy xml file, which allows only files and apps that come pre-installed in Windows to run and anything else is blocked.

    New-WDACConfig -PolicyType DefaultWindows\n

    Now what we have the policy xml file for the Default Windows base policy, we need to sign and deploy it.

    Deploy-SignedWDACConfig -CertPath \"C:\\Certificate.cer\" -PolicyPaths \"C:\\DefaultWindowsPlusBlockRules.xml\" -CertCN \"WDAC Certificate\" -Deploy\n

    Since this is a signed base policy, you need to perform a reboot after deployment so that the anti-tamper protection of a signed base policy will start.

    After deploying the base policy, you can create Supplemental policies to allow other apps that don't come by default with Windows to run. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    If you deployed the Default Windows base policy on a system that already had apps installed, you can create Supplemental policy for them using the following syntaxes. After creating each Supplemental policy, you need to sign and deploy it using the same Cmdlet we used above.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the Default Windows base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-apps-install-directory-and-other-signals","title":"Based on App's install directory and Other Signals","text":"
    Edit-SignedWDACConfig -AllowNewApps -CertPath \"C:\\Certificate.cer\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\" -CertCN \"WDAC Certificate\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/","title":"WDAC policy for Fully Managed device - Variant 1","text":"Base policy type Method used Signed Protection score 1-5 Allow Microsoft / Default Windows WDACConfig module No 4

    Note

    This variant helps you create and deploy a WDAC policy for fully managed device using only Event Viewer audit logs.

    This scenario includes using explicit Allow rules for files and certificates/signers, anything not allowed by the policies we are going to make are automatically denied/blocked.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#prepare-a-virtual-machine","title":"Prepare a Virtual Machine","text":"

    Install Hyper-V role from optional Windows features if you haven't already.

    Enable-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM -All -norestart\n

    Download the latest Windows .ISO file from Microsoft website, create a new VM with it, install Windows and log in. Fully update Windows and then restart to apply the updates. You can create a Hyper-V checkpoint at this point so that you can return back to this clean state later on if you need to.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#prepare-a-base-policy","title":"Prepare a Base policy","text":"

    There are 2 types of base policies you can choose from.

    1. Allow Microsoft: Allows only files and apps that are signed by Microsoft's trusted root certificates.

    2. Default Windows: Allows only files and apps that come pre-installed by Windows.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#deploy-the-allow-microsoft-audit-mode-base-policy","title":"Deploy the Allow Microsoft Audit Mode Base Policy","text":"
    New-WDACConfig -PolicyType AllowMicrosoft -Audit -LogSize 20MB\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#deploy-the-default-windows-audit-mode-base-policy","title":"Deploy the Default Windows Audit Mode Base Policy","text":"
    New-WDACConfig -PolicyType DefaultWindows -Audit -LogSize 20MB\n

    Depending on whichever of the option you choose, it deploys the base policy in audit mode. No reboot required.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#generate-audit-event-logs-on-the-system","title":"Generate Audit Event Logs on the System","text":"

    Install all of the programs that you want to allow in the WDAC policy, on the VM. These are the programs that you want to allow to run and be installed on the target system once you've deployed the WDAC policy.

    These event logs are exactly what we need to identify and create Allow rules for the detected files.

    Only files that are executed during audit mode phase generate event logs, so by simply installing a program using its installer, we can't trigger event log generation for each of the components and executables that each program has. So, after installing the programs, run them, use them a bit as you normally would so that all of the programs' components are executed and event logs generated for them.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#generate-supplemental-policy-from-the-audit-event-logs","title":"Generate Supplemental Policy From the Audit Event Logs","text":"

    Run the following command which will scan the local machine's Code Integrity and AppLocker logs and display them to you in a nice GUI (Graphical User Interface) window so that you can see detailed information of each file and choose which ones you want to include in the supplemental policy.

    ConvertTo-WDACPolicy -BasePolicyFile <Path To The Base Policy XML File>\n

    The cmdlet offers a lot more features, you can read about them here.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/","title":"WDAC policy for Lightly managed device","text":"Base policy type Method used Signed Protection score 1-5 SignedAndReputable (ISG) WDACConfig module No / Yes 3.5 / 4
    flowchart TD\n    A(Deploy WDAC base policy with ISG) -->B(Start using your apps)\n    B --> C(Did your app run without problem?)\n    C -->|Yes| D[Awesome]\n    C -->|No| E[Create a Supplemental policy for it]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically any software that you can run.

    This scenario provides a high protection level, higher if you cryptographically Sign it. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#deploy-the-signedandreputable-base-policy-on-the-system","title":"Deploy the SignedAndReputable Base Policy on the System","text":"

    Start by deploying the SignedAndReputable base policy on the system, which allows only files and apps that are authorized by the Intelligent Security Graph Authorization which have known good state to run and anything else is blocked.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#unsigned-version","title":"Unsigned version","text":"
    New-WDACConfig -PolicyType SignedAndReputable -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#signed-version","title":"Signed version","text":"
    New-WDACConfig -PolicyType SignedAndReputable\n
    Deploy-SignedWDACConfig -CertPath \"C:\\Certificate.cer\" -PolicyPaths \"C:\\Users\\HotCakeX\\SignedAndReputable.xml\" -CertCN \"WDAC Certificate\" -Deploy\n

    After finishing deploying the SignedAndReputable base policy, if there is an app that is getting blocked and you want to allow it, you can create Supplemental policies to expand your base policy. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    The following commands use the -Deploy optional switch parameter, meaning after Supplemental policy creation, they are automatically deployed on the system.

    If you chose the Signed path, omit it from the commands and instead use the Deploy-SignedWDACConfig cmdlet to Sign and Deploy the Supplemental policy xml files.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\SignedAndReputable.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\SignedAndReputable.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\SignedAndReputable.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed, and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the \"SignedAndReputable\" base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-apps-install-directory-and-other-signals-unsigned-version","title":"Based on App\u2019s Install Directory and Other Signals - Unsigned Version","text":"
    Edit-WDACConfig -AllowNewApps -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\SignedAndReputable.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-apps-install-directory-and-other-signals-signed-version","title":"Based on App\u2019s Install Directory and Other Signals - Signed Version","text":"
    Edit-SignedWDACConfig -AllowNewApps -CertPath \"C:\\Certificate.cer\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\SignedAndReputable.xml\" -CertCN \"WDAC Certificate\"\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#security-considerations","title":"Security Considerations","text":"

    One of the differences between using ISG in a WDAC policy vs using Smart App Control (which also use ISG) is that WDAC policy + ISG rule option passes along reputation from app installers to the binaries they write to disk, it can over-authorize files in some cases. For example, if the installer launches the app upon completion, any files the app writes during that first run will also be allowed.

    Smart App Control however doesn't do this, it will trust the installer file itself if it's trustworthy and subsequently checks the trustworthiness of any binaries the installer tries to use and write to the disk, if any of those binaries or components can't be verified or are malicious, they get blocked.

    Explained more in here:

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/","title":"WDAC Policy for BYOVD Kernel Mode Only Protection","text":"

    This scenario involves removing the trust to any Kernel mode driver, whether they are vulnerable or not. It does not affect User-mode binaries or drivers. Any 3rd party software/hardware Kernel mode driver will need to be explicitly allowed. This scenario protects against all BYOVD scenarios and much more.

    Drivers can access the Kernel which is the core of the operating system. Microsoft requires all drivers to be digitally signed:

    A BYOVD (Bring Your Own Vulnerable Driver) scenario involves exploiting one of the digitally signed drivers that harbors a security flaw to attain direct access to the core of the OS. This attack vector applies to all OSes, not just Windows.

    People who seek to obtain code signing certificates, even for Extended Validation certificates, are not undergoing proper verification.

    YOUTUBE VIDEO: How to easily protect against BYOVD attack scenarios with WDAC policy in Windows

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#there-are-3-types-of-kernel-mode-drivers-that-can-run-on-windows","title":"There Are 3 Types of Kernel Mode Drivers That Can Run on Windows","text":""},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#regular-drivers","title":"Regular drivers","text":"

    A regular signed driver is a driver that has been digitally signed by the developer using a software publisher certificate (SPC) issued by a Microsoft approved Certificate Authority (CA).

    These are regular signed Kernel mode drivers from 3rd parties that shouldn't be trusted by default in a secure and high-risk environment.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#whql-drivers","title":"WHQL drivers","text":"

    A WHQL driver is a driver that has been tested and certified by Microsoft's Windows Hardware Quality Labs (WHQL). A WHQL driver has passed Microsoft's compatibility tests and can be distributed through Windows Update or other Microsoft-supported channels, while a regular signed driver may not have passed those tests and may not be eligible. A WHQL driver is signed by Microsoft.

    WHQL drivers have a slightly higher security bar than regular Kernel mode drivers. Any driver updates are required to pass the WHQL testing too.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#ev-signed-drivers","title":"EV Signed Drivers","text":"

    EV signed kernel mode drivers are drivers that have been signed with an extended validation code signing certificate issued by a trusted certificate authority (CA).

    EV certificates cost more than regular code signing certificates, they require to be on an HSM (to ensure the private key is stored properly) and CAs issuing them only validate that the company of the person requesting them exists. Anyone can get EV certificate as long as they have a HSM and a company, which is not hard to come by, costs about ~100$ to set up in the US as a resident.

    Sometimes the issuing CA also needs you to send in your driver's license and a picture of you holding it, but things like extended background checks, criminal history check, nationality check, or the proper checks explained in here are not performed.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#what-is-the-solution","title":"What Is the Solution?","text":"

    We need to establish a Zero-Trust situation by eliminating the default trust to any signed driver and explicitly authorizing each driver that seeks to access the kernel.

    Numerous applications incorporate drivers that interact with the Kernel. Ordinarily, they are unnoticeable, but if you deploy the WDAC policy that we are going to create, in Audit mode, you will be able to observe event logs generated for each of the kernel-mode drivers.

    By creating a strict kernel mode WDAC policy, you will have a powerful security feature at your fingertips.

    This approach is the kind of future-leading technology you need. You can't afford waiting for analysis to predict malicious behavior or wait for malware to be found and cataloged before something is done about it.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#how-to-make-a-strict-kernel-mode-wdac-policy","title":"How to make a strict Kernel mode WDAC policy","text":"

    We take the Default Windows example policy from C:\\Windows\\schemas\\CodeIntegrity\\ExamplePolicies and remove the following items from it:

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-ekus-section","title":"From the EKUs section","text":"
    <EKU ID=\"ID_EKU_WHQL\" Value=\"010A2B0601040182370A0305\" />\n<EKU ID=\"ID_EKU_RT_EXT\" Value=\"010a2b0601040182370a0315\" />\n<EKU ID=\"ID_EKU_STORE\" FriendlyName=\"Windows Store EKU - 1.3.6.1.4.1.311.76.3.1 Windows Store\" Value=\"010a2b0601040182374c0301\" />\n<EKU ID=\"ID_EKU_DCODEGEN\" FriendlyName=\"Dynamic Code Generation EKU - 1.3.6.1.4.1.311.76.5.1\" Value=\"010A2B0601040182374C0501\" />\n<EKU ID=\"ID_EKU_AM\" FriendlyName=\"AntiMalware EKU -1.3.6.1.4.1.311.76.11.1 \" Value=\"010a2b0601040182374c0b01\" />\n

    For our strict Kernel-mode-only WDAC policy, only the following EKUs are necessary

    <EKUs>\n    <EKU ID=\"ID_EKU_WINDOWS\" Value=\"010A2B0601040182370A0306\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_ELAM\" Value=\"010A2B0601040182373D0401\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_HAL_EXT\" Value=\"010a2b0601040182373d0501\" FriendlyName=\"\" />\n</EKUs>\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-filerules-section","title":"From the FileRules section","text":"

    User Mode Refresh policy program

    <FileAttrib ID=\"ID_FILEATTRIB_REFRESH_POLICY\" FriendlyName=\"RefreshPolicy.exe FileAttribute\" FileName=\"RefreshPolicy.exe\" MinimumFileVersion=\"10.0.19042.0\" />\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-signers-section","title":"From the Signers section","text":"
    <Signer ID=\"ID_SIGNER_RT_PRODUCTION\" Name=\"Microsoft Product Root 2010 RT EKU\">\n    <CertRoot Type=\"Wellknown\" Value=\"06\" />\n    <CertEKU ID=\"ID_EKU_RT_EXT\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_RT_FLIGHT\" Name=\"Microsoft Flighting Root 2014 RT EKU\">\n    <CertRoot Type=\"Wellknown\" Value=\"0E\" />\n    <CertEKU ID=\"ID_EKU_RT_EXT\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_RT_STANDARD\" Name=\"Microsoft Standard Root 2011 RT EKU\">\n    <CertRoot Type=\"Wellknown\" Value=\"07\" />\n    <CertEKU ID=\"ID_EKU_RT_EXT\" />\n</Signer>\n
    <Signer ID=\"ID_SIGNER_WHQL_SHA2\" Name=\"Microsoft Product Root 2010 WHQL EKU\">\n  <CertRoot Type=\"Wellknown\" Value=\"06\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_WHQL_SHA1\" Name=\"Microsoft Product Root WHQL EKU SHA1\">\n  <CertRoot Type=\"Wellknown\" Value=\"05\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_WHQL_MD5\" Name=\"Microsoft Product Root WHQL EKU MD5\">\n  <CertRoot Type=\"Wellknown\" Value=\"04\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n

    <Signer ID=\"ID_SIGNER_WHQL_FLIGHT_SHA2\" Name=\"Microsoft Flighting Root 2014 WHQL EKU\">\n  <CertRoot Type=\"Wellknown\" Value=\"0E\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n

    <Signer ID=\"ID_SIGNER_TEST2010\" Name=\"MincryptKnownRootMicrosoftTestRoot2010\">\n<CertRoot Type=\"Wellknown\" Value=\"0A\" />\n</Signer>\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-signingscenarios-section","title":"From the SigningScenarios section","text":""},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#in-the-kernel-mode-signing-scenario-block","title":"In the Kernel Mode Signing Scenario block","text":"
    <AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA2\" />\n<AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA1\" />\n<AllowedSigner SignerId=\"ID_SIGNER_WHQL_MD5\" />\n
    <AllowedSigner SignerId=\"ID_SIGNER_WHQL_FLIGHT_SHA2\" />\n
    <AllowedSigner SignerId=\"ID_SIGNER_TEST2010\" />\n
    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#in-the-user-mode-signing-scenario-block","title":"In the User Mode Signing Scenario block","text":"

    This entire block should either be removed

    <!--User Mode Signing Scenario-->\n<SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_UMCI\" FriendlyName=\"User Mode Signing Scenario\">\n  <ProductSigners>\n    <AllowedSigners>\n      <AllowedSigner SignerId=\"ID_SIGNER_WINDOWS_PRODUCTION_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_ELAM_PRODUCTION_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_HAL_PRODUCTION_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA2_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA1_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_MD5_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WINDOWS_FLIGHT_ROOT_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_ELAM_FLIGHT_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_HAL_FLIGHT_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_FLIGHT_SHA2_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_STORE\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_STORE_FLIGHT_ROOT\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_RT_PRODUCTION\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_DRM\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_DCODEGEN\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_AM\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_RT_FLIGHT\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_RT_STANDARD\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_MICROSOFT_REFRESH_POLICY\" />\n      <!-- Test signer is trusted by ConfigCI, however, it will not be trusted by CI unless testsigning BCD is set -->\n      <AllowedSigner SignerId=\"ID_SIGNER_TEST2010_USER\" />\n    </AllowedSigners>\n  </ProductSigners>\n</SigningScenario>\n

    Or replaced with

    <SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_UMCI\" FriendlyName=\"User Mode Signing Scenario\">\n  <ProductSigners />\n</SigningScenario>\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#flight-root-signers-optional","title":"Flight root signers - Optional","text":"

    They can also be removed if you don't intend to use Windows insider builds. They all have flight or _flight in their ID.

    When removing them, also use the 4 Disabled:Flight Signing policy rule option.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-cisigners","title":"From CiSigners","text":"

    Remove this item which is for Windows Store EKU

    <CiSigner SignerId=\"ID_SIGNER_STORE\" />\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#how-to-use-and-automate-this-entire-process","title":"How to Use and Automate This Entire Process","text":"

    Use the WDACConfig module to automatically Audit and deploy the Strict Kernel-mode WDAC policies.

    As mentioned earlier, this policy only enforces and applies to Kernel-mode drivers, so your non-Kernel mode files are unaffected. Keep in mind that Kernel-mode does not mean programs that require Administrator privileges, those 2 categories are completely different. Also, not all drivers are Kernel mode, there are user-mode drivers too.

    This strict Kernel mode policy can be perfectly deployed side by side any other WDAC policy.

    For instance, since HVCI is turned on by default on my system, the Microsoft Recommended driver block rules is automatically deployed and it's only Kernel mode. It has 2 allow all rules, making it primarily a block-list policy.

    Then I deploy Strict Kernel-mode WDAC policy, which also only applies to Kernel-mode drivers. It doesn't have allow all rules of course, instead it allows Windows components that are required for Windows to function properly to run and then will let you hand pick any 3rd party Kernel-mode drivers and easily allow them in your policy.

    Now the Allow all rules that exist in the first policy are neutralized. Only applications allowed by both policies run without generating block events., so since the same allow all rules do not exist in our Strict Kernel-mode base policy, they no longer apply.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#what-about-user-mode-binaries","title":"What About User-mode Binaries?","text":"

    So far, we've only been doing Kernel-mode administration. We can use User-mode WDAC policies as well.

    After using those 2 Kernel-mode policies, I deploy a 3rd policy which is going to authorize and validate User-mode binaries too. I choose the Lightly managed WDAC policy that utilizes ISG (Intelligent Security Graph). This policy applies to both Kernel and User modes, but since we already know the logic and learned that only applications allowed by all base policies are allowed to run, we're confident that our Strict Kernel-mode base policy is the only one in charge of authorizing and validating Kernel-mode files/drivers. Our User-mode WDAC policy that utilizes ISG validates User-mode binaries only.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#a-rule-of-thumb","title":"A rule of thumb","text":"

    The strictest policy wins the race in multiple base policy deployments, which in this case is the Strict Kernel-Mode policy. Even though ISG policy which uses Allow Microsoft rules and allows all the WHQL signed drivers, they still won't be able to run unless the Kernel-Mode policy authorizes them, because for a Kernel driver to be allowed to run in this scenario, all base policies must allow it.

    So only the policy that has the least allow listings in common with all other policies takes priority.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#supplemental-policy","title":"Supplemental policy","text":"

    Each of the deployed policies (except for the automatically deployed block rules by HVCI) support having supplemental policies. So, whenever you feel the need to allow additional files that are Kernel-mode drivers or User-mode binaries blocked by ISG, you can add a Supplemental policy for them.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#about-elam-early-launch-anti-malware","title":"About ELAM (Early Launch Anti-Malware)","text":"

    Anti-malware or antivirus vendors need to sign enforceable and binding legal agreements and develop an early launched anti-malware driver that Microsoft will sign. This driver includes a list of certificate hashes that enable that AV vendor to sign new versions without Microsoft\u2019s involvement each time. When code integrity loads this ELAM driver, it permits any executables signed by the certificates in that list to run as anti-malware light.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#continue-reading-about-important-wdac-notes","title":"Continue reading about important WDAC notes","text":""},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#important-notes-and-tips-about-wdac-policies","title":"Important Notes and Tips about WDAC policies","text":""},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/","title":"Assert-WDACConfigIntegrity available parameters","text":""},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#syntax","title":"Syntax","text":"
    Assert-WDACConfigIntegrity\n    [-SaveLocally]\n    [-Path <FileInfo>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#description","title":"Description","text":"

    This cmdlet scans all of the relevant files in the WDACConfig module's folder and computes their SHA2/SHA3-512 hashes.

    Then it downloads the cloud CSV file from the GitHub repository and compares the hashes of the local files with the ones in the cloud.

    By doing so, you can ascertain that the files in your local WDACConfig folder are identical to the ones in the cloud and devoid of any interference.

    If there is any indication of tampering, the outcomes will be displayed on the console.

    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#-savelocally","title":"-SaveLocally","text":"

    This parameter is used to generate hashes of the final module's files prior to publishing them to the GitHub. This parameter shouldn't be used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#-path","title":"-Path","text":"

    Can define a different path for the Hashes.csv file. This parameter shouldn't be used.

    Type: FileInfo Position: Named Default value: Module's Root Directory Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#note","title":"Note","text":"

    The WDACConfig module comprises of .ps1 and .psm1 files that bear the cryptographic signature of my local certificate authority's (CA) certificate. The module incorporates mechanisms to automatically ascertain the integrity of the module files and prevent any unauthorized modifications. The module manifest, .psd1 file, on the other hand, lacks a signature due to the installation error that arises from the PowerShell gallery when it is signed with a self-signed certificate.

    The public key of the certificate used to sign the module files can be obtained from here.

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/","title":"Build-WDACCertificate available parameters","text":""},{"location":"WDACConfig%20Module/Build-WDACCertificate/#syntax","title":"Syntax","text":"
    Build-WDACCertificate\n    [[-CommonName] <String>]\n    [[-FileName] <String>]\n    [[-BuildingMethod] <String>]\n    [[-Password] <SecureString>]\n    [-Force]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#description","title":"Description","text":"

    This cmdlet constructs self-signed certificates that adhere to Microsoft's specifications for WDAC policy signing. With this cmdlet, you can dispense with Windows Server with a CA role to generate a certificate.

    The generated certificates type is Code Signing, they employ SHA2-512 hashing algorithm with RSA 4096-bit encryption (the maximum supported key size for WDAC signing.)

    Upon constructing a certificate, the cmdlet stores it in the Current User's personal store, then it exports that certificate in 2 files. One of the files has a .cer extension and encompasses only the public key, the other file has a .pfx extension and encompasses both public and private keys.

    The PFX file is encrypted with SHA-256 encryption and safeguarded with the password supplied by the user. After the 2 files are exported, the cmdlet eliminates the certificate from Current Users personal store and then re-imports it using the PFX file, but this time it will store the private key using VSM (Virtual Secure Mode). In this method, the private keys are stored in the TPM and are highly secured with VBS (Virtualized-Based Security). The entire process happens in just few seconds.

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-commonname","title":"-CommonName","text":"

    The common name of the certificate, it will also be assigned as the friendly name of the certificate.

    Tip

    If you enter a CommonName but do not enter a FileName, the FileName will be set to the same value as the CommonName for better user experience.

    Type: String Position: Named Default value: Code Signing Certificate Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-filename","title":"-FileName","text":"

    The name of the .cer and .pfx files that will be generated.

    Type: String Position: Named Default value: Code Signing Certificate Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-buildingmethod","title":"-BuildingMethod","text":"

    2 methods are used to build the certificates. Method 1 uses the Certreq and the Method 2 uses the New-SelfSignedCertificate.

    Type: String Position: Named Default value: Method2 Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-password","title":"-Password","text":"

    The password to be employed to encrypt the .pfx file that encompasses the private and public keys of the certificate. It necessitates being in Secure String type. If it\u2019s not supplied, the user will be prompted to input a password (and a second time to verify it). The minimum password length is 5 characters.

    Type: SecureString Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-force","title":"-Force","text":"

    The cmdlet verifies whether there is any certificate with the identical common name as the certificate that is being created, on the system. If it detects one, it will prompt the user to for permission to remove them. If this parameter is employed, the prompt will be omitted as it will presume that the user acquiesced.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#related-resources","title":"Related Resources","text":""},{"location":"WDACConfig%20Module/Build-WDACCertificate/#additional-resources","title":"Additional Resources","text":"

    To enhance the security and safeguarding of your certificate further, you can remove the certificate from the Personal store of the Current User certificates and then utilize the PFX file to import it anew in the same location, but this time you will mark additional boxes in the import wizard.

    This video illustrates how to safeguard the Code Signing Certificate generated by the WDACConfig module, so that you will be compelled to either enter your security password or verify your identity every time the certificate is employed. By storing the certificate in this manner, only your user account will have access to it, and you will inherently possess administrator privileges to implement the signed WDAC policy on the system.

    These options are only accessible in GUI and they are to deter automatic scripts from utilizing the certificates without authentication, this is why the Build-WDACCertificate cmdlet does not activate this security feature by default.

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#hsm-hardware-security-module","title":"HSM (Hardware Security Module)","text":"

    The most secure method of storing code signing certificates is to use a hardware security module (HSM) or a similar device. Furthermore, obtaining certificates from a regulated or publicly trusted certificate authority (CA) requires the use of an HSM. The HSMs must also comply with the Federal Information Processing Standards (FIPS).

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/","title":"Confirm-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#confirm-wdacconfig-listactivepolicies","title":"Confirm-WDACConfig -ListActivePolicies","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#syntax","title":"Syntax","text":"
    Confirm-WDACConfig\n    [-ListActivePolicies]\n    [-OnlyBasePolicies]\n    [-OnlySupplementalPolicies]\n    [-OnlySystemPolicies]\n
    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#description","title":"Description","text":"

    Lists the deployed Base and Supplemental WDAC Policies using CITool and displays their counts and details.

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#-onlybasepolicies","title":"-OnlyBasePolicies","text":"

    Using this will only display Base policies.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#-onlysupplementalpolicies","title":"-OnlySupplementalPolicies","text":"

    Using this will only display Supplemental policies.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#-onlysystempolicies","title":"-OnlySystemPolicies","text":"

    Using this will only display system policies.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#confirm-wdacconfig-verifywdacstatus","title":"Confirm-WDACConfig -VerifyWDACStatus","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#syntax_1","title":"Syntax","text":"
    Confirm-WDACConfig\n    [-VerifyWDACStatus]\n
    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#description_1","title":"Description","text":"

    Shows the status of User-mode and Kernel-mode application control.

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#confirm-wdacconfig-checksmartappcontrolstatus","title":"Confirm-WDACConfig -CheckSmartAppControlStatus","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#syntax_2","title":"Syntax","text":"
    Confirm-WDACConfig\n    [-CheckSmartAppControlStatus]\n
    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#description_2","title":"Description","text":"

    Checks the status of Smart App Control and reports the results on the console, including the evaluation mode expiration date.

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/","title":"ConvertTo-WDACPolicy available parameters","text":""},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#syntax","title":"Syntax","text":"
    ConvertTo-WDACPolicy\n    [-PolicyToAddLogsTo <FileInfo>]\n    [-Source <String>]\n    [-SuppPolicyName <String>]\n    [-MDEAHLogs <FileInfo[]>]\n    [-EVTXLogs <FileInfo[]>]\n    [-FilterByPolicyNames <String[]>]\n    [-TimeSpan <String>]\n    [-TimeSpanAgo <UInt64>]\n    [-KernelModeOnly]\n    [-LogType <String>]\n    [-Deploy]\n    [-ExtremeVisibility]\n    [<CommonParameters>]\n
    ConvertTo-WDACPolicy\n    [-BasePolicyFile <FileInfo>]\n    [-Source <String>]\n    [-SuppPolicyName <String>]\n    [-MDEAHLogs <FileInfo[]>]\n    [-EVTXLogs <FileInfo[]>]\n    [-FilterByPolicyNames <String[]>]\n    [-TimeSpan <String>]\n    [-TimeSpanAgo <UInt64>]\n    [-KernelModeOnly]\n    [-LogType <String>]\n    [-Deploy]\n    [-ExtremeVisibility]\n    [<CommonParameters>]\n
    ConvertTo-WDACPolicy\n    [-BasePolicyGUID <Guid>]\n    [-Source <String>]\n    [-SuppPolicyName <String>]\n    [-MDEAHLogs <FileInfo[]>]\n    [-EVTXLogs <FileInfo[]>]\n    [-FilterByPolicyNames <String[]>]\n    [-TimeSpan <String>]\n    [-TimeSpanAgo <UInt64>]\n    [-KernelModeOnly]\n    [-LogType <String>]\n    [-Deploy]\n    [-ExtremeVisibility]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#description","title":"Description","text":"

    This is a multi-purpose cmdlet that offers a wide range of functionalities that can either be used separately or mixed together for very detailed and specific tasks.

    It currently supports Code Integrity and AppLocker logs from the following sources:

    The cmdlet displays the logs in a GUI and allows the user to select the logs to be processed further.

    The logs can be filtered based on many criteria using the available parameters.

    The output of this cmdlet is a Supplemental Application Control (WDAC) policy. Based on the input parameters, it can be associated with a base policy or merged with an existing Base or Supplemental policy.

    The cmdlet can be used for local and remote systems. You can utilize this cmdlet to create Application Control for Business policies from MDE Advanced Hunting and then deploy them using Microsoft Intune to your endpoints.

    You can utilize this cmdlet to use the evtx log files you aggregated from your endpoints and create a WDAC policy from them.

    This offers scalability and flexibility in managing your security policies.

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-policytoaddlogsto","title":"-PolicyToAddLogsTo","text":"

    The policy to add the selected logs to, it can either be a base or supplemental policy.

    Important

    Only select one of the following three parameters: -PolicyToAddLogsTo, -BasePolicyFile, or -BasePolicyGUID.

    Type: FileInfo Aliases: AddLogs Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-basepolicyfile","title":"-BasePolicyFile","text":"

    The base policy file to associate the supplemental policy with.

    Important

    Only select one of the following three parameters: -PolicyToAddLogsTo, -BasePolicyFile, or -BasePolicyGUID.

    Type: FileInfo Aliases: BaseFile Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-basepolicyguid","title":"-BasePolicyGUID","text":"

    The GUID of the base policy to associate the supplemental policy with.

    Important

    Only select one of the following three parameters: -PolicyToAddLogsTo, -BasePolicyFile, or -BasePolicyGUID.

    Type: Guid Aliases: BaseGUID Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-source","title":"-Source","text":"

    The source of the logs. Supports validate set and auto-completion, press TAB key to view the list of the available options.

    Type: String Aliases: Src Position: Named Accepted values: LocalEventLogs, MDEAdvancedHunting, EVTXFiles Default value: LocalEventLogs Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-supppolicyname","title":"-SuppPolicyName","text":"

    The name of the supplemental policy to create

    Type: String Aliases: Name Position: Named Default value: The cmdlet will generate a proper name based on the selected source and time Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-mdeahlogs","title":"-MDEAHLogs","text":"

    The path(s) to use MDE AH CSV files.

    Note

    This is a dynamic parameter and will only be available if the Source parameter is set to MDEAdvancedHunting.

    Important

    Please read this article for complete information on how to use this feature.

    Type: FileInfo[] Aliases: MDELogs Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-evtxlogs","title":"-EVTXLogs","text":"

    The path(s) of EVTX files to use.

    Note

    This is a dynamic parameter and will only be available if the Source parameter is set to EVTXFiles.

    Type: FileInfo[] Aliases: Evtx Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-timespan","title":"-TimeSpan","text":"

    The unit of time to use when filtering the logs by the time.

    Type: String Aliases: Duration Position: Named Accepted values: Minutes, Hours, Days Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-timespanago","title":"-TimeSpanAgo","text":"

    The number of the selected time unit to go back in time from the current time.

    Note

    This is a dynamic parameter and will only be available if the TimeSpan parameter is set.

    Type: String Aliases: Past Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-filterbypolicynames","title":"-FilterByPolicyNames","text":"

    The names of the policies to filter the logs by. Supports auto-completion, press TAB key to view the list of the deployed base policy names to choose from. It will not display the policies that are already selected on the command line.

    You can manually enter the name of the policies that are no longer available on the system.

    Type: String[] Aliases: FilterNames Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-kernelmodeonly","title":"-KernelModeOnly","text":"

    If used, will filter the logs by including only the Kernel-Mode logs.

    Type: SwitchParameter Aliases: KMode Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-logtype","title":"-LogType","text":"

    The type of logs to display.

    Type: String Aliases: LogKind Position: Named Accepted values: Audit, Blocked Default value: Audit Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-deploy","title":"-Deploy","text":"

    If used, will deploy the policy on the system.

    Type: SwitchParameter Aliases: Up Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-extremevisibility","title":"-ExtremeVisibility","text":"

    If used, will display all the properties of the logs without any filtering.

    Type: SwitchParameter Aliases: XVis Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/","title":"Deploy-SignedWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#syntax","title":"Syntax","text":"
    Deploy-SignedWDACConfig\n    -PolicyPaths <FileInfo[]>\n    [-Deploy]\n    [-CertPath <FileInfo>]\n    [-CertCN <String>]\n    [-SignToolPath <FileInfo>]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#description","title":"Description","text":"

    Creates and signs a .CIP file that can be either deployed locally using the -Deploy parameter or you can deploy the signed policy binary on a different machine later using the built-in Citool, Intune etc.

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-policypaths","title":"-PolicyPaths","text":"

    The XML Policies to deploy. Supports File picker GUI.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-certpath","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-certcn","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-deploy","title":"-Deploy","text":"

    Deploys the signed policy on the system

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with deploying the signed policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/","title":"Edit-SignedWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#edit-signedwdacconfig-allownewapps","title":"Edit-SignedWDACConfig -AllowNewApps","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#syntax","title":"Syntax","text":"
    Edit-SignedWDACConfig\n     [-AllowNewApps]\n     -SuppPolicyName <String>\n     [-BoostedSecurity]\n     [-PolicyPath <FileInfo>]\n     [-CertPath <FileInfo>]\n     [-CertCN <String>]\n     [-LogSize <UInt64>]\n     [-NoScript]\n     [-NoUserPEs]\n     [-SpecificFileNameLevel <String>]\n     [-Level <String>]\n     [-Fallbacks <String[]>]\n     [-SignToolPath <FileInfo>]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#description","title":"Description","text":"

    While a Signed Windows Defender Application Control (WDAC) policy is already deployed on the system, rebootlessly turns on Audit mode in it, which will allow you to install a new app that was otherwise getting blocked.

    After installation, you will be able to browse for the path(s) of the installed app(s) for scanning, which is optional.

    Any file outside of the paths you select that was executed or run during the audit mode phase and was detected in the audit logs, will be displayed to you in a nice GUI (Graphical User Interface) so you will be able to see detailed information about them and decide whether to include them in the Supplemental policy or not.

    This parameter can also be used for apps that are already installed on the system.

    A new supplemental policy will be created, it will be signed and deployed on the system. The base policy that was initially set to Audit mode will also revert back to enforced mode. The entire process happens without the need for reboot. If something like a power outage occurs during the audit mode phase, on the next reboot, the enforced mode base policy will be automatically deployed.

    Note

    This parameter can also detect and create allow rules for Kernel protected files, such as the executables of games installed using Xbox app. Make sure you run the game while the base policy is deployed in Audit mode so that it can capture those executables.

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-supppolicyname","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-boostedsecurity","title":"-BoostedSecurity","text":"

    Implements Sandboxing-like restrictions around the program's dependencies.

    Tip

    When using this mode, it's recommended to only target one program at a time. E.g., don't use this method for creating a supplemental policy for Adobe Photoshop and Steam client at the same time, because they will be put in the same supplemental policy and the dependency sandboxing will be ineffective.

    This mode requires the main executable(s) of the programs that need access to the dependencies (such as DLLs) to have the OriginalFileName property. Most of the time they do. Use the -Verbose parameter to see when they don't.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certpath","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certcn","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-policypath","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports tab completion by showing only .xml files with Base Policy Type.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels for scanning event logs and the specified directory path(s).

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks for scanning event logs and the specified directory path(s).

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-logsize","title":"-LogSize","text":"

    Specifies the log size for Microsoft-Windows-CodeIntegrity/Operational events. The values must be in the form of <Digit + Data measurement unit>. e.g., 2MB, 10MB, 1GB, 1TB. The minimum accepted value is 1MB which is the default.

    Type: UInt64 Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default, the module includes user PEs in the scan. When you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#edit-signedwdacconfig-mergesupplementalpolicies","title":"Edit-SignedWDACConfig -MergeSupplementalPolicies","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#syntax_1","title":"Syntax","text":"
    Edit-SignedWDACConfig\n     [-MergeSupplementalPolicies]\n     -SuppPolicyName <String>\n     -SuppPolicyPaths <FileInfo[]>\n     [-PolicyPath <FileInfo>]\n     [-KeepOldSupplementalPolicies]\n     [-CertPath <FileInfo>]\n     [-CertCN <String>]\n     [-SignToolPath <FileInfo>]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#description_1","title":"Description","text":"

    Merge multiple deployed Signed Supplemental policies into 1 and deploy it, remove the individual ones, all happening automatically.

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-supppolicyname_1","title":"-SuppPolicyName","text":"

    Choose a descriptive name for the Supplemental policy that is going to be the merge of multiple policies.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-supppolicypaths","title":"-SuppPolicyPaths","text":"

    Path to the Supplemental policies xml files. Supports argument tab completion by showing only Supplemental policy types.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certpath_1","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certcn_1","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-policypath_1","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports tab completion by showing only .xml files with Base Policy Type.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-signtoolpath_1","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-keepoldsupplementalpolicies","title":"-KeepOldSupplementalPolicies","text":"

    Indicates that the module will not remove the old Supplemental policy xml files after creating and deploying the new merged one.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#edit-signedwdacconfig-updatebasepolicy","title":"Edit-SignedWDACConfig -UpdateBasePolicy","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#syntax_2","title":"Syntax","text":"
    Edit-SignedWDACConfig\n     [-UpdateBasePolicy]\n     -CurrentBasePolicyName <String[]>\n     -NewBasePolicyType <String>\n     [-CertPath <FileInfo>]\n     [-CertCN <String>]\n     [-SignToolPath <FileInfo>]\n     [-RequireEVSigners]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#description_2","title":"Description","text":"

    It can rebootlessly change the type or rule options of the deployed signed base policy. The deployed Supplemental policies will stay intact and continue to work with the new Base policy.

    Note

    When switching from a more permissive base policy type to a more restrictive one, make sure your Supplemental policies will continue to work. E.g., if your current base policy type is AllowMicrosoft and the one you are switching to is DefaultWindows, there might be files that will get blocked as a result of this switch.

    That's simply because they were allowed by the more permissive AllowMicrosoft policy type so they didn't trigger audit logs (in case the supplemental policy was created based on audit logs) thus weren't needed to be included in the Supplemental policy. You will need to update those Supplemental policies if that happens by deleting and recreating them, no immediate reboot required.

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-currentbasepolicyname","title":"-CurrentBasePolicyName","text":"

    The name of the currently deployed base policy. It supports tab completion so just press tab to autofill it.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-newbasepolicytype","title":"-NewBasePolicyType","text":"

    The new type of the base policy to deploy. It supports tab completion so just press tab to autofill it. Supports all 3 main Base policy types.

    Note

    If the selected policy type is DefaultWindows and the detected PowerShell is not installed through Microsoft Store, the module will scan the PowerShell files and add them to the DefaultWindows base policy as allowed files so you will be able to continue using the module after deploying the policy.

    Type: String Position: Named Accepted values: AllowMicrosoft, DefaultWindows, SignedAndReputable Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certpath_2","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certcn_2","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-signtoolpath_2","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-requireevsigners","title":"-RequireEVSigners","text":"

    Indicates that the created/deployed policy will have Require EV Signers policy rule option.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/","title":"Edit-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#edit-wdacconfig-allownewapps","title":"Edit-WDACConfig -AllowNewApps","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#syntax","title":"Syntax","text":"
    Edit-WDACConfig\n     [-AllowNewApps]\n     -SuppPolicyName <String>\n     [-BoostedSecurity]\n     [-PolicyPath <FileInfo>]\n     [-Level <String>]\n     [-Fallbacks <String[]>]\n     [-NoScript]\n     [-NoUserPEs]\n     [-SpecificFileNameLevel <String>]\n     [-LogSize <UInt64>]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#description","title":"Description","text":"

    While a Windows Defender Application Control (WDAC) policy is already deployed on the system, rebootlessly turns on Audit mode in it, which will allow you to install a new app that was otherwise getting blocked.

    After installation, you will be able to browse for the path(s) of the installed app(s) for scanning, which is optional.

    Any file outside of the paths you select that was executed or run during the audit mode phase and was detected in the audit logs, will be displayed to you in a nice GUI (Graphical User Interface) so you will be able to see detailed information about them and decide whether to include them in the Supplemental policy or not.

    This parameter can also be used for apps that are already installed on the system.

    A new supplemental policy will be created and deployed on the system. The base policy that was initially set to Audit mode will also revert back to enforced mode. The entire process happens without the need for reboot. If something like a power outage occurs during the audit mode phase, on the next reboot, the enforced mode base policy will be automatically deployed.

    Note

    This parameter can also detect and create allow rules for Kernel protected files, such as the executables of games installed using Xbox app. Make sure you run the game while the base policy is deployed in Audit mode so that it can capture those executables.

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-supppolicyname","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-boostedsecurity","title":"-BoostedSecurity","text":"

    Implements Sandboxing-like restrictions around the program's dependencies.

    Tip

    When using this mode, it's recommended to only target one program at a time. E.g., don't use this method for creating a supplemental policy for Adobe Photoshop and Steam client at the same time, because they will be put in the same supplemental policy and the dependency sandboxing will be ineffective.

    This mode requires the main executable(s) of the programs that need access to the dependencies (such as DLLs) to have the OriginalFileName property. Most of the time they do. Use the -Verbose parameter to see when they don't.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-policypath","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports tab completion by showing only .xml files with Base Policy Type.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-logsize","title":"-LogSize","text":"

    Specifies the log size for Microsoft-Windows-CodeIntegrity/Operational events. The values must be in the form of <Digit + Data measurement unit>. e.g., 2MB, 10MB, 1GB, 1TB. The minimum accepted value is 1MB which is the default.

    Type: UInt64 Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels for scanning event logs and the specified directory path(s).

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks for scanning event logs and the specified directory path(s).

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default, the module includes user PEs in the scan. When you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#edit-wdacconfig-mergesupplementalpolicies","title":"Edit-WDACConfig -MergeSupplementalPolicies","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#syntax_1","title":"Syntax","text":"
    Edit-WDACConfig\n     [-MergeSupplementalPolicies]\n     -SuppPolicyName <String>\n     [-PolicyPath <FileInfo>]\n     -SuppPolicyPaths <FileInfo[]>\n     [-KeepOldSupplementalPolicies]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#description_1","title":"Description","text":"

    Merge multiple deployed Supplemental policies into 1 and deploy it, remove the individual ones, all happening automatically.

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-supppolicyname_1","title":"-SuppPolicyName","text":"

    Choose a descriptive name for the Supplemental policy that is going to be the merge of multiple policies.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-supppolicypaths","title":"-SuppPolicyPaths","text":"

    Path to the Supplemental policies xml files. Supports argument tab completion by showing only Supplemental policy types.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-policypath_1","title":"-PolicyPath","text":"

    Path to the Base policy xml file the Supplemental policies belong to. Supports argument tab completion by showing only Base policy types.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-keepoldsupplementalpolicies","title":"-KeepOldSupplementalPolicies","text":"

    Indicates that the module will not remove the old Supplemental policy xml files after creating and deploying the new merged one.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#edit-wdacconfig-updatebasepolicy","title":"Edit-WDACConfig -UpdateBasePolicy","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#syntax_2","title":"Syntax","text":"
    Edit-WDACConfig\n     [-UpdateBasePolicy]\n     -CurrentBasePolicyName <String[]>\n     -NewBasePolicyType <String>\n     [-RequireEVSigners]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#description_2","title":"Description","text":"

    It can rebootlessly change the type or rule options of the deployed base policy. The deployed Supplemental policies will stay intact and continue to work with the new Base policy.

    Note

    When switching from a more permissive base policy type to a more restrictive one, make sure your Supplemental policies will continue to work. E.g., if your current base policy type is AllowMicrosoft and the one you are switching to is DefaultWindows, there might be files that will get blocked as a result of this switch.

    That's simply because they were allowed by the more permissive AllowMicrosoft policy type so they didn't trigger audit logs (in case the supplemental policy was created based on audit logs) thus weren't needed to be included in the Supplemental policy. You will need to update those Supplemental policies if that happens by deleting and recreating them, no immediate reboot required.

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-currentbasepolicyname","title":"-CurrentBasePolicyName","text":"

    The name of the currently deployed base policy. It supports tab completion so just press tab to autofill it.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-newbasepolicytype","title":"-NewBasePolicyType","text":"

    The new type of the base policy to deploy. It supports tab completion so just press tab to autofill it. Supports all 3 main Base policy types.

    Note

    If the selected policy type is DefaultWindows and the detected PowerShell is not installed through Microsoft Store, the module will scan the PowerShell files and add them to the DefaultWindows base policy as allowed files so you will be able to continue using the module after deploying the policy.

    Type: String Position: Named Accepted values: AllowMicrosoft, DefaultWindows, SignedAndReputable Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-requireevsigners","title":"-RequireEVSigners","text":"

    Indicates that the created/deployed policy will have Require EV Signers policy rule option.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/","title":"Get-CIPolicySetting available parameters","text":""},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#syntax","title":"Syntax","text":"
    Get-CIPolicySetting\n    [-Provider] <String>\n    [-Key] <String>\n    [-ValueName] <String>\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#description","title":"Description","text":"

    Gets the secure settings value from the deployed CI policies. If there is a policy with the same provider, key and value then it returns the following details:

    Property Description Value The actual value of the string ValueType The type of setting: WldpString, WldpInteger or WldpBoolean ValueSize the size of the returned value Status True/False depending on whether the setting exists on the system or not StatusCode 0 if the value exists on the system, non-zero if it doesn't."},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#-provider","title":"-Provider","text":"

    The provider of the secure setting.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#-key","title":"-Key","text":"

    The key of the secure setting.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#-valuename","title":"-ValueName","text":"

    The name of the secure setting.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CiFileHashes/","title":"Get-CiFileHashes available parameters","text":""},{"location":"WDACConfig%20Module/Get-CiFileHashes/#syntax","title":"Syntax","text":"
    Get-CiFileHashes\n    [-FilePath] <FileInfo>\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Get-CiFileHashes/#description","title":"Description","text":"

    Calculates the Authenticode hash and first page hash of the PEs with SHA1 and SHA256 algorithms. The hashes are compliant wih the Windows Defender Application Control (WDAC) policy.

    The cmdlet outputs an ordered hashtable. The keys are the hash algorithm names and the values are the hashes.

    For more information please visit this page

    Tip

    If the file is non-conformant, the function will calculate the flat hash of the file using the specified hash algorithm and return them as the Authenticode hashes. This is compliant with how the WDAC engine in Windows works.

    "},{"location":"WDACConfig%20Module/Get-CiFileHashes/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Get-CiFileHashes/#-filepath","title":"-FilePath","text":"

    The path to the file for which the hashes are to be calculated. Supports TAB completion, when you press Tab key, file picker GUI will open allowing you to select a file.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/","title":"Get-CommonWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#syntax","title":"Syntax","text":"
    Get-CommonWDACConfig\n    [-CertCN]\n    [-CertPath]\n    [-SignToolPath]\n    [-SignedPolicyPath]\n    [-UnsignedPolicyPath]\n    [-StrictKernelPolicyGUID]\n    [-StrictKernelNoFlightRootsPolicyGUID]\n    [-Open]\n    [-LastUpdateCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#description","title":"Description","text":"

    Use this cmdlet to query and display the values for common and frequently used parameters in the User Configurations Json file.

    All of the applicable cmdlets of the module automatically check the User Configuration file for any available input, if you don't specify values for their parameters. Learn more about the User Configuration file here.

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-certcn","title":"-CertCN","text":"

    Displays the Common Name of an installed certificate.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-certpath","title":"-CertPath","text":"

    Displays the path to a certificate .cer file.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Displays the path to the SignTool executable.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-signedpolicypath","title":"-SignedPolicyPath","text":"

    Displays the path to the xml file of a Signed policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-unsignedpolicypath","title":"-UnSignedPolicyPath","text":"

    Displays the path to the xml file of an Unsigned policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-open","title":"-Open","text":"

    Opens the User Config Json file in the default editor.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-lastupdatecheck","title":"-LastUpdateCheck","text":"

    Displays the last time online update check was performed.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/","title":"Invoke-WDACSimulation available parameters","text":""},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#syntax","title":"Syntax","text":"
    Invoke-WDACSimulation\n  [-XmlFilePath] <FileInfo>\n  [[-FolderPath] <DirectoryInfo>]\n  [[-FilePath] <FileInfo>]\n  [-BooleanOutput]\n  [-Log]\n  [-CSVOutput]\n  [-SkipVersionCheck]\n  [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#description","title":"Description","text":"

    This cmdlet allows you to simulate a WDAC (App Control for Business) policy deployment. Simply select a folder or file and a policy XML file, it will show you whether the selected files would be allowed or blocked by your WDAC policy if it was actually deployed on a system and those files were run.

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#supported-levels-and-specificfilenamelevel-options","title":"Supported Levels and SpecificFileNameLevel Options","text":"

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#accuracy","title":"Accuracy","text":"

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#some-use-cases","title":"Some Use Cases","text":""},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-folderpath","title":"-FolderPath","text":"

    Path to a folder. Supports argument tab completion, select the parameter then press TAB to open the Folder picker GUI.

    Tip

    Either FilePath or FolderPath must be provided.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-filepath","title":"-FilePath","text":"

    Provide path to a file that you want WDAC simulation to run against

    Uses LiteralPath to take the path exactly as typed including Special characters such as [ and ]

    Tip

    Either FilePath or FolderPath must be provided.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-xmlfilepath","title":"-XmlFilePath","text":"

    Path to a xml file. Supports argument tab completion, select the parameter then press TAB to open the file picker GUI that only shows xml files.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-booleanoutput","title":"-BooleanOutput","text":"

    Can be used with any parameter to return a boolean value instead of displaying the object output

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-log","title":"-Log","text":"

    Use this switch to start a transcript of the WDAC simulation and log everything displayed on the screen.

    Tip

    Highly recommended to use the -Verbose parameter with this switch to log the verbose output as well.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-csvoutput","title":"-CSVOutput","text":"

    Upon completion of the simulation, you will obtain a CSV file containing the output of the simulation with exhaustive details of each file that would be blocked/allowed by the selected policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#notes","title":"Notes","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/","title":"New-DenyWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-normal","title":"New-DenyWDACConfig -Normal","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-Normal]\n    -PolicyName <String>\n    [-ScanLocations <DirectoryInfo[]>]\n    [-Deploy]\n    [-Level <String>]\n    [-Fallbacks <String[]>]\n    [-SpecificFileNameLevel <String>]\n    [-NoUserPEs]\n    [-NoScript]\n    [-SkipVersionCheck]\n    [-WhatIf]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description","title":"Description","text":"

    Creates a Deny base policy by scanning a directory. The base policy will have 2 allow all rules, meaning it can be deployed as a standalone base policy, side-by-side any other Base/Supplemental policies.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-scanlocations","title":"-ScanLocations","text":"

    Accepts one or more comma separated folder paths. Supports argument completion, when you press tab, folder picker GUI will open allowing you to easily select a folder, you can then add a comma , and press tab again to select another folder path or paste a folder path manually, works both ways.

    Type: DirectoryInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels to scan the specified directory path(s).

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks to scan the specified directory path(s).

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default the module includes user PEs in the scan, but when you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-drivers","title":"New-DenyWDACConfig -Drivers","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax_1","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-Drivers]\n    -PolicyName <String>\n    [-ScanLocations <DirectoryInfo[]>]\n    [-Deploy]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description_1","title":"Description","text":"

    Creates a Deny base policy by scanning a directory, this parameter uses DriverFile objects so it's best suitable for driver files. The base policy will have 2 allow all rules, meaning it can be deployed as a standalone base policy, side-by-side any other Base/Supplemental policies.

    Note

    The scan uses WHQLFilePublisher level without any fallbacks, and includes both usermode and kernel mode drivers.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname_1","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-scanlocations_1","title":"-ScanLocations","text":"

    Accepts one or more comma separated folder paths. Supports argument completion, when you press tab, folder picker GUI will open allowing you to easily select a folder, you can then add a comma , and press tab again to select another folder path or paste a folder path manually, works both ways.

    Type: DirectoryInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy_1","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-installedappxpackages","title":"New-DenyWDACConfig -InstalledAppXPackages","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax_2","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-InstalledAppXPackages]\n    -PackageName <String>\n    -PolicyName <String>\n    [-Deploy]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description_2","title":"Description","text":"

    Creates a Deny base policy for one or more installed Windows Apps (Appx) based on their PFN (Package Family Name). The base policy will have 2 allow all rules, meaning it can be deployed as a standalone base policy, side-by-side any other Base/Supplemental policies.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-packagename","title":"-PackageName","text":"

    Enter the package name of an installed app. Supports wildcard * character. e.g, *Edge* or \"*Microsoft*\".

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname_2","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy_2","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with creating the deny policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-pathwildcards","title":"New-DenyWDACConfig -PathWildCards","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax_3","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-PathWildCards]\n    -PolicyName <String>\n    -FolderPath <DirectoryInfo>\n    [-Deploy]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description_3","title":"Description","text":"

    Creates a Deny standalone base policy for a folder using wildcards. The base policy created by this parameter can be deployed side by side any other base/supplemental policy.

    Note

    This feature is also used internally by the Harden Windows Security Module.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters_3","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname_3","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-folderpath","title":"-FolderPath","text":"

    A folder path that includes at least one wildcard * character. Press TAB to open the folder picker GUI. Once you selected a folder, you will see the path will have \\* at the end of it. You can modify the selected path by adding/removing wildcards * to it before proceeding.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy_3","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/","title":"New-KernelModeWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#syntax","title":"Syntax","text":"
    New-KernelModeWDACConfig\n    -Mode <String>\n    [-Deploy]\n    [-EVSigners]\n    [-Base <String>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#description","title":"Description","text":"

    This cmdlet generates a Kernel-mode WDAC policy derived from the Default Windows template policy. You can learn more about that procedure in here.

    Initially, you need to use the -Mode Prep parameter to deploy the base policy in Audit mode, then restart your system. After restarting, event logs are produced for Kernel-mode drivers that are running but would otherwise be blocked if the policy was not deployed in Audit mode.

    Subsequently, you need to use the -Mode AuditAndEnforce parameter to generate the final base policy. This parameter will:

    1. Scan all of the event logs that were produced after deploying the audit mode policy on the system
    2. Generate a supplemental policy for the drivers detected in event logs
    3. Merge the supplemental policy with the Strict Kernel-mode base policy
    4. Deploy it as a single base policy, rebootlessly.

    Tip

    All Kernel-mode drivers are scanned with WHQLFilePublisher level, so they will not necessitate a policy update when they are updated.

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-mode","title":"-Mode","text":"

    Specifies the mode of operation. The acceptable values for this parameter are: Prep and AuditAndEnforce.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the policy will be deployed. If you want to deploy the final strict kernel-mode base policy Signed, do not use this parameter, Instead just create the policy and then use the Deploy-SignedWDACConfig cmdlet to deploy it.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-evsigners","title":"-EVSigners","text":"

    Uses EVSigners policy rule option. If you want to use this parameter, make sure you use it for both Prep and AuditAndEnforce modes. Read more about EV Signers

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-base","title":"-Base","text":"

    The base policy to be used. The acceptable values for this parameter are: Default and NoFlightRoots.

    Note

    The NoFlightRoots value signifies that the Strict Kernel-mode WDAC policy will not be deployed with flight root certificates, disallowing you to use insider builds of the OS in the Dev and Canary channels. Insider builds in the Beta and Release Preview channels are signed with production root certificates and will not be affected.

    Type: String Position: Named Default value: Default Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/","title":"New-SupplementalWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-normal","title":"New-SupplementalWDACConfig -Normal","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax","title":"Syntax","text":"
    New-SupplementalWDACConfig\n    [-Normal]\n    -ScanLocation <DirectoryInfo>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-SpecificFileNameLevel <String>]\n    [-NoUserPEs]\n    [-NoScript]\n    [-Level <String>]\n    [-Fallbacks <String[]>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description","title":"Description","text":"

    Creates a Supplemental policy for a base policy based on a folder path.

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-scanlocation","title":"-ScanLocation","text":"

    The directory or drive that you want to scan for files that will be allowed to run by the Supplemental policy. Supports GUI folder picker, press TAB after the parameter to launch it.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels to scan the specified directory path.

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks to scan the specified directory path.

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default, the module includes user PEs in the scan. When you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#the-outputs-of-the-parameter-are","title":"The outputs of the parameter are","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-pathwildcards","title":"New-SupplementalWDACConfig -PathWildCards","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax_1","title":"Syntax","text":"
    New-SupplementalWDACConfig\n    [-PathWildCards]\n    -FolderPath <DirectoryInfo>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description_1","title":"Description","text":"

    Creates a Supplemental policy that allows a folder path that includes one or more wildcard * character in it.

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-folderpath","title":"-FolderPath","text":"

    A folder path that includes at least one wildcard * character. Press TAB to open the folder picker GUI. Once you selected a folder, you will see the path will have \\* at the end of it. You can modify the selected path by adding/removing wildcards * to it before proceeding.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname_1","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath_1","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy_1","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#the-outputs-of-the-parameter-are_1","title":"The outputs of the parameter are","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-installedappxpackages","title":"New-SupplementalWDACConfig -InstalledAppXPackages","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax_2","title":"Syntax","text":"
    New-SupplementalWDACConfig\n    [-InstalledAppXPackages]\n    -PackageName <String>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description_2","title":"Description","text":"

    Creates a Supplemental policy based on the package name of an installed app. More information at Microsoft Learn

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-packagename","title":"-PackageName","text":"

    Enter the package name of an installed app. Supports wildcard * character. e.g., *Edge* or \"*Microsoft*\".

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname_2","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath_2","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy_2","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with creating the Supplemental policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#the-outputs-of-the-parameter-are_2","title":"The outputs of the parameter are","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-certificates","title":"New-SupplementalWDACConfig -Certificates","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax_3","title":"Syntax","text":"
        New-SupplementalWDACConfig\n    [-Certificates]\n    -CertificatePaths <FileInfo[]>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-SigningScenario <String>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description_3","title":"Description","text":"

    Creates a Supplemental policy based on the certificate paths.

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters_3","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-certificatepaths","title":"-CertificatePaths","text":"

    Browse for the certificate file(s) that you want to use to create the Supplemental policy. Supports file picker GUI by showing only .cer files.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname_3","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath_3","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy_3","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-signingscenario","title":"-SigningScenario","text":"

    You can choose one of the following options: \"UserMode\", \"KernelMode\" The certificate will be added to the policy based on the selected scenario.

    Type: SwitchParameter Position: Named Default value: UserMode Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/","title":"New-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#new-wdacconfig-policytype","title":"New-WDACConfig -PolicyType","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#syntax","title":"Syntax","text":"
    New-WDACConfig\n    [-PolicyType <String>]\n    [-Deploy]\n    [-Audit]\n    [-TestMode]\n    [-RequireEVSigners]\n    [-EnableScriptEnforcement]\n    [-LogSize <UInt64>]\n
    "},{"location":"WDACConfig%20Module/New-WDACConfig/#description","title":"Description","text":"

    Use this parameter to create a new WDAC (Application Control) base policy with different policy types and configurations.

    Note

    If the selected policy type is DefaultWindows and the detected PowerShell is not installed through Microsoft Store, the module will scan the PowerShell files and add them to the DefaultWindows base policy as allowed files so you will be able to continue using the module after deploying the policy.

    Tip

    The SignedAndReputable policy type uses ISG, The Microsoft Intelligent Security Graph.

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#-policytype","title":"-PolicyType","text":"

    There are 3 policy types you can choose from and they are listed below:

    Type: String Position: Named Accepted values: AllowMicrosoft, DefaultWindows, SignedAndReputable Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the policy is to be deployed to the local machine.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-audit","title":"-Audit","text":"

    Turns on Audit mode in the policy so that the policy will be auditing files after deployment instead of blocking them.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-testmode","title":"-TestMode","text":"

    Indicates that the created policy will have Enabled:Boot Audit on Failure and Enabled:Advanced Boot Options Menu policy rule options.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-requireevsigners","title":"-RequireEVSigners","text":"

    Indicates that the created policy will have Require EV Signers policy rule option.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-enablescriptenforcement","title":"-EnableScriptEnforcement","text":"

    Enables script enforcement in the created policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-logsize","title":"-LogSize","text":"

    Note

    This parameter is only available when the -Audit parameter is used.

    Specifies the log size for Microsoft-Windows-CodeIntegrity/Operational events. The values must be in the form of <Digit + Data measurement unit>. e.g., 2MB, 10MB, 1GB, 1TB. The minimum accepted value is 1MB which is the default.

    Type: UInt64 Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#new-wdacconfig-getusermodeblockrules","title":"New-WDACConfig -GetUserModeBlockRules","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#syntax_1","title":"Syntax","text":"
    New-WDACConfig\n    [-GetUserModeBlockRules]\n    [-Deploy]\n
    "},{"location":"WDACConfig%20Module/New-WDACConfig/#description_1","title":"Description","text":"

    Downloads the latest Microsoft Recommended User-Mode Block Rules.

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#-deploy_1","title":"-Deploy","text":"

    Indicates that the policy is to be deployed to the local machine.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#new-wdacconfig-getdriverblockrules","title":"New-WDACConfig -GetDriverBlockRules","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#syntax_2","title":"Syntax","text":"
    New-WDACConfig\n    [-GetDriverBlockRules]\n    [-Deploy]\n    [-AutoUpdate]\n
    "},{"location":"WDACConfig%20Module/New-WDACConfig/#description_2","title":"Description","text":"

    Downloads the latest Microsoft Recommended Drivers Block rules.

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#-deploy_2","title":"-Deploy","text":"

    Indicates that the policy is to be deployed to the local machine.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-autoupdate","title":"-AutoUpdate","text":"

    Creates a scheduled task that runs every 7 days to automatically perform the official method for updating Microsoft recommended driver block rules.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/","title":"Remove-CommonWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#syntax","title":"Syntax","text":"
    Remove-CommonWDACConfig\n    [-CertCN]\n    [-CertPath]\n    [-SignToolPath]\n    [-UnsignedPolicyPath]\n    [-SignedPolicyPath]\n    [-StrictKernelPolicyGUID]\n    [-StrictKernelNoFlightRootsPolicyGUID]\n
    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#description","title":"Description","text":"

    Use this cmdlet to remove the values stored in the User Configurations JSON file. If you use it without any parameters it will delete the User configuration folder and everything in it, which is located in C:\\Users\\UserName\\.WDACConfig

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-certcn","title":"-CertCN","text":"

    Removes the saved Certificate Common Name from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-certpath","title":"-CertPath","text":"

    Removes the saved Certificate path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Removes the saved SignTool.exe Path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-unsignedpolicypath","title":"-UnsignedPolicyPath","text":"

    Removes the saved Unsigned Policy Path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-signedpolicypath","title":"-SignedPolicyPath","text":"

    Removes the saved Signed Policy Path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-strictkernelpolicyguid","title":"-StrictKernelPolicyGUID","text":"

    Removes the saved Strict Kernel Policy GUID from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-strictkernelnoflightrootspolicyguid","title":"-StrictKernelNoFlightRootsPolicyGUID","text":"

    Removes the saved Strict Kernel NoFlight Roots Policy GUID from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/","title":"Remove-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#remove-wdacconfig-signedbase","title":"Remove-WDACConfig -SignedBase","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#syntax","title":"Syntax","text":"
    Remove-WDACConfig\n    [-SignedBase]\n    -PolicyPaths <FileInfo[]>\n    [-CertCN <String>]\n    [-SignToolPath <FileInfo>]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#description","title":"Description","text":"

    Uses the official procedure to Re-Deploy the Signed base WDAC policies with Enabled:Unsigned System Integrity Policy rule option.

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-policypaths","title":"-PolicyPaths","text":"

    Path to xml file(s) of the currently deployed policy that you want to remove. Supports tab completion by showing only .xml files.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-certcn","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN. Make sure the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with redeploying the signed base policy in unsigned mode.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#remove-wdacconfig-unsignedorsupplemental","title":"Remove-WDACConfig -UnsignedOrSupplemental","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#syntax_1","title":"Syntax","text":"
    Remove-WDACConfig\n    [-UnsignedOrSupplemental]\n    [-PolicyNames <String[]>]\n    [-PolicyIDs <String[]>]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#description_1","title":"Description","text":"

    Removes Unsigned deployed WDAC policies as well as Signed deployed Supplemental WDAC policies

    Note

    When using -PolicyNames parameter, if multiple policies with the exact same name are deployed, when you press TAB, you will only see 1 of them, if you select it, all of the policies with that name will be removed. If that's not desired, consider using -PolicyIDs parameter instead.

    Note

    The auto-completion in these 2 parameters are smart. E.g., if there are 10 policies deployed on the system, you can press Tab to select 5 of them by IDs, but when you try to select the other 5 by their names, the name of the policies that you already selected by IDs don't show up anymore. This greatly reduces user error and simplifies the workflow for end user.

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-policyids","title":"-PolicyIDs","text":"

    The submitted values are verified against the currently deployed policies and if they match, the policies are removed.

    Just press TAB key and it will autofill the values for you based on the deployed policies. If you want to select multiple names, after each one, enter a comma , and then press TAB again to choose another name.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-policynames","title":"-PolicyNames","text":"

    The submitted values are verified against the currently deployed policies and if they match, the policies are removed.

    Just press TAB key and it will autofill the values for you based on the deployed policies. If you want to select multiple IDs, after each one, enter a comma , and then press TAB again to choose another ID.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/","title":"Set-CiRuleOptions available parameters","text":""},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#syntax","title":"Syntax","text":"
    Set-CiRuleOptions\n    -FilePath <FileInfo>\n    [-Template <String>]\n    [-RulesToAdd <String[]>]\n    [-RulesToRemove <String[]>]\n    [-RequireWHQL <Boolean>]\n    [-EnableAuditMode <Boolean>]\n    [-DisableFlightSigning <Boolean>]\n    [-RequireEVSigners <Boolean>]\n    [-ScriptEnforcement <Boolean>]\n    [-TestMode <Boolean>]\n    [-RemoveAll]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#description","title":"Description","text":"

    Configures the Policy rule options in a given XML file and sets the HVCI to Strict in the output XML file. It offers many ways to configure the policy rule options in a given XML file.

    All of its various parameters provide the flexibility that ensures only one pass is needed to configure the policy rule options.

    Tip

    First the template is processed, then the individual boolean parameters, and finally the individual rules to add and remove.

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-filepath","title":"-FilePath","text":"

    The path to the XML file that contains the WDAC Policy.

    Type: FileInfo Aliases: MDELogs Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-template","title":"-Template","text":"

    Specifies the template to use for the CI policy rules.

    Type: String Position: Named Accepted values: Base, BaseISG, BaseKernel, Supplemental Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-rulestoadd","title":"-RulesToAdd","text":"

    Specifies the rule options to add to the policy XML file. Supports auto tab-completion so you don't need to type them manually.

    Note

    If a rule option is already selected by the RulesToRemove parameter, it won't be suggested by the argument completer of this parameter.

    Type: String[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-rulestoremove","title":"-RulesToRemove","text":"

    Specifies the rule options to remove from the policy XML file. Supports auto tab-completion so you don't need to type them manually.

    Note

    If a rule option is already selected by the RulesToAdd parameter, it won't be suggested by the argument completer of this parameter.

    Type: String[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-requirewhql","title":"-RequireWHQL","text":"

    Specifies whether to require WHQL signatures for all drivers.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-enableauditmode","title":"-EnableAuditMode","text":"

    Specifies whether to enable audit mode.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-disableflightsigning","title":"-DisableFlightSigning","text":"

    Specifies whether to disable flight signing.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-requireevsigners","title":"-RequireEVSigners","text":"

    Specifies whether to require EV signers.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-scriptenforcement","title":"-ScriptEnforcement","text":"

    Specifies whether to disable script enforcement

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-testmode","title":"-TestMode","text":"

    Specifies whether to enable Enabled:Boot Audit on Failure and Enabled:Advanced Boot Options Menu rule options in the policy XML file.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-removeall","title":"-RemoveAll","text":"

    Removes all the existing rule options from the policy XML file.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/","title":"Set-CommonWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#syntax","title":"Syntax","text":"
    Set-CommonWDACConfig\n    [[-CertCN] <String>]\n    [[-CertPath] <FileInfo>]\n    [[-SignToolPath] <FileInfo>]\n    [[-UnsignedPolicyPath] <FileInfo>]\n    [[-SignedPolicyPath] <FileInfo>]\n    [[-StrictKernelPolicyGUID] <Guid>]\n    [[-StrictKernelNoFlightRootsPolicyGUID] <Guid>]\n    [[-LastUpdateCheck] <DateTime>]\n    [[-StrictKernelModePolicyTimeOfDeployment] <DateTime>]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#description","title":"Description","text":"

    Use this cmdlet to store the values for common and frequently used parameters so that you won't have to specify them again every time.

    All of the applicable cmdlets of the module automatically check the User Configuration file for any available input, if you don't specify values for their parameters. Learn more about the User Configuration file here.

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#an-example","title":"An Example","text":"

    Instead of specifying all of the parameters for Edit-SignedWDACConfig cmdlet like this:

    Edit-SignedWDACConfig -AllowNewApps -SuppPolicyName \"App 1\" -CertPath \"Path To Certificate.cer\" -PolicyPaths \"Path To Policy.xml\" -CertCN \"Certificate Common Name\"\n

    You can just run this

    Edit-SignedWDACConfig -AllowNewApps -SuppPolicyName \"App 1\"\n

    If correct and valid values for the missing parameters exist in User Configuration file, the cmdlet will automatically detect and use them seamlessly.

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-certcn","title":"-CertCN","text":"

    Common Name of an installed certificate. Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-certpath","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-unsignedpolicypath","title":"-UnSignedPolicyPath","text":"

    Path to the xml file of an Unsigned policy. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-signedpolicypath","title":"-SignedPolicyPath","text":"

    Path to the xml file of a Signed policy. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Test-CiPolicy/","title":"Test-CiPolicy available parameters","text":""},{"location":"WDACConfig%20Module/Test-CiPolicy/#syntax","title":"Syntax","text":"
    Test-CiPolicy\n    -XmlFile <FileInfo>\n    -CipFile <FileInfo>\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Test-CiPolicy/#description","title":"Description","text":"

    Tests a Code Integrity (WDAC) Policy XML file against the Schema file located at:

    $Env:SystemDrive\\Windows\\schemas\\CodeIntegrity\\cipolicy.xsd\n

    It returns a boolean value indicating whether the XML file is valid or not.

    It can also be used to display the signer certificates used to sign a .CIP binary file.

    "},{"location":"WDACConfig%20Module/Test-CiPolicy/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Test-CiPolicy/#-xmlfile","title":"-XmlFile","text":"

    The Code Integrity Policy XML file to test. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Test-CiPolicy/#-cipfile","title":"-CipFile","text":"

    The binary Code Integrity Policy file to test for signers. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/WDACConfig/","title":"WDACConfig (Windows Defender Application Control) Module","text":"

    WDACConfig is an advanced PowerShell module designed with the aim of automating Application and File whitelisting in Windows using Windows Defender Application Control (App Control for Business Policies). You can always find its source code on GitHub and Install it from PowerShell Gallery.

    This page is also available on my website.

    "},{"location":"WDACConfig%20Module/WDACConfig/#requirements","title":"Requirements","text":"

    "},{"location":"WDACConfig%20Module/WDACConfig/#features","title":"Features","text":"

    "},{"location":"WDACConfig%20Module/WDACConfig/#install-the-module","title":"Install The Module","text":"
    Install-Module -Name 'WDACConfig' -Scope 'AllUsers' -Force\n
    "},{"location":"WDACConfig%20Module/WDACConfig/#video-guides","title":"Video Guides","text":"Video Link Description Microsoft Defender For Endpoint Advanced Hunting With WDACConfig Module Sandboxing-like capabilities in the WDAC Policies Create, Deploy & Audit WDAC Policies How To Set And Query Secure Settings in WDAC Policies How To Create And Deploy Signed WDAC Policies Create Code Signing Certificate Using Windows Server"},{"location":"WDACConfig%20Module/WDACConfig/#wdacconfig-modules-table-of-content","title":"WDACConfig Module's Table of Content","text":"Cmdlet Guide Usage PowerShell Console Help New-WDACConfig Mainly for creating and deploying WDAC policies Get-Help New-WDACConfig New-SupplementalWDACConfig To create and deploy Supplemental policies Get-Help New-SupplementalWDACConfig Remove-WDACConfig To remove deployed WDAC policies Get-Help Remove-WDACConfig Edit-WDACConfig To edit deployed unsigned WDAC policies Get-Help Edit-WDACConfig Edit-SignedWDACConfig To edit deployed signed WDAC policies Get-Help Edit-SignedWDACConfig Deploy-SignedWDACConfig To sign and deploy WDAC policies Get-Help Deploy-SignedWDACConfig Confirm-WDACConfig To confirm deployment and check the status of WDAC policies Get-Help Confirm-WDACConfig New-DenyWDACConfig To create a deny mode WDAC policy Get-Help New-DenyWDACConfig Set-CommonWDACConfig To add or edit user configurations for common WDACConfig parameters Get-Help Set-CommonWDACConfig New-KernelModeWDACConfig To create a Strict Kernel mode WDAC policy for total BYOVD protection Get-Help New-KernelModeWDACConfig Get-CommonWDACConfig To display or fetch user configurations for common WDACConfig parameters Get-Help Get-CommonWDACConfig Invoke-WDACSimulation To simulate a WDAC policy deployment quickly Get-Help Invoke-WDACSimulation Remove-CommonWDACConfig To remove user configurations for common WDACConfig parameters Get-Help Remove-CommonWDACConfig Assert-WDACConfigIntegrity To ascertain that the files in your local WDACConfig folder are identical to the ones in the cloud Get-Help Assert-WDACConfigIntegrity Build-WDACCertificate To create proper code signing certificates for WDAC policy signing Get-Help Build-WDACCertificate Test-CiPolicy Tests a Code Integrity (WDAC) Policy XML file against the Schema and shows the signers in a signed .CIP files Get-Help Test-CiPolicy Get-CiFileHashes Calculates the Authenticode hash and first page hash of the PEs with SHA1 and SHA256 algorithms Get-Help Get-CiFileHashes ConvertTo-WDACPolicy Multi-Purpose & Powerful functionalities such as converting local and MDE logs to App Control Policies Get-Help ConvertTo-WDACPolicy Set-CiRuleOptions Configures Policy Rule Options in the WDAC policies Get-Help Set-CiRuleOptions Get-CIPolicySetting Queries the Secure Settings among the deployed policies on the system Get-Help Get-CIPolicySetting"},{"location":"WDACConfig%20Module/WDACConfig/#user-configurations-directory","title":"User Configurations Directory","text":"

    The module stores user configurations and all of the outputs only in the following directory:

    C:\\Program Files\\WDACConfig\n

    It's an Admin-protected path that provides security against non-elevated users and processes.

    "},{"location":"WDACConfig%20Module/WDACConfig/#the-temporary-files-are-stored-in-the-following-directory","title":"The Temporary Files Are Stored in the Following Directory","text":"
    C:\\Program Files\\WDACConfig\\StagingArea\n

    Each cmdlet of the module creates a subdirectory in the StagingArea to store its temporary files. The subdirectory is named after the cmdlet's name. At the end of the cmdlet's execution, the temporary subdirectory is deleted, unless the -Debug parameter is used.

    "},{"location":"WDACConfig%20Module/WDACConfig/#about-automatic-parameters","title":"About Automatic Parameters","text":"

    A parameter with an Automatic value of True in the description means that the module will use its default value set by the Set-CommonWDACConfig cmdlet. This simplifies the process and avoids redundancy. However, if an Automatic parameter has no value in User Configurations and you do not specify one in the command line, you will encounter an error requesting a value. Specifying a value for an Automatic parameter in the command line supersedes its default value in User Configurations, so the module will disregard the value of that parameter in the User Configurations file.

    "},{"location":"WDACConfig%20Module/WDACConfig/#the-logic-behind-the-signtoolpath-parameter-in-the-module","title":"The Logic Behind The -SignToolPath Parameter in the Module","text":"
    1. If Windows SDK Signing Tools for Desktop Apps components is installed in the default location C:\\Program Files (x86)\\Windows Kits, then specifying -SignToolPath parameter isn't necessary as the SignTool.exe will be detected automatically.

    2. If Windows SDK Signing Tools for Desktop Apps components is not installed in the default location or you want to manually browse for the signtool.exe, then make sure you either specify its path using Set-CommonWDACConfig -SignToolPath or use the -SignToolPath parameter.

    3. If SignTool.exe path is available in user configurations then it will be automatically used.

    4. Specifying -SignToolPath parameter explicitly on the command line takes priority over auto detection and value in the user configurations.

    5. If SignTool.exe cannot be auto-detected and the user didn't specify it on the command line, you will receive a prompt to authorize the automatic download of the most recent SignTool.exe version from the official Microsoft servers. Upon confirmation, it will be saved in your user configurations and utilized by the cmdlet.

    "},{"location":"WDACConfig%20Module/WDACConfig/#feedback-and-feature-request","title":"Feedback and Feature Request","text":"

    If there are any feedback or feature requests regarding this module, please open a new discussion/issue on GitHub.

    "}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome to SpyNetGirl Blog","text":""},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/","title":"Clean Source principle, Azure and Privileged Access","text":""},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#clean-source-principle","title":"Clean Source principle","text":"

    The clean source principle states that all security dependencies must be as trustworthy as the object being secured. The source of the control and/or trust must have an equal or higher level of trustworthiness and/or security than the destination.

    This article reveals the significance of the clean source principle, common short comings, and how it radically transforms the security architecture paradigm.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#a-case-study-of-using-bitlocker-and-tpm-with-nested-vms-in-azure","title":"A Case Study of Using BitLocker and TPM with Nested VMs in Azure","text":"

    Now that you are generally aware of the Clean Source principle, you might want to try to make an architecture that is resistant to tamper/compromise from upstream systems or identities.

    We will examine a scenario that may appear very secure and advanced but is still susceptible to side channel attacks because of not adhering to the clean source principle. In this hypothetical scenario, the Global Admin account is compromised, and we want to safeguard our data from admin abuse.

    Let us assume that you create an Azure VM, which we will refer to as the \u201cHost VM\u201d. We will also create another virtual machine inside of the Host VM using Hyper-V. We will refer to this new guest VM as the \u201cNested VM\u201d. The nested VM\u2019s operating system volume is encrypted with BitLocker. You configure the Key Protectors to be Startup PIN, TPM and a recovery password. Only you have access to the PIN and recovery password of the BitLocker encrypted drive.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#how-to-use-bitlocker-in-azure","title":"How to Use BitLocker in Azure","text":"

    You can utilize Bitlocker in Azure to encrypt the disks of the virtual machines. The service is called Azure Disk Encryption, and it employs Key Vault to store the key instead of a TPM.

    Key Vaults are extremely economical, and disk encryption does not incur any licensing fees, only Key Vault hosting, which is negligible.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#flaws-of-the-above-mentioned-scenario","title":"Flaws of the Above-Mentioned Scenario","text":"

    None of the protections mentioned in the scenario can defend against a compromised admin which has gotten Host VM admin permissions. They can install Command and Control (C2) software using the Azure VM guest agent.

    Once the host VM is compromised, the C2 software can be used as a key logger to steal the startup PIN and authentication credentials of the Nested VM. After the PIN and/or the credentials are stolen, the threat actor can use \u202fPowerShell Direct\u202f to access the virtual machine through the host's hypervisor if it is already booted, or they can boot the Nested VM themselves using the PIN they skimmed.

    At this point, the nested virtual machine can be booted up, and no brute forcing is needed.

    Another attack path is if they download the Nested VM\u2019s disks, they can offline attack the VM once they gain access to the recovery key or the key that is stored in the vTPM of the Nested VM\u2019s hypervisor which is on the disk of the host VM. All software based KSPs just get decoded at runtime and there are tools to skim the decoded value.

    When the nested VM is running, the system sees the disk as plain text, not encrypted. BitLocker encryption is transparent drive encryption, not encryption in use. (For encryption in use, I recommend something like Microsoft Purview\u202fon the data itself.)

    BitLocker is not easy to brute force if the right algorithms are configured (XTS-AES-256) so they would not want to go that direction in most cases.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#what-if-you-deploy-a-signed-wdac-policy-on-the-host-vm","title":"What if You Deploy a Signed WDAC Policy on the Host VM?","text":"

    You could, but what would prevent the threat actor from disabling it on the host? The host is controlled by the threat actor in this scenario and not having the private keys of the deployed signed policy won't matter.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#so-what-alternative-will-the-threat-actor-pursue","title":"So, What Alternative Will the Threat Actor Pursue?","text":"

    They could simply download the VHDX of the main host (Azure virtual machine), extract the nested VHDX that pertains to the guest operating system, construct a new operating system with your data in it but devoid of security, upload that and await your login. You would remain oblivious to the tampering since the operating system is identical but bereft of security, or the threat actor can even deploy their own signed policy on the new operating system.

    Bear in mind, host compromise entails all security dependencies are also compromised. So, you must presume through some black magic that your guest is compromised. What happens if they alter Hyper-V's binaries to perform custom stuff?

    You can technically insert custom guest firmware. Custom firmware is not officially supported and is usually used by pirates to get ACPI tables altered to activate Windows for free.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#clean-source-and-assume-breach-principle-a-match-made-in-heaven","title":"Clean Source and Assume Breach Principle, a Match Made in Heaven","text":"

    It is not only virtual machines that are mistaken to be secure, but also jump boxes (RDP) and session manager apps (PAM) are insufficiently secure. The problem with RDP and PAMs is session hijacking. You can use keyboard and mouse takeover capabilities to control anything downstream without having to install any malware, because the system that is running the RDP client / session manager app is technically in charge of the secure system.

    The control and/or trust that is being originated from hardware is insecure and propagated downstream through the remote-control apps. So, all insecure states can be transmitted onto the secure systems, and you do not even have to install anything on the remote systems to compromise them.

    Clean source done right will prevent session takeovers, because the system hosting the session will be as secure as the upstream system requires.

    However, on Azure, things are much superior. Azure is a hosting fabric that receives commands from an admin. The admin must be hosted on a secure system, which is where the PAW comes in. Azure fabric itself is more secure than anything you can provide.

    The guest has to abide by the rules of its host, and the host has to conform to the rules of Azure, and Azure adheres to the rules of the admins, so by proxy, the guest complies with the rules of the admins, because the chain of control/trust flows through the host virtual machine. Any type of direct guest guarding is futile.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#so-what-is-the-solution","title":"So, What Is the Solution?","text":"

    What you desire is to create something that can remain protected in most hostile environment and preserve its integrity.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#introducing-privileged-access-workstations-paw","title":"Introducing Privileged Access Workstations (PAW)","text":"

    PAW is the highest security configuration designed for extremely sensitive roles that would have a significant or material impact on the organization if their account was compromised. The PAW configuration includes security controls and policies that restrict local administrative access and productivity tools to minimize the attack surface to only what is absolutely needed for performing sensitive jobs or tasks.

    Often, the servers are considerably less secure than the PAW itself. Likewise with intermediaries, they are usually less secure than the PAW itself. Consequently, the session host and/or client is not the weakest chain link. Which also implies that the clean source principle is kept at least on the start of the chain.

    For more of a do-it-your-self experience, check out my harden windows security repository over at GitHub.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#azure-confidential-compute","title":"Azure Confidential Compute","text":"

    Confidential computing is an industry term defined by the Confidential Computing Consortium (CCC) - a foundation dedicated to defining and accelerating the adoption of confidential computing. The CCC defines confidential computing as: The protection of data in use by performing computations in a hardware-based Trusted Execution Environment (TEE).

    Unlike Guarded hosts, Azure confidential compute VMs use Intel SGX or AMD's Secure Encrypted Virtualization-Secure Nested Paging, or SEV-SNP.

    "},{"location":"Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/#conclusion","title":"Conclusion","text":"

    In this article, we have explored the clean source principle, which states that all security dependencies must be as trustworthy as the object being secured. We have seen how this principle can help us design more secure architectures and avoid common pitfalls that can compromise our data and systems.

    We have also learned about some of the solutions that Microsoft offers to help us achieve clean source, such as Privileged Access Workstations (PAW) and Azure Confidential Compute. These solutions leverage advanced technologies such as Intel SGX and AMD SEV-SNP to protect our sensitive workloads from upstream attacks and side channel threats.

    By following the clean source principle and using these solutions, we can enhance our security posture and reduce our risk exposure in the cloud and beyond.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/","title":"How to Securely Connect to Azure VMs and Use RDP","text":""},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#what-are-azure-vms","title":"What Are Azure VMs","text":"

    Azure Virtual Machines (VMs) run on Microsoft\u2019s cloud computing platform, Azure. They allow users to create, manage, and scale their own virtualized infrastructure in the cloud, without having to invest in physical hardware or deal with maintenance issues.

    To establish a secure connection to your Azure VM, you need to make some preparations. You can avoid exposing your VM\u2019s RDP port to the Internet, which reduces the risk of port scanning and brute force attacks.

    None of the methods described below require you to assign a public IP address or open inbound ports in your Azure VM. They only need a virtual network with a private IP address assigned to the Azure VM.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#bastion","title":"Bastion","text":"

    Azure Bastion uses TLS encryption and firewall traversal for RDP connections, which means your traffic is more secure and less vulnerable to attacks. You also don\u2019t need to manage network security groups (NSGs) for your VM, as you can configure them to allow RDP only from Azure Bastion

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#there-are-many-ways-to-use-bastion-to-connect-to-your-azure-vm","title":"There Are Many Ways to Use Bastion to Connect to Your Azure VM","text":"

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#lets-get-started-with-using-bastion-with-native-client","title":"Let's Get Started With Using Bastion with Native Client","text":"
    1. First get the Bastion ready by Configuring it for native client connections
    Screenshots
    1. Install Azure CLI on your computer. There are many ways to do that but the easiest way is using Winget:
    winget install -e --id Microsoft.AzureCLI\n
    1. Log in to your Azure account, a web page will open.
    az login\n
    1. Gather the following details needed for the next command

      • Bastion name, you can find it by going to your Azure VM and search for \"Bastion\"
      • Azure Resource Group name
      • The VM's Resource ID. The Resource ID can be easily located in the Azure portal. Go to the Overview page for your VM and select the JSON View link to open the Resource JSON. Copy the Resource ID at the top of the page.
    2. Log into RDP, paste this in PowerShell

    az network bastion rdp --name \"<BastionName>\" --resource-group \"<ResourceGroupName>\" --target-resource-id \"<VMResourceId>\"\n

    You now have a secure connection to your Azure VM using Bastion Native Client.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#using-azure-vpn-gui-method","title":"Using Azure VPN - GUI Method","text":"

    Azure VPN Gateway connects your on-premises networks to Azure, or connects Azure virtual networks together, through VPN setups such as Site-to-Site, Point-to-Site etc. The connectivity is secure and uses the industry-standard protocols such as SSTP, IKEv2, OpenVPN etc.

    We need a resource group first because we're going to need a few components: Azure Virtual Network, Azure Public IP address, Azure VPN Gateway. We can either install everything in a separate group or install them in the same resource group as Azure VMs. It will work either way. For this guide, all of the resources reside in the same location, which is UK South.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-resource-group","title":"Create a Resource Group","text":""},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-virtual-network-with-subnets","title":"Create a Virtual Network With Subnets","text":" Screenshots

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-vm-skip-if-you-already-have-one","title":"Create a VM - Skip if You Already Have One","text":"

    Create a VM in Azure and do not allow any open ports from Internet. Do not assign any public IP to the VM.

    In the Virtual Network section, choose the VirtualNetwork1 for the VM and set its Default Subnet accordingly.

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-virtual-network-gateway","title":"Create a Virtual Network Gateway","text":" Screenshot

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#create-a-point-to-site-vpn-connection","title":"Create a Point-To-Site VPN Connection","text":" Screenshot

    You can connect to other VMs (using RDP) on the same subnet using their private IPs from inside a VM.

    When you don't assign a public IP to a VM, it will only have a private IP address; You can verify this from Control Panel inside the OS.

    Screenshots

    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#using-azure-vpn-cloud-powershell-method","title":"Using Azure VPN - Cloud PowerShell Method","text":""},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#run-on-azure-cloud-powershell","title":"Run on Azure Cloud PowerShell","text":"
    # get all of the available location for Azure resources\nGet-AzLocation | Format-Table -Property Location, DisplayName\n\n# Create a new Resource Group\nNew-AzResourceGroup -Name 'ResourceGroup1' -Location uksouth\n\n# Create a new Virtual Network\nNew-AzVirtualNetwork -ResourceGroupName 'ResourceGroup1' -Location 'uksouth' -Name 'VirtualNetwork1' -AddressPrefix '10.0.0.0/14'\n\n# Get the virtual network we created\n$VirtualNetwork1 = Get-AzVirtualNetwork -ResourceGroupName 'ResourceGroup1' -Name 'VirtualNetwork1'\n\n# Add a new subnet to the virtual network named default\nAdd-AzVirtualNetworkSubnetConfig -Name 'Default' -AddressPrefix '10.0.0.0/24' -VirtualNetwork $VirtualNetwork1\n\n# Add the GateWay subnet to the virtual network\nAdd-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -AddressPrefix '10.0.1.0/24' -VirtualNetwork $VirtualNetwork1\n\n# Apply the configurations to the virtual network\n$VirtualNetwork1 | Set-AzVirtualNetwork\n\n# Create a public IP address\nNew-AzPublicIpAddress -Name 'PublicIP1' `\n    -ResourceGroupName 'ResourceGroup1' `\n    -Location 'uksouth' `\n    -AllocationMethod 'Static'\n\n# Get the Public IP address\n$PublicIP1 = Get-AzPublicIpAddress -Name 'PublicIP1' -ResourceGroupName 'ResourceGroup1'\n\n# Get the virtual network\n$VirtualNetwork1 = Get-AzVirtualNetwork -ResourceGroupName 'ResourceGroup1' -Name 'VirtualNetwork1'\n\n# Get the subnet that belongs to Virtual network Gateway from our Virtual Network\n$VN1GatewaySubnet = Get-AzVirtualNetworkSubnetConfig -Name 'GatewaySubnet' -VirtualNetwork $VirtualNetwork1\n\n# Specify the details of the IP Config for the Virtual Network Gateway\n$IpConfigurations1 = New-AzVirtualNetworkGatewayIpConfig -Name 'IpConfigurations1' -Subnet $VN1GatewaySubnet -PublicIpAddress $PublicIP1\n\n# Create the Virtual Network Gateway - This can take a few minutes to complete\nNew-AzVirtualNetworkGateway -Name 'VNGateWay1' `\n    -ResourceGroupName 'ResourceGroup1' `\n    -Location 'uksouth' `\n    -IpConfigurations $IpConfigurations1  `\n    -GatewayType 'Vpn' `\n    -VpnType 'RouteBased' `\n    -GatewaySku 'VpnGw2' `\n    -VpnGatewayGeneration 'Generation2'\n
    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#run-on-your-local-computer","title":"Run on Your Local Computer","text":"
    # Create Root Certificate\n$RootCert = New-SelfSignedCertificate -Type Custom -KeySpec Signature `\n    -Subject 'CN=AzureVirtualGateway1RootCert' -KeyExportPolicy Exportable `\n    -HashAlgorithm sha512 -KeyLength 4096 `\n    -CertStoreLocation 'Cert:\\CurrentUser\\My' -KeyUsageProperty Sign -KeyUsage CertSign `\n    -NotAfter (Get-Date).AddYears(10)\n\n# Create Client Certificate\n$ClientCert = New-SelfSignedCertificate -Type Custom -DnsName 'AzureVirtualGateway' -KeySpec Signature `\n    -Subject 'CN=AzureVirtualGateway1ClientCert' -KeyExportPolicy Exportable `\n    -HashAlgorithm sha512 -KeyLength 4096 `\n    -CertStoreLocation 'Cert:\\CurrentUser\\My' `\n    -Signer $RootCert -TextExtension @('2.5.29.37={text}1.3.6.1.5.5.7.3.2') `\n    -NotAfter (Get-Date).AddYears(10)\n\n# Get the RAW content of the Root certificate for upload to Azure - will be copied to your clipboard\n[System.Convert]::ToBase64String($RootCert.RawData) | clip\n\n# Export the Client certificate with private keys as PFX file\nExport-PfxCertificate -Cert $ClientCert `\n-FilePath \".\\P2SClientCert.pfx\" `\n-Password $(ConvertTo-SecureString -String \"123\" -Force -AsPlainText) -CryptoAlgorithmOption AES256_SHA256 -Force\n
    "},{"location":"Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/#run-on-azure-cloud-powershell_1","title":"Run on Azure Cloud PowerShell","text":"
    $p2srootcert = \"<Root certificate's .cer file's content that is between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----->\"\n\n$RootCertificateAzure = New-AzVpnClientRootCertificate -PublicCertData $p2srootcert -Name 'VPNRootCertificate'\n\n$Gateway = Get-AzVirtualNetworkGateway -ResourceGroupName 'ResourceGroup1' -Name 'VNGateWay1'\n\nSet-AzVirtualNetworkGateway -VirtualNetworkGateway $Gateway `\n    -VpnClientRootCertificate $RootCertificateAzure `\n    -VpnClientAddressPool '20.20.0.0/16' `\n    -VpnAuthenticationType 'Certificate' `\n    -VpnClientProtocol 'SSTP', 'IkeV2'\n\n# Download the VPN client using Azure CLI command\naz network vnet-gateway vpn-client generate --resource-group ResourceGroup1 --name VNGateWay1\n
    \u26a1 Click/Tap here for info about Cmdlets used in the PowerShell commands \u26a1

    "},{"location":"GitHub/Cloning%20Personal%20and%20Enterprise%20Repositories%20Using%20GitHub%20Desktop/","title":"Cloning Personal and Enterprise Repositories Using GitHub Desktop","text":"

    GitHub Desktop enables you to effortlessly clone and manage repositories using a user-friendly graphical interface. GitHub offers various types of repositories, such as personal, Enterprise Cloud and Enterprise Server (Self-Hosted). All of them can either be configured as public or private.

    Cloning a GitHub Enterprise Cloud repository differs from cloning a personal repository. GitHub personal repositories necessitate you to provide the clone URL or simply authenticate with your personal GitHub account credentials.

    GitHub Enterprise Cloud repositories, however, require SSO (Single Sign-On) claim to be added to GitHub Desktop before you can access those repositories. GitHub Desktop runs a loopback token collection server when you sign in.

    If you attempt to sign in without SSO claim, it will be absent from the GitHub Desktop app and you will not be able to clone GitHub Enterprise Cloud repositories.

    At this point, you have to:

    1. Sign out of GitHub Desktop
    2. Go to GitHub.com
    3. Use the \"Single Sign-on\" link at the top to sign in to your Enterprise Cloud
    4. Now go back again to GitHub Desktop -> Options
    5. Use the Sign in button; The browser will be opened and this time when you sign in to GitHub Desktop, the SSO claim to your existing account that grants you access to Enterprise Cloud repositories will be appended as well.

    "},{"location":"GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/","title":"Git GitHub Desktop and Mandatory ASLR","text":"

    Git executables are among few poorly written programs that have problem with Mandatory ASLR (Address Space Layout Randomization) Exploit protection feature. When you turn on Mandatory ASLR in Microsoft Defender (which is off by default), those executables fail to run.

    The same Git executables are bundled with GitHub desktop app. In order to use Git in Visual Studio Code or use GitHub desktop app, we need to exclude Git executables from Mandatory ASLR and let them bypass it. Executables can be excluded from Mandatory ASLR rebootlessly.

    You can use the following PowerShell commands to automatically add all Git executables bundled with GitHub desktop or Git itself, to the exclusion for Mandatory ASLR

    "},{"location":"GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/#for-github-desktop-git-binaries","title":"For GitHub desktop Git binaries","text":"
    Get-ChildItem -Recurse -Path \"C:\\Users\\$env:username\\AppData\\Local\\GitHubDesktop\\*\\resources\\app\\git\\*.exe\" | ForEach-Object -Process { Set-ProcessMitigation -Name $_.Name -Disable ForceRelocateImages }\n
    "},{"location":"GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/#for-git-binaries-installed-using-standalone-installer","title":"For Git binaries installed using standalone installer","text":"
    Get-ChildItem -Recurse -File -Path 'C:\\Program Files\\Git\\*.exe' | ForEach-Object -Process { Set-ProcessMitigation -Name $_.Name -Disable ForceRelocateImages }\n
    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/","title":"Signed and Verified commits with GitHub desktop","text":"

    Web commits, the commits you perform using GitHub website, are automatically verified, but the ones you do from GitHub desktop need to be manually signed.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#signing-using-gpg-key","title":"Signing using GPG key","text":""},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#setting-up-gpg","title":"Setting up GPG","text":"

    Download gpg4win from their official website

    (suggested by GitHub too)

    Begin the installation, choose to only install GnuPG and Kleopatra, don't need any other component.

    After installation, open Kleopatra and create a new GPG key pair by selecting \"New Key Pair\"

    Enter your real name and the email address that is added as one your verified email addresses in your GitHub account settings.

    Select advanced settings and here you can optionally check the box next to \"Authentication\" and also increase the validity period of your GPG key.

    Choosing a passphrase is not mandatory.

    Export the public key by right-clicking on the GPG key and selecting Export. Open the exported file in Notepad or VS code, copy its content and paste it in your GitHub profile's GPG key section so it can be added as a new GPG key to your GitHub account.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#configuring-gitconfig-file","title":"Configuring .gitconfig file","text":"

    Assuming GitHub desktop is installed and logged in on your system, open the .gitconfig file, usually located in User's folder, and add the following items to it.

    Add this section to the end of the file

    [commit]\n  gpgsign = true\n

    And then add this to the [user] section

    signingkey = YourGPGSigningkeyID\n

    Replace YourGPGSigningkeyID with your actual GPG key ID. You can get it from Kleopatra GUI in Key-ID column (enter them without spaces in the .gitconfig file) or you can get it from your GPG keys section in GitHub account settings, Key ID will be visible for you after adding your GPG public key.

    You can set the validity period of your GPG certificate to unlimited, set/change/remove its passphrase and other modifications. You can publish it on the GPG server too so others can look it up and verify it.

    Make sure you backup your secret key using Kleopatra and store it in a safe place, you can import it again on another machine to continue signing your GitHub commits. Public key doesn't need to be backed up as you can regenerate it again by importing the secret GPG key on a different machine.

    Now every time you commit using GitHub desktop, your commits will be signed. If your GPG key has a passphrase, you will be asked to enter it before committing and pushing in GitHub desktop, otherwise signing will happen automatically. Your repository commit history on GitHub website will show verified badge next to them.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#how-to-restore-gpg-for-commit-signing-using-your-current-key-on-a-new-environment","title":"How to restore GPG for commit signing using your current key on a new environment","text":"
    1. Install GitHub desktop and log in with your GitHub account
    2. Configure the .gitconfig file as explained above
    3. install gpg4win as explained above
    4. Open Kleopatra GUI and use the Import button to import your GPG secret key backup to the program. You can also double-click on your GPG secret key backup file and add it to the program that way.
    5. Start committing and pushing changes to your repository using GitHub desktop app, your commits will have a verified badge on GitHub website commit history.
    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#official-resources","title":"Official resources","text":"

    Telling Git about your signing key

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#signing-using-ssh-key","title":"Signing using SSH key","text":""},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#generating-the-key-pair","title":"Generating the key pair","text":"

    Run this command to create a new SSH key pair, using the provided email as a label. It should be one of the emails added to your account as a verified emails.

    ssh-keygen -t ed25519 -C \"spynetgirl@outlook.com\"\n

    Replace spynetgirl@outlook.com with your own email address

    When asked, enter a file name, don't need to specify a file extension (such as .txt). 2 files will be created in User folder. The one with .pub extension contains your public key, the other one contains your private keys. Both of them must be backed up and stored in a safe place.

    Set a passphrase when asked, not mandatory so you can just press enter when asked for a passphrase.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#configuring-ssh-windows-service","title":"Configuring SSH Windows service","text":"
    Set-Service -Name ssh-agent -StartupType Automatic\nSet-Service -Name ssh-agent -Status Running\n

    First make sure you've moved the generated SSH key pair from the default User folder location and stored them somewhere else, can be OneDrive's personal vault, and then run the following command to add the private key of your SSH key pair to the SSH agent.

    ssh-add \"Path/To/SSH/Privatekey\"\n

    If you set a passphrase for your private key from previous steps then you'll be asked to enter it, otherwise you will see the successful message saying \"Identity added\".

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#add-your-ssh-public-key-to-github-account","title":"Add your SSH public key to GitHub account","text":"

    Open the file containing your SSH public key, which has a .pub extension, using a text editor such as Notepad or VS code, copy its content and paste it in your GitHub account settings and save.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#configuring-gitconfig-file_1","title":"Configuring .gitconfig file","text":"

    Add these new sections to the end of your .gitconfig file. It's usually located in User folder C:\\Users\\YourUserName

    [gpg]\n    format = ssh\n[commit]\n    gpgsign = true\n

    and add this to the [user] section to define your SSH public key, it's a direct path to that file.

    signingkey = \"Path/To/SSH/SSHKey.pub\"\n

    You must replace all of the normal backward slashes \\ to forward slash / in your path, otherwise GitHub desktop throws an error.

    Now every time you commit using GitHub desktop, your commits will be signed. If your SSH key has a passphrase, you will be asked to enter it before committing and pushing in GitHub desktop, otherwise signing will happen automatically. Your repository commit history on GitHub website will show verified badge next to them.

    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#how-to-restore-ssh-for-commit-signing-using-your-current-key-on-a-new-environment","title":"How to restore SSH for commit signing using your current key on a new environment","text":"
    1. Install GitHub desktop and log in with your GitHub account
    2. Configure the .gitconfig file as explained above
    3. Turn on the ssh-agent Windows service
    4. Add your SSH private key to ssh-agent using ssh-add \"Path/To/SSH/Privatekey\" command
    5. Start committing and pushing changes to your repository, your commits will have a verified badge on GitHub website commit history.
    "},{"location":"GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/#official-resources_1","title":"Official resources","text":"

    Telling Git about your SSH key

    Key-based authentication in OpenSSH for Windows

    About commit signature verification

    Adding a new SSH key to your GitHub account

    Generating a new SSH key and adding it to the ssh-agent

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/","title":"Harden Windows Security Module","text":"

    It is a PowerShell module that can apply all of the hardening measures described in the readme. It also offers rigorous compliance verification and security assessment. It enables you to evaluate the conformity of your system based on the security standards and recommendations of this repository. The module employs various techniques such as Security Policy, PowerShell cmdlet and Registry keys to conduct the checks.

    It is also useful for security researchers and penetration testers who want to assess their system security posture. The module works with any system locale and language.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#automatic-updates","title":"Automatic Updates","text":"

    The module checks for updates every time you run it and updates itself if there is a new version available, so you don't have to manually do anything.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#how-to-install-and-use","title":"How to Install and Use","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#install-the-harden-windows-security-module-from-powershell-gallery","title":"Install the Harden Windows Security Module from PowerShell Gallery","text":"
    Install-Module -Name 'Harden-Windows-Security-Module' -Force\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#use-the-gui-graphical-user-interface","title":"Use the GUI (Graphical User Interface)","text":"
    Protect-WindowsSecurity -GUI\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#apply-the-hardening-measures-described-in-the-readme","title":"Apply the Hardening measures described in the Readme","text":"
    Protect-WindowsSecurity\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#perform-compliance-check","title":"Perform Compliance Check","text":"
    Confirm-SystemCompliance\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#remove-the-hardening-measures-described-in-the-readme","title":"Remove the Hardening Measures Described in The Readme","text":"
    Unprotect-WindowsSecurity\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#uninstall-the-harden-windows-security-module","title":"Uninstall the Harden Windows Security Module","text":"
    Uninstall-Module -Name 'Harden-Windows-Security-Module' -Force -AllVersions\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#quick-demo","title":"Quick Demo","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#youtube-demo-of-the-modules-gui","title":"YouTube demo of the Module's GUI","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#protect-windowssecurity","title":"Protect-WindowsSecurity","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#syntax","title":"Syntax","text":"
    Protect-WindowsSecurity\n    [-GUI]\n    [-Categories <String[]>]\n    [-Log]\n    [-Offline]\n    [<CommonParameters>]\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#description","title":"Description","text":"

    The Protect-WindowsSecurity cmdlet's hybrid design allows it to operate as a standalone script and as a module component. It allows it to operate with and without administrator privileges. You can use this cmdlet in both interactive and non-interactive modes.

    In Interactive mode, the cmdlet will ask you to confirm the changes before applying them. In non-interactive mode, you can pre-configure the hardening categories you want to apply and the cmdlet will apply them without asking for confirmation.

    It possesses the ability to operate entirely in isolation, useful for systems or servers that are disconnected from the Internet.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#parameters","title":"Parameters","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-gui","title":"-GUI","text":"

    Shows a graphical user interface (GUI) that allows you to select the hardening categories you want to apply.

    Tip

    In the GUI experience:

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-categories","title":"-Categories","text":"

    Specify the hardening categories that you want to apply. This will tell the module to operate in non-interactive or headless/silent mode which won't ask for confirmation before running each selected categories.

    You can specify multiple categories by separating them with a comma. If you don't specify any category, the cmdlet will run in interactive mode. Use this parameter for deployments at a large scale.

    If a selected category requires Administrator privileges and the module is running with Standard privileges, that category is skipped.

    This parameter has automatic tab completion. You can press the Tab key to see the available categories.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-verbose","title":"-Verbose","text":"

    Shows verbose messages on the console about what the cmdlet is doing.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-log","title":"-Log","text":"

    Activates comprehensive logging by recording all the information shown on the screen and some additional data to a text file. It is strongly advised to use the -Verbose parameter when you want to enable logging.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-logpath","title":"-LogPath","text":"

    The path to save the log file to. If not specified, the log file will be saved in the current working directory.

    Note

    Only available if the -Log switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-offline","title":"-Offline","text":"

    Indicates that the module is being run in offline mode. Will not download any files from the internet. Will not check for updates. Using this parameter will make the following 3 parameters available and mandatory: PathToLGPO, PathToMSFTSecurityBaselines and PathToMSFT365AppsSecurityBaselines.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-pathtolgpo","title":"-PathToLGPO","text":"

    The path to the 'LGPO.zip'. Make sure it's in the zip format just like it's downloaded from the Microsoft servers. File name can be anything. The parameter has argument completer so you can press tab and use the file picker GUI to select the zip file.

    Note

    Only available if the -Offline switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-pathtomsftsecuritybaselines","title":"-PathToMSFTSecurityBaselines","text":"

    The path to the 'Windows Security Baseline.zip'. Make sure it's in the zip format just like it's downloaded from the Microsoft servers. File name can be anything. The parameter has argument completer so you can press tab and use the file picker GUI to select the zip file.

    Note

    Only available if the -Offline switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-pathtomsft365appssecuritybaselines","title":"-PathToMSFT365AppsSecurityBaselines","text":"

    The path to the 'Microsoft 365 Apps for Enterprise zip'. Make sure it's in the zip format just like it's downloaded from the Microsoft servers. File name can be anything. The parameter has argument completer so you can press tab and use the file picker GUI to select the zip file.

    Note

    Only available if the -Offline switch is used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    Note

    You can further control the sub-categories of each category by using the following switch parameters. Pay attention to the naming convention of them. They are named after the category they belong to. For example, the switch parameter -MSFTDefender_SAC belongs to the MicrosoftDefender category. The switch parameters are dynamic and will only appear if you specify the corresponding category in the -Categories parameter. For example, if you don't specify the MicrosoftDefender category in the -Categories parameter, the switch parameters related to it won't appear. The following table shows the available switch parameters and their corresponding categories.

    Parameter Name Description Required Category -SecBaselines_NoOverrides Applies the Microsoft Security Baselines without the optional overrides MicrosoftSecurityBaselines -MSFTDefender_SAC Enables Smart App Control MicrosoftDefender -MSFTDefender_NoDiagData Will not enable optional diagnostics data required for Smart App Control (Does not have any effect if Smart App Control is already turned on) MicrosoftDefender -MSFTDefender_NoScheduledTask Will not create scheduled task for fast MSFT driver block rules MicrosoftDefender -MSFTDefender_BetaChannels Set Defender Engine and Intelligence update channels to beta MicrosoftDefender -LockScreen_CtrlAltDel Require CTRL + ALT + Delete at lock screen LockScreen -LockScreen_NoLastSignedIn Will not display the last signed in user at the lock screen LockScreen -UAC_NoFastSwitching Hide entry points for fast user switching UserAccountControl -UAC_OnlyElevateSigned Only elevate signed and validated executables UserAccountControl -CountryIPBlocking_OFAC Include the IP ranges of OFAC Sanctioned Countries in the firewall block rules CountryIPBlocking

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#what-if-you-dont-configure-the-sub-categories","title":"What if You Don\u2019t Configure the Sub-Categories?","text":"

    If you do not specify any sub-categories using the switch parameters above, the following sub-category configuration will be applied when the corresponding category exists in the -Categories parameter.

    Indicator Sub-Category Status Is Applied Is Not Applied

    Important

    It is highly recommended to always include the Microsoft Security Baselines category and place it first as it forms the foundation of all subsequent categories.

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#examples","title":"Examples","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-1","title":"Example 1","text":"

    If you run the module like this without specifying any categories, the module will run in interactive mode and the usual beautiful prompts will be displayed to the user.

    Protect-WindowsSecurity\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-2","title":"Example 2","text":"

    If you run the module like this, the 2 categories will be executed automatically without requiring any user input. The results will be displayed on the console.

    Protect-WindowsSecurity -Categories MicrosoftDefender, AttackSurfaceReductionRules\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-3","title":"Example 3","text":"

    This example will apply the Microsoft Defender category with the Smart App Control sub-category, without the need for user interaction, and will show verbose messages.

    Protect-WindowsSecurity -Categories MicrosoftDefender -MSFTDefender_SAC -Verbose\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-4","title":"Example 4","text":"

    This example will apply the Microsoft Security Baselines, BitLocker, User Account Control, Lock Screen and Downloads Defense Measures categories. It will also apply the \"Only Elevate Signed and Validated Executables\" sub-category of the User Account Control category, and the \"Require CTRL + ALT + DEL on Lock Screen\" sub-category of the Lock Screen category.

    Protect-WindowsSecurity -Categories MicrosoftSecurityBaselines,BitLockerSettings,UserAccountControl,LockScreen,DownloadsDefenseMeasures -UAC_OnlyElevateSigned -LockScreen_CtrlAltDel\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-5","title":"Example 5","text":"

    This example instructs the cmdlet to run in offline mode and will not download any files from the internet. It also runs it in headless/silent mode by specifying which categories to automatically run. -MSFTDefender_SAC switch is used so the Smart App Control sub-category is also applied in the headless/silent mode. -Log switch is mentioned which will save the output of the cmdlet to a text file in the current working directory.

    Protect-WindowsSecurity -Verbose -Offline -PathToLGPO 'C:\\Users\\Admin\\Desktop\\LGPO.zip' -PathToMSFTSecurityBaselines 'C:\\Users\\Admin\\Desktop\\Baselines.zip' -PathToMSFT365AppsSecurityBaselines 'C:\\Users\\Admin\\Desktop\\M365Baselines.zip' -Log -Categories MicrosoftSecurityBaselines,MicrosoftDefender -MSFTDefender_SAC\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#example-6","title":"Example 6","text":"

    This will display a GUI (Graphical UI) allowing you to easily select various options and categories to apply.

    Protect-WindowsSecurity -GUI\n

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#confirm-systemcompliance","title":"Confirm-SystemCompliance","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#syntax_1","title":"Syntax","text":"
    Confirm-SystemCompliance\n    [-Categories]\n    [-ExportToCSV]\n    [-ShowAsObjectsOnly]\n    [-DetailedDisplay]\n    [-Offline]\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#description_1","title":"Description","text":"

    This cmdlet verifies and validates all of the applied security measures. It checks registry keys if the module uses Group Policy or registry, PowerShell cmdlets if the module invokes them and Security Group Policy if the module applies them.

    Compliance checking strictly follows the guidelines and security measures of this GitHub repository. Any minor deviation from them will result in a false value for the corresponding check.

    Note

    Based on the score that you get you will see a different ASCII art!

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#parameters_1","title":"Parameters","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-categories_1","title":"-Categories","text":"

    Specify the categories to check compliance for. If not specified, all categories will be checked.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-exporttocsv","title":"-ExportToCSV","text":"

    In addition to displaying the results on the screen, also exports them in a nicely formatted CSV for easier viewing. The CSV is fully compatible with GitHub too so you can upload it to GitHub and view it.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-showasobjectsonly","title":"-ShowAsObjectsOnly","text":"

    Instead of displaying strings on the console, outputs actionable objects and properties. You can use this parameter for when you need to store the output of the function in a variable and use it that way. This provides a very detailed nested object and suppresses the normal string output on the console.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-detaileddisplay","title":"-DetailedDisplay","text":"

    Shows the output on the PowerShell console with more details and in the list format instead of table format

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-offline_1","title":"-Offline","text":"

    Skips the online update check and allows you to run the cmdlet in completely offline mode.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#unprotect-windowssecurity-cmdlet","title":"Unprotect-WindowsSecurity Cmdlet","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#syntax_2","title":"Syntax","text":"
    Unprotect-WindowsSecurity\n    [-OnlyProcessMitigations]\n    [-OnlyDownloadsDefenseMeasures]\n    [-OnlyCountryIPBlockingFirewallRules]\n    [-Force]\n
    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#description_2","title":"Description","text":"

    You can use this cmdlet to remove all of the applied hardening measures, with the following exceptions:

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#parameters_2","title":"Parameters","text":""},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-onlyprocessmitigations","title":"-OnlyProcessMitigations","text":"

    Indicates that the cmdlet will only remove Process Mitigations (Exploit Protection) settings and doesn't change anything else.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-onlydownloadsdefensemeasures","title":"-OnlyDownloadsDefenseMeasures","text":"

    Indicates that the cmdlet will only remove the Downloads Defense Measures WDAC policy from the system and doesn't change anything else.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"Harden-Windows-Security-Module/Harden-Windows-Security-Module/#-onlycountryipblockingfirewallrules","title":"-OnlyCountryIPBlockingFirewallRules","text":"

    Indicates that the cmdlet will only remove the country IP blocking firewall rules and doesn't change anything else.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    Any feedback or suggestions? Please use GitHub issues or discussions

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/","title":"About TLS, DNS, Encryption and OPSEC concepts","text":"

    The contents here are for beginners, to learn the basics of TLS, encrypted connections and some preliminary OPSEC (Operational security) concepts.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns","title":"DNS","text":"

    Let's talk about DNS first. Whether you are using Secure DNS such as DNS over HTTPS or using plain text DNS (Default port: 53), the domain name is the only piece of information that the DNS server provider will see. DNS does not deal with URLs, only domain names.

    E.g., in this URL, anything after the first / is inaccessible to the DNS server.

    Github.com/HotCakeX/Harden-Windows-Security\n

    The DNS provider will know that you are accessing GitHub.com but won't know which repository on GitHub.com you are visiting.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#about-dns-leak-in-plain-text-dns","title":"About DNS Leak in plain text DNS","text":"

    When you are using VPN or proxies, it's important to make sure there is no DNS leakage. Properly implemented and configured VPNs/Proxies don't have this problem.

    The most practical way to see if you have DNS leak while using a VPN/Proxy is to use Wireshark to monitor your outbound connections on the edge of your network. Simply type dns in the Wireshark's display filter bar and observe the results. If you are using a proper VPN/Proxy or if you are using Secure DNS such as DoH or DoT, then you shouldn't see any results because that keyword only displays plain text DNS over the default port 53.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns-security","title":"DNS Security","text":"

    DNSSEC by itself without using DoH/DoT can be downgraded. If you're using DoH or DoT you must be safe as long as you are using a trusted DNS provider and your certificate authority storage is not poisoned/compromised.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#certificates-and-tls","title":"Certificates and TLS","text":"

    Certain countries with dictatorship or theocracy governments make people install their own root certificate to perform TLS-termination and view their data in plain-text even when HTTPS is being used. One example is what happened in Kazakhstan.

    Certain applications install root certificates, such as 3rd party antiviruses. They are all equally dangerous and must be avoided.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns-privacy","title":"DNS Privacy","text":"

    Using DNS-over-TLS or DNS-over-HTTPS mitigates some privacy leaks, because now the ISP won't have the domain you are visiting, but only the IP address. It's possible that more than one site uses the same IP address, so in some cases, it's not possible to say for sure that you are visiting SiteA.com when SiteB.com shares the same IP (Unless you are using TLS v1.2 which leaks Certificate's common name, more on that later), and high-traffic sites usually employ a CDN (content delivery network) to distribute traffic, and the IP they use are not the site's IP, but an IP belonging to the CDN (like CloudFlare or Akamai).

    Website owners use CDNs like Cloudflare for two purposes:

    1. Best user response time by using the nearest server.

    2. Load-balancing in case of the nearest server being overloaded (DDoS and more) and then pointing to the next-nearest server.

    Browsers such as Microsoft Edge only support DNS over HTTPS. Windows supports DNS over HTTPS and DNS over TLS.

    DNS over HTTPS is preferred because by default it uses the same port 443 as the rest of the HTTPS traffic on the Internet, that makes it harder to be detected and blocked. DNS over TLS on the other hand uses TCP port 853 by default and a filter on that port would block DNS over TLS entirely, whereas blocking port 443 is impractical as it essentially cripples the entire Internet.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns-caching","title":"DNS Caching","text":"

    DNS caches, just like DNS itself, only map domain names to values ('A' records), never the other way around.

    Both the DNS cache, and the DNS system as a whole, only care that bing.com points to 1.2.3.4, not that the address \"points\" back.

    Entries in the DNS cache look exactly like entries in authoritative DNS servers, with domain name as the lookup key.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#tls-security-in-windows","title":"TLS Security in Windows","text":"

    Windows components (Tested on Windows 11 22H2) rely on TLS 1.2, and that makes them dependent on ECC Curves. So, when enforcing TLS 1.3 only for Schannel, Windows components stop working.

    TLS 1.3 cipher suites don't require ECC curves.

    NistP256 ECC curve is a must have, otherwise Windows update won't work.

    nistP521 is the best ECC curve in terms of security, but curve25519 is also the best non-Nist one, which is also secure and popular.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#certificates","title":"Certificates","text":"

    Handshake messages contain the certificates (both from server and client), and they are encrypted in TLS 1.3, which means that you cannot see these without breaking the encryption.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#sni","title":"SNI","text":"

    SNI, which is part of the handshake, is still unencrypted even in TLS v1.3. The only way to encrypt SNI is to use ECH (Encrypted Client Hello).

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#opsec","title":"OPSEC","text":"

    Assuming you are operating in a hostile country (E.g, China, Russia, Iran), you must be aware of the following information to keep your digital footprint minimal.

    There are 4 pieces of information that can reveal which websites/apps/services you use, to the ISP/government.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#dns_1","title":"DNS","text":"

    Avoid using plain text DNS as much as you can. Use DNS over HTTPS for security and anonymity. Governments can block well-known servers quickly, you can however self-host on a private cloud or use a serverless DNS to have access to a new endpoint for DoH over a newly setup domain.

    If plain text DNS over port 53 is used, and you are not using a proper VPN like OpenVPN or WireGuard, or you are using proxy, then eavesdropper can see the website domain/sub-domain you are visiting. If you use secure DNS like DNS over HTTPS, then DNS becomes fully encrypted and all they can see is the domain name of the Secure DNS server as well as the IP addresses of the websites you connect to.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#certificate-common-name-etc","title":"Certificate (common name etc.)","text":"

    Use TLS v1.3. When using TLS v1.3, the certificate part of the HTTPS connection is encrypted and none of its details are visible to the eavesdropper. TLS v1.2 handshakes do not encrypt the certificates, resulting in the common name and the website you are visiting to be revealed to the eavesdropper.

    Read more

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#url","title":"URL","text":"

    The full path to a web page or web resource is sent over HTTP protocol, so if website uses HTTPS, it's all encrypted.

    When using\u202fHTTPS, the path and query string (everything after TLD and slash /) is encrypted and not available to anybody but the client and server, the answer is encrypted as well.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#sni-server-name-indication-or-client-hello","title":"SNI (Server Name Indication or Client Hello)","text":"

    This is the most important part. Even after using:

    1. HTTPS to encrypt the full URL path

    2. DoH to encrypt the DNS

    3. TLS v1.3 to encrypt the certificate

    If you don't use a proper VPN, SNI can still reveal the domain and sub-domain of the website you are visiting to the eavesdropper. To secure that, the browser and the website must support ECH (Encrypted Client Hello) or use proper VPN like OpenVPN or WireGuard.

    "},{"location":"Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/#wireshark","title":"Wireshark","text":"

    Interesting and useful columns to add to the Wireshark GUI for better visibility into your network connections:

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/","title":"BitLocker, TPM and Pluton","text":""},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#introduction","title":"Introduction","text":"

    The optimal kind of security measure is imperceptible to the user during deployment and usage. Whenever there is a potential delay or difficulty due to a security feature, there is a high probability that users will attempt to circumvent security. This situation is particularly prevalent for data protection, and that is a scenario that organizations need to prevent. Whether intending to encrypt entire volumes, removable devices, or individual files, Windows satisfies these requirements by providing streamlined, usable solutions. BitLocker Device Encryption safeguards the system by seamlessly implementing device-wide data encryption.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#bitlocker-and-virtual-hard-disks-such-as-vhdx","title":"BitLocker and Virtual Hard Disks such as VHDX","text":"

    When using VHDX native boot, you can employ BitLocker to encrypt the drives that reside in it, they will be equally secure. In the native VHDX boot scenario, the decryption keys are still retained in the TPM, precluding an offline attack against the stored data. BitLocker still operates the same as it does on a normal installed system.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#a-discourse-on-the-modes-and-methods-of-protection-from-physical-intrusions","title":"A Discourse on the Modes and Methods of Protection from Physical Intrusions","text":""},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#bitlocker-with-tpm","title":"BitLocker With TPM","text":"

    BitLocker with TPM only, uses PCRs, if the hashes are the same the decryption key is released. With TPM only mode, a threat actor can access the secret data when it is released and can obtain the decryption key when the TPM releases it automatically.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#bitlocker-with-tpm-and-startup-key","title":"BitLocker With TPM and Startup Key","text":"

    With a Startup PIN, a PIN is required before the secret material is released. This thwarts a jumper cable attack where a threat actor can directly access the secret material from the TPM. Therefore, the only security benefit a PIN would provide during the boot sequence is a physical attack prevention.

    If you are a threat actor and the system lacks a Startup PIN, the disk remains encrypted even when you boot it to the logon screen where authentication is required via Windows Hello credential providers. Conversely, when you use a Startup PIN and enter it correctly, the disk stays encrypted until you authenticate at the logon screen.

    When BitLocker is activated, the disk is constantly encrypted. It is irrelevant whether you utilize a Startup PIN, or you operate in TPM only mode or you employ a smart card to unlock it. However, a Startup PIN is invariably recommended as a deterrent mechanism against physical attacks.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#the-power-of-bitlocker-and-tpm-against-offline-and-side-channel-attacks","title":"The Power of BitLocker and TPM Against Offline and Side Channel Attacks","text":"

    Now there is the in-band versus out of band security system paradigm we need to discuss. For instance, Windows login screen is in-band and TPM is out of band.

    The TPM is used to deter side channel attacks while login screen is to deter brute force/cryptographic attacks. Windows Hello, which is a very robust system, is TPM backed just like BitLocker.

    BitLocker is to prevent offline attacks primarily, secondarily it is to prevent data loss. If you can alter the Windows operating system files while it is offline, it has no means to protect itself. That is why BitLocker exists to impede tampering while the system is offline. Most people assume it is used for data loss prevention; in reality the primary defense capability is tampering with OS files.

    I can guarantee breach into any operating system that has an unencrypted disk, and I don\u2019t have to use any zero days or exploit code.

    BitLocker is a transparent drive encryption technology operating below the file system level and BitLocker encrypted disks always remain encrypted even after Windows Hello authentication and unlocking the OS.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#how-do-the-bitlocker-key-protectors-work","title":"How Do The BitLocker Key Protectors Work?","text":"

    BitLocker key protectors safeguard the encryption key, which encrypts and decrypts the data on the disk. BitLocker provides various key protectors and allows using multiple key protectors simultaneously. However, some key protectors must be combined with other key protectors to attain the required level of security.

    Suppose you want your BitLocker encrypted drive to demand a PIN at Startup, need TPM for verification, and also necessitate a USB flash drive to be plugged in. In this document, you can see there is a -StartupKeyProtector option for the USB flash drive, -TPMProtector option for TPM, and a -Pin option for the PIN.

    Using those parameters individually will not mandate all 3 key protectors to be used concurrently. It will only oblige one of them to be used. So you will have to either enter the PIN, have the disk connected to the same computer (TPM) or have the USB flash drive plugged in, but all 3 of them are not enforced.

    If you want to enforce a multifactor authentication, you need to use the following command

    Add-BitLockerKeyProtector -MountPoint C: -TpmAndPinAndStartupKeyProtector\n

    This time, all 3 key protectors are essential to unlock the drive. You will have to enter the PIN, have the disk connected to the same computer (TPM), and have the USB flash drive plugged in.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#pluton-the-ultimate-security-chip","title":"Pluton, The Ultimate Security Chip","text":"

    One of the most formidable technologies that is impervious to tampering, jumper cable or other vulnerabilities is the Pluton chip. The same technology that has been employed in Xbox to stop even the most sophisticated physical attacks.

    Pluton is a dedicated physical chip that runs on Azure sphere architecture. It is very much out of band and is technically physically on the same die as the CPU, but the CPU has no control over it at all because it has its own dedicated self-maintaining operating system.

    A firmware based TPM is reliant on the CPU to emulate it, Pluton is not dependent on the CPU to emulate it or run it. Pluton is completely self-sufficient which implies that it is out of band. dTPM (discrete TPMs) are usually more susceptible than fTPMs (Firmware based TPMs).

    Pluton addresses security needs like booting an operating system securely even against firmware threats and storing sensitive data safely even against physical attacks.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#conclusion","title":"Conclusion","text":"

    We learned how important it is to use BitLocker and protect our data at rest. The Harden Windows Security repository employs BitLocker to encrypt the operation system drive and optionally any other drives that user chooses to. It utilizes the most secure configuration and military grade encryption algorithm, XTS-AES-256, TPM 2.0 and Start-up PIN.

    "},{"location":"Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/#continue-reading","title":"Continue Reading","text":""},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/","title":"Comparison of security benchmarks","text":"

    I conducted a thorough analysis of some of the prominent security benchmarks/guidelines for my GitHub repository and I discovered some fascinating insights. By analysis, I mean that I examined every single recommendation in them and compared them with my own suggestions and Microsoft Security Baselines.

    The majority of the recommendations in the security benchmarks align with the Microsoft Security Baselines, which are a set of best practices for securing various products and services. Only a small fraction of the recommendations deviate from the baselines, and they are either additional enhancements (rarely), redundant suggestions or erroneous advice that undermine security!

    For my reviews I used the latest available version of each benchmark.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#some-of-the-pitfalls-of-relying-on-third-party-benchmarks","title":"Some of the Pitfalls of Relying on Third-Party Benchmarks","text":""},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#clipboard-sharing-from-guest-to-host","title":"Clipboard sharing from guest to host !","text":"

    CIS 18.10.44.5 (L1) recommends allowing clipboard operation from an isolated session to the host, i.e. guest to host redirection, which is a highly insecure and irrational suggestion!

    These are their precise official words:

    Rationale: The primary purpose of Microsoft Defender Application Guard is to present a \"sandboxed container\" for visiting untrusted websites. If the host clipboard is made available to Microsoft Defender Application Guard, a compromised Microsoft Defender Application Guard session will have access to its content, potentially exposing sensitive information to a malicious website or application. However, the risk is reduced if the Microsoft Defender Application Guard clipboard is made accessible to the host, and indeed that functionality may often be necessary from an operational standpoint

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#renaming-built-in-administrator-and-guest-accounts","title":"Renaming built-in administrator and guest accounts !","text":"

    Both CIS and STIG suggest altering the name of the built-in administrator and guest accounts as a security measure.

    This is futile as those built-in accounts can be readily identified by PowerShell, regardless of any modifications to its name or description (which I have done).

    For example, the BUILTIN\\Administrator account always has a relative identifier (RID) of 500.

    Get-LocalUser | Where-Object -FilterScript {$_.SID -like 'S-1-5-*-500'}\n

    Thanks Elliot Huffman for suggesting the shorter command!

    Add-Type -AssemblyName System.DirectoryServices.AccountManagement\n$principalContext = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)\n$userPrincipal = New-Object System.DirectoryServices.AccountManagement.UserPrincipal($principalContext)\n$searcher = New-Object System.DirectoryServices.AccountManagement.PrincipalSearcher\n$searcher.QueryFilter = $userPrincipal\n$searcher.FindAll() | Where-Object { $_.Sid -Like \"*-500\" } | Select-Object SamAccountName</details>\n

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#disabling-windows-hello-pin-and-using-traditional-passwords-instead","title":"Disabling Windows Hello PIN and using traditional passwords instead !","text":"

    These benchmarks recommend disabling Windows Hello PIN and opting for passwords instead. Stig V-253423 and CIS 18.9.27.4.

    They argue that this is for domain accounts

    Their rationale, which is very wrong, is

    A PIN is created from a much smaller selection of characters than a password, so in most cases a PIN will be much less robust than a password.

    It is a grave security lapse to propose such a policy and then label the benchmark/guideline as \u201cCIS Microsoft Windows 11 Stand-alone Benchmark\u201d, highlighting that it is intended for stand-alone computers, while simultaneously suggesting to disable PIN for domain-joined devices. This is a glaring inconsistency and a perilous practice.

    The guideline/benchmark is fundamentally flawed if it presupposes that the computer is domain-joined, despite the label indicating that it is stand-alone. It also neglects to consider that some users may actually be stand-alone (home users that account for the majority of the users) or use Microsoft Entra ID, and this policy is nonsensical for them.

    STIG commits the same error, as it only provides a generic Windows 11 guideline/benchmark and recommends disabling Windows Hello PIN, without taking into account the factors mentioned above.

    You can read this Microsoft document to find out why a PIN is better than an online password

    There are proper policies regarding anti-hammering features that can enhance the security of PINs over passwords. I utilize them in my module and you can find them here.

    The benchmarks/guidelines seem to be uninformed of the fact that Windows allows multi-factor unlock, which can enforce a combination of PIN and biometric factors (plus more), to enforce PIN + Facial recognition OR PIN + Fingerprint etc.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#bad-configuration-for-early-launch-anti-malware","title":"Bad configuration for Early Launch Anti Malware","text":"

    CIS in 18.9.13.1

    The recommended state for this setting is: Enabled: Good, unknown and bad but critical

    That's not even a recommendation, that's the default value! If you use Harden Windows Security module it sets it to Good Only, which is the correct recommendation for a secure environment.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#disabling-windows-error-reporting","title":"Disabling Windows Error reporting !","text":"

    Their rationale is:

    ...There is no benefit to the corporation to report these errors directly to Microsoft...

    Indeed, the corporation that uses the software benefits from it by reporting the problems. This exact way of thinking that leads to making such a policy is the reason why problems remain unsolved, because they are not reported to Microsoft and the IT staff of the companies are simply unable to resolve the problem themselves, since they are not the ones developing the OS.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#disabling-cloud-protection","title":"Disabling Cloud Protection!","text":"

    CIS 18.10.43.5.2 (L2), suggests disabling Cloud Protection of Microsoft Defender. This is precisely the kind of security measure that Threat Actors and advanced persistent threats (APTs) seek to disable and then CIS is suggesting to disable it, astonishing.

    This is an extremely important security feature that should never be disabled and there is no rationale that justifies disabling it. This feature also uses the Intelligent Security Graph (ISG).

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#not-enabling-important-attack-surface-reduction-rules","title":"Not enabling important Attack Surface Reduction rules","text":"

    CIS in 18.10.43.6.1.2 (L1) intentionally leaves out very important ASR rules

    1. Use advanced protection against ransomware
    2. Block executable files from running unless they meet a prevalence, age, or trusted list criterion
    3. Block process creations originating from PSExec and WMI commands

    Rule #2 has the potential to prevent zero-days!

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#to-be-continued","title":"To be continued...","text":"

    These benchmarks or guidelines have numerous flaws and I have only examined two of them. There are many other benchmarks, standards, guidelines, etc. that may also contain errors or inconsistencies and are totally unsafe to implement them.

    "},{"location":"Miscellaneous/Comparison%20of%20Security%20Benchmarks/#aspects-that-are-lacking","title":"Aspects that are lacking","text":"

    The benchmarks omit many new security features that the Harden Windows Security module implements.

    Everything in the repository is carefully researched, evaluated and tested. The module ensures that nothing is redundant or incompatible with the latest version of Windows. Older versions of the OS are obsolete and insecure, and should be avoided in any environment that requires protection. Threat actors can exploit vulnerabilities and use PoCs even on the same day that an update is released, this applies to any OS.

    The security measures in the Harden Windows Security repository are also perfectly suitable for regular home users.

    There are many security measures that are missing from the benchmarks/guidelines, such as the ones I use in:

    The benchmarks/guidelines suggest using application control or whitelisting, but that's just it, a suggestion, no comprehensive guide about how to do it.

    "},{"location":"Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/","title":"Create Bootable flash drive no 3rd party tools","text":""},{"location":"Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/#create-bootable-usb-flash-drive-with-no-3rd-party-tools","title":"Create Bootable USB flash drive with no 3rd party tools","text":""},{"location":"Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/#steps-to-create-bootable-usb-flash-drive-with-no-3rd-party-tools","title":"Steps to create Bootable USB flash drive with no 3rd party tools","text":"
    1. Plug in a USB flash drive that has at least 8GB capacity.

    2. Delete all partitions on the USB flash drive either using Disk Management \u00b9 \u00b2 or using Windows Settings => System => Storage => Advanced Storage Settings => Disks & Volumes

    3. Using either of the methods above, create a 1GB FAT32 partition, let's name it BOOT\ud83d\udfe8

    4. Create a 2nd partition on the USB flash drive with the rest of the remaining unused space, formatted as NTFS, let's name this one DATA\ud83d\udfe9

    5. Mount your Windows ISO file by double clicking on it.

    6. Select all and Copy everything from Windows ISO file to the NTFS partition (DATA partition\ud83d\udfe9)

    7. Copy everything from Windows ISO file, except for the \"sources\" folder, to the FAT32 partition (BOOT partition\ud83d\udfe8)

    8. Create a new folder in the FAT32 partition (BOOT partition\ud83d\udfe8), and name it sources

    9. copy the boot.wim from the \"sources\" folder inside the Windows ISO file to the newly created \"sources\" folder in the FAT32 partition (BOOT partition\ud83d\udfe8).

    10. That's it, your USB flash drive is ready and bootable.

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/","title":"Device Guards","text":""},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-guards","title":"Device Guards","text":""},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-guard","title":"Device Guard","text":"

    Most of the Device Guard and Virtualization-Based Security features are Automatically enabled by default on capable and modern hardware. The rest of them will be enabled and configured to the most secure state after you apply the Microsoft Security Baselines 23H2 or later.

    The Harden Windows Security Module has a feature that is accessible through confirm-SystemCompliance cmdlet. It will let you scan your system and verify the implementations of the Device Guard policies.

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#about-uefi-lock","title":"About UEFI Lock","text":"

    UEFI locked security measures are rooted in Proof of Physical Presence and they can't be disabled by modifying Group Policy, registry keys or other Administrative tasks.

    The only way to disable UEFI locked security measures is to have physical access to the computer, reboot and access the UEFI settings, supply the credentials to access the UEFI, turn off Secure Boot, reboot the system and then you will be able to disable those security measures with Administrator privileges.

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-guard-controls-and-policies","title":"Device Guard Controls and Policies","text":"

    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#device-protection-in-windows-security-gives-you-one-of-these-4-hardware-scores","title":"Device Protection in Windows Security Gives You One of These 4 Hardware Scores","text":"
    1. Standard hardware security not supported
      • This means that your device does not meet at least one of the requirements of Standard Hardware Security.
    2. Your device meets the requirements for Standard Hardware Security.
      • TPM 2.0
      • Secure boot
      • DEP
      • UEFI MAT
    3. Your device meets the requirements for Enhanced Hardware Security
      • TPM 2.0
      • Secure boot
      • DEP
      • UEFI MAT
      • Memory Integrity
    4. Your device has all Secured-core PC features enabled
      • TPM 2.0
      • Secure boot
      • DEP
      • UEFI MAT
      • Memory Integrity
      • System Management Mode (SMM)
    "},{"location":"Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/#additional-resources","title":"Additional Resources","text":""},{"location":"Miscellaneous/Event%20Viewer/","title":"Event Viewer","text":""},{"location":"Miscellaneous/Event%20Viewer/#event-viewer","title":"Event Viewer","text":""},{"location":"Miscellaneous/Event%20Viewer/#windows-event-viewer","title":"Windows Event Viewer","text":"

    This document is dedicated to offering various ways to use Event logs to achieve different purposes.

    "},{"location":"Miscellaneous/Event%20Viewer/#how-to-identify-which-windows-firewall-rule-is-responsible-for-a-blocked-packet","title":"How to identify which Windows Firewall rule is responsible for a blocked packet","text":"

    I've mostly considered this for the Country IP Blocking category, but you can use it for any purpose.

    Before doing this, you need to activate one of the system Audits.

    I suggest doing it using GUI because it will have a permanent effect:

    Or you can activate that Audit using this command, but it will only temporarily activate it and it'll be disabled again after you restart Windows.

    "},{"location":"Miscellaneous/Event%20Viewer/#for-systems-with-english-locale-only","title":"For Systems With English Locale Only","text":"
    Auditpol /set /category:\"System\" /SubCategory:\"Filtering Platform Packet Drop\" /success:enable /failure:enable\n
    "},{"location":"Miscellaneous/Event%20Viewer/#for-systems-with-any-locale","title":"For Systems With Any Locale","text":"
    Auditpol /set /category:\"{69979848-797A-11D9-BED3-505054503030}\" /SubCategory:\"{0CCE9225-69AE-11D9-BED3-505054503030}\" /success:enable /failure:enable\n

    After the Audit is activated, running this PowerShell code will generate an output showing you blocked packets (if any).

    For example, if you visit a website or access a server that is hosted in one of the countries you blocked, or a connection was made from one of those countries to your device, it will generate an event log that will be visible to you once you run this code.

    "},{"location":"Miscellaneous/Event%20Viewer/#link-to-the-get-blockedpackets-function","title":"\u27a1\ufe0f Link to the Get-BlockedPackets Function","text":""},{"location":"Miscellaneous/Event%20Viewer/#how-to-get-event-logs-in-real-time-in-powershell","title":"How to Get Event Logs in Real Time in PowerShell","text":"

    This code assumes you've already used the Harden Windows Security Module and the event logs custom views exist on your machine.

    In this example, any logs generated for Exploit Protection is displayed in real time on PowerShell console. You can modify and improve the displayed output more according to your needs.

    "},{"location":"Miscellaneous/Event%20Viewer/#link-to-the-get-eventdata-function","title":"\u27a1\ufe0f Link to the Get-EventData Function","text":"

    If you don't want the real time mode and just want to get the logs one time, you can use the following code

    # Load the XML content from a file or a string\n$xml = [xml](Get-Content -Path 'C:\\ProgramData\\Microsoft\\Event Viewer\\Views\\Hardening Script\\Exploit Protection Events.xml')\n\n# Get the QueryList element using XPath\n$queryList = $xml.SelectSingleNode(\"//QueryList\")\n\n# Convert the QueryList element to a string\n$queryListString = $queryList.OuterXml\n\n$Events = Get-WinEvent -FilterXml $queryListString -Oldest\n$Events | Format-Table -AutoSize\n

    "},{"location":"Miscellaneous/Group%20Policy/","title":"Group Policy usage in this GitHub repository","text":""},{"location":"Miscellaneous/Group%20Policy/#microsoft-security-compliance-toolkit","title":"Microsoft Security Compliance Toolkit","text":"

    This set of tools allows enterprise security administrators to download, analyze, test, edit and store Microsoft-recommended security configuration baselines for Windows and other Microsoft products, while comparing them against other security configurations.

    Microsoft Security Compliance Toolkit includes multiple files and useful programs that are required for the Harden Windows Security Module to operate.

    "},{"location":"Miscellaneous/Group%20Policy/#microsoft-security-baseline","title":"Microsoft Security Baseline","text":"

    Microsoft is dedicated to providing its customers with secure operating systems, such as Windows and Windows Server, and secure apps, such as Microsoft 365 apps for enterprise and Microsoft Edge. In addition to the security assurance of its products, Microsoft also enables you to have fine control over your environments by providing various configuration capabilities.

    Even though Windows and Windows Server are designed to be secure out-of-the-box, many organizations still want more granular control over their security configurations. Continue reading more in the Microsoft website

    When you unzip the Microsoft Security Baseline file, you will find this folder structure:

    1. Documentation - contains PDF and Excel files describing the differences between the previous baseline release and the new settings that were added. contains the default policyrules file, which is used with the Security Compliance Toolkit, you can view it using Policy Analyzer program.
    2. GP Reports - contains reports in HTML format, describes the GPO settings that can be applied for each category.
    3. GPOs \u2013 contains GPO objects for different scenarios, these are the actual policies that will be applied.
    4. Scripts - contains multiple PowerShell scripts for different scenarios and helps us easily import GPO settings to our system. The most important PowerShell script here is Baseline-LocalInstall.ps1.
    5. Templates \u2013 contains additional Group Policy Object templates that are not available by default on Windows, such as MSS-legacy.admx, these are in ADMX and ADML formats. They will be copied to C:\\Windows\\PolicyDefinitions, where they belong, so that the new Security Baselines GPOs can be interpreted.

    "},{"location":"Miscellaneous/Group%20Policy/#lgpo","title":"LGPO","text":"

    Quoting from the PDF file supplied by LGPO:

    LGPO.exe is a command-line utility that is designed to help automate management of Local Group Policy. It can import and apply settings from Registry Policy (Registry.pol) files, security templates, Advanced Auditing backup files, as well as from formatted \"LGPO text\" files and Policy Analyzer '.PolicyRules' XML files.

    It can export local policy to a GPO backup. It can export the contents of a Registry Policy file to the 'LGPO textformat' that can then be edited, and can build a Registry Policy file from an LGPO text file. (The syntax for LGPO text files is described later in this document.)

    LGPO.exe has four command-line forms: for importing and applying settings to local policy \u2013 including to Multiple Local Group Policy Objects (MLGPO)1 ; for creating a GPO backup; for parsing a Registry Policy file and outputting \"LGPO\" text; for producing a Registry Policy file from an LGPO text file.

    All output is written to LGPO.exe's standard output, and all diagnostic and error information is written to its standard error. Both can be redirected to files using standard command shell operations. To support batch file use, LGPO.exe's exit code is 0 on success and non-zero on any error.

    LGPO is the most crucial program for our workflow, it is part of the Security Compliance Toolkit (SCT)

    What is the Local Group Policy Object (LGPO) tool?

    LGPO.exe - Local Group Policy Object Utility

    "},{"location":"Miscellaneous/Group%20Policy/#how-to-manually-back-up-group-policy-objects-from-a-system-using-lgpoexe","title":"How to Manually Back up Group Policy Objects From a System Using LGPO.exe","text":"

    Use this command to back up the currently set local group policies to drive C

    .\\LGPO.exe /b C:\n
    "},{"location":"Miscellaneous/Group%20Policy/#how-to-import-group-policy-objects-from-a-backup-created-using-lgpoexe-to-the-local-system","title":"How to Import Group Policy Objects From a Backup, Created Using LGPO.exe, to the Local System","text":"
    .\\LGPO.exe /g 'Path to the backup'\n

    Example:

    .\\LGPO.exe /g 'C:\\{841474E6-33EC-418C-B884-EA0F7C8195DB}'\n
    "},{"location":"Miscellaneous/Group%20Policy/#how-to-import-only-the-settings-from-a-registry-policy-file-into-computer-machine-configuration","title":"How to Import Only the Settings From a Registry Policy File Into Computer (Machine) Configuration","text":"

    (This only contains everything in Computer (Machine) Configuration -> Administrative Templates and some policies in Computer Configuration -> Windows Settings)

    Registry Policy File Format

    .\\LGPO.exe /m <Path to registry.pol file>\n
    "},{"location":"Miscellaneous/Group%20Policy/#how-to-import-only-the-security-policies-file-into-computer-machine-configuration","title":"How to Import only the Security policies file into Computer (Machine) Configuration","text":"

    (This only contains everything in Computer (Machine) Configuration -> Windows Settings => Security Settings => everything in the subfolders except for the Advanced Audit Policy Configuration)

    Security policy settings

    .\\LGPO.exe /s \".\\GPOX\\DomainSysvol\\GPO\\Machine\\microsoft\\windows nt\\SecEdit\\GptTmpl.inf\"\n

    "},{"location":"Miscellaneous/Group%20Policy/#policy-analyzer","title":"Policy Analyzer","text":"

    Quoting from the PDF file supplied by Policy Analyzer:

    Policy Analyzer is a lightweight utility for analyzing and comparing sets of Group Policy Objects (GPOs). It can highlight when a set of Group Policies has redundant settings or internal inconsistencies and can highlight the differences between versions or sets of Group Policies.

    It can also compare one or more GPOs against local effective state. You can export all its findings to a Microsoft Excel spreadsheet.

    Policy Analyzer lets you treat a set of GPOs as a single unit, and represents all settings in one or more GPOs in a single \".PolicyRules\" XML file. You can also use .PolicyRules files with LGPO.exe v3.0 to apply those GPOs to a computer's local policy, instead of having to copy GPO backups around.

    What is the Policy Analyzer tool?

    Policy Analyzer Tool

    "},{"location":"Miscellaneous/Group%20Policy/#about-compare-to-effective-state","title":"About Compare to Effective State","text":"

    In Policy Analyzer, there is an option called Compare to Effective State. Quoting from the PDF file that ships with Policy Analyzer program regarding that option:

    Enable one or more of the Policy Rule sets' checkboxes and click \"Compare to Effective State\" to compare the selected baselines against the local computer's current configured state. The operation will require UAC elevation if any of the selected baselines include security template or advanced auditing settings that require elevation to retrieve.

    The Policy Viewer will show the combined settings from all the selected Policy Rule sets in one column under the heading \"Baseline(s),\" and the corresponding current settings on the local computer and the logged-on user in a separate column under the heading \"Effective state.\"

    The effective state settings are also saved to a new .PolicyRules file with a name combining \"EffectiveState_,\" the current computer name, and the current date and time in the format \"yyyyMMdd- HHmmss.\" For example, \"EffectiveState_WKS51279_20200210-183947.PolicyRules.\"

    "},{"location":"Miscellaneous/Group%20Policy/#how-are-group-policies-used-by-the-harden-windows-security-module","title":"How Are Group Policies Used by the Harden Windows Security Module?","text":"
    1. The module downloads the official Microsoft Security Baselines from Microsoft servers and applies them to the system.

    2. It then downloads Group Policies from this GitHub repository, which represent the configurations explained in the main Readme page, and applies them to the system, on top of Microsoft Security Baselines, so where there is a conflict of policy, the module will replace the configurations set by Microsoft Security Baselines.

    3. When applying the Microsoft Security Baselines, you have the option to apply the optional overrides too, you can find the details of those overrides in here,, they are required to be applied if you are using Harden Windows Security Module in Azure VMs and highly recommended in general.

    "},{"location":"Miscellaneous/Group%20Policy/#how-are-group-policies-for-the-module-created-and-maintained","title":"How Are Group Policies for the Module Created and Maintained?","text":""},{"location":"Miscellaneous/Group%20Policy/#how-i-created-them-for-the-first-time","title":"How I Created Them for the First Time","text":"
    1. Installed the newest available Windows build on a fresh Hyper-V VM, fully updated it, created a standard checkpoint.

    2. Opened Group Policy editor and started applying security measures described in the Readme page.

    3. After completing each category, used LGPO.exe /b C: to backup Group Policies of the system by creating a full GPO.

    4. Then I took only files needed from the backup, registry.pol and GptTmpl.inf and put them in a zip file, renamed it to Security-Baselines-X.zip

    "},{"location":"Miscellaneous/Group%20Policy/#how-i-maintain-them","title":"How I Maintain Them","text":"
    1. As long as the VM is still using the latest available build of Windows, I use the standard checkpoint I had created to revert the VM back to that new state. If there is a newer build of Windows available, I delete that old VM, download the new Windows ISO file from Microsoft servers, then I create a fresh Hyper-V VM using it.

    2. I copy the Group Policy files, registry.pol or GptTmpl.inf to the VM, import them by using .\\LGPO.exe /m \"path\" for registry.pol files or .\\LGPO.exe /s \"path\" for GptTmpl.inf files.

    3. Open Group Policy editor and change anything that is needed, once I'm done, I create a full backup of the Group Policies of the system using LGPO.exe /b C: command, again take out the modified file, either registry.pol or GptTmpl.inf.

    4. Use PolicyAnalyzer to double check everything by comparing the old file with the new one and making sure the correct changes are applied.

    5. Replace the old Group Policy file with the new file and create a new Security-Baselines-X to upload to the GitHub repository.

    "},{"location":"Miscellaneous/Group%20Policy/#we-can-use-policy-analyzer-for-verification-and-comparison","title":"We Can Use Policy Analyzer for Verification and Comparison","text":""},{"location":"Miscellaneous/Group%20Policy/#to-verify-the-settings-are-applied-correctly-by-the-module","title":"To Verify the Settings Are Applied Correctly by The Module","text":"
    1. Use folder options in Control Panel or File Explorer to show hidden files and folder.

    2. Open Policy Analyzer program, Navigate to Add -> File -> Add files from GPO(s)... -> Browser for this folder \"C:\\Windows\\System32\\GroupPolicy\", Select the folder -> Import -> save the Policy Rules file in \\Documents\\PolicyAnalyzer\\

    3. Back at the main window, use View/Compare button to view applied Group Policies. The result that you will see is all of the Group Policies that are applied to your system.

    Another way to verify the applied Group Policies is to perform the 3 tasks above; What it will give you is the Policy Rules file which is generated from Group Policy state after using the module. If we take this policy rules file to a different machine where we just clean installed Windows and use Policy Analyzer to compare it to the Effective State of the system, we will see what Group Policy settings have changed as a result of using the module.

    Note: At first, when we clean install Windows, the Group Policy folder C:\\Windows\\System32\\GroupPolicy is empty, it will get populated with empty folders and a 1kb file that contains only 1 word when we first open the local Group Policy editor. It will get more populated with actual policies once we start modifying any group policies.

    "},{"location":"Miscellaneous/Group%20Policy/#how-to-verify-security-baselines-xzip-file-and-100-trust-it","title":"How to verify security-baselines-x.zip file and 100% trust it?","text":"
    1. Download the security-baselines-x.zip file, extract it.
    2. Open Policy Analyzer, Navigate to Add -> File -> Select either Add User Configuration (registry.pol) or Add Security Template (*.inf) -> Browser for the folder that was extracted from the security-baselines-x.zip, navigate to the category you want.
    3. Select either .pol or .inf file, Import it, give it a name, save it in \\Documents\\PolicyAnalyzer\\

    4. Back at the main window, use \"Compare to Effective State\" button to view what policies are included in the file.

    5. As you will see, everything is according to what has been explicitly stated in the GitHub's Readme page.

    You can also use Virus Total website to scan security-baselines-x.zip without downloading it first

    "},{"location":"Miscellaneous/Group%20Policy/#using-configuration-service-providers-csps-and-provisioning-packages-work-in-progress","title":"Using Configuration Service Providers (CSPs) and Provisioning Packages (Work in Progress)","text":"

    This command gets the information about all installed provisioning packages on your system.

    Get-ProvisioningPackage -AllInstalledPackages\n

    Configuration service providers for IT pros

    Settings changed when you uninstall a provisioning package

    Why Intune and CSPs are the future of Windows management instead of Group Policy

    Link to Microsoft Employee's comment

    Download Windows Configuration Designer from Microsoft Store or from Windows ADK or from Windows insiders ADK, to easily create provisioning packages for your device(s)

    You can use gpresult to see more info about Group Policies on your computer

    # What policies are applied to your computer:\ngpresult /z\n# or\ngpresult /v\n\n# What policies are applied to the current user:\ngpresult /scope user /v\n

    We can manually backup and restore Group Policy settings by copying this folder and all of its content:

    C:\\Windows\\System32\\GroupPolicy

    "},{"location":"Miscellaneous/How%20to%20Detect%20Changes%20in%20User%20and%20Local%20Machine%20Certificate%20Stores%20in%20Real%20Time%20Using%20PowerShell/","title":"How to Detect Changes in User and Local Machine Certificate Stores in Real Time Using PowerShell","text":"

    Here is a PowerShell script that can display the changes in User and Local Machine Certificate Stores in Real Time. It performs the check every 3 seconds. The script is published to PowerShell Gallery and you can easily install it using the following command:

    Install-Script -Name Certificates-Change-Detection -Force\n

    "},{"location":"Miscellaneous/How%20to%20Detect%20Changes%20in%20User%20and%20Local%20Machine%20Certificate%20Stores%20in%20Real%20Time%20Using%20PowerShell/#the-code-used-in-the-script","title":"The Code used in the script","text":"
    #Requires -RunAsAdministrator\n#Requires -Version 7.3\n\n# Custom colors\n[scriptblock]$WritePink = { Write-Output \"$($PSStyle.Foreground.FromRGB(255,192,203))$($PSStyle.Blink)$($args[0])$($PSStyle.Reset)\" }\n[scriptblock]$WriteMintGreen = { Write-Output \"$($PSStyle.Foreground.FromRGB(152,255,152))$($PSStyle.Blink)$($args[0])$($PSStyle.Reset)\" }\n\n# Create variables to store the initial certificates for both locations\n$InitialLocal = Get-ChildItem Cert:\\LocalMachine\\* -Recurse\n$InitialUser = Get-ChildItem Cert:\\CurrentUser\\* -Recurse\n\n# Create a loop that runs indefinitely\nwhile ($true) {\n    # Create variables to store the current certificates for both locations\n    $CurrentLocal = Get-ChildItem Cert:\\LocalMachine\\* -Recurse\n    $CurrentUser = Get-ChildItem Cert:\\CurrentUser\\* -Recurse\n\n    # Compare the variables and check if there is any difference in certificates for LocalMachine\n    $DifferenceLocal = Compare-Object $InitialLocal $CurrentLocal\n\n    # Compare the variables and check if there is any difference in certificates for CurrentUser\n    $DifferenceUser = Compare-Object $InitialUser $CurrentUser\n\n    # If there is any difference in certificates for LocalMachine, display it and update the initial variable\n    if ($DifferenceLocal) {\n        foreach ($Diff in $DifferenceLocal) {\n            # Check if the change is an addition or a removal based on the side indicator\n            if ($Diff.SideIndicator -eq '=>') {\n                &$WritePink \"Certificate Added to LocalMachine at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(255,192,203))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n            elseif ($Diff.SideIndicator -eq '<=') {\n                &$WriteMintGreen \"Certificate Removed from LocalMachine at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(152,255,152))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n        }\n        $InitialLocal = $CurrentLocal\n    }\n\n    # If there is any difference in certificates for CurrentUser, display it and update the initial variable\n    if ($DifferenceUser) {\n        foreach ($Diff in $DifferenceUser) {\n            # Check if the change is an addition or a removal based on the side indicator\n            if ($Diff.SideIndicator -eq '=>') {\n                &$WritePink \"Certificate Added to CurrentUser at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(255,192,203))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n            elseif ($Diff.SideIndicator -eq '<=') {\n                &$WriteMintGreen \"Certificate Removed from CurrentUser at $(Get-Date -Format 'MM/dd/yyyy HH:mm:ss K')\"\n                $PSStyle.Formatting.FormatAccent = \"$($PSStyle.Foreground.FromRGB(152,255,152))\"\n                $Diff.InputObject | Format-List -Property PSPath, EnhancedKeyUsageList, DnsNameList, SendAsTrustedIssuer, FriendlyName, HasPrivateKey, NotAfter, NotBefore, SerialNumber, Thumbprint, Issuer, Subject\n            }\n        }\n        $InitialUser = $CurrentUser\n    }\n\n    # Wait for 3 seconds before repeating the loop\n    Start-Sleep -Seconds 3\n}\n
    "},{"location":"Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/","title":"How to compact your OS and free up extra space","text":""},{"location":"Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/#how-to-compact-your-os-and-free-up-extra-space","title":"How to compact your OS and free up extra space","text":""},{"location":"Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/#run-the-following-commands-in-an-elevated-powershell","title":"Run the following commands in an elevated PowerShell","text":"

    To turn on CompactOS:

    Compact.exe /CompactOS:always\n

    To turn off CompactOS:

    Compact.exe /CompactOS:never\n

    To Query whether CompactOS is on or off:

    Compact.exe /CompactOS:Query\n

    Source

    "},{"location":"Miscellaneous/Hyper%20V/","title":"Hyper-V Tips and Tricks","text":""},{"location":"Miscellaneous/Hyper%20V/#how-to-import-and-export-tpm-enabled-hyper-v-vm-certificates-with-powershell","title":"How to Import and Export TPM-enabled Hyper-V VM certificates with PowerShell","text":"

    TPM requirement, which is a great security feature, was added to Windows 11. On the host, it is managed by the OS and UEFI, but when you create a Virtual Machine (VM) that runs an OS like Windows 11, you have to know how to manage it properly so that your VM will stay secure everywhere and you will maintain your access to your VM even if you import/export it to a different Hyper-V host or reinstall your host OS.

    Here is a screenshot of my Hyper-V VM on Windows 11 with the following security features enabled:

    1. Secure Boot
    2. Trusted Platform Module (TPM)

    When a VM uses TPM, Windows creates 2 certificates in the Local Machine Certificate Store => Shielded VM Local Certificates => Certificates

    One of them is for encryption and the other one is for signing. They both contain private keys. If these 2 certificates don't exist in that folder in the Local Machine Certificate store of a Hyper-V host, your VM won't be able to start

    What you need to do is to export those 2 certificates (with private keys) and store them in a safe place (such as OneDrive's personal Vault) as a backup.

    If you completely reinstall Windows or move the VMs to a different Hyper-V host and Import the certificates, you will be able to continue using your VMs, but when you create new TPM enabled VMs on the new host, 2 more certificates will be added to the Local Machine Certificate Store => Shielded VM Local Certificates => Certificates, so you will have 4 certificates in total, 2 of which are tied to your old VMs and the other 2 are tied to the new VMs. Each generated certificate has 10 years expiry date from the time it was created.

    You can Import/Export the certificates using GUI, but here I'm going to show how to automate it using PowerShell:

    "},{"location":"Miscellaneous/Hyper%20V/#export-all-the-available-host-guardian-service-certificates-with-private-keys-and-extended-properties","title":"Export all the available Host Guardian service certificates with private keys and extended properties","text":"
    $CertificatePassword = ConvertTo-SecureString -String \"hotcakex\" -Force -AsPlainText\nGet-Item \"Cert:\\LocalMachine\\Shielded VM Local Certificates\\*\" | ForEach-Object {\nExport-PfxCertificate -Cert $_ -FilePath \".\\$($_.Issuer)-$($_.Thumbprint).pfx\" -Password $CertificatePassword -CryptoAlgorithmOption AES256_SHA256}\n
    "},{"location":"Miscellaneous/Hyper%20V/#import-the-certificates-with-private-keys","title":"Import the certificates with private keys","text":"
    $ShieldedCertsPath = 'Cert:\\LocalMachine\\Shielded VM Local Certificates'\nif (-NOT (Test-Path $ShieldedCertsPath)) { New-Item -Path $ShieldedCertsPath -Force }\n$CertificatePassword = 'hotcakex' | ConvertTo-SecureString -AsPlainText -Force\nGet-Item \"C:\\Users\\$($env:USERNAME)\\OneDrive\\Desktop\\Hyper-V Guardian certificates\\*.pfx\" | Import-PfxCertificate -CertStoreLocation $ShieldedCertsPath -Password $CertificatePassword -Exportable\n

    You should change the values for $CertificateLocation and $CertificatePassword varaibles according to your own needs and environment.

    "},{"location":"Miscellaneous/Hyper%20V/#how-to-enable-nested-virtualization-for-all-the-vms-on-the-hyper-v-host","title":"How to Enable Nested Virtualization for All the VMs on the Hyper-V Host","text":"

    Use the following command to enable Nested Virtualization for a single VM

    Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true\n

    Use the following command to automatically enable Nested Virtualization for all VMs

    (Get-VM).name | ForEach-Object {Set-VMProcessor -VMName $_ -ExposeVirtualizationExtensions $true}\n

    All of the VMs must be in Off state when enabling nested virtualization for them

    This is how to verify Nested Virtualization is enabled for all of your VMs

    (Get-VM).name | ForEach-Object {get-VMProcessor -VMName $_} | Select-Object -Property VMName,ExposeVirtualizationExtensions\n

    "},{"location":"Miscellaneous/Hyper%20V/#confidential-computing-on-azure","title":"Confidential Computing on Azure","text":"

    Azure confidential computing makes it easier to trust the cloud provider, by reducing the need for trust across various aspects of the compute cloud infrastructure. Azure confidential computing minimizes trust for the host OS kernel, the hypervisor, the VM admin, and the host admin.

    "},{"location":"Miscellaneous/Hyper%20V/#continue-reading","title":"Continue reading","text":"

    "},{"location":"Miscellaneous/Hyper%20V/#shielded-vms-are-deprecated-concepts","title":"Shielded VMs are deprecated concepts","text":"

    They are deprecated starting with Windows Server 2022. They were prone to modern attacks such as side-channel.

    The following details about Shielded VMs are old and no longer valid
    HgsClientConfiguration\n

    Note that this configuration is for standalone systems. an actual shielded virtual machine is a lot more secure because the host's security and health is properly attested in a Guarded Fabric, using Host Guardian Service (HGS) on a Windows Server.

    "},{"location":"Miscellaneous/Hyper%20V/#scenario-hyper-v-enhanced-session-mode-no-authentication-in-the-vms-os","title":"Scenario: Hyper-V, Enhanced session mode, no authentication in the VM's OS","text":"

    When you create a VM in Hyper-V that doesn't have any authentication method for login such as Password or PIN, and use Enhanced session-mode to connect to it, there might be an issue where the RDP disconnects once after each restart of the VM and Hyper-V virtual machine connection asks you to connect to the VM again by clicking/tapping on the connect button. To fix this, set a local password for the user account of the OS in VM.

    "},{"location":"Miscellaneous/Hyper%20V/#native-boot-hyper-v-vms-vhdx","title":"Native boot Hyper-V VMs, VHDX","text":"

    There are guides for native booting a VHDX and it's very easy to do. If you already have a Hyper-V VM, you can add it to the Windows boot manager so that during a reboot you will have the option to boot the VHDX.

    "},{"location":"Miscellaneous/Hyper%20V/#you-need-to-pay-attention-to-a-few-things-though","title":"You need to pay attention to a few things though:","text":"
    1. The VHDX should be on a drive that is NTFS formatted, for now booting from ReFS is not supported.

    2. The drive that hosts the VHDX file must have more free space than the assigned size of the VHDX. The size you see in the file explorer is not the same as the size of the disk you assigned to the VHDX when creating it. It's easier if you have a fixed size VHDX instead of a dynamically expanding one. To find the real size of the VHDX, you can boot it in Hyper-V and check the drives inside it.

    3. Merge all checkpoints and delete them before attempting to native boot VHDX.

    "},{"location":"Miscellaneous/Hyper%20V/#vhdx-native-booting-is-very-easy-and-flexible-you-can-do-it-even-if","title":"VHDX native booting is very easy and flexible, you can do it even if:","text":"
    1. Your host has Secure boot enabled

    2. You use Signed WDAC policies

    3. Your VM wasn't SysPrepped before natively booting it on physical machine

    4. VM has secure boot and TPM

    "},{"location":"Miscellaneous/Hyper%20V/#how-to-make-the-vhdx-bootable","title":"How to make the VHDX bootable:","text":"
    1. Double-click/tap on the VHDX file to mount it
    2. Run this in CMD or PowerShell
    bcdboot D:\\Windows /d\n

    Bcdboot

    Use the /d option to preserve the existing boot order.

    "},{"location":"Miscellaneous/Hyper%20V/#verify-the-change-by-running-this-command","title":"Verify the change by running this command","text":"
    bcdedit /enum\n

    Bcdedit

    The description of the boot entry is the same one you see during OS selection menu. You can change it with this command in PowerShell:

    bcdedit /set '{default}' description 'VHDX Boot'\n

    or in CMD:

    bcdedit /set {default} description 'VHDX Boot'\n

    If {default} is not the correct identifier, then change it according to the result of the bcdedit /enum

    There are three different identifiers: The chosen default OS has identifier {default}, the current OS you are signed in at the moment is {current}. All other entries have a long hexadecimal identifier.

    "},{"location":"Miscellaneous/Hyper%20V/#some-hyper-v-nested-virtualization-screenshots","title":"Some Hyper-v Nested Virtualization Screenshots","text":"

    To display how optimized and powerful Hyper-V hypervisor is (including any feature that runs on it such as Windows Sandbox, WSL, WSA, MDAG and more), here are some screenshots taken on a very old hardware, hardware that is not even officially supported by Windows 11, yet you can virtualize 5 operation systems nested in each other, and the last nested virtualized OS still has full functionality including direct file copy from host to guest, full Internet connectivity, ability to listen to music, do tasks and so on.

    "},{"location":"Miscellaneous/Hyper%20V/#hardware-specs-all-from-2016-2017-couldnt-find-any-older-to-test","title":"Hardware specs - All from 2016-2017, couldn't find any older to test","text":"
    1. CPU: Intel Core I7 7700k
    2. RAM: 16GB
    3. GPU: N/A (Intel IGPU)
    4. SSD: 256 GB M.2
    Click/Tap here to see the screenshots"},{"location":"Miscellaneous/Hyper%20V/#important-hyper-v-related-documents","title":"Important Hyper-V Related Documents","text":"

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/","title":"Only a Small Portion of The Windows OS Security Apparatus","text":"

    Tip

    Many of the features mentioned in the map above can be automatically deployed and configured via the Harden Windows Security repository's offerings.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#superiority","title":"SUPERIORITY","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#intelligent-security-graph-isg","title":"Intelligent Security Graph (ISG)","text":"

    This cloud-based AI is based on trillions of signals collected from Windows endpoints and other data sources, and processed every 24 hours. As a result, the decision from the cloud can change.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#no-0-dayunknown-file-allowed-asr","title":"No 0-day/Unknown File Allowed (ASR)","text":"

    This rule blocks untrusted or unknown executable files such as .exe, .dll, or .scr, from launching that can be risky, as it might not be initially clear if the files are malicious.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#rigorous-custom-exploit-protections","title":"Rigorous Custom Exploit Protections","text":"

    Exploit protection helps protect devices from malware that uses exploits to spread and infect other devices. Mitigation can be applied to either the operating system or to an individual app.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#network-protection","title":"Network Protection","text":"

    Network protection helps protect devices from Internet-based events. Network protection is an attack surface reduction capability. It helps prevent employees from accessing dangerous domains through applications. Domains that host phishing scams, exploits, and other malicious content on the Internet are considered dangerous.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#cloud-protection","title":"Cloud Protection","text":"

    Next-generation technologies in Microsoft Defender Antivirus provide near-instant, automated protection against new and emerging threats. To identify new threats dynamically, next-generation technologies work with large sets of interconnected data in the Microsoft Intelligent Security Graph and powerful artificial intelligence (AI) systems driven by advanced machine learning models. Cloud protection works together with Microsoft Defender Antivirus to deliver accurate, real-time, and intelligent protection.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#cloud-based-remote-detonation-and-analysis","title":"Cloud-Based Remote Detonation And Analysis","text":"

    Advanced cloud-based protection is provided for cases when Microsoft Defender Antivirus running on the endpoint needs more intelligence to verify the intent of a suspicious file.

    After files are submitted to cloud protection, the submitted files can be scanned, detonated, and processed through big data analysis machine-learning models to reach a verdict.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#block-at-first-sight","title":"Block At First Sight","text":"

    Block at first sight is a threat protection feature of next-generation protection that detects new malware and blocks it within seconds.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#intel-threat-detection-technology-tdt","title":"Intel Threat Detection Technology (TDT)","text":"

    Intel TDT is a detection approach that can augment traditional file-based or behavior-based detection. This technology integration focuses on the CPU execution patterns that are characteristic of ransomware attacks. Intel TDT is available in a broad range of Intel hardware over multiple generations and will be available for consumers through Microsoft Defender Antivirus.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#remote-encryption-protection","title":"Remote Encryption Protection","text":"

    Remote Encryption Protection in Microsoft Defender Antivirus detects and blocks attempts to replace local files with encrypted versions from another device.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#brute-force-protection","title":"Brute Force Protection","text":"

    Brute-Force Protection in Microsoft Defender Antivirus detects and blocks attempts to forcibly sign in and initiate sessions.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#windows-updates-installed-within-24-hours-of-release","title":"Windows Updates Installed Within 24 Hours Of Release","text":"

    Windows updates are extremely important. They always should be installed as fast as possible to stay secure and if a reboot is required, it should be done immediately. Threat actors can weaponize publicly disclosed vulnerabilities the same day their POC (Proof-Of-Concept) is released.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#microsoft-defender-updates-installed-every-3-hours","title":"Microsoft Defender Updates Installed Every 3 Hours","text":"

    Regularly updating Microsoft Defender Antivirus is crucial for maintaining robust security on your Windows OS. These updates ensure that your system has the latest security intelligence, which is vital for identifying and mitigating the most recent threats. Cyber threats evolve rapidly, and outdated antivirus signatures leave your system vulnerable to new malware, viruses, and other security risks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#ultimatum","title":"ULTIMATUM","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#application-control-for-business-wdac","title":"Application Control For Business (WDAC)","text":"

    Application control is a crucial line of defense for protecting computer systems given today's threat landscape, and it has an inherent advantage over traditional antivirus solutions. Specifically, application control moves away from an application trust model where all applications are assumed trustworthy to one where applications must earn trust in order to run.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#complete-byovd-protection","title":"Complete BYOVD Protection","text":"

    This scenario involves removing the trust to any Kernel mode driver, whether they are vulnerable or not. It does not affect User-mode binaries or drivers. Any 3rd party software/hardware Kernel mode driver will need to be explicitly allowed. This scenario protects against all BYOVD scenarios and much more.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#application-cross-dependency-usage-control","title":"Application Cross-Dependency Usage Control","text":"

    Implements Sandboxing-like restrictions around the program's dependencies so that only the main executable(s) of the program can use its dependencies and any other executable will be blocked from using them.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#controlled-folder-access","title":"Controlled Folder Access","text":"

    Controlled folder access helps you protect valuable data from malicious apps and threats, such as ransomware.

    Controlled folder access applies to many system folders and default locations, including folders such as Documents, Pictures, and Movies. You can add other folders to be protected, but you cannot remove the default folders in the default list.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#smart-app-control","title":"Smart App Control","text":"

    Smart App Control is a new app execution control feature that combines Microsoft\u2019s app intelligence services and Windows' code integrity features to protect users from untrusted or potentially dangerous code. Smart App Control selectively allows apps and binaries to run only if they're likely to be safe. Microsoft's app intelligence services provide safety predictions for many popular apps. If the app intelligence service is unable to make a prediction, then Smart App Control will still allow an app to run if it is signed with a certificate issued by a certificate authority (CA) within the Trusted Root Program.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#hyper-v-windows-sandbox-untrusted-software-usage","title":"Hyper-V & Windows Sandbox (Untrusted Software Usage)","text":"

    Hyper-V is the most secure and one of the best, if not the best Type-1 hypervisor. It's available in Windows and can virtualize an OS.

    Windows Sandbox provides a lightweight desktop environment to safely run applications in isolation. Software installed inside the Windows Sandbox environment remains \"sandboxed\" and runs separately from the host machine.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#windows-defender-firewall-rule-based","title":"Windows Defender Firewall (Rule Based)","text":"

    Windows Firewall is a Stateful Firewall. It is a security feature that helps to protect your device by filtering network traffic that enters and exits your device. This traffic can be filtered based on several criteria, including source and destination IP address, IP protocol, or source and destination port number.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#automated-firewall-with-appid-tagging","title":"Automated Firewall With AppID Tagging","text":"

    Windows Firewall supports the use of Windows Defender Application Control (WDAC) Application ID (AppID) tags. With this capability, you'll be able to scope your firewall rules to an application or a group of applications and rely on WDAC policies to define those applications. The WDAC AppID functionality adds an administrator defined tag to the given process token.

    For example, you can easily use a policy that allows only files that come with Windows by default to be allowed to access the Internet while everything else will be blocked.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#win32-app-isolation","title":"Win32 App Isolation","text":"

    Win32 app isolation is a new security feature designed to be the default isolation standard on Windows clients. It is built on AppContainers and offers several added security features to help windows platform defend against attacks that leverage vulnerabilities in the application (this could be 3P libraries as well). To isolate their apps, application developers can update their applications using the tools provided by Microsoft.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#vbs-enclaves","title":"VBS Enclaves","text":"

    A Virtualization-based security (VBS) Enclave is a software-based trusted execution environment inside the address space of a host application. VBS Enclaves leverage underlying VBS technology to isolate the sensitive portion of an application in a secure partition of memory. VBS Enclaves enable isolation of sensitive workloads from both the host application and the rest of the system.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#uefi-locked-settings-to-require-proof-of-physical-presence","title":"UEFI Locked Settings (To Require Proof Of Physical Presence)","text":"

    UEFI locked security measures are rooted in Proof of Physical Presence and they can't be disabled by modifying Group Policy, registry keys or other Administrative tasks.

    The only way to disable UEFI locked security measures is to have physical access to the computer, reboot and access the UEFI settings, supply the credentials to access the UEFI, turn off Secure Boot, reboot the system and then you will be able to disable those security measures with Administrator privileges.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#early-launch-antimalware-elam","title":"Early Launch AntiMalware (ELAM)","text":"

    A security model in the kernel to better defend against malicious attacks on system-critical components. This security model extends the protected process infrastructure into a general-purpose model that can be used by 3rd party anti-malware vendors. The protected process infrastructure only allows trusted, signed code to load and has built-in defense against code injection attacks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#physical-security","title":"Physical Security","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#bitlocker","title":"BitLocker","text":"

    BitLocker is a Windows security feature that provides encryption for entire volumes, addressing the threats of data theft or exposure from lost, stolen, or inappropriately decommissioned devices.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#startup-key-usb-flash-drive","title":"Startup Key (USB Flash Drive)","text":"

    Requires a USB flash drive to be inserted into the computer to start the computer. The USB flash drive must contain the startup key for the encrypted drive. This key is only a portion of the complete key required to perform a successful authentication. The other portion of of the key is provided by the Startup PIN.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-boot-pcr7-binding","title":"Secure Boot (PCR7 Binding)","text":"

    Secure Boot blocks untrusted firmware and bootloaders (signed or unsigned) from being able to start on the system. By default, BitLocker provides integrity protection for Secure Boot by utilizing the TPM PCR 7 measurement. An unauthorized EFI firmware, EFI boot application, or bootloader can't run and acquire the BitLocker key.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#tpm","title":"TPM","text":"

    A TPM is a microchip designed to provide basic security-related functions, primarily involving encryption keys. The TPM is installed on the motherboard of a computer, and it communicates with the rest of the system by using a hardware bus.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#startup-pin","title":"Startup PIN","text":"

    In addition to the protection that the TPM provides, part of the encryption key is stored on a USB flash drive, and a PIN is required to authenticate the user to the TPM. This configuration provides multifactor authentication so that if the USB key is lost or stolen, it can't be used for access to the drive, because the PIN is also required. Preboot authentication with a PIN can mitigate an attack vector for devices that use a bootable eDrive because an exposed eDrive bus can allow an attacker to capture the BitLocker encryption key during startup.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#firmware-security","title":"Firmware Security","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#system-management-mode-smm-protection","title":"System Management Mode (SMM) Protection","text":"

    SMM code executes in the highest privilege level and is invisible to the OS. SMM protection is built on top of the Secure Launch technology and requires it to function. A hardware-enforced processor feature known as a supervisor SMI handler can monitor the SMM and make sure it doesn't access any part of the address space that it isn't supposed to. Windows measures SMI Handler's behavior and attest that no OS-owned memory has been tampered with.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#static-root-of-trust-for-measurement-srtm","title":"Static Root of Trust for Measurement (SRTM)","text":"

    It is a hardware-based root of trust that helps ensure no unauthorized firmware or software (such as a bootkit) can start before the Windows bootloader. This hardware-based root of trust comes from the device's Secure Boot feature, which is part of the Unified Extensible Firmware Interface (UEFI). This technique of measuring the static early boot UEFI components is called the Static Root of Trust for Measurement (SRTM).

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-launch-drtm","title":"Secure Launch (DRTM)","text":"

    The Dynamic Root of Trust for Measurement (DRTM) lets the system freely boot into untrusted code initially, but shortly after launches the system into a trusted state by taking control of all CPUs and forcing them down a well-known and measured code path. This has the benefit of allowing untrusted early UEFI code to boot the system, but then being able to securely transition into a trusted and measured state.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-memory-overwrite","title":"Secure Memory Overwrite","text":"

    Secure MOR protects the MOR lock setting using a UEFI secure variable. This helps guard against advanced memory attacks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#tcg-storage-security-drive-password","title":"TCG Storage Security Drive Password","text":"

    This is a password for modern SSDs that can be set in the UEFI firmware. User is asked for this password during the boot process before the OS is loaded. The SSD itself can be encrypted by BitLocker and still require this additional password before the Startup PIN.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#mode-based-execution-control","title":"Mode Based Execution Control","text":"

    MBEC virtualization provides an extra layer of protection from malware attacks. It enables hypervisors to more reliably and efficiently verify and enforce the integrity of kernel-level code.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#uefi-password","title":"UEFI Password","text":"

    It's a password that is set in the UEFI firmware. It is required to access the UEFI settings. This password can be used to prevent unauthorized changes to the UEFI settings.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#uefi-code-readonly","title":"UEFI Code ReadOnly","text":"

    All UEFI memory that is marked executable is set to be read only. Memory marked writable must not be executable. Entries may not be left with neither of the attributes set, indicating memory that is both executable and writable.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#kernel-dma-protection","title":"Kernel DMA Protection","text":"

    Kernel Direct Memory Access (DMA) Protection is a Windows security feature that protects against external peripherals from gaining unauthorized access to memory. Windows uses the system Input/Output Memory Management Unit (IOMMU) to block external peripherals from starting and performing DMA, unless the drivers for these peripherals support memory isolation (such as DMA-remapping).

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#pluton","title":"Pluton","text":"

    Microsoft Pluton security processor is a chip-to-cloud security technology built with Zero Trust principles at the core. Microsoft Pluton provides hardware-based root of trust, secure identity, secure attestation, and cryptographic services. Pluton technology is a combination of a secure subsystem, which is part of the System on Chip (SoC) and Microsoft authored software that runs on this integrated secure subsystem.

    It addresses security needs like booting an operating system securely even against firmware threats and storing sensitive data safely even against physical attacks.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#apic-virtualization","title":"APIC Virtualization","text":"

    APIC virtualization is a collection of features that can be used to support the virtualization of interrupts and the Advanced Programmable Interrupt Controller (APIC). When APIC virtualization is enabled, the processor emulates many accesses to the APIC, tracks the state of the virtual APIC, and delivers virtual interrupts \u2014 all in VMX non-root operation without a VM exit.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#secure-boot","title":"Secure Boot","text":"

    Secure Boot is a security standard developed by members of the PC industry to help ensure that a device boots using only software that's trusted by the original equipment manufacturer (OEM).

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#identity-in-the-abstract-sense","title":"IDENTITY (In the Abstract Sense)","text":""},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#smart-screen","title":"Smart Screen","text":"

    Microsoft Defender SmartScreen protects against phishing or malware websites and applications, and the downloading of potentially malicious files.

    Microsoft Defender SmartScreen provide an early warning system against websites that might engage in phishing attacks or attempt to distribute malware through a socially engineered attack.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#potentially-unwanted-application-pua-protection","title":"Potentially Unwanted Application (PUA) Protection","text":"

    Potentially unwanted applications (PUA) are a category of software that can cause your machine to run slowly, display unexpected ads, or at worst, install other software that might be unexpected or unwanted. PUA isn't considered a virus, malware, or other type of threat, but it might perform actions on endpoints that adversely affect endpoint performance or use. The term PUA can also refer to an application that has a poor reputation, as assessed by Microsoft Defender for Endpoint, due to certain kinds of undesirable behavior.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#valid-signature-required-for-elevation","title":"Valid Signature Required For Elevation","text":"

    Only elevate executable files that are signed and validated. This setting enforces public key infrastructure (PKI) signature checks for any interactive applications that request elevation of privilege. Enterprise administrators can control which applications are allowed to run by adding certificates to the Trusted Publishers certificate store on local computers.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#behavioral-analysis","title":"Behavioral Analysis","text":"

    Behavior monitoring (Analysis) is a critical detection and protection functionality of Microsoft Defender Antivirus.

    Monitors process behavior to detect and analyze potential threats based on the behavior of applications, services, and files. Rather than relying solely on signature-based detection (which identifies known malware patterns), behavior monitoring focuses on observing how software behaves in real-time

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#static-signature-analysis","title":"Static Signature Analysis","text":"

    Microsoft Defender's security definition updates are a critical component of the cybersecurity infrastructure, designed to continuously enhance protection against new malware and sophisticated attack techniques. These updates regularly refresh the definition files that are crucial for identifying spyware, viruses, and other potentially unwanted software.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#personal-data-encryption-pde","title":"Personal Data Encryption (PDE)","text":"

    PDE utilizes Windows Hello for Business to link data encryption keys with user credentials. When a user signs in to a device using Windows Hello for Business, decryption keys are released, and encrypted data is accessible to the user. When a user logs off, decryption keys are discarded and data is inaccessible, even if another user signs into the device.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#enhanced-sign-in-security-ess","title":"Enhanced Sign-in Security (ESS)","text":"

    Windows Hello enables a user to authenticate using their biometrics or a PIN eliminating the need for a password. Biometric authentication uses facial recognition or fingerprint to prove a user's identity in a way that is secure, personal, and convenient. Enhanced Sign-in Security provides an additional level of security to biometric data by leveraging specialized hardware and software components, such as Virtualization Based Security (VBS) and Trusted Platform Module 2.0 to isolate and protect a user's authentication data and secure the channel by which that data is communicated.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#credential-guard","title":"Credential Guard","text":"

    Credential Guard prevents credential theft attacks by protecting NTLM password hashes, Kerberos Ticket Granting Tickets (TGTs), and credentials stored by applications as domain credentials.

    Credential Guard uses Virtualization-based security (VBS) to isolate secrets so that only privileged system software can access them. Unauthorized access to these secrets can lead to credential theft attacks like pass the hash and pass the ticket.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#admin-less","title":"Admin-less","text":"

    Most people run as full admins on their devices, which means apps and services have the same access to the kernel and other critical services as users. And the problem is that these apps and services can access critical resources without the user knowing. This is why Windows requires just in time administrative access to the kernel and other critical services as needed, not all the time, and certainly not by default. This makes it harder for an app to unexpectedly abuse admin privileges and secretly put malware or malicious code on Windows. When this feature is enabled, such as when an app needs special permissions like admin rights, you'll be asked for approval.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#windows-hello-multi-factor-authentication","title":"Windows Hello Multi-Factor Authentication","text":"

    Windows Hello for Business supports the use of a single credential (PIN and biometrics) for unlocking a device. Therefore, if any of those credentials are compromised (shoulder surfed), an attacker could gain access to the system.

    Windows Hello for Business can be configured with multi-factor unlock, by extending Windows Hello with trusted signals. Administrators can configure devices to request a combination of factors and trusted signals to unlock them.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#zero-trust-dns-ztdns","title":"Zero Trust DNS (ZTDNS)","text":"

    ZTDNS integrates the Windows DNS client and the Windows Filtering Platform (WFP) to enable this domain-name-based lockdown. First, Windows is provisioned with a set of DoH or DoT capable Protective DNS servers; these are expected to only resolve allowed domain names. This provisioning may also contain a list of IP address subnets that should always be allowed (for endpoints without domain names), expected Protective DNS server certificate identities to properly validate the connection is to the expected server, or certificates to be used for client authentication.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#advanced-intelligence-based-phishing-protection","title":"Advanced Intelligence-Based Phishing Protection","text":"

    This feature is constantly learning from phishing attacks seen throughout the entire Microsoft security stack. It works alongside other Microsoft security products, to provide a layered approach to password security, especially for organizations early in their password-less authentication journey.

    "},{"location":"Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/#continue-reading","title":"Continue Reading","text":"

    Head over to the main page of the GitHub repository to learn more about Windows Security and how to automate a lot of the features talked about in this page.

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/","title":"Optional overrides for Microsoft Security Baseline","text":"

    Since Microsoft Security Baselines are geared towards Enterprise level security, some functionalities that home users might require are disabled. Use the following overrides in the Harden Windows Security module to bring back those functionalities. Some of these are necessary when using the module in Azure VMs.

    Tip

    All of the features and functionalities listed below are enabled by default in Windows.

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#1-windows-game-recording-and-broadcasting","title":"1. Windows Game Recording and Broadcasting","text":"

    This setting enables or disables the Windows Game Recording and Broadcasting features. If you disable this setting, Windows Game Recording will not be allowed. If the setting is enabled or not configured, then Recording and Broadcasting (streaming) will be allowed.

    Policy path:

    Computer Configuration\\Administrative Templates\\Windows Components\\Windows Game Recording and Broadcasting\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#2-prohibit-use-of-internet-connection-sharing-on-your-dns-domain-network","title":"2. Prohibit use of Internet Connection Sharing on your DNS domain network","text":"

    Determines whether administrators can enable and configure the Internet Connection Sharing (ICS) feature of an Internet connection and if the ICS service can run on the computer.

    ICS lets administrators configure their system as an Internet gateway for a small network and provides network services, such as name resolution and addressing through DHCP, to the local private network.

    If you enable this setting, ICS cannot be enabled or configured by administrators, and the ICS service cannot run on the computer. The Advanced tab in the Properties dialog box for a LAN or remote access connection is removed. The Internet Connection Sharing page is removed from the New Connection Wizard. The Network Setup Wizard is disabled.

    If you disable this setting or do not configure it and have two or more connections, administrators can enable ICS. The Advanced tab in the properties dialog box for a LAN or remote access connection is available. In addition, the user is presented with the option to enable Internet Connection Sharing in the Network Setup Wizard and Make New Connection Wizard. (The Network Setup Wizard is available only in Windows XP Professional.)

    By default, ICS is disabled when you create a remote access connection, but administrators can use the Advanced tab to enable it. When running the New Connection Wizard or Network Setup Wizard, administrators can choose to enable ICS.

    Note: Internet Connection Sharing is only available when two or more network connections are present.

    Note: When the \"Prohibit access to properties of a LAN connection,\" \"Ability to change properties of an all user remote access connection,\" or \"Prohibit changing properties of a private remote access connection\" settings are set to deny access to the Connection Properties dialog box, the Advanced tab for the connection is blocked.

    Note: Non-administrators are already prohibited from configuring Internet Connection Sharing, regardless of this setting.

    Note: Disabling this setting does not prevent Wireless Hosted Networking from using the ICS service for DHCP services. To prevent the ICS service from running, on the Network Permissions tab in the network's policy properties, select the \"Don't use hosted networks\" check box.

    Policy path:

    Computer Configuration\\Administrative Templates\\Network\\Network Connections\\Prohibit use of Internet Connection Sharing on your DNS domain network\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#3-firewall-local-rule-merging","title":"3. Firewall local rule merging","text":"

    This can prevent Hyper-V default switch from working properly, please see this forum post on Microsoft Tech Community for more info.

    The Group policies that we change back to default values are located in:

    Computer Configuration\\Windows Settings\\Security Settings\\Windows Defender Firewall with Advanced Security\\\n

    From there you need to select properties and then in each relevant profile tab, you need to select Customize and change the 2 settings for Rule merging to Yes (Default) and also set Display a notification to Yes, which is the default value in Windows.

    Here is an screenshot of the settings for the Public Profile tab:

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#4-deny-write-access-to-removable-drives-not-protected-by-bitlocker","title":"4. Deny write access to removable drives not protected by BitLocker","text":"

    Disabling this policy because it can cause inconvenience and if your flash drive is BitLocker encrypted, it can't be used as a bootable Windows installation USB flash drive.

    Policy path:

    Computer Configuration\\Administrative Templates\\Windows Components\\BitLocker Drive Encryption\\Removable Data Drives\\Deny write access to removable drives not protected by BitLocker\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#5-set-the-status-of-these-4-xbox-services-back-to-their-default-states","title":"5. Set the status of these 4 Xbox services back to their default states","text":"

    XboxGipSvc, XblAuthManager,XblGameSave,XboxNetApiSvc

    Microsoft Security Baseline sets their status to disabled.

    Policy path:

    Computer Configuration\\Windows Settings\\\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#6-enable-clipboard-and-drive-redirection-when-using-remote-desktop-connection","title":"6. Enable Clipboard and Drive redirection when using Remote Desktop connection","text":"

    It is necessary when using Hyper-V VM Enhanced session mode and you want to copy items between guest and host OS.

    Policy path:

    Computer Configuration\\Administrative Templates\\Windows Components\\Remote Desktop Services\\Remote Desktop Session Host\\Device and Resource Redirection\\\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#7-enable-the-xblgamesave-standby-task","title":"7. Enable the XblGameSave Standby Task","text":"

    The scheduled task is disabled as a result of applying the Microsoft Security Baselines. Using the optional overrides, it will be enabled and its status will be set back to the default state. The task syncs Xbox game saves on PC.

    PowerShell command

    SCHTASKS.EXE /Change /TN \\Microsoft\\XblGameSave\\XblGameSaveTask /Enable\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#8-enable-microsoft-defender-exclusion-lists-to-be-visible-to-local-admins","title":"8. Enable Microsoft Defender exclusion lists to be visible to Local Admins","text":"

    This policy is located in the following Group Policy path

    Computer Configuration\\Administrative Templates\\Windows Components\\Microsoft Defender Antivirus\\Control whether or not exclusions are visible to Local Admins\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#9-disabled-turn-off-microsoft-consumer-experiences","title":"9. Disabled \"Turn off Microsoft Consumer Experiences\"","text":"

    It disables some important features in Windows Settings -> Bluetooth & Devices -> Mobile Devices

    More info in this PR

    Computer Configuration\\Administrative Templates\\Windows Components\\Cloud Content\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#10-disabled-configure-password-backup-directory","title":"10. Disabled \"Configure password backup directory\"","text":"

    Microsoft Security Baselines set its value to \"Active Directory\", but since the Harden Windows Security module does not apply to computers managed by domain controllers or Entra ID, there is no need for this policy to be active.

    Computer Configuration\\Administrative Templates\\System\\LAPS\n

    "},{"location":"Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/#11-enabled-apply-uac-restrictions-to-local-accounts-on-network-logons","title":"11. Enabled \"Apply UAC restrictions to local accounts on network logons\"","text":"

    A Security feature that is enabled by default and should stay enabled.

    Computer Configuration\\Administrative Templates\\MS Security Guide\n

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/","title":"Things to do when clean installing Windows","text":"

    There are certain tasks that need to be performed for a proper Windows clean installation. Not all of the items below apply to all hardware.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#bitlocker","title":"BitLocker","text":"

    Suspend the protection of the OS drive and make sure you have the recovery password of all other non-OS drives so that you will be able to unlock them after clean installation of the OS.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#intel-vmd-drivers-varies-by-device","title":"Intel VMD Drivers (Varies by device)","text":"

    If you use a modern hardware that uses Intel\u00ae Volume Management Device (Intel\u00ae VMD) technology, you will need to download the VMD drivers on a flash drive and load them during Windows OS installation so that the OS installer will be able to detect the internal SSD and its partitions. You can download the VMD drivers from your hardware manufacturer's website.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#clear-the-tpm-varies-by-device","title":"Clear the TPM (Varies by device)","text":"

    Not all devices have this capability in the UEFI. If your UEFI has the option to clear the TPM, use it prior to clean installation of the OS.

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#formatdelete-the-following-partitions","title":"Format/Delete the following partitions","text":"

    Let Windows recreate them during clean installation process

    "},{"location":"Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/#how-to-create-a-bootable-usb-drive-without-3rd-party-tools","title":"How to create a bootable USB drive without 3rd party tools","text":"

    Refer to this Wiki post

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/","title":"Basic PowerShell Tricks and Notes Part 2","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 2 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#view-all-predictive-intellisense-suggestions-based-on-past-history","title":"View All Predictive Intellisense Suggestions Based on Past History","text":"

    Press F2 to see the complete list of the Predictive IntelliSense suggestions as you type on the PowerShell console.

    More info

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#where-is-the-powershell-command-history-stored","title":"Where Is the Powershell Command History Stored?","text":"

    In this directory

    $env:USERPROFILE\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\n

    There is a file called ConsoleHost_history.txt and it contains the history of all the commands you've ever typed in PowerShell on your device. If you want to clear it, open the file, delete all of its content. If PowerShell is already open, close and reopen it to see the change.

    You can open the file with this command

    Invoke-Item -Path \"$env:USERPROFILE\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt\"\n

    You can use the following command to set the maximum remembered history to 1

    Set-PSReadLineOption -MaximumHistoryCount 1\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-clear-the-automatic-error-variable-in-powershell","title":"How to Clear the Automatic Error Variable in Powershell","text":"
    $error.clear()\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-last-error-type-in-powershell","title":"How to Get the Last Error Type in Powershell","text":"
    $Error[0].Exception.GetType().FullName\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-display-all-environment-variables-and-their-values-in-powershell","title":"How to Display All Environment Variables and Their Values in Powershell","text":"
    gci env:\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#list-all-mscs-and-cpls-for-microsoft-management-console-and-control-panels-in-powershell","title":"List All MSCs and CPLs for Microsoft Management Console and Control Panels in Powershell","text":"
    Get-ChildItem -Path C:\\Windows\\system32\\* -Include *.msc, *.cpl | Sort-Object -Property Extension | Select-Object -Property Name | Format-Wide -Column 2\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-mount-the-efi-system-partition","title":"How to Mount the EFI System Partition?","text":"
    mountvol u: /s\n

    This isn't a native PowerShell cmdlet, it uses mountvol CLI.

    With that command you can mount the EFI partition and assign the letter U to it, it will appear in This PC. You can browse it in PowerShell as admin.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-check-if-a-file-is-in-use-in-powershell","title":"How to Check if a File Is in Use in Powershell?","text":"

    Here is an example function that tries to rename files given to it with the same names and if it was successful, it will consider that file not in use.

    function IsFileAccessible {\n    param ([System.String]$FullFileName)\n    [System.Boolean]$IsAccessible = $false\n    try {\n        Rename-Item $FullFileName $FullFileName -ErrorVariable LockError -ErrorAction Stop\n        $IsAccessible = $true\n    }\n    catch {\n        $IsAccessible = $false\n    }\n    return $IsAccessible, $FullFileName\n}\n

    You can use it like this:

    (Get-ChildItem -Path 'C:\\Program Files\\Windows Defender' -Filter '*.exe*').FullName | ForEach-Object { IsFileAccessible -FullFileName $_ }\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#choosing-between-powershell-and-powershell-preview","title":"Choosing Between Powershell and Powershell Preview","text":"

    Use PowerShell Preview if you want to test new features and don't need to call PowerShell with its alias, pwsh, from CMD. If you do need to call it like that, use PowerShell stable.

    Use cases for it are when you need to use pwsh.exe in Windows Task Scheduler.

    PowerShell Preview by default doesn't set its pwsh.exe available system wide, the path to that file isn't added to the system environment variables, only PowerShell stable does that, but of course if you want to use PowerShell preview you can manually modify the PATH environment variable to have pwsh.exe of PowerShell Preview be available system wide.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#variable-types-in-powershell","title":"Variable Types in Powershell","text":"

    PowerShell variables can have types and type accelerator. The following command lists all of the types and their equivalent type accelerators. The fully qualified type names replace implicit with explicit.

    [PSObject].Assembly.GetType('System.Management.Automation.TypeAccelerators')::Get\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#success-codes-and-error-codes","title":"Success Codes and Error Codes","text":"

    In PowerShell, or for programming languages in general, 0 = success, 1 or anything else means failure/error.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-names-and-appids-of-installed-apps-of-the-current-user-in-powershell","title":"How to Get the Names and AppIDs of Installed Apps of the Current User in Powershell?","text":"
    Get-StartApps\n

    More info

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#difference-between-async-and-sync","title":"Difference Between Async and Sync","text":"

    Async is faster than Sync

    PowerShell supports sync/async commands workflows, also known as parallel.

    Note

    A comment under this answer:

    Oddly enough \"Synchronously\" means \"using the same clock\" so when two instructions are synchronous they use the same clock and must happen one after the other. \"Asynchronous\" means \"not using the same clock\" so the instructions are not concerned with being in step with each other. That's why it looks backwards, the term is not referring to the instructions relationship to each other. It's referring to each instructions relationship to the clock.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-enable-a-disabled-event-log-using-powershell","title":"How to Enable a Disabled Event Log Using Powershell","text":"

    First we create a new\u202fEventLogConfiguration\u202fobject and pass it the name of the log we want to configure, then we set it to enabled and save the changes.

    $LogName = 'Microsoft-Windows-DNS-Client/Operational'\n$Log = New-Object -TypeName System.Diagnostics.Eventing.Reader.EventLogConfiguration -ArgumentList $LogName\n$Log.IsEnabled = $true\n$Log.SaveChanges()\n

    We can confirm the change by running this command:

    Get-WinEvent -ListLog Microsoft-Windows-DNS-Client/Operational | Format-List -Property *\n

    Using the same method we can configure many other options of the log file, just take a look at the\u202fEventLogConfiguration Class\u202ffor a list of configurable properties.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#find-the-current-users-username-in-powershell","title":"Find the Current User\u2019s Username in Powershell","text":"
    [Environment]::UserName\n
    $env:username\n
    whoami\n
    [System.Security.Principal.WindowsIdentity]::GetCurrent().Name\n

    Most secure way

    Example

    $UserSID = [System.Security.Principal.WindowsIdentity]::GetCurrent().user.value\n(Get-LocalUser | Where-Object -FilterScript { $_.SID -eq $UserSID }).name\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-access-properties-of-an-object-in-powershell","title":"How to Access Properties of an Object in Powershell","text":"

    For example, you can first assign the entire object to a variable:

    $Preferences = Get-MpPreference\n

    Then call properties of that variable

    $Preferences.PUAProtection\n

    Another method is this:

    $(Get-MpPreference).puaprotection\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#dot-sourcing","title":"Dot-Sourcing","text":"

    To dot-source a PowerShell function in the same script file, you can use the dot operator . followed by the path of the script file containing the function. The path can be relative or absolute. Here's an example:

    # Contents of MyFunctions.ps1\nfunction New-Function {\n    Write-Host \"Hello World!\"\n}\n\n# Contents of Main.ps1\n. .\\MyFunctions.ps1\n\nNew-Function\n

    In this example, Main.ps1 dot-sources MyFunctions.ps1 using the dot operator and then calls MyFunction. When you run Main.ps1, it will output Hello World! to the console.

    The dot operator tells PowerShell to execute the script file in the current scope instead of a new scope. This means that any functions or variables defined in the script file will be available in the current scope.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#a-custom-script-to-generate-random-words-in-powershell","title":"A Custom Script to Generate Random Words in Powershell","text":"
    # Generate four variables with random names\n$TotallyRandomNamesArray = @() # Create an empty array to store the names\nfor ($i = 0; $i -lt 4; $i++) {\n    # Loop four times\n    $Chars = [CHAR[]](Get-Random -Minimum 97 -Maximum 123 -Count 11) # Generate random English letters\n    $Chars[0] = [CHAR]::ToUpper($Chars[0]) # Change the first character to upper-case\n    $TotallyRandomNamesArray += -join $Chars # Add the name to the array\n}\n# Assign the names from the Names array to the individual variables\n$TotallyRandomName1, $TotallyRandomName2, $TotallyRandomName3, $TotallyRandomName4 = $TotallyRandomNamesArray\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-see-all-the-shared-folders-and-drives","title":"How to See All the Shared Folders and Drives","text":"
    Get-CimInstance -Class Win32_Share\n

    There are other ways that are not native PowerShell cmdlets, such as

    net view \\\\$env:computername /all\n

    And

    net share\n

    Also visible from Computer => System Tools => Shared Folders => Shares

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#an-example-of-using-f-format-operator","title":"An Example of Using -F Format Operator","text":"
    Write-output(\"The drivername {0} is vulnerable with a matching SHA256 hash of {1}\" -f $Filename, $SHA256)\n

    More info

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-list-all-of-the-positional-parameters-of-a-cmdlet","title":"How to List All of the Positional Parameters of a Cmdlet","text":"

    In this example we use the

    Get-Help -Name 'Get-ChildItem' -Parameter * |\nSort-Object -Property position |\nSelect-Object -Property name, position\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-number-of-fans-and-details-about-them-in-powershell","title":"How to Get the Number of Fans and Details About Them in Powershell","text":"
    (Get-CimInstance -Namespace root/CIMV2 -ClassName Win32_Fan).count\nGet-CimInstance -Namespace root/CIMV2 -ClassName Win32_Fan\n

    P.S VMs don't have fans.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-get-the-last-reboot-time-in-powershell","title":"How to Get the Last Reboot Time in Powershell","text":"
    [System.DateTime](Get-CimInstance -ClassName win32_operatingsystem -ComputerName $_.Name).LastBootUpTime\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-add-a-ps-custom-object-to-another-ps-custom-object","title":"How to Add a PS Custom Object to Another PS Custom Object","text":"

    You can use the Add-Member cmdlet with the -InputObject parameter. The -InputObject parameter specifies the custom object that you want to add a property to, and the -Value parameter specifies the custom object that you want to add as a property. For example, you can use this code to add the $CustomObject to another custom object called $ParentObject:

    $HashTable = @{\n    Name = 'Alice'\n    Age = 25\n    Occupation = 'Teacher'\n}\n$CustomObject = [PSCustomObject]$HashTable\n\n# Create another custom object\n$ParentObject = [PSCustomObject]@{\n    ID = 123\n    Location = 'London'\n}\n\n# Add the $CustomObject as a property to the $ParentObject\nAdd-Member -InputObject $ParentObject -MemberType NoteProperty -Name Child -Value $CustomObject\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#use-crlf-instead-of-lf-for-end-of-line-characters","title":"Use CRLF Instead of LF for End of Line Characters","text":"

    In Visual Studio Code for example, you can see at the bottom right corner whether your end of line sequence is set to CRLF or LF, Windows uses CRLF.

    When you upload a PowerShell script to GitHub you need to make sure it's set to CRLF. PowerShell codes that are signed have big signature blocks at the end of them. PowerShell expects CRLF when doing authenticode signatures. You can also add those scripts to a .gitattribute config to your repo so that PowerShell files are uploaded with CRLF and not with LF.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-securely-get-the-temp-directorys-path","title":"How to Securely Get the Temp Directory's Path","text":"
    [System.IO.Path]::GetTempPath()\n

    A less secure way is this

    $env:Temp\n

    The problem with the 2nd method is that if the path is long, contains too many spaces or contains non-English characters, it might lead to pattern matching using ~1.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-securely-get-the-user-directorys-path","title":"How to Securely Get the User Directory's Path","text":"

    The Get-CimInstance cmdlet can query the Win32_UserProfile class and filter by the current user's SID to get the LocalPath property, which is the path of the current user's profile directory. This method is more accurate than using the environment variable.

    (Get-CimInstance Win32_UserProfile -Filter \"SID = '$([System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value)'\").LocalPath\n

    A less secure or accurate way is this

    $env:USERPROFILE\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-run-multiple-kernel-drivers-in-powershell","title":"How to Run Multiple Kernel Drivers In PowerShell","text":"

    If you have a folder full of .bin driver files, you can use the following command to create a kernel service and run them one by one.

    This can be useful for testing drivers against a deployed WDAC policy.

    (Get-ChildItem \"C:\\drivers\").FullName | ForEach-Object -begin {$global:i=1} -Process {\n    sc create \"DriverTest$global:i\" type=kernel binpath=\"$_\"\n    Start-Sleep -Seconds 1\n    Start-Service -Name \"DriverTest$global:i\" -ErrorAction SilentlyContinue\n    $global:i++\n}\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/#how-to-run-powershell-code-in-cmdbatch","title":"How to Run PowerShell Code in CMD/Batch","text":"

    Example, the code has no double quotes inside it

    powershell.exe -Command \"$UserSID = [System.Security.Principal.WindowsIdentity]::GetCurrent().user.value;(Get-LocalUser | where-object {$_.SID -eq $UserSID}).name\"\n

    Example, the code has double quotes inside it. We have to escape double quotes with \\\"

    powershell.exe -Command \"$UserSID = [System.Security.Principal.WindowsIdentity]::GetCurrent().user.value;$UserName = (Get-LocalUser | where-object {$_.SID -eq $UserSID}).name;Get-Process | where-object {$_.path -eq \"\\\"C:\\Users\\$UserName\\AppData\\Local\\Microsoft\\Edge SxS\\Application\\msedge.exe\\\"\"} | ForEach-Object {Stop-Process -Id $_.id -Force -ErrorAction SilentlyContinue}\"\n

    A good related answer from StackOverflow

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/","title":"Basic PowerShell Tricks and Notes Part 3","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 3 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-get-unique-items-from-a-list-of-objects-based-on-a-specific-property-only","title":"How to Get Unique Items From a List of Objects Based on a Specific Property Only","text":"

    Let's create some dummy data first

    # Create an array of 10 objects with 4 properties each\n$Objects = @()\nfor ($i = 1; $i -le 10; $i++) {\n    $Object = New-Object -TypeName PSObject -Property @{\n        'Name'         = \"Person$i\"\n        'Age'          = Get-Random -Minimum 20 -Maximum 40\n        'Gender'       = Get-Random -InputObject @('Male', 'Female')\n        'Occupation'   = Get-Random -InputObject @('Teacher', 'Engineer', 'Doctor', 'Lawyer', 'Journalist', 'Chef', 'Artist', 'Writer', 'Student', 'Manager')\n        'RandomNumber' = Get-Random -InputObject @('694646152', '9846152', '3153546')\n    }\n    $Objects += $Object\n}\n

    Then we can display that data like this in a table

    $objects | Format-Table -AutoSize\n

    Now we want to filter the result to get the unique values, but the uniqueness should be based on a specific property, which here is \"RandomNumber\". We don't want more than 1 object with the same \"RandomNumber\" property.

    To do that, we use this method in PowerShell

    $Objects | Group-Object -Property RandomNumber | ForEach-Object -Process { $_.Group[0] } | Format-Table -AutoSize\n

    You can use the Group-Object cmdlet to group the objects by the property you want to filter, and then select the first object from each group. This way, you will get one object for each \"RandomNumber\" property with all the properties intact. Using other methods such as Get-Unique or Select-Object -Unique won't work in this particular case.

    You can find more information about the Group-Object cmdlet and its parameters in this article.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#install-big-powershell-modules-system-wide","title":"Install Big Powershell Modules System Wide","text":"

    Modules such as Az or Microsoft.Graph.Beta are big, can have thousands of files and take more than 1GB space after installation.

    By default modules are installed in the Documents directory and when you use OneDrive, everything in there is synced automatically.

    You can install such modules system wide so that they won't be stored in the Documents\\PowerShell directory and instead will be stored in C:\\Program Files\\PowerShell\\Modules (for PowerShell core). This will also improve security since Administrator privileges will be required to change module files in that directory.

    To do this, you need to use the -Scope AllUsers parameter.

    Install-Module Az -Scope AllUsers\n\nInstall-Module Microsoft.Graph.Beta -Scope AllUsers\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#variable-scopes-in-foreach-object-parallel","title":"Variable Scopes in ForEach-Object -Parallel","text":"

    When using ForEach-Object -Parallel, the variables from the parent scope are read-only within the parallel script block when accessed with the $using: scope modifier. You cannot write to them or modify them inside the parallel script block. If you do not use the $using: scope modifier, they won't be available in the parallel script block at all.

    If you need to collect or aggregate results from each parallel run, you should output the results to the pipeline, and then collect them after the parallel execution. Here's an example of how you can do that:

    [System.String[]]$AnimalsList = @()\n$AnimalsList = 'Cat', 'Dog', 'Zebra', 'Horse', 'Mouse' | ForEach-Object -Parallel {\n    $_\n}\n

    In that example, the count of the $AnimalsList will be 5 and it will contain the animals in the input array.

    This example however would not work:

    [System.String[]]$AnimalsList = @()\n'Cat', 'Dog', 'Zebra', 'Horse', 'Mouse' | ForEach-Object -Parallel {\n    $AnimalsList += $_\n}\n
    Because the $AnimalsList variable is read-only in the parallel script block and only available in the local scriptblock's scope.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-get-the-sid-of-all-of-the-accounts-on-the-system","title":"How to Get the SID of All of the Accounts on the System","text":"

    SID stands for Security Identifier. It is a unique value of variable length that is used to identify a security principal or security group in Windows operating systems. SIDs are used in access control lists (ACLs) and in the user manager database (SAM) in Windows operating systems.

    You can get the SID of all the accounts on the system using the following PowerShell script:

    (Get-CimInstance -Class Win32_UserAccount -Namespace 'root\\cimv2').Name | ForEach-Object -Process {\n    [System.Security.Principal.NTAccount]$ObjSID = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $_\n    [System.Security.Principal.SecurityIdentifier]$ObjUser = $ObjSID.Translate([System.Security.Principal.SecurityIdentifier])\n    [PSCustomObject]@{\n        User = $_\n        SID  = $ObjUser.Value\n    }\n}\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-convert-a-sid-to-user-name","title":"How To Convert a SID to User Name","text":"
    [System.String]$SID = 'S-1-5-21-348961611-2991266383-1085979528-1004'\n$ObjSID = New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $SID\n$ObjUser = $ObjSID.Translate([System.Security.Principal.NTAccount])\nWrite-Host -Object 'Resolved user name: ' $ObjUser.Value -ForegroundColor Magenta\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-convert-a-user-name-to-sid","title":"How To Convert a User Name to SID","text":"
    [System.String]$UserName = 'HotCakeX'\n$ObjUser = New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList $UserName\n$ObjSID = $ObjUser.Translate([System.Security.Principal.SecurityIdentifier])\nWrite-Host -Object \"Resolved User's SID: \" $ObjSID.Value -ForegroundColor Magenta\n
    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-block-edge-traversal-for-all-of-the-firewall-rules","title":"How To Block Edge Traversal For All of the Firewall Rules","text":"
    Get-NetFirewallRule | Where-Object -FilterScript { $_.EdgeTraversalPolicy -ne 'Block' } | ForEach-Object -Process {\n    Set-NetFirewallRule -Name $_.Name -EdgeTraversalPolicy Block\n}\n

    Edge Traversal controls whether an application or service the firewall rule applies to can receive unsolicited traffic from the internet. Unsolicited traffic is traffic that is not a response to a request from the computer or user and is originated from the Internet. Solicited traffic is initiated by the computer or user.

    You can read more about it here

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#function-manipulation-with-variables-and-scriptblocks","title":"Function Manipulation With Variables And ScriptBlocks","text":"

    Suppose you have this function

    Function Write-Text {\n    [CmdletBinding()]\n    Param(\n        [Parameter(Mandatory = $true)][System.String]$InputText\n    )\n    Write-Output -InputObject $InputText\n}\n

    You can store the function in a variable like this

    [System.Management.Automation.FunctionInfo]$Function = Get-Item -Path 'Function:Write-Text'\n

    Or do it in bulk like this. In this example, $SyncHash is a synchronized hashtable used for communications between runspaces and ExportedFunctions is a nested hashtable that stores the functions inside of it.

    'Function-1', 'Function-2', 'Function-3' | ForEach-Object -Process {\n  $SyncHash['ExportedFunctions'][\"$_\"] = Get-Item -Path \"Function:$_\"\n}\n

    You can redefine the function using the same name or a different name like this. This is useful for passing the function to a different RunSpace or session.

    New-Item -Path 'Function:\\Write-TextAlt' -Value $Function -Force\n

    Redefining the functions in bulk just like the previous bulk operation above.

    Tip

    This is the recommended method of redefining the function in a different RunSpace because it completely strips its ScriptBlock of its affinity to the original RunSpace, so it'll just run on whatever the current RunSpace is without attempting to marshal.

    The affinity is about which RunSpace the script block was created in (rather than is allowed to run on).

    Basically when a scriptblock is created in a RunSpace, it knows where it came from, and when invoked outside of that RunSpace, the engine tries to send it back. This often fails because the main RunSpace is busy. So after a ~200ms time out, it will sometimes just run it on the current thread against the busy RunSpace, that causes a lot of issues, one of which is the inability to see it's parent scope. So it just forgets all commands exist and the result will be unexpected.

    Thanks to SeeminglyScience for providing this additional info.

    New-Item -Path \"Function:\\$($_.Key)\" -Value $_.Value.ScriptBlock.Ast.Body.GetScriptBlock() -Force | Out-Null\n

    Tip

    This method isn't recommended as it will maintain the ScriptBlock's affinity to the original RunSpace.

    $SyncHash.ExportedFunctions.GetEnumerator() | ForEach-Object -Process {\n    New-Item -Path \"Function:\\$($_.Key)\" -Value $_.Value.ScriptBlock -Force | Out-Null\n}\n

    Invoke the function using its new name, just as you would with the original function.

    Write-Text -InputText 'Hello from the original function!'\nWrite-TextAlt -InputText 'Hello from the new function!'\n

    You can also create a scriptblock from the function using the following approach

    $ScriptBlock = [System.Management.Automation.ScriptBlock]::Create($Function.Definition)\n

    And then call the scriptblock like this

    &$ScriptBlock 'Hello from the ScriptBlock! (direct call)'\n. $ScriptBlock 'Hello from the ScriptBlock! (dot sourced)'\nInvoke-Command -ScriptBlock $ScriptBlock -ArgumentList 'Hello from the ScriptBlock! (Invoke-Command)'\n

    Tip

    When orchestrating tasks across multiple RunSpaces with synchronized Hashtables, it's crucial to ensure seamless function transfer. Follow these steps for optimal results:

    1. Convert the desired function into a ScriptBlock.
    2. Store the ScriptBlock in the synchronized Hashtable.
    3. Redefine the ScriptBlock in the target RunSpace.

    This approach is necessary because simply saving the function to a variable, redefining it as a function in the destination RunSpace, and executing it won't replicate the original function's behavior outside the RunSpace context.

    Alternatively, you can define your code as ScriptBlocks instead of functions from the beginning.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/#how-to-achieve-pseudo-lexical-variable-scoping-in-powershell","title":"How To Achieve Pseudo-Lexical Variable Scoping in PowerShell","text":"

    Lexical Scoping means:

    PowerShell does not have true lexical scoping, but you can achieve pseudo-lexical scoping using C# types. Here's an example where we define a C# class with static members to store variables.

    # A path defined in the parent scope\n$SomePath = 'C:\\FolderName\\FolderName2'\n\nAdd-Type -TypeDefinition @\"\nnamespace NameSpace\n{\n    public static class ClassName\n    {\n        public static int SomeNumber = 456;\n        public static string path = $(\"`\"$($SomePath -replace '\\\\', '\\\\')`\"\");\n    }\n}\n\"@ -Language CSharp\n

    The benefit of this approach is that you can access the variables from any scope across the PowerShell App Domain. That means any RunSpace you create, or any job started by either Start-ThreadJob or Start-Job cmdlets, without having to pass them as arguments.

    Another great feature of this approach is that you don't need to set the value of the variables in the C# code, you can simply define the variable in C# and then assign the values in PowerShell side.

    In this example, I'm only defining the variables:

    Add-Type -TypeDefinition @\"\nnamespace NameSpace\n{\n    public static class ClassName\n    {\n        public static int SomeNumber;\n        public static string path;\n        public static object MDAVConfigCurrent;\n    }\n}\n\"@ -Language CSharp\n

    And now I can set any value to the variables in PowerShell side

    [NameSpace.ClassName]::SomeNumber = 123\n[NameSpace.ClassName]::path = 'C:\\FolderName\\FolderName2'\n[NameSpace.ClassName]::MDAVConfigCurrent = Get-MpPreference\n

    You can now use the variables anywhere by accessing them

    Write-Host -Object ([NameSpace.ClassName]::SomeNumber)\nWrite-Host -Object ([NameSpace.ClassName]::path)\nWrite-OutPut -InputObject ([NameSpace.ClassName]::MDAVConfigCurrent)\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/","title":"Basic PowerShell Tricks and Notes Part 4","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 4 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/#how-to-bypass-powershell-constant-variables-and-how-to-prevent-the-bypass","title":"How To Bypass PowerShell Constant Variables And How To Prevent The Bypass","text":"

    When using Set-Variable cmdlet to create a constant variable, you can't change the value of that variable later in the script by simple assignments, but there is a way to bypass this limitation using reflection.

    Set-Variable -Name 'MyConstantVariable' -Value 'Hello World' -Option 'Constant'\n$MyConstantVariable\n\n$PSVar = Get-Variable -Name 'MyConstantVariable'\n$PSVar.GetType().GetField('_value', [System.Reflection.BindingFlags] 'NonPublic, Instance').SetValue($PSVar, 'Wut')\n$MyConstantVariable\n\n$PSVar.GetType().GetField('_options', [System.Reflection.BindingFlags] 'NonPublic, Instance').SetValue($PSVar, [System.Management.Automation.ScopedItemOptions]::None)\n$MyConstantVariable = 'Lolz'\n$MyConstantVariable\n

    Shout out to Santiago Squarzon for this trick.

    The way you can prevent this bypass is by defining constant variables in C# code in PowerShell. The reflection method demonstrated above won't work on this type of constant variables.

    Add-Type -TypeDefinition @'\nnamespace NS\n{\n    public static class Const\n    {\n        public const int myConst = 66;\n    }\n}\n'@ -Language CSharp\n\n([NS.Const]::myConst)\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/#how-to-prevent-powershell-optimization-from-being-disabled","title":"How To Prevent PowerShell Optimization From Being Disabled","text":"

    In PowerShell, the presence of the following commands in a ScriptBlock will completely disable optimizations in that ScriptBlock:

    New-Variable\nRemove-Variable\nSet-Variable\nSet-PSBreakpoint\n# Also Dot-Sourcing\n. .\\file.ps1\n# Also if any type of breakpoint is already set\n

    Also usage of any AllScope variable in a ScriptBlock will disable optimization in there.

    You can view those commands in here too.

    Shout out to SeeminglyScience for this info.

    Any PowerShell code at some point will run and be in a ScriptBlock. Functions are their own ScriptBlock, modules (.psm1 files) are their own ScriptBlock, script files (.ps1 files) are their own ScriptBlock, ScriptBlocks themselves are their own ScriptBlock and so on.

    So the presence of the above methods and commands inside a ScriptBlock in the context explained above will disable optimization in that ScriptBlock, you can however use them outside of the ScriptBlock and then utilize them inside which will not disable optimization in that ScriptBlock.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/#the-fastest-way-to-enumerate-all-files-in-directories-based-on-specific-extensions","title":"The Fastest Way To Enumerate All Files In Directories Based On Specific Extensions","text":"

    This example will enumerate all files in an array of directories based on specific extensions and return an array of FileInfo objects. This is potentially the fastest and most optimized way to do this. This command takes ~9 seconds to complete on my system.

    # Define a HashSet of file extensions to filter by\n$Extensions = [System.Collections.Generic.HashSet[System.String]]@('.sys', '.exe', '.com', '.dll', '.rll', '.ocx', '.msp', '.mst', '.msi', '.js', '.vbs', '.ps1', '.appx', '.bin', '.bat', '.hxs', '.mui', '.lex', '.mof')\n# Define an array of directory paths to scan through\n[System.IO.DirectoryInfo[]]$Paths = 'C:\\ProgramData\\Microsoft', 'C:\\Program Files\\Windows Defender', 'C:\\Program Files\\Hyper-V'\n# Define a HashSet to store the initial output\n$Output = [System.Collections.Generic.HashSet[System.IO.FileInfo]]@()\n# Define the GetFiles parameters\n$Options = [System.IO.EnumerationOptions]@{\n    IgnoreInaccessible    = $true\n    # This is equal to -Recurse parameter in Get-ChildItem cmdlet\n    RecurseSubdirectories = $true\n    # By default is skips hidden and system files, here we just skip the System files\n    # https://learn.microsoft.com/en-us/dotnet/api/system.io.fileattributes\n    # https://learn.microsoft.com/en-us/dotnet/api/system.io.enumerationoptions.attributestoskip\n    AttributesToSkip      = 'System'\n}\n\n# Loop over each path and add the files to the output HashSet using UnionWith\nforeach ($Path in $Paths) {\n    $Output.UnionWith((Get-Item -LiteralPath $Path).GetFiles('*', $Options))\n}\n# Define a HashSet to store the filtered output - Making sure the comparison is case-insensitive since \"Get-ChildItem -Include\" is case-insensitive as well and we don't want to miss files with \".DLL\" extension and so on\n$OutputAfterFiltering = [System.Collections.Generic.HashSet[System.IO.FileInfo]]@( $Output.Where({ $Extensions.Contains($_.Extension.ToLower()) }))\n

    This is an improved variation of the script above that handles inaccessible directories better but takes a few seconds (~3) more to complete.

    # Define a HashSet of file extensions to filter by\n$Extensions = [System.Collections.Generic.HashSet[System.String]]::new(\n    [System.String[]] ('.sys', '.exe', '.com', '.dll', '.rll', '.ocx', '.msp', '.mst', '.msi', '.js', '.vbs', '.ps1', '.appx', '.bin', '.bat', '.hxs', '.mui', '.lex', '.mof'),\n    # Make it case-insensitive\n    [System.StringComparer]::InvariantCultureIgnoreCase\n)\n# Define an array of directory paths to scan through\n[System.IO.DirectoryInfo[]]$Paths = 'C:\\ProgramData\\Microsoft', 'C:\\Program Files\\Windows Defender', 'C:\\Program Files\\Hyper-V'\n# Define a HashSet to store the initial output\n$Output = [System.Collections.Generic.HashSet[System.IO.FileInfo]]@()\n# Define the GetFiles parameters\n$Options = [System.IO.EnumerationOptions]@{\n    IgnoreInaccessible    = $true\n    # This is equal to -Recurse parameter in Get-ChildItem cmdlet\n    RecurseSubdirectories = $true\n    # This is equal to -Force parameter in Get-ChildItem cmdlet\n    AttributesToSkip      = 'None'\n}\n\n$Output = foreach ($Path in $Paths) {\n    [System.IO.Enumeration.FileSystemEnumerator[System.IO.FileInfo]]$Enum = $Path.EnumerateFiles('*', $Options).GetEnumerator()\n    while ($true) {\n        try {\n            # Move to the next file\n            if (-not $Enum.MoveNext()) {\n                # If we reach the end of the enumeration, we break out of the loop\n                break\n            }\n            # Check if the file extension is in the Extensions HashSet\n            if ($Extensions.Contains($Enum.Current.Extension)) {\n                # Pass the file to the output\n                $Enum.Current\n            }\n        }\n        catch {}\n    }\n}\n

    Shout out to Santiago Squarzon for providing this method.

    For comparison, the following command takes ~20 minutes to complete on my system and produces the same exact output as the scripts above but it's 100x times slower.

    [System.IO.DirectoryInfo[]]$Paths = 'C:\\ProgramData\\Microsoft', 'C:\\Program Files\\Windows Defender', 'C:\\Program Files\\Hyper-V'\n[System.String[]]$Extensions = @('*.sys', '*.exe', '*.com', '*.dll', '*.rll', '*.ocx', '*.msp', '*.mst', '*.msi', '*.js', '*.vbs', '*.ps1', '*.appx', '*.bin', '*.bat', '*.hxs', '*.mui', '*.lex', '*.mof')\n[System.IO.FileInfo[]]$Output = Get-ChildItem -Recurse -File -LiteralPath $Paths -Include $Extensions -Force -ErrorAction SilentlyContinue\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/","title":"Basic PowerShell Tricks and Notes","text":"

    This page is designed for beginners and newcomers to PowerShell who want to quickly learn the essential basics, the most frequently used syntaxes, elements and tricks. It should help you jump start your journey as a PowerShell user.

    The main source for learning PowerShell is Microsoft Learn websites. There are extensive and complete guides about each command/cmdlet with examples.

    PowerShell core at Microsoft Learn

    You can also use the Windows Copilot for asking any PowerShell related questions, code examples etc.

    This is part 1 of this series, find other parts here:

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#pipeline-variable","title":"Pipeline Variable","text":"

    $_ is the variable for the current value in the pipeline.

    Examples

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#filtering-data-with-where-object","title":"Filtering Data With Where-Object","text":"

    ? which is an alias for Where-Object, is used to filter all the data given to it.

    Where-Object

    Example

    Get-PSDrive | ?{$_.free -gt 1}\n

    Example

    Get-PSDrive | Where-Object {$_.free -gt 1}\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#show-the-properties-of-an-object-selectively","title":"Show the Properties of an Object Selectively","text":"

    Select or Select-Object show the properties that we want to see from an object

    If we use * then all of the properties will be shown and from there we can choose which properties to add.

    Example:

    Get-PSDrive | Where-Object {$_.free -gt 1} | Select-Object -Property *\n\nGet-PSDrive | Where-Object {$_.free -gt 1} | Select-Object -Property root, used, free\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#looping-using-foreach-object","title":"Looping Using Foreach-Object","text":"

    The ForEach-Object cmdlet performs an operation on each item in a collection of input objects. The input objects can be piped to the cmdlet or specified using the InputObject parameter.

    In other words: for every item in the pipe, run this line.

    Examples:

    Get-PSDrive | Where-Object { $_.free -gt 1 } | Select-Object -Property root, used, free | ForEach-Object { 'zebra' }\n
    Get-PSDrive | Where-Object { $_.free -gt 1 } | Select-Object -Property root, used, free | ForEach-Object { Write-Host 'Free Space for ' $_.Root 'is' ($_.free / 1gb ) }\n

    The parenthesis, ($_.free/1gb ) must be there if we want to modify one of the output strings.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#to-get-online-help-about-any-cmdlet","title":"To Get Online Help About Any Cmdlet","text":"

    These commands open the webpage for the specified cmdlet or command

    Get-help <cmdlet> \u2013online\n
    Get-Help dir \u2013online\n
    Get-Help ForEach-Object \u2013online\n

    This shows the full help on the PowerShell console

    Get-help Get-Service -full\n

    This opens a new window showing the full help content and offers other options such as Find

    Get-help Get-Service -ShowWindow\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#to-query-windows-services","title":"To Query Windows Services","text":"

    This gets any Windows service that has the word \"Xbox\" in it.

    Get-Service \"*xbox*\"\n

    This gets any Windows service that has the word \"x\" in it.

    Get-Service \"*x*\"\n

    Putting * around the word or letter finds anything that contains it.

    Get-Service \"*x*\" | Sort-Object status\n

    Example syntax:

    Get-Service [[-Name] <System.String[]>] [-ComputerName <System.String[]>] [-DependentServices] [-Exclude <System.String[]>] [-Include <System.String[]>] [-RequiredServices] [<CommonParameters>]\n

    In this part

    Get-Service [[-Name] <System.String[]>]\n

    The -Name Parameter accepts <System.String[]>, which is a StringList, and when [] is included, that means there can be multiple inputs/strings, separated by comma ,.

    So [[-Name] <System.String[]>] can be used like this:

    Get-Service -Name WinRM,BITS,*Xbox*\n

    Also in another similar example syntax:

    Get-Service [-ComputerName <System.String[]>] [-DependentServices] -DisplayName <System.String[]> [-Exclude <System.String[]>] [-Include <System.String[]>] [-RequiredServices] [<CommonParameters>]\n

    Everything is inside a bracket except for -DisplayName, that means it is mandatory. If a parameter is inside a bracket, that means it is optional.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-suppress-errors-in-powershell","title":"How to Suppress Errors in Powershell","text":"
    -ErrorAction SilentlyContinue\n

    Everything you wanted to know about exceptions

    Try/Catch will only 'trigger' on a terminating exception. Most cmdlets in PowerShell, by default, won't throw terminating exceptions. You can set the error action with the\u202f-ErrorAction\u202for -ea parameters:

    Do-Thing 'Stuff' -ErrorAction Stop\n

    Be careful when using -ErrorAction Stop. If using it in loops like with ForEach-Object, it will stop the entire loop after the first encounter of error.

    Handling Errors the PowerShell Way

    Tip: If you set

    $ErrorActionPreference = 'Stop'\n

    In your PowerShell code, either locally or globally for the entire script, Write-Error will cause the script to stop because it will be like throwing an error.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#get-file-signature-of-all-of-the-files-in-a-folder","title":"Get File Signature of All of the Files in a Folder","text":"

    This will check all of the files' signatures in the current directory

    Get-ChildItem -File | ForEach-Object -Process {Get-AuthenticodeSignature -FilePath $_}\n

    More info about Get-ChildItem cmdlet

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#write-output-to-a-file-or-string","title":"Write Output to a File or String","text":"
    > output.txt\n

    Example:

    ipconfig /all > mynetworksettings.txt\n

    about_Redirection

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-add-delaypause-to-the-execution-of-powershell-script","title":"How to Add Delay/Pause to the Execution of Powershell Script","text":"

    To sleep a PowerShell script for 5 seconds, you can run the following command

    Start-Sleep -Seconds 5\n

    You can also use the -milliseconds parameter to specify how long the resource sleeps in milliseconds.

    Start-Sleep -Milliseconds 25\n

    Start-Sleep

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-stopkill-a-a-process-or-exe-executable-in-powershell","title":"How to Stop/Kill a a Process or (.exe) Executable in Powershell","text":"

    Using native PowerShell cmdlet

    Stop-Process -Name \"Photoshop\"\n

    Stop-Process

    Using taskkill.exe

    taskkill /IM \"photoshop app.exe\" /F\n

    taskkill

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#automatically-answer-yes-to-a-prompt-in-powershell","title":"Automatically Answer \u201cYes\u201d to a Prompt in Powershell","text":"

    Use \u2013force at the end of the command

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#displays-all-information-in-the-current-access-token","title":"Displays All Information in the Current Access Token","text":"

    The command below displays all information in the current access token, including the current user name, security identifiers (SID), privileges, and groups that the current user belongs to.

    whoami /all\n

    whoami

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#display-all-the-tcp-and-udp-ports-on-which-the-computer-is-listening","title":"Display All the Tcp and Udp Ports on Which the Computer Is Listening","text":"
    netstat -a\n

    netstat

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#copy-the-result-of-a-command-to-clipboard-automatically","title":"Copy the Result of a Command to Clipboard Automatically","text":"

    Add | clip at the end the command

    Example:

    Get-TimeZone | clip\n

    Example:

    rg -i -F URL: | clip\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-scan-2-text-files-for-differences-and-pipe-the-difference-to-a-third-file","title":"How to Scan 2 Text Files for Differences and Pipe the Difference to a Third File","text":"
    $File1 = \"C:\\Scripts\\Txt1.txt\"\n$File2 = \"C:\\Scripts\\Txt2.txt\"\n$Location = \"C:\\Scripts\\Txt3.txt\"\n\nCompare-Object -ReferenceObject (Get-Content -Path $File1) -DifferenceObject (Get-Content -Path $File2) | Format-List | Out-File -FilePath $Location\n

    Compare-Object

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#difference-between-strings-and-stringlists","title":"Difference Between Strings and StringLists","text":"

    This is Stringlist in PowerShell:

    [String[]]

    And this is a string

    [String]

    When we define Stringlist in a parameter, then the argument will keep asking for multiple values instead of 1, if we want to stop adding arguments for the parameter, we have to enter twice.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-run-a-powershell-ps1-script","title":"How to Run a Powershell (.PS1) Script ?","text":"
    &\"Path\\To\\PS\\Script.ps1\"\n

    Using the & Call operator

    Set-Location 'Path\\To\\Folder\\OfThe\\Script'\n.\\Script.ps1\n
    pwsh.exe -File 'Path\\To\\Folder\\OfThe\\Script.ps1'\n

    This example uses PowerShell Core

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#enclosing-strings-that-have-a-lot-of-single-and-double-quotation-marks","title":"Enclosing Strings That Have a Lot of Single and Double Quotation Marks","text":"
    $string =@\"\n\nSome string text\n\n\"@\n\n$string\n

    the markers @\" and \"@ indicating the beginning and end of the string must be on separate lines.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#how-to-find-the-type-of-the-output-of-a-command-in-powershell","title":"How to Find the Type of the Output of a Command in Powershell","text":"

    Using GetType()

    Examples:

    (Get-BitlockerVolume -MountPoint \"C:\").KeyProtector.keyprotectortype.GetType()\n
    (Get-NetTCPConnection).GetType()\n

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#make-sure-to-use-pascal-case-for-variable-names","title":"Make Sure to Use Pascal Case for Variable Names","text":"

    Pascal Case requires variables made from compound words and have the first letter of each appended word written with an uppercase letter.

    Example: $Get-CurrentTime

    This will make your code readable and more understandable.

    "},{"location":"PowerShell/Basic%20PowerShell%20tricks%20and%20notes/#some-popular-resources-and-cmdlets","title":"Some Popular Resources and Cmdlets","text":"

    "},{"location":"PowerShell/How%20To%20Access%20All%20Stream%20Outputs%20From%20Thread%20Jobs%20In%20PowerShell%20In%20Real%20Time/","title":"How To Access All Stream Outputs From Thread Jobs In PowerShell In Real Time","text":"

    The following code snippet demonstrates how to access all stream outputs from thread jobs in PowerShell in real time. It uses the Start-ThreadJob cmdlet to start the thread jobs and the Receive-Job cmdlet to access the job output streams. The code snippet also demonstrates how to access the warning, debug, verbose, output, host, and information streams from the thread jobs.

    It is properly commented to explain each part of the code.

    [System.String[]]$JobNames = 'cat', 'dog', 'Zebra', 'kangaroo'\n\n# A hashtable to store the jobs\n[System.Collections.Hashtable]$Jobs = @{}\n\n# Start a job for each animal in the list\nforeach ($JobName in $JobNames) {\n\n    [System.Management.Automation.Job2]$CurrentJob = Start-ThreadJob -Name \"Animals $JobName\" -ScriptBlock {\n        Param ($JobNameInput)\n        #   $ErrorActionPreference = 'Stop'\n\n        Write-Output -InputObject \"Job started for $JobNameInput\"\n\n        # Simulate some real work\n        Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 10)\n\n        Throw 1 / 0\n\n        Write-Error -Message \"Error message for $JobNameInput\"\n\n        Write-Warning -Message \"Warning message for $JobNameInput\"\n        Write-Debug -Message \"Debug Message for $JobNameInput\" -Debug\n        Write-Verbose -Message \"Verbose message for $JobNameInput\" -Verbose\n        Write-Output -InputObject \"Output message for $JobNameInput\"\n        Write-Host -Object \"Host message for $JobNameInput\"\n        Write-Information -MessageData \"Information message for $JobNameInput\"\n\n    } -ArgumentList $JobName\n\n    # Add the job to the hashtable with the job object as the key and its name as the value\n    $Jobs[$CurrentJob] = $JobName\n}\n\n# Continuously check for job output\nwhile ($Jobs.Count -ne 0) {\n\n    # An array of the jobs to remove\n    [System.Management.Automation.Job2[]]$JobsToRemove = @()\n\n    foreach ($Job in $Jobs.Keys) {\n\n        # Accessing individual output streams from the job that Receive-Job does not display\n        # $Job.Warning - not required - Receive-Job shows it\n        $Job.Debug\n        $Job.Progress\n        # $Job.Error - not required - Receive-Job shows it\n        $Job.Information # Also displays the Write-Host message\n\n        # Gets the success, error, warning and host stream from Write-Host\n        Receive-Job -Job $Job\n\n        if ($Job.State -eq 'Completed' -or $Job.State -eq 'Failed') {\n\n            #  if ($Job.State -eq 'Failed') {\n            #      Write-Output \"Job $($Job.Id) failed with reason: $($Job.JobStateInfo.Reason)\"\n            #  }\n\n            # Remove the job\n            Remove-Job -Job $Job -Force\n\n            # Add the job to the list of jobs to remove\n            $JobsToRemove += $Job\n        }\n    }\n\n    # Remove the jobs from the hashtable\n    foreach ($Job in $JobsToRemove) {\n        $Jobs.Remove($Job)\n    }\n\n    # Define the interval for checking the jobs\n    Start-Sleep -Milliseconds 500\n}\n\n# Getting all of the jobs to make sure nothing is left\nGet-Job\n

    "},{"location":"PowerShell/How%20To%20Access%20All%20Stream%20Outputs%20From%20Thread%20Jobs%20In%20PowerShell%20In%20Real%20Time/#highly-recommended-to-read-the-following-related-articles","title":"Highly recommended to read the following related articles:","text":""},{"location":"PowerShell/How%20To%20Asynchronously%20Access%20All%20Stream%20Outputs%20From%20Background%20Jobs%20In%20PowerShell/","title":"How To Asynchronously Access All Stream Outputs From Background Jobs In PowerShell","text":"

    In this article, we will learn how to asynchronously access all stream outputs from background jobs in PowerShell. We will use the Start-Job cmdlet to start a job for each animal in the list. We will then use the Register-ObjectEvent cmdlet to create an event subscriber for the job to automatically receive the job output for all streams and discard itself and the job. We will also use the Unregister-Event cmdlet to remove the event itself and the Remove-Job cmdlet to remove the event subscriber's job.

    We will also properly communicate any terminating or non-terminating error that ocurred inside of each job to the console.

    [System.String[]]$JobNames = 'cat', 'dog', 'Zebra', 'kangaroo'\n\n# Start a job for each animal in the list\nforeach ($JobName in $JobNames) {\n\n    $CurrentJob = Start-Job -Name \"Animals $JobName\" -ScriptBlock {\n        Param ($JobNameInput)\n\n        Start-Sleep -Seconds 2\n\n        Write-Output -InputObject \"Job started for $JobNameInput\"\n\n        # Simulate some real work\n        Start-Sleep -Seconds (Get-Random -Minimum 1 -Maximum 10)\n\n        # Generate terminating error\n        # Throw \"Error message for $JobNameInput\"\n\n        # Generate Non-terminating error\n        Write-Error -Message \"Error message 1 for $JobNameInput\"\n\n        Write-Warning -Message \"Warning message for $JobNameInput\"\n        Write-Debug -Message \"Debug Message for $JobNameInput\" -Debug\n        Write-Verbose -Message \"Verbose message for $JobNameInput\" -Verbose\n        Write-Error -Message \"Error message 2 for $JobNameInput\"\n        Write-Output -InputObject \"Output message for $JobNameInput\"\n        Write-Host -Object \"Host message for $JobNameInput\"\n        Write-Information -MessageData \"Information message for $JobNameInput\"\n\n    } -ArgumentList $JobName\n\n    # Create an event subscriber for the job to automatically receive the job output for all streams and discard itself and the job\n    Register-ObjectEvent -InputObject $CurrentJob -EventName StateChanged -Action {\n\n        # Receive the Write-Output stream for success stream\n        # Write-Host is needed to display the error message on the console\n        # We need to use loop because all of the Write-Output messages are stored in the ChildJobs.Output property\n        # And without a loop, they would all be written as a single string on in one line\n        if ($null -ne $EventSubscriber.SourceObject.ChildJobs.Output) {\n            $EventSubscriber.SourceObject.ChildJobs.Output | ForEach-Object -Process {\n                Write-Host -Object $_\n            }\n        }\n\n        # Check if a terminating error ocurred in the job\n        if ($EventSubscriber.SourceObject.State -eq 'Failed') {\n            Write-Host -Object \"The Job $($EventSubscriber.SourceObject.Name) Failed\" -ForegroundColor Red\n        }\n\n        # Receive the Terminating error stream - Write-Host is needed to display the error message on the console\n        if ($null -ne $EventSubscriber.SourceObject.ChildJobs.JobStateInfo.Reason.Message) {\n            $EventSubscriber.SourceObject.ChildJobs.JobStateInfo.Reason.Message | ForEach-Object -Process {\n                Write-Host -Object $_ -ForegroundColor Red\n            }\n        }\n\n        # Receive the Non-Terminating error stream - Write-Host is needed to display the error message on the console\n        if ($null -ne $EventSubscriber.SourceObject.ChildJobs.Error) {\n            $EventSubscriber.SourceObject.ChildJobs.Error | ForEach-Object -Process {\n                Write-Host -Object $_ -ForegroundColor DarkRed\n            }\n        }\n\n        # Receive the job output except for Wire-Output and error stream\n        Receive-Job -Job $EventSubscriber.SourceObject\n\n        # Unregister the event itself\n        Unregister-Event -SourceIdentifier $EventSubscriber.SourceIdentifier -Force\n        # Remove the event subscriber's job, it is the same as the event subscriber's SourceIdentifier\n        Remove-Job -Name $EventSubscriber.SourceIdentifier -Force\n        # Remove the input job initiated by Start-Job\n        Remove-Job -Id $EventSubscriber.SourceObject.Id -Force\n\n    } | Out-Null\n}\n\n# Get all of the jobs at the end to make sure there is no leftover\n# Get-Job\n\n# Make sure all of the event subscriptions have been properly removed at the end\n# (Get-EventSubscriber).SourceIdentifier\n\n# https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables#eventsubscriber\n# $EventSubscriber inside of the action block is the same as the following objects\n# (Get-EventSubscriber)[0].SourceObject.ChildJobs.JobStateInfo.Reason.Message\n# (Get-EventSubscriber).SourceObject.ChildJobs.output\n

    "},{"location":"PowerShell/How%20To%20Asynchronously%20Access%20All%20Stream%20Outputs%20From%20Background%20Jobs%20In%20PowerShell/#note-about-why-we-needed-to-access-childjobs-property","title":"Note About Why We Needed To Access ChildJobs Property","text":"

    when you use Start-Job to initiate a background job, it executes the provided script block in a separate, child job. This is because Start-Job is designed to run tasks asynchronously, allowing the main PowerShell session to continue without waiting for the task to complete.

    The child job is essentially a separate PowerShell process that runs in the background. It's isolated from the parent job, which means it has its own scope and doesn't share variables or RunSpaces with the parent. This isolation ensures that the main session remains responsive and that the background task doesn't interfere with the ongoing tasks in the main session.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/","title":"PowerShell Best Practices To Follow When Coding","text":"

    It is important to follow best practices when coding in PowerShell to ensure that your codes are efficient, maintainable, and secure.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#specify-the-variable-types-explicitly","title":"Specify The Variable Types Explicitly","text":"

    \ud83d\udeab Don't do this

    $Var = 5\n

    \u2705 Do this instead

    [System.Int32]$Var = 5\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-full-type-names-instead-of-type-accelerators","title":"Use Full Type Names Instead of Type Accelerators","text":"

    \ud83d\udeab Don't do this

    [String]$Var = 'Hello'\n

    \u2705 Do this instead

    [System.String]$Var = 'Hello'\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-single-quotes-instead-of-double-quotes-unless-absolutely-necessary","title":"Use Single Quotes Instead of Double Quotes Unless Absolutely Necessary","text":"

    \ud83d\udeab Don't do this

    $Var = \"Hello\"\n

    \u2705 Do this instead

    $Var = 'Hello'\n

    This is because double quotes allow for string interpolation, which can be a security risk if the string is not sanitized properly and also slightly slower than single quotes.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-full-cmdlet-names-instead-of-aliases","title":"Use Full Cmdlet Names Instead of Aliases","text":"

    \ud83d\udeab Don't do this

    Gci\ncls\n

    \u2705 Do this instead

    Get-ChildItem\nClear-Host\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-pascal-casing-for-everything","title":"Use Pascal Casing for Everything","text":"

    \ud83d\udeab Don't do this

    $myvariable\nget-childitem\nnew-item\n

    \ud83d\udeab or this (camelCase)

    $myVariable\nget-ChildItem\nnew-Item\n

    \u2705 Do this instead

    $MyVariable\nGet-ChildItem\nNew-Item\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-regions-to-organize-your-code","title":"Use Regions to Organize Your Code","text":"

    \u2705 Using regions like this allows you to collapse and expand sections of your code for better readability.

    #Region Functions\nfunction Get-MyFunction1 {\n    # Function code here\n}\nfunction Get-MyFunction2 {\n    # Function code here\n}\nfunction Get-MyFunction3 {\n    # Function code here\n}\n#EndRegion\n

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#use-visual-studio-code-powershell-extension-for-automatic-best-practice-formatting","title":"Use Visual Studio Code PowerShell Extension For Automatic Best Practice Formatting","text":"

    You can access the settings page of PowerShell extension in VS Code and enable options that automatically apply some of the aforementioned best practices when you format your code with (CTRL + Shift + F) shortcut.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#refrain-from-defining-and-using-global-variables-as-much-as-possible","title":"Refrain From Defining and Using Global Variables as Much as Possible","text":"

    Global variables are not recommended in general because of security implications. They can be overwritten by the user on console as well.

    If you need to define global variables, make sure you set them as constants or read-only so that they cannot be overwritten once they are defined.

    "},{"location":"PowerShell/PowerShell%20Best%20Practices/#more-resources-from-microsoft-that-you-should-check-out","title":"More Resources From Microsoft That You Should Check Out","text":""},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/","title":"Powershell Dynamic Parameters and How to Add Them to the Get-Help Syntax","text":"

    PowerShell has a feature called dynamic parameters that allows you to add parameters to a cmdlet based on the value of another parameter. This is useful when you have a parameter that can take multiple values and you want to add additional parameters based on the value of the first parameter.

    Dynamic parameters also allow you to make a parameter conditionally mandatory based on different criteria.

    They are very powerful but have a downside: since they are runtime-defined, they are not displayed in the Get-Help output. This can be a problem if you want to provide help to users of your cmdlet and inform them of all of the available parameters that your cmdlet supports, including the dynamic ones.

    Usually, PowerShell developers use comment-based help inside of the cmdlet's function to provide help content to the user, however that approach doesn't allow us to control all aspects of the help content, such as the syntax. If you want to add the dynamic parameters to the Get-Help output's syntax, you will need to switch to XML-based help.

    "},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/#platyps","title":"PlatyPS","text":"

    PlatyPS is a module that allows you to generate XML-based help for your cmdlets. It can be used to add dynamic parameters to the Get-Help output's syntax. You will be editing a Markdown file which is convenient and the module will automatically generate the XML help file for you.

    "},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/#create-a-markdown-file-based-on-your-cmdlet","title":"Create a Markdown file Based on your Cmdlet","text":"
    New-MarkdownHelp -Command 'YourCmdletName' -OutputFolder \".\\docs\"\n

    After you've created a markdown file based on your current cmdlet's parameters and details, you can start adding the dynamic parameters to it and modify the syntax, because dynamic parameters are not automatically added to it. Once you are done, you can run the following command to generate the XML help file.

    "},{"location":"PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/#generate-the-xml-help-file-from-the-markdown-file","title":"Generate the XML Help File from the Markdown file","text":"
    New-ExternalHelp -Path \"Path-To-Markdown-File.md\" -OutputPath \"Path-To-XML-File.xml\" -Force\n

    After creating your XML-based help file, you will then have to reference it in your cmdlet's function like this

    .EXTERNALHELP .\\Help\\Cmdlet-Name.xml\n

    The path doesn't accept variables but it can be either relative or full path to the XML help file. Once you reference that, you can either remove all of the comment-based help from the function or keep them, the XML-based help takes precedence over the comment-based help when both types of help content are present.

    "},{"location":"PowerShell/RunSpaces%20In%20PowerShell/","title":"RunSpaces In PowerShell","text":"

    The concept of Runspaces is built upon the .NET threading model, which allows PowerShell to execute multiple scripts or commands in parallel. This is achieved by creating separate instances of the PowerShell engine, each running in its own thread, thus not interfering with the primary PowerShell session or other Runspaces.

    Utilizing Runspaces effectively requires an understanding of threading and synchronization, as data sharing between threads must be handled carefully to avoid race conditions and ensure thread safety. The synchronized hashtable, as demonstrated in the provided script, is a prime example of a thread-safe data structure that facilitates communication between Runspaces.

    "},{"location":"PowerShell/RunSpaces%20In%20PowerShell/#how-to-create-runspace-and-powershell-instance-and-reuse-them","title":"How To Create RunSpace and PowerShell Instance and Reuse Them","text":"
    # Display the number of the runspaces before operation\n(Get-Runspace).count\n\n# Create a synchronized hashtable for inter-runspace communication\n$SyncHash = [System.Collections.Hashtable]::Synchronized(@{})\n\n# Create a new runspace\n$GUIRunSpace = [System.Management.Automation.RunSpaces.RunSpaceFactory]::CreateRunSpace()\n$GUIRunSpace.ApartmentState = 'STA'\n$GUIRunSpace.ThreadOptions = 'ReuseThread'\n\n# Create a new PowerShell object\n$GUIPowerShell = [System.Management.Automation.PowerShell]::Create()\n# Assign the runspace to the PowerShell object's Runspace property\n$GUIPowerShell.RunSpace = $GUIRunSpace\n# Open the runspace\n$GUIRunSpace.Open()\n\n# Make the synchronized hashtable available in the runspace\n$GUIRunSpace.SessionStateProxy.SetVariable('SyncHash', $SyncHash)\n\n# Add a script to the PowerShell object so that it can run inside the runspace\n[System.Void]$GUIPowerShell.AddScript({\n        Write-Output -InputObject '1st output'\n    })\n\n# Invoke the PowerShell object asynchronously and store the resulting handle in a variable\n$GUIAsyncObject = $GUIPowerShell.BeginInvoke()\n\n# End the asynchronous operation and display the output\n$GUIPowerShell.EndInvoke($GUIAsyncObject)\n\n# Add another script to the PowerShell object to run, replacing the previous script added to the object.\n# The runspace is still open\n[System.Void]$GUIPowerShell.AddScript({\n        Write-Output -InputObject '2nd output'\n    })\n\n# Again invoke the PowerShell object asynchronously and store the resulting handle in a variable\n$GUIAsyncObject = $GUIPowerShell.BeginInvoke()\n\n# End the asynchronous operation and display the output\n$GUIPowerShell.EndInvoke($GUIAsyncObject)\n\n# Close and dispose of the runspace and PowerShell object\n$GUIPowerShell.Dispose()\n$GUIRunSpace.Close()\n$GUIRunSpace.Dispose()\n\n# Display the number of the runspaces after operation\n(Get-Runspace).count\n
    "},{"location":"PowerShell/RunSpaces%20In%20PowerShell/#how-to-handle-runspace-events-asynchronously-from-the-parent-runspace","title":"How To Handle RunSpace Events Asynchronously From The Parent RunSpace","text":"

    This example demonstrates how to create a runspace that runs a GUI thread asynchronously and based on the events happening in the GUI thread, different actions are taken in the parent thread. The parent thread is responsible for handling the events generated by the GUI thread, such as button clicks, window closures, and errors. At the end of the operation, the runspace is closed and disposed of, ensuring no leftover runspaces or jobs.

    # Get the count of the RunSpaces before the operation to compare it with the count after the operation\n(Get-Runspace).count\n\n# Creating a synchronized hashtable to store shared data between the two runspaces\n$SyncedHashtable = [System.Collections.Hashtable]::Synchronized(@{})\n\n# Define the XAML code for WPF GUI\n$SyncedHashtable.XAML = [System.Xml.XmlDocument]@'\n<Window xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\nMaxWidth=\"600\" WindowStartupLocation=\"CenterScreen\" SizeToContent=\"WidthAndHeight\">\n<Button Name=\"Button1\" Content=\"Press Me\"/>\n</Window>\n'@\n\n# Assigning the parent runspace's host to the $SyncedHashtable.Host property.\n# It will be used to detect or rather, refer back to the parent runspace from inside of the GUI runspace.\n# This is crucial for the event communication between the two runspaces.\n$SyncedHashtable.Host = $Host\n\n$RunSpace = [System.Management.Automation.RunSpaces.RunSpaceFactory]::CreateRunspace()\n$RunSpace.ApartmentState = 'STA'\n$RunSpace.ThreadOptions = 'ReuseThread'\n\n$RunSpace.Open()\n$RunSpace.SessionStateProxy.SetVariable('SyncedHashtable', $SyncedHashtable)\n\n$PowerShell = [System.Management.Automation.PowerShell]::Create()\n$PowerShell.Runspace = $RunSpace\n\n[System.Void]$PowerShell.AddScript({\n\n        try {\n            # Add the required assembly for WPF\n            Add-Type -AssemblyName PresentationFramework\n\n            $Reader = New-Object -TypeName 'System.Xml.XmlNodeReader' -ArgumentList $SyncedHashtable.XAML\n            $SyncedHashtable.Window = [System.Windows.Markup.XamlReader]::Load( $Reader )\n\n            # Find the button object in the XAML\n            [System.Windows.Controls.Button]$SyncedHashtable.Button1 = $SyncedHashtable.Window.FindName('Button1')\n\n            # Add a click event to the button\n            $SyncedHashtable.Button1.Add_Click({\n                    $SyncedHashtable.Host.Runspace.Events.GenerateEvent('Button1Clicked', $null, 'Button Click Event', $null)\n                })\n\n            # Add a closed event to the window\n            $SyncedHashtable.Window.Add_Closed({\n                    $SyncedHashtable.Host.Runspace.Events.GenerateEvent('WindowClosed', $null, 'Sender', $null)\n                })\n\n            # Throw a dummy error to test the async error handling\n            # throw 'Test Error'\n\n            # Show the GUI\n            $SyncedHashtable.Window.ShowDialog()\n        }\n        catch {\n            $SyncedHashtable.ErrorMessage = $_.Exception.Message\n            $SyncedHashtable.Host.Runspace.Events.GenerateEvent('ErrorsOccurred', $null, $null, $null)\n        }\n    })\n\n# Start the GUI PowerShell instance asynchronously\n$AsyncHandle = $PowerShell.BeginInvoke()\n\n# You can inspect the events that the 'Register-EngineEvent' cmdlet receives here\n# $Button1ClickedEvent = Get-Event -SourceIdentifier 'Button1Clicked'\n# $WindowClosedEvent = Get-Event -SourceIdentifier 'WindowClosed'\n# $ErrorsOccurredEvent = Get-Event -SourceIdentifier 'ErrorsOccurred'\n\n# Register an event for the button click\n$Button1ClickedSub = Register-EngineEvent -SourceIdentifier 'Button1Clicked' -Action {\n    param (\n        $Sender\n    )\n    Write-Host -Object $Sender\n}\n\n# Register an event for the window closure\n$WindowClosedSub = Register-EngineEvent -SourceIdentifier 'WindowClosed' -Action {\n    param (\n        $Sender\n    )\n    Write-Host -Object 'The GUI has been closed.'\n\n    # Remove the event subscription and the job for the button click event since the GUI Windows was closed\n    Unregister-Event -SubscriptionId $Button1ClickedSub.Id\n    Remove-Job -InstanceId $Button1ClickedSub.InstanceId\n\n    # Remove the event subscription and the job for the errors occurred event since the GUI Windows was closed\n    Unregister-Event -SubscriptionId $ErrorsOccurredSub.Id\n    Remove-Job -InstanceId $ErrorsOccurredSub.InstanceId\n\n    # Close the runspace and dispose of it\n    $RunSpace.Close()\n    $RunSpace.dispose()\n\n    # Remove the event subscription and the job of the current event subscription\n    Unregister-Event -SubscriptionId $WindowClosedSub.Id\n    Remove-Job -InstanceId $WindowClosedSub.InstanceId\n}\n\n# Register an event for the errors occurred in the GUI RunSpace\n$ErrorsOccurredSub = Register-EngineEvent -SourceIdentifier 'ErrorsOccurred' -Action {\n    Write-Host -Object \"Errors Occurred: $($SyncedHashtable.errorMessage)\"\n}\n\n# Get the count of the runspaces after the operation to see there is no leftover runspace\n(Get-Runspace).count\n\n# There won't be any leftover jobs or event subscriptions once the GUI window is closed\n# Get-EventSubscriber\n# Get-Job\n
    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/","title":"Application Control (WDAC) Frequently Asked Questions (FAQs)","text":""},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#whats-the-difference-between-application-control-policies-and-an-antivirus","title":"What's The Difference Between Application Control Policies And An Antivirus?","text":"

    Application Control policies are based on whitelisting strategy, meaning everything is blocked by default unless explicitly allowed. Antiviruses on the other hand are based on blacklisting strategy, meaning everything is allowed by default unless explicitly blocked.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-does-wdac-in-the-os-compare-to-3rd-party-solutions","title":"How Does WDAC In The OS Compare To 3rd Party Solutions?","text":"

    WDAC which is built deep inside of the OS kernel doesn\u2019t need any \u201cagents\u201d to be installed, that means it can\u2019t be killed using techniques used against 3rd party solutions, it also doesn\u2019t increase the attack surface of the system. It\u2019s native and exceedingly fast which makes it transparent to the user.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#can-i-use-microsoft-defender-for-endpoint-mde-to-collect-wdac-logs","title":"Can I Use Microsoft Defender For Endpoint (MDE) To Collect WDAC Logs?","text":"

    Yes. MDE Should definitely be used to manage your endpoints and collect Code Integrity logs used to create WDAC policies. They provide very detailed CI info at scale for your entire fleet of machines. Then Intune can be used for at scale deployment of the policies after creation.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#can-supplemental-policies-have-deny-rules","title":"Can Supplemental Policies Have Deny Rules?","text":"

    No, Supplemental policies are only used to expand a base policy by allowing more files.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-can-i-make-my-wdac-policy-tamper-proof","title":"How Can I Make My WDAC Policy Tamper Proof?","text":"

    If you cryptographically sign and deploy your WDAC policy, it will be tamper-proof and even the system administrator won't be able to remove it without the certificate's private keys \ud83d\udd11.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-do-enterprises-and-businesses-use-application-control-wdac","title":"How Do Enterprises And Businesses Use Application Control (WDAC)?","text":"

    Businesses and Enterprises have a variety of options. They can set Intune as Managed Installer so any application pushed by the administrator to the endpoints will be trusted and installed but the users won't be able to install new applications on their own.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#how-many-wdac-policies-can-be-deployed-on-a-system","title":"How Many WDAC Policies Can Be Deployed On a System?","text":"

    There is no limit on how many Application Control (WDAC) policies you can deploy on a system.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-are-the-tools-i-need-to-get-started-with-application-control-wdac-policies","title":"What Are The Tools I Need To Get Started With Application Control (WDAC) Policies?","text":"

    WDACConfig PowerShell module and WDAC Wizard are all you need to begin your Application Control journey and create a robust security policy for your environment. They provide many advanced features that you can explore further when you're ready.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-is-isg-and-how-can-i-use-it-in-an-application-control-wdac-policy","title":"What Is ISG And How Can I Use It In An Application Control (WDAC) Policy?","text":"

    ISG stands for The Intelligent Security Graph. It's a very powerful AI-based system that processes Trillions of signals from all kinds of data sources every day. You can utilize it as the arbiter in WDAC policies so it can help you allow trusted apps and block unknown or malicious apps automatically.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-is-smart-app-control","title":"What Is Smart App Control?","text":"

    Smart App Control is an automated AI-based Application Control mechanism that uses the same underlying components as WDAC (Windows Defender Application Control). It can be used in all Windows editions and provides great level of security by default for all systems it's enabled on.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#what-is-the-most-secure-level-to-use-for-authorizing-files","title":"What Is The Most Secure Level To Use For Authorizing Files?","text":"

    For signed files, you should always use WHQLFilePublisher as main level and FilePublisher as fallback. For unsigned files, use Hash level.

    "},{"location":"WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/#is-there-a-more-automated-way-to-use-application-control-at-scale","title":"Is There A More Automated Way To Use Application Control At Scale?","text":"

    Yes. Microsoft Defender for Cloud's adaptive application controls enhance your security with this data-driven, intelligent automated solution that defines allowlists of known-safe applications for your machines. It uses Machine Learning models and is based on the collected telemetry data.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/","title":"EKUs in WDAC, App Control for Business, Policies","text":""},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#introduction","title":"Introduction","text":"

    EKU stands for Extended Key Usage, which is an extension of X.509 certificates that delineates the functions for which the public key of the certificate can be employed. EKUs are designated by Object Identifiers (OIDs), which are sequences of digits that distinctly characterize a kind of usage.

    The EKUs extension can be either critical or non-critical. If the extension is critical, it implies that the certificate must be utilized solely for the functions indicated by the EKUs. If the extension is non-critical, it implies that the certificate can be employed for other functions as well, provided that they are not prohibited by other extensions or policies.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#a-detailed-analysis-of-object-identifiers-and-their-usage","title":"A Detailed Analysis of Object Identifiers and Their Usage","text":"

    Let's consider 1.3.6.1.4.1.311.61.4.1 as an example which is an OID accountable for ELAM EKU. An Object Identifier (OID) is a method of denominating distinguishing objects in a hierarchical fashion. OIDs are frequently employed in cryptography, security, and networking protocols to indicate various kinds of data or algorithms.

    Each cluster of digits in an OID is termed an arc. The arcs are separated by dots and constitute a tree structure. The first arc is the root of the tree, and the last arc is the leaf. The arcs in between are denoted as nodes. Each arc has a designation and a numeral, which are allocated by different authorities or standards organizations.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#ekus-in-wdac-policies","title":"EKUs in WDAC Policies","text":"

    EKUs are employed in WDAC policies to indicate the functions for which a certificate can be employed. Consider EKUs as a whitelist of permitted functions. If a certificate does not encompass any of the EKUs indicated in the WDAC policy, it will be discarded. They can be employed to confine the range of a certificate to a specific function.

    For instance, if a certificate is issued to an individual or an organization solely for code signing functions, it cannot be employed for high-value operations such as Early Launch AntiMalware (ELAM) driver signing. To have the capacity to sign ELAM drivers, the certificate must encompass the ELAM EKU which is only attained by fulfilling specific requirements demonstrated by Microsoft.

    We can readily verify this in the subsequent example. Let's assume you have deployed the DefaultWindows template policy on a machine, and now you want to enable a 3rd party application such as OBS to be allowed to run. You create a supplemental policy by scanning the components of the OBS software. If we now open the generated XML file, we can observe that there are signer rules in there.

    And if we open the properties of one of those signed files, we can observe that they are signed by a certificate that was issued to an individual for Code Signing function only.

    If we append an EKU that is not supported by this certificate, such as ELAM, to one of the signer rules in the supplemental policy, the OBS software will no longer be permitted by the Code Integrity to run because the certificate the components of the OBS software are signed with does not encompass the ELAM EKU.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-to-obtain-the-oid-of-an-eku-by-knowing-its-friendly-name-and-vice-versa","title":"How to Obtain the OID of an EKU by Knowing Its Friendly Name and Vice Versa","text":"

    If you know the OID or the friendly name of an EKU, you can readily obtain the other one by using the following PowerShell command

    [Security.Cryptography.Oid]::new($OIDOrFriendlyName)\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-to-convert-an-oid-to-hexadecimal-format-for-wdac-policies","title":"How to Convert an OID to Hexadecimal Format for WDAC Policies","text":"

    In a WDAC Policy XML file, each EKU must be defined in the EKUs node. For each EKU, there are 3 available attributes, 2 of which are mandatory and 1 is optional. The mandatory attributes are ID and Value, and the optional attribute is FriendlyName.

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#we-can-convert-the-oid-of-an-eku-to-its-hexadecimal-representation-by-using-the-following-powershell-function","title":"We can convert the OID of an EKU to its hexadecimal representation by using the following PowerShell function:","text":"
    # Import the System.Formats.Asn1 namespaces\nusing namespace System.Formats.Asn1\nFunction Convert-OIDToHex {\n  [CmdletBinding()]\n  Param (\n    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]\n    [ValidateNotNullOrEmpty()][System.String]$OID\n  )\n  <#\n.SYNOPSIS\n  Converts an OID to a hexadecimal string\n.PARAMETER OID\n  The OID to convert\n.EXAMPLE\n  Convert-OIDToHex -OID '1.3.6.1.4.1.311.10.3.5'\n.INPUTS\n  System.String\n.OUTPUTS\n  System.String\n  #>\n\n  # Create an AsnWriter object with the default encoding rules\n  [AsnWriter]$AsnWriter = New-Object -TypeName AsnWriter -ArgumentList ([AsnEncodingRules]::BER)\n  # Write the OID as an ObjectIdentifier\n  $AsnWriter.WriteObjectIdentifier(\"$OID\")\n  # Get the encoded bytes as an array\n  [System.Byte[]]$NumArray = $AsnWriter.Encode()\n  # Check if the first byte is 6, otherwise throw an exception\n  if ($NumArray[0] -ne 6) {\n    throw 'Invalid OID encoding'\n  }\n  # Change the first byte to 1\n  $NumArray[0] = 1\n  # Create a StringBuilder to store the hexadecimal value\n  [System.Text.StringBuilder]$StringBuilder = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($NumArray.Length * 2)\n\n  # Loop through the bytes and append them as hex strings\n  for ($Index = 0; $Index -lt $NumArray.Length; $Index++) {\n    # Convert each byte to a two-digit hexadecimal string using the invariant culture\n    # The invariant culture is a culture that is culture-insensitive and independent of the system settings\n    # This ensures that the hexadecimal string is consistent across different locales and platforms\n    # The 'X2' format specifier indicates that the byte should be padded with a leading zero if necessary\n    # The ToString method returns the hexadecimal string representation of the byte\n    [System.String]$Hex = $NumArray[$Index].ToString('X2', [System.Globalization.CultureInfo]::InvariantCulture)\n    # Append the hexadecimal string to the StringBuilder object\n    # The StringBuilder class provides a mutable string buffer that can efficiently concatenate strings\n    # The Out-Null cmdlet suppresses the output of the Append method, which returns the StringBuilder object itself\n    $StringBuilder.Append($Hex) | Out-Null\n  }\n\n  # Return the hexadecimal value as string\n  return [System.String]$StringBuilder.ToString().Trim()\n}\n
    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-to-convert-the-hexadecimal-format-to-an-oid-for-wdac-policies","title":"How to Convert the Hexadecimal Format to an OID for WDAC Policies","text":"

    The following PowerShell function does the exact opposite of the previous function. It converts the hexadecimal representation of an OID to the OID itself.

    # Import the System.Formats.Asn1 namespaces\n# This allows you to use the AsnReader and AsnWriter classes\nusing namespace System.Formats.Asn1\n\nFunction Convert-HexToOID {\n  [CmdletBinding()]\n  [OutputType([System.String])]\n  Param (\n    [Parameter(Mandatory = $true, ValueFromPipeline = $true)]\n    [ValidateNotNullOrEmpty()][System.String]$Hex\n  )\n  <#\n.SYNOPSIS\n  Converts a hexadecimal string to an OID\n.DESCRIPTION\n  Used for converting hexadecimal values found in the EKU sections of the WDAC policies to their respective OIDs.\n.PARAMETER Hex\n  The hexadecimal string to convert to an OID\n.EXAMPLE\n  Convert-HexToOID -Hex '010a2b0601040182374c0301'\n\n  Returns '1.3.6.1.4.1.311.76.3.1'\n.INPUTS\n  System.String\n.OUTPUTS\n  System.String\n  #>\n\n  begin {\n    # Convert the hexadecimal string to a byte array by looping through the string in pairs of two characters\n    # and converting each pair to a byte using the base 16 (hexadecimal) system\n    [System.Byte[]]$NumArray = for ($Index = 0; $Index -lt $Hex.Length; $Index += 2) {\n      [System.Convert]::ToByte($Hex.Substring($Index, 2), 16)\n    }\n  }\n\n  process {\n    # Change the first byte from 1 to 6 because the hexadecimal string is missing the tag and length bytes\n    # that are required for the ASN.1 encoding of an OID\n    # The tag byte indicates the type of the data, and for an OID it is 6\n    # The length byte indicates the number of bytes that follow the tag byte\n    # and for this example it is 10 (0A in hexadecimal)\n    $NumArray[0] = 6\n\n    # Create an AsnReader object with the default encoding rules\n    # This is a class that can read the ASN.1 BER, CER, and DER data formats\n    # BER (Basic Encoding Rules) is the most flexible and widely used encoding rule\n    # CER (Canonical Encoding Rules) is a subset of BER that ensures a unique encoding\n    # DER (Distinguished Encoding Rules) is a subset of CER that ensures a deterministic encoding\n    # The AsnReader object takes the byte array as input and the encoding rule as an argument\n    [AsnReader]$AsnReader = New-Object -TypeName AsnReader -ArgumentList ($NumArray, [AsnEncodingRules]::BER)\n\n    # Read the OID as an ObjectIdentifier\n    # This is a method of the AsnReader class that returns the OID as a string\n    # The first two numbers are derived from the first byte of the encoded data\n    # The rest of the numbers are derived from the subsequent bytes using a base 128 (variable-length) system\n    [System.String]$OID = $AsnReader.ReadObjectIdentifier()\n  }\n\n  End {\n    # Return the OID value as string\n    return $OID\n  }\n}\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#common-ekus-in-wdac-policies","title":"Common EKUs in WDAC Policies","text":"
    <EKU ID=\"ID_EKU_WINDOWS\" FriendlyName=\"Windows System Component Verification - 1.3.6.1.4.1.311.10.3.6\" Value=\"010A2B0601040182370A0306\" />\n<EKU ID=\"ID_EKU_WHQL\" FriendlyName=\"Windows Hardware Quality Labs (WHQL) - 1.3.6.1.4.1.311.10.3.5\" Value=\"010A2B0601040182370A0305\" />\n<EKU ID=\"ID_EKU_ELAM\" FriendlyName=\"Early Launch Anti Malware - 1.3.6.1.4.1.311.61.4.1\" Value=\"010A2B0601040182373D0401\" />\n<EKU ID=\"ID_EKU_HAL_EXT\" FriendlyName=\"HAL Extension - 1.3.6.1.4.1.311.61.5.1\" Value=\"010A2B0601040182373D0501\" />\n<EKU ID=\"ID_EKU_RT_EXT\" FriendlyName=\"Windows RT - 1.3.6.1.4.1.311.10.3.21\" Value=\"010a2b0601040182370a0315\" />\n<EKU ID=\"ID_EKU_STORE\" FriendlyName=\"Windows Store - 1.3.6.1.4.1.311.76.3.1\" Value=\"010a2b0601040182374c0301\" />\n<EKU ID=\"ID_EKU_DCODEGEN\" FriendlyName=\"Dynamic Code Generation - 1.3.6.1.4.1.311.76.5.1\" Value=\"010A2B0601040182374C0501\" />\n<EKU ID=\"ID_EKU_AM\" FriendlyName=\"AntiMalware - 1.3.6.1.4.1.311.76.11.1\" Value=\"010a2b0601040182374c0b01\" />\n
    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#oids-for-common-microsoft-ekus","title":"OIDs for Common Microsoft EKUs","text":""},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#how-ekus-are-used-by-the-wdac-engine-for-validation","title":"How EKUs Are Used by the WDAC Engine for Validation","text":"

    Regarding the incorporation of EKUs in file validation, WDAC verifies that the file's leaf certificate (File's signer) possesses identical EKUs as the signer element's EKUs. Regardless of whether the Signer's CertRoot (TBS value) and name (CN of the certificate) match with file's root, intermediate or leaf certificates, the EKUs only need to match with the leaf certificate.

    For example, in the Default Windows template policy, the Kernel32.dll is authorized by the following signer:

    <Signer ID=\"ID_SIGNER_WINDOWS_PRODUCTION\" Name=\"Microsoft Product Root 2010 Windows EKU\">\n  <CertRoot Type=\"Wellknown\" Value=\"06\" />\n  <CertEKU ID=\"ID_EKU_WINDOWS\" />\n</Signer>\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#you-can-see-the-details-in-the-screenshots-below","title":"You can see the details in the screenshots below","text":""},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#the-placement-of-the-certeku-elements","title":"The Placement of the CertEKU Elements","text":"

    In every Signer, the CertEKU node should only be placed directly after CertRoot. It is against the Code Integrity schema for any other nodes to exist between them. Below is a example of such configuration

    <Signer ID=\"ID_SIGNER_F_1\" Name=\"Microsoft Windows Production PCA 2011\">\n  <CertRoot Type=\"TBS\" Value=\"TBS Hash\" />\n  <CertEKU ID=\"ID_EKU_WINDOWS\" />\n  <CertEKU ID=\"ID_EKU_RT_EXT\" />\n  <CertEKU ID=\"ID_EKU_ELAM\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n  <CertPublisher Value=\"Microsoft Windows\" />\n  <FileAttribRef RuleID=\"ID_FILEATTRIB_F_1\" />\n</Signer>\n

    "},{"location":"WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/#continue-reading","title":"Continue Reading","text":""},{"location":"WDAC/Fast%20and%20Automatic%20Microsoft%20Recommended%20Driver%20Block%20Rules%20updates/","title":"Fast and Automatic Microsoft Recommended Driver Block Rules updates","text":"

    The blocklist is updated with each new major release of Windows, typically 1-2 times per year, but you can deploy the recommended driver block rules policy more frequently.

    This is the GitHub source for the XML content shown on the Microsoft document website. You can see when the last time it was changed was, read the change history and commit messages. The script below automates the required steps explained on the document to download and deploy the recommended driver block rules. Make sure you are using the latest version of Windows.

    "},{"location":"WDAC/Fast%20and%20Automatic%20Microsoft%20Recommended%20Driver%20Block%20Rules%20updates/#use-the-wdacconfig-module","title":"Use the WDACConfig Module","text":"

    You can use the WDACConfig Module to create a scheduled task in Windows that will automatically run the script below every 7 days.

    Install-Module -Name WDACConfig -Force\nNew-WDACConfig -GetDriverBlockRules -AutoUpdate\n
    The script
    try {\n    Invoke-WebRequest -Uri 'https://aka.ms/VulnerableDriverBlockList' -OutFile VulnerableDriverBlockList.zip -ErrorAction Stop\n}\ncatch {\n    exit 1\n}\nExpand-Archive -Path .\\VulnerableDriverBlockList.zip -DestinationPath 'VulnerableDriverBlockList' -Force\nRename-Item -Path .\\VulnerableDriverBlockList\\SiPolicy_Enforced.p7b -NewName 'SiPolicy.p7b' -Force\nCopy-Item -Path .\\VulnerableDriverBlockList\\SiPolicy.p7b -Destination \"$env:SystemDrive\\Windows\\System32\\CodeIntegrity\"\ncitool --refresh -json\nRemove-Item -Path .\\VulnerableDriverBlockList -Recurse -Force\nRemove-Item -Path .\\VulnerableDriverBlockList.zip -Force\nexit 0\n

    Microsoft recommended driver block rules that are enforced as a result of using either memory integrity (also known as hypervisor-protected code integrity or HVCI), Smart App Control, or S mode, are saved in a file called driversipolicy.p7b in the %windir%\\system32\\CodeIntegrity directory. The file you will be downloading from Microsoft document is called SiPolicy.p7b and it won't overwrite the driversipolicy.p7b but it will take precedence over the driversipolicy.p7b when deployed, because it has newer version and you can verify it after using CiTool by observing the Code Integrity event logs as described in the document.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/","title":"Create and Deploy Signed Application Control (WDAC) Policies","text":"

    Important

    WDACConfig module can easily and quickly generate a Code Signing certificate to be used for signing Application Control (WDAC) policies.

    This guide is only for those who want to learn how to setup a Windows Server with Active Directory and Certification Authority roles and create their own CA.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#introduction","title":"Introduction","text":"

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#video-guide","title":"Video Guide","text":""},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#tldr-short-version","title":"TL;DR (Short version)","text":"
    1. Install the latest Windows Server, Install AD/DS and AD/CS roles on it. (\u224815 mins depending on hardware and if downloaded ISO or VHDX)
    2. Use the Enterprise CA's code signing template to create a customized certificate template for WDAC Signing (\u22485 minutes)
    3. Generate the certificate and use it to sign the WDAC Policy (\u22483 minutes)

    That's essentially everything we have to do. So, if you are already familiar with the concepts, you can go straight to the bottom of this page and use the resources section to refer to Microsoft guides to create and deploy the Signed WDAC policy.

    But if you aren't familiar, keep reading as I've thoroughly explained every step to set up Windows Server, generate signing certificate and sign the WDAC policy. It takes about 20 minutes for me (as you can see in the video) and depending on the hardware, it can even take less time.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#prerequisites","title":"Prerequisites","text":"

    Latest Windows Server, it's free for 180 days for evaluation and comes in ISO and VHDX formats. Preferably use Windows Server insider vNext because it has the newest features and visual upgrades.

    Once we have our Windows installation media (ISO or VHDX), we need to set up a Hyper-V VM on our host. For this guide, our host is a Windows 11 pro for workstations machine.

    Create a Hyper-V VM with these specifications:

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#windows-server-vm-setup","title":"Windows Server VM setup","text":"

    After Windows Server installation has finished, you can create a Hyper-V standard checkpoint so you'll be able to restore the VM's state to this point in time if you misconfigure something later on.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#rename-the-server","title":"Rename the server","text":"

    Choose a meaningful name, like CAServer. Use this PowerShell cmdlet to easily do that, it will restart the server to apply the new name.

    Rename-Computer CAServer -Restart\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-gui-install-active-directory-domain-services","title":"Using GUI: Install Active Directory Domain Services","text":"

    From Server Manager => Add Roles and Features => Role-based or feature-based installation => Select the current server you are on => Select Active Directory Domain Services from the list => Select \"Add Features\" => Continue the rest of the steps by selecting Next.

    After installation is over, open the notifications in the Server Manager, (there will probably be a yellow icon on it), Select \"Promote this server to a domain controller\".

    In the Deployment Configuration window that will be opened, select \"Add a new forest\" and in the Root domain name, enter a domain name.

    It can be anything, even Bing.com, but for our usage let's use CAServer.com. On the next step, set a password for DSRM (Directory Services Restore Mode), It needs to have uppercase, lowercase and numbers (e.g., Bing6969), write this password down somewhere, like in Sticky notes app on your host.

    Next, choose a NetBIOS domain name, the default one will be OK. Confirm and proceed with the rest of the steps by selecting Next and at the end select Install. Wait for the installation to finish. It will restart the Server once the Installation is finished.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-powershell-install-active-directory-domain-services","title":"Using PowerShell: Install Active Directory Domain Services","text":"

    Install (AD DS) role

    Install-windowsfeature -name AD-Domain-Services -IncludeManagementTools\n

    Install a forest and set a forest password

    $password = ConvertTo-SecureString 'Bing6969' -AsPlainText -Force\n\nInstall-ADDSForest -DomainName CAServer.com -DomainNetbiosName CASERVER0 -SafeModeAdministratorPassword $password -InstallDNS:$false -Force\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-gui-install-active-directory-certification-service-and-set-up-an-enterprise-root-ca-certificate-authority","title":"Using GUI: Install Active Directory Certification Service and set up an Enterprise root CA (Certificate Authority)","text":"

    From Server Manager => Add Roles and Features => Role-based or feature-based installation => Select the current server we are on => Select Active Directory Certification Service => Select Next for the rest of the steps and finally select install.

    After installation is over, open the notifications in the Server Manager, (there will probably be a yellow icon on it), Select \"Configure Active Directory Certificate Service on the destination server\".

    On the newly opened configuration window, on credentials section select next, on the Role services section check the box for Certification Authority and select next.

    Select Enterprise CA (because Standalone CA does not support certificate templates that we are going to use) and select Next. On the CA Type section select Root CA. On the Private Key section select Create a new private key.

    On the Cryptography section, for Cryptographic Provider choose RSA#Microsoft Software Key Storage Provider, for Key length choose 4096, for Hash Algorithm choose SHA512 and select Next. On the CA name section select next. On the Validity Period section set validity period to something like 50 Years. Select next for the rest of the sections and finally select Configure.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#using-powershell-install-active-directory-certification-services-and-set-up-an-enterprise-root-ca","title":"Using PowerShell: Install Active Directory Certification Services and set up an Enterprise root CA","text":"

    Install Active Directory Certificate Services

    Install-WindowsFeature Adcs-Cert-Authority -IncludeAllSubFeature\n

    Install a new Enterprise CA

    Install-AdcsCertificationAuthority -CAType EnterpriseRootCa -CryptoProviderName \"RSA#Microsoft Software Key Storage Provider\" -KeyLength 4096 -HashAlgorithmName SHA512 -ValidityPeriod Years -ValidityPeriodUnits 50 -Force\n

    Restart the server because it is required, and Server Manager says it too

    Restart-Computer\n

    Lastly do this so that Certification Authority option will be added to Server Manager => Tools and its GUI will become accessible and visible

    Add-WindowsFeature Adcs-Cert-Authority -IncludeManagementTools\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#configure-the-validity-period-of-the-issued-certificates-on-the-server","title":"Configure the Validity period of the issued certificates on the server","text":"

    Microsoft guide for this

    We Increase the validity period of the certificates issued by the CA to 30 years:

    certutil -setreg ca\\ValidityPeriod \"Years\"\ncertutil -setreg ca\\ValidityPeriodUnits \"30\"\n

    Restart the Server after this step.

    You can verify and confirm the results using these commands:

    certutil -getreg ca\\ValidityPeriod\ncertutil -getreg ca\\ValidityPeriodUnits\n

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#follow-the-official-guide-to-create-certificate-template-and-generate-the-signing-certificate","title":"Follow the official guide to create certificate template and generate the signing certificate","text":"

    Now open Certification Authority, you can do so by searching for it in Windows search or from Server Manager => Tools. Once you open it, you can follow the guide from Microsoft to create the certificate template for WDAC policy signing and then request and create a certificate.

    Note that If the Server doesn't have at least 1 network adapter connected to it, then Certificate Templates don't load,

    Screenshot

    That's why our Hyper-V VM Server needs at least one Virtual Network Adapter.

    The guide suggests using a client computer to request and create the certificate but since we are going to use the certificate for non-domain-joined computers and don't need to use the Active Directory, we can perform all of the steps on the same Windows Server VM.

    These are some optional deviations from the official guide that result in creating a successful and more secure certificate for our WDAC policy signing:

    As the Microsoft's guide suggests, you need to go to security tab to verify account access of the user(s) requesting the certificate, but since we are requesting and creating our certificate on the same CA server, we don't need to change anything there.

    If we want to use a 2nd PC to do this, as described in Microsoft document (Totally Unnecessary) Additional steps to perform on Windows Server If you are going to create a new user account in \"Active Directory Users and Computers\" for use on the client VM, in Certification Authority when duplicating the certificate template, go to Security Tab and set the correct permissions for that user account so that it will be able to request and enroll the certificate. For instance, since you are the only person who is going to use the Active Directory, you can even give `Full Control` permission to `Authenticated Users` group. Alternatively, you can use the same administrator account that you are currently using on Windows Server, which exists by default in the Active Directory, to log into the other client computer. One can log into multiple computers with the same user account across an Active Directory domain. There is no limit by default to how many concurrent logins an active directory user can have. Make sure the Windows Server and Windows client VMs both use the same Hyper-V Private Virtual switch network adapter. The VMs need to have static IP addresses on the same subnet in order to communicate with each other. Go to Windows Settings => Network & Internet => Ethernet => in \"IP Assignment\" select \"Edit\" => Set it to \"Manual\" => Toggle the IPv4 => in IP Address Enter `10.10.10.1` and in Subnet Mask enter `255.0.0.0`. Without configuring anything else, save it. Use the Edit button for DNS server assignment, set it to Manual, toggle the IPv4 button and in the Preferred DNS field enter `127.0.0.1`. Save everything and exit settings. Steps to perform on Client VM Make sure the client VM is running the latest version of Windows, and it follows the same prerequisites explained above. Go to Windows Settings => Network & Internet => Ethernet => in \"IP Assignment\" select \"Edit\" => Set it to \"Manual\" => Toggle the IPv4 => in IP Address Enter `10.10.10.2` and in Subnet Mask enter `255.0.0.0`. Without configuring anything else, save it. Now use the Edit button for DNS server assignment, set it to Manual, toggle the IPv4 button and in the Preferred DNS field enter the static IP address of the Windows Server VM, which was `10.10.10.1`. Save everything and exit settings. Open an elevated PowerShell and enter this to join the Active Directory domain:
    Add-Computer -DomainName <Domain> -Restart\n
    You will be asked for credentials. If you are going to use the same Administrator account from Windows Server, use `Administrator` for username and enter the password of the Windows Server in the password field, otherwise use the password you set when creating the new user account in Active Directory Users and Computers. After the client machine restarted, use `Other user` option on the lock screen and this time you will be using the Active Directory credentials to log into the machine. If using the built-in Administrator account, the password will be the same as the password on Windows Server account, but the username will be in the format, so in this case, it will be `Administrator@CAServer.com`. Since you are using Administrator account, you can by default use Enhanced session in Hyper-V too. To request the certificate and enroll it, you can follow the Microsoft guide.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#create-a-signed-wdac-policy","title":"Create a Signed WDAC policy","text":"

    Once we have the certificate in the User Certificates store of either the Windows Server or a client machine, Right-click on it => All tasks => Export. Export the Private key and export all the Extended Properties, set a password for the certificate and set Encryption to AES256-SHA256. Select a location to export and it will create a .pfx file.

    You also need to export the certificate without private key, in DER encoded binary X.509 format which will create a .cer certificate file. We need this certificate to sign the WDAC policy.

    It is important to keep these 2 files, specially .pfx that contains the private key, in a safe place, such as Azure Key Vault Managed HSM or OneDrive Personal Vault, so that if you delete all the VMs you created, you will be able to continue using the same certificate to sign further WDAC policies and supplemental policies, at least for the next 22 years, before it needs a renewal. As you can see, all of that setup must be done just once every few decades.

    The Personal Information Exchange (.pfx) file has great importance because it contains the Public key and Private key of the certificate so anyone who has access to this file can disable the deployed Signed WDAC policy. It should never be shared with anyone outside your circle of trust. It is a password-protected file by nature.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#use-wdacconfig-module-to-sign-and-deploy-wdac-policies","title":"Use WDACConfig module to sign and deploy WDAC policies","text":"

    WDACConfig module with the Deploy-SignedWDACConfig cmdlet can automate the entire process of signing and deploying a signed WDAC policy.

    Deploy-SignedWDACConfig -CertPath <String> -PolicyPaths <String[]> -CertCN <String>\n

    Cmdlet Info

    Note

    The Deploy-SignedWDACConfig cmdlet will offer to automatically download the SignTool.exe from the Microsoft server if it cannot find it on your system.

    If you want to manually download it, here are the steps:

    Run it and only select Windows SDK Signing Tools for Desktop Apps to install. After that signtool.exe will be placed at C:\\Program Files (x86)\\Windows Kits\\10\\bin and the WDACConfig module will automatically detect and use it for signing. You can even copy the executable to another location for later usage on another system where SDK is not installed and then use the optional -SignToolPath <String> parameter of WDACConfig module to browse for executable.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#system-behavior-after-deploying-a-signed-application-control-policy","title":"System Behavior After Deploying a Signed Application Control Policy","text":""},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#activation-process","title":"Activation Process","text":"

    After the signed Application Control (WDAC) policy binary .cip is copied to the EFI partition as part of the deployment process, and system is restarted once, we can see in System Information that Application Control User-Mode is being enforced and when you try to install an application not permitted by the deployed policy, it will be successfully blocked.

    At this point, since we are using UEFI Secure Boot, the Anti Tampering protection of the Signed policy kicks in and starts protecting WDAC policy against any tampering. We need to reboot the system one more time, to verify everything and make sure there is no boot failure.

    Deploying a Signed WDAC policy without restarting is the same as deploying Unsigned policies, because the Signed policy can be easily removed just like an Unsigned policy. So always make sure you restart at least once after deploying a Signed WDAC policy.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#if-someone-forcefully-deletes-the-deployed-wdac-policy-file","title":"If Someone forcefully deletes the deployed WDAC policy file","text":" Screenshot of a message after forcefully deleting a Signed WDAC policy from the EFI partition

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#what-happens-when-we-turn-on-smart-app-control","title":"What Happens When We Turn On Smart App Control","text":"

    Smart App Control works side-by-side any signed or unsigned Application Control policy (WDAC) because it is itself a special type of WDAC policy. It will be in enforced mode and continue to do its job.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#dual-boot-os-configurations","title":"Dual boot OS configurations","text":"

    When you deploy a Signed WDAC policy on a system that uses Secure Boot, it will be enforced on all of the OSes that boot on the physical machine, because the policy resides on the EFI partition and is not tied to any specific OS. That means if you perform a clean install of a second Windows OS or natively boot a VHDX (Hyper-V VM), the policy will apply to them as well.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#extras","title":"Extras","text":""},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#how-to-interact-with-the-hidden-efi-partition","title":"How to interact with the hidden EFI partition","text":"

    Using Diskpart, Open an elevated PowerShell console and run these commands one by one:

    diskpart\nlist disk\n# double check to make sure it's the correct disk if you have more than 1\nselect disk 0\nlist part\n# The EFI partitions type is System, and its size is approximately 100MB, make sure you choose the correct one\nselect part 1\nassign letter=z\n

    The EFI partition will be available in This PC with letter Z, but you can't access it without modifying permissions. There is however an easier way to access it and manually copy the Signed WDAC policy binary to it. Open Task Manager as admin, select Run New Task, select Browse and now you can access drive Z (EFI partition) and copy the Signed .cip file in Z:\\EFI\\Microsoft\\Boot\\CIPolicies\\Active.

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#how-to-find-the-fqdn-fully-qualified-domain-name-of-the-windows-server","title":"How to find the FQDN (Fully Qualified Domain Name) of the Windows Server","text":"

    Using PowerShell

    (Get-ADComputer $(hostname)).DNSHostName\n

    or

    \"$env:computername.$env:userdnsdomain\"\n

    You can also use GUI of Server Manager => Local Server

    The syntax is: Computer_Name.Domain

    So, if:

    then FQDN is: CAServer.CAServer.com

    "},{"location":"WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/#resources","title":"Resources","text":""},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/","title":"How to Use Microsoft Defender for Endpoint Advanced Hunting With WDAC App Control","text":"

    Windows Defender Application Control (WDAC), also referred to as Application Control for Business, is a highly effective security feature that empowers you to manage the execution of applications on your endpoints.

    The application whitelisting approach serves as a potent defense against emerging and unknown threats. By emphasizing the identification of trusted applications, it automatically blocks any software that falls outside this trusted realm.

    Microsoft Defender for Endpoint (MDE) is one of the tools that can be used by enterprises and organizations to develop the trusted applications policy and mange it at scale. MDE provides the intelligence and insights needed to create and maintain a robust application control policy through its Advanced Hunting feature. This feature uses KQL (Kusto Query Language) to query the data collected by MDE and using the WDACConfig module, we can turn this actionable data into WDAC policies. We can then use Intune to deploy these policies to our endpoints. All of these tools are built for scalability.

    Note

    You can access Intune portal by navigating to: https://intune.microsoft.com

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#preparing-the-code-integrity-and-applocker-data","title":"Preparing the Code Integrity and AppLocker Data","text":"

    To start, we need our endpoints to be generating data and intelligence we can work with. These data points are the Code Integrity and AppLocker events. These events are generated when an application or file is blocked or audited by WDAC, or when a script or MSI file is blocked or audited by AppLocker. We can trigger the data generation by deploying WDAC policies to our endpoints in Audit mode. This mode will not block any applications, instead it will generate data points for any application, file, script, MSI file and so on that would have been blocked if the policy was in Enforce mode.

    You can create Audit mode policies using the WDACConfig module based on different levels of trust.

    For instance, the following command will create an Audit mode policy that once deployed on an endpoint, starts generating Audit logs for any file that runs but is not part of the Windows by default.

    New-WDACConfig -PrepDefaultWindowsAudit\n

    Another option would be the following command, which will create an Audit mode policy that once deployed, starts generating Audit logs for any file that runs but is not signed by Microsoft certificates.

    New-WDACConfig -PrepMSFTOnlyAudit\n

    Please refer to this document for further info about the commands.

    You will then use Intune to deploy the generated policies to as many endpoints as you want.

    Tip

    Deploy WDAC policies using Mobile Device Management (MDM)

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#collecting-the-data-from-mde-advanced-hunting","title":"Collecting the Data from MDE Advanced Hunting","text":"

    Now we need to collect the data from MDE Advanced Hunting. We can customize this query to be more specific to our environment, for instance by targeting specific devices and so on, but the following query will give us a good starting point by collecting all of the Code Integrity and AppLocker events:

    DeviceEvents\n| where ActionType startswith \"AppControlCodeIntegrity\"\n   or ActionType startswith \"AppControlCIScriptBlocked\"\n   or ActionType startswith \"AppControlCIScriptAudited\"\n

    Note

    You can access Microsoft Defender for Endpoint's portal by navigating to: https://security.microsoft.com

    That query generates a standard output of the data in CSV file format which is compatible with what the WDACConfig module requires in order to generate WDAC policies. If you want to customize the query further, make sure the subsequent filters are applied after the initial query to ensure correct data format.

    Tip

    Proactively hunt for threats with advanced hunting in Microsoft Defender XDR

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#generating-the-wdac-policies","title":"Generating the WDAC Policies","text":"

    After exporting the data from MDE Advanced Hunting, we can use the WDACConfig module to generate WDAC policies. We need to feed the CSV file(s) we collected MDE Advanced Hunting data into the module like so:

    ConvertTo-WDACPolicy -Source MDEAdvancedHunting -MDEAHLogs <Path to one or more CSV files> -BasePolicyGUID <Base policy GUID>\n

    It is only one example of how you can utilize the WDACConfig for policy generation based on MDE AH data, for more information about the cmdlet please refer to its documentations available here.

    The command we used above will process the CSV file(s) and open a GUI window where you can filter the logs based on many criteria, and then either select all or only select some of the logs to be included in the WDAC policy.

    Note that the generated policy will be a Supplemental policy.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#wdacconfig-features-for-mde-advanced-hunting","title":"WDACConfig Features For MDE Advanced Hunting","text":""},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#the-module-can-create-3-types-of-rules-for-files","title":"The Module Can Create 3 Types of Rules for Files:","text":"

    These levels are selected based on their security. You can read more about the levels security comparison in this article.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#video-demonstration","title":"Video Demonstration","text":"

    The following video demonstrates the process of collecting the data from MDE Advanced Hunting and generating WDAC policies using the WDACConfig module

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#deploying-the-wdac-policies","title":"Deploying the WDAC Policies","text":"

    After generating the Supplemental policies based off of the MDE Advanced Hunting data, you need to remove the Audit mode policies you deployed to your endpoints initially and replace them with Enforced mode policies.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#generate-allow-microsoft-base-policy-enforced-mode","title":"Generate Allow Microsoft Base Policy (Enforced Mode)","text":"
    New-WDACConfig -MakeAllowMSFTWithBlockRules\n
    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#generate-default-windows-base-policy-enforced-mode","title":"Generate Default Windows Base Policy (Enforced Mode)","text":"
    New-WDACConfig -MakeDefaultWindowsWithBlockRules\n

    Important

    Ensure that the Enforced mode policies align with the type of policies set during Audit mode. For example, if you utilized an Audit mode policy that permits Microsoft-signed files, it is crucial to employ an Enforced mode policy that also allows such files. Conversely, when dealing with the default Windows policy, consistency is key. Mixing these policies can result in files that were allowed during Audit mode being unexpectedly blocked during Enforce mode.

    You can deploy the policies using Intune, SCCM, or any other MDM solution you are using.

    After deploying the base policies, you will then deploy the Supplemental policies generated from MDE AH data, these policies are responsible for allowing any 3rd party apps or files that your endpoints need to use.

    You can put your endpoints into different groups and each group can receive different Supplemental policy based on their needs.

    Note

    ApplicationControl CSP

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#strict-kernel-mode-code-integrity-policy-scenario","title":"Strict Kernel Mode Code Integrity Policy Scenario","text":"

    I've created a scenario where you can strictly control what is allowed to run in Kernel mode, without blocking any user mode applications. You can read all about this scenario in here. Using the WDACConfig module and MDE Advanced Hunting intel, you can deploy this scenario across your entire fleet of endpoints.

    This approach demands very minimal upkeep as it exclusively manages Kernel-mode activities, yet it offers an exceptional degree of security. A significant benefit of this method is the safeguarding of your endpoints from all Bring Your Own Vulnerable Driver (BYOVD) threats.

    "},{"location":"WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/#feedback-and-support","title":"Feedback and Support","text":"

    If you have any questions, feature requests or feedback regarding this guide or the WDACConfig module, please feel free to reach out to me on GitHub by opening a new issue or discussion.

    "},{"location":"WDAC/Introduction/","title":"Introduction","text":""},{"location":"WDAC/Introduction/#introduction","title":"Introduction","text":""},{"location":"WDAC/Introduction/#what-is-windows-defender-application-control","title":"What is Windows Defender Application Control?","text":"

    Application control is a crucial line of defense for protecting computer systems given today's threat landscape, and it has an inherent advantage over traditional antivirus solutions. Specifically, application control moves away from an application trust model where all applications are assumed trustworthy to one where applications must earn trust in order to run.

    Devices where Windows Defender Application control (WDAC) policies are deployed on can either be centrally managed via MDM, Intune etc. or they can be home devices, devices that are private and don't belong to any organization, the computer of someone that you want to keep very much safe and secure so that even the device's owner can't willingly or forcefully compromise themselves, the possibilities are endless.

    Important

    The WDACConfig module is a one-stop shop for all your Application Control (WDAC) needs. It is scalable, easy to use, enterprise-ready, Azure VM ready and more importantly, it is free and always will be. Check it out here

    "},{"location":"WDAC/Introduction/#windows-defender-application-control-wdac-wiki-posts","title":"Windows Defender Application Control (WDAC) wiki posts","text":""},{"location":"WDAC/Introduction/#wdacconfig-module","title":"WDACConfig Module","text":"

    WDACConfig is an advanced PowerShell module designed with the aim of automating Application and File whitelisting in Windows using Windows Defender Application Control. It is available in PowerShell gallery.

    "},{"location":"WDAC/Introduction/#application-control-usage-levels","title":"Application Control Usage Levels","text":"

    There are many ways you can utilize Application Control features and here they are sorted by the level of restriction and protection they provide; From top (having the least restriction and protection) to bottom (having the most restriction and protection).

    1. Use Microsoft recommended driver block rules.

      • No user action required; The vulnerable driver blocklist is enabled by default for all devices using HVCI or Memory Integrity.
      • The built-in driver blocklist is updated with each new major release of Windows, typically 1-2 times per year.
    2. Update Microsoft recommended driver block rules outside of the twice a year schedule.

      • The drivers block list itself is updated more frequently than twice a year schedule, use the WDACConfig Module to setup a scheduled task that keeps the list up-to-date.
    3. Use Microsoft recommended block rules + Recommended driver block rules
      • Use the WDACConfig Module to easily deploy the User-Mode Microsoft recommended block rules on your system.
    4. Create WDAC policy for Lightly managed devices
      • Microsoft's guide: Create a WDAC policy for lightly managed devices
      • My guide: WDAC for Lightly Managed Devices
    5. Use Smart App Control
      • It's just a toggle in Windows Security under App & Browser control. It uses a special kind of WDAC policy that provides more protection than a lightly managed workstation but less protection than a fully managed workstation.
      • It uses both of Microsoft's recommended block rules.
    6. Use Smart App Control + Strict Kernel-Mode WDAC Policy
    7. Create WDAC policy for Fully managed devices
      • The following scenarios provide the highest protection against any threats from any sources when cryptographically signed and deployed and properly configured.
      • WDAC for Fully managed device - Variant 1
      • WDAC for Fully managed device - Variant 2
      • WDAC for Fully managed device - Variant 3
      • WDAC for Fully managed device - Variant 4
      • Microsoft's guide: Create a WDAC policy for fully managed devices
      • Microsoft's guide: Create a WDAC policy for fixed-workload devices (reference computer)
      • Microsoft's guide: Use audit events to create WDAC policy rules

    "},{"location":"WDAC/Introduction/#methods-we-can-use-to-create-an-application-control-policy-wdac","title":"Methods we can use to create an Application Control policy (WDAC)","text":""},{"location":"WDAC/Introduction/#plan-for-windows-defender-application-control-lifecycle-policy-management","title":"Plan for Windows Defender Application Control lifecycle policy management","text":"

    Microsoft provides the following official document to understand the decisions you need to make to establish the processes for managing and maintaining Windows Defender Application Control (WDAC) policies. The rest of them are mentioned below at the Resources section.

    "},{"location":"WDAC/Introduction/#resources","title":"Resources","text":"

    There are a lot more WDAC resources and cmdlets available on Microsoft's websites.

    "},{"location":"WDAC/Introduction/#cmdlets","title":"Cmdlets","text":""},{"location":"WDAC/Introduction/#documents","title":"Documents","text":""},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/","title":"Script Enforcement and PowerShell Constrained Language Mode in WDAC App Control Policies","text":""},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#introduction","title":"Introduction","text":"

    This article explores some of the technical details of how to deploy a WDAC (Application Control) policy that uses Script Enforcement and forces PowerShell to run in Constrained Language Mode. It expands aspects of this topic that are not covered enough in the official docs.

    Tip

    Check out these 2 documents from Microsoft for more info and basics:

    Below are the required steps to enable Script Enforcement and allow a PowerShell module to run in Constrained Language Mode, if its code meets the requirements of it.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#signing-the-powershell-module-files","title":"Signing the PowerShell Module files","text":"

    The PowerShell module that you intend to use in Constrained Language Mode must be completely signed, that means all of its .psm1 and .psd1 files must be signed by a code signing certificate.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#type-of-certificate-to-use-to-sign-the-powershell-module-files","title":"Type of Certificate to Use to Sign the PowerShell Module Files","text":"

    The Code Signing certificate you're going to use to sign the PowerShell module files with can be a self-signed certificate or a certificate from a trusted certification authority (CA).

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#making-the-system-trust-the-certificate","title":"Making the System Trust the Certificate","text":"

    If the certificate you used to sign the PowerShell module files with is from a trusted certification authority (CA) and the root certificate of that CA exists in the \"Trusted Root Certification Authorities\" store of either the Local Machine or Current User certificate store, then you're good to go, but if the certificate is self-signed, you need to add the certificate's root certificate to either of those locations.

    For instance, if you generated a Code Signing certificate from Windows Server Active Directory Certificate Services, and you used that certificate to sign the PowerShell module files, you need to export the root certificate containing the public key, to a .cer file and then add it to one of the locations mentioned earlier. Adding the leaf certificate, which is the one you used to sign the module files with, to those locations, will not count and won't allow the signed PowerShell module to run in Constrained Language Mode.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#base-policy-requirements","title":"Base Policy Requirements","text":"

    The WDAC (Application Control) base policy you're going to deploy must have 0 Enabled:UMCI and it must not have the 11 Disabled:Script Enforcement rule options.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#how-to-create-a-supplemental-policy-to-allow-the-certificates","title":"How to Create a Supplemental Policy to Allow the Certificate(s)","text":"

    The root certificate's details must be added as a Signer rule in a WDAC policy in the User-Mode Signing Scenario.

    Adding the Certificate's Signer rule to the Kernel-mode Signing Scenario does not allow the modules signed by that certificate to run, which is expected.

    For better management, you should allow the certificate in a new supplemental policy.

    Here is an example of a valid Supplemental policy that allows a root certificate as a signer.

    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n<SiPolicy xmlns=\"urn:schemas-microsoft-com:sipolicy\" PolicyType=\"Supplemental Policy\">\n  <VersionEx>1.0.0.0</VersionEx>\n  <PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID>\n  <Rules>\n    <Rule>\n      <Option>Enabled:Unsigned System Integrity Policy</Option>\n    </Rule>\n  </Rules>\n  <EKUs />\n  <FileRules />\n  <Signers>\n    <Signer ID=\"ID_SIGNER_S_1_1\" Name=\"Root Certificate\">\n      <CertRoot Type=\"TBS\" Value=\"e3fbf9a3dc3022eab22b5e961bc6fee45782ae8aaed1d8402f2101a5f393db876444ef1d0e302f03b64463bae816f701cc5cda41068a8bf1954a0cd262eb9d6f\" />\n    </Signer>\n  </Signers>\n  <SigningScenarios>\n    <SigningScenario Value=\"131\" ID=\"ID_SIGNINGSCENARIO_DRIVERS_1\" FriendlyName=\"Auto generated policy on 04-26-2024\">\n      <ProductSigners />\n    </SigningScenario>\n    <SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_WINDOWS\" FriendlyName=\"Auto generated policy on 04-26-2024\">\n      <ProductSigners>\n        <AllowedSigners>\n          <AllowedSigner SignerId=\"ID_SIGNER_S_1_1\" />\n        </AllowedSigners>\n      </ProductSigners>\n    </SigningScenario>\n  </SigningScenarios>\n  <UpdatePolicySigners />\n    <CiSigners>\n  <CiSigner SignerId=\"ID_SIGNER_S_1_1\" />\n  </CiSigners>\n  <HvciOptions>2</HvciOptions>\n  <BasePolicyID>{7558D4BF-69E3-45CA-9C52-915E48A7C50E}</BasePolicyID>\n  <PolicyID>{32C551AF-C243-477A-9955-D37EDF435414}</PolicyID>\n  <Settings>\n    <Setting Provider=\"PolicyInfo\" Key=\"Information\" ValueName=\"Name\">\n      <Value>\n        <String>Supplemental Policy</String>\n      </Value>\n    </Setting>\n  </Settings>\n</SiPolicy>\n

    As you can see, we need the TBS Hash value of the root certificate.

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#use-the-wdacconfig-module-to-automatically-allow-certificates","title":"Use the WDACConfig Module to Automatically Allow Certificates","text":"

    You can use the WDACConfig module to create a supplemental policy that allows the certificates you select to be allowed by WDAC. To do that, you can use the following command:

    New-SupplementalWDACConfig -Certificates -CertificatePaths \"certificate.cer\" -SuppPolicyName '<Certificate Name>' -PolicyPath \"<Path to Base policy XML file>\"\n

    More info regarding the cmdlet is available here

    A manual way to get the TBS Hash value of a certificate is using the following command, which also works for signed files and will show the details of the certificates in the chain as well.

    certutil.exe \u2013v <Path To .cer file>\n

    "},{"location":"WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/#powershell-engine-behavior","title":"PowerShell Engine Behavior","text":"

    When a WDAC policy with script enforcement is deployed and you try to import an unauthorized module, you might see different errors. For instance, you might see an error about classes not being allowed or other reasons for a module not being able to load, but in essence, the PowerShell engine is trying to load the module in Constrained Language Mode and the module is failing to meet the requirements, most likely because:

    Important

    WDACConfig module is currently not compatible with constrained language mode due to using advanced PowerShell features that are not allowed in that mode.

    "},{"location":"WDAC/WDAC%20Notes/","title":"Important Notes and Tips about WDAC policies","text":""},{"location":"WDAC/WDAC%20Notes/#supplemental-wdac-policy-considerations","title":"Supplemental WDAC Policy Considerations","text":""},{"location":"WDAC/WDAC%20Notes/#verify-policy-type","title":"Verify Policy type","text":"

    We have to make sure the WDAC policy that we are going to use as a supplemental policy has PolicyType=\"Supplemental Policy\" in the SiPolicy element of the XML file. If it doesn't, then we have to use this command to change it from base policy to supplemental policy of our base policy.

    That will also change/create the <BasePolicyID>GUID</BasePolicyID> element in the supplemental policy XML file. The GUID will be the PolicyID of the base policy specified in the command.

    "},{"location":"WDAC/WDAC%20Notes/#verify-policy-rule-options","title":"Verify Policy Rule options","text":"

    We have to make sure that the supplemental policy does not contain any policy rule options that only work with a base policy. This chart shows which ones can be used in a supplemental policy.

    You can use this PowerShell code to automatically make sure non-supplemental policy rule options don't exist in a supplemental policy XML file:

    [System.String]$SupplementalPolicyPath = \"<Path to SupplementalPolicy.xml>\"\n@(0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 15, 16, 17, 19, 20) | ForEach-Object -Process {\n    Set-RuleOption -FilePath $SupplementalPolicyPath -Option $_ -Delete\n}\n

    A supplemental policy can only have these policy rule options:

    "},{"location":"WDAC/WDAC%20Notes/#deny-rules-in-supplemental-policy-are-invalid","title":"Deny Rules in Supplemental Policy Are Invalid","text":"

    Deny rules are ignored in supplemental policies by the WDAC engine. Supplemental policies are only meant to expand what the base policy trusts, that's why only allow rules are supported in supplemental policies, and that's also the reason why we don't need to merge Microsoft recommended block rules or driver block rules with a supplemental policy.

    "},{"location":"WDAC/WDAC%20Notes/#rule-precedence","title":"Rule Precedence","text":"

    When the base policy has a deny rule for a file and we allow the same file in a supplemental policy, the file will still be blocked, because explicit deny rules have the highest priority.

    More info

    "},{"location":"WDAC/WDAC%20Notes/#signing-a-supplemental-policy","title":"Signing a Supplemental Policy","text":"

    Suppose you have a base policy which will subsequently have supplemental policies. To add the details of the code signing certificate to the base policy, ensuring its readiness for signing, you need to use the -Supplemental switch parameter with the Add-SignerRule cmdlet. Failing to do so would render the signed base policy, post-deployment, incapable of accepting any signed supplemental policies. Note that the -Supplemental parameter is exclusively applicable to base policies.

    Important

    Using -Supplemental parameter with Add-SignerRule cmdlet on a Supplemental policy will cause boot failure after deploying it, because that parameter should only be used when adding signer rules to a base policy.

    "},{"location":"WDAC/WDAC%20Notes/#removing-supplemental-policies","title":"Removing Supplemental Policies","text":"

    Whether the deployed supplemental policy is unsigned or signed, you can remove it just like any unsigned policy using CITool.

    "},{"location":"WDAC/WDAC%20Notes/#what-if-you-deployed-an-unsigned-supplemental-policy-for-a-signed-base-policy","title":"What if You Deployed an Unsigned Supplemental Policy for a Signed Base Policy?","text":"

    If you deploy an unsigned supplemental policy on a system where all policies including base and supplemental, are signed, the deployed unsigned supplemental policy will be ignored.

    "},{"location":"WDAC/WDAC%20Notes/#how-deny-rules-for-files-and-certificatessigners-are-specified","title":"How Deny Rules for Files and Certificates/Signers Are Specified","text":""},{"location":"WDAC/WDAC%20Notes/#denied-file-rules","title":"Denied File Rules","text":"

    First, Block/Deny File rules are specified in the <FileRules> node which is directly under the <SiPolicy> node in the XML file. Deny rules are created by having <Deny ID=\"ID_DENY_\" at the beginning of their lines. For example:

    <Deny ID=\"ID_DENY_AGENT64_SHA1\" FriendlyName=<Textual Description/Name> Hash=<Hash Numbers> />\n

    Second, there are File Reference rules for each Deny rule that only mentions them by ID, and these are exactly the same as Allow rules because only Rule IDs are mentioned and nothing about the nature of the rule itself. These are in:

    <SiPolicy>\n    <SigningScenarios>\n        <SigningScenario>\n            <ProductSigners>\n                <FileRulesRef>\n                    <FileRuleRef RuleID=\"<The same ID of the Deny File rule mentioned earlier>\" />\n                </FileRulesRef>\n            </ProductSigners>\n        </SigningScenario>\n    </SigningScenarios>\n</SiPolicy>\n ```\n\n<br>\n\n### Denied Certificates/Signer\n\nDenied certificates/signers are first mentioned in `<SiPolicy` => `<Signers>` with the following syntax:\n\n```xml\n<Signer ID=\"ID_SIGNER_VERISIGN_2010\" Name=\"VeriSign Class 3 Code Signing 2010 CA\">\n... Other possible elements ...\n</Signer>\n

    Unlike file rules, this first part doesn't specify whether the certificate/signer must be allowed or blocked by the WDAC policy.

    In order to specify whether a certificate/signer should be denied/allowed, the ID of each signer must be specified in the second part of the XML policy file in <DeniedSigners> element:

    <SigningScenarios>\n    <SigningScenario Value=\"131\" ID=\"ID_SIGNINGSCENARIO_<Some generic String>\" FriendlyName=\"<Name>\">\n        <ProductSigners>\n            <DeniedSigners>\n                <DeniedSigner SignerId=\"<ID of the Signer mentioned above in the <Signers> section>\" />\n            </DeniedSigners>\n        </ProductSigners>\n    </SigningScenario>\n</SigningScenarios>\n
    "},{"location":"WDAC/WDAC%20Notes/#guidance-on-creating-wdac-deny-policies","title":"Guidance on Creating WDAC Deny Policies","text":""},{"location":"WDAC/WDAC%20Notes/#how-to-verify-the-status-of-user-mode-and-kernel-mode-application-control-on-the-system","title":"How to Verify the Status of User-Mode and Kernel-Mode Application Control on the System","text":""},{"location":"WDAC/WDAC%20Notes/#using-powershell","title":"Using PowerShell","text":"
    Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\\Microsoft\\Windows\\DeviceGuard | select -Property *codeintegrity* | fl\n

    2 means Enforced, 1 means Audit mode, 0 means Disabled/Not running.

    "},{"location":"WDAC/WDAC%20Notes/#using-system-information","title":"Using System Information","text":"

    "},{"location":"WDAC/WDAC%20Notes/#refreshing-wdac-policies","title":"Refreshing WDAC Policies","text":""},{"location":"WDAC/WDAC%20Notes/#using-the-built-in-citool","title":"Using the built-in CiTool","text":"
    CITool --refresh\n

    Old Method: using RefreshPolicy(AMD64).exe

    Note

    When a Supplemental policy is removed from the system and you refresh the policies, that doesn't instantly block the apps that were allowed by the removed policy, simply because those apps might be still running on the system, either in the background or foreground. To properly stop them, a system restart is required.

    "},{"location":"WDAC/WDAC%20Notes/#about-signingscenarios-node-in-the-wdac-policy-xml","title":"About <SigningScenarios> Node in the WDAC Policy XML","text":"

    It consists of 2 elements:

    This one contains the Certificates/Signers of the Kernel-mode drivers

    <SigningScenario Value=\"131\" ID=\"ID_SIGNINGSCENARIO_DRIVERS_1\" FriendlyName=\"Driver Signing Scenarios\">\n

    And this one contains the Certificates/Signers of the User-mode binaries

    <SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_WINDOWS\" FriendlyName=\"User Mode Signing Scenarios\">\n

    Only the Value needs to stay the same. So, for Kernel-mode drivers it should always be 131 and for User-mode binaries it should always be 12, anything else can be customized, this is according to the CI policy schema.

    "},{"location":"WDAC/WDAC%20Notes/#merging-policies","title":"Merging Policies","text":"

    Merge-cipolicy cmdlet does not include duplicates, neither duplicate rules nor rules with duplicate file hashes.

    "},{"location":"WDAC/WDAC%20Notes/#wdac-forces-allow-list-architecture-by-nature","title":"WDAC Forces Allow-list Architecture by Nature","text":"

    WDAC forces Allow-list architecture by nature, not deny-list architecture. An empty deployed policy allows nothing to run and leads to system failure. This is why Microsoft recommended blocklists include 2 Allow All rules with the Deny rules, that changes the WDAC policy's nature from being an Allow-list to being a Deny-list.

    "},{"location":"WDAC/WDAC%20Notes/#about-microsoft-recommended-block-rules","title":"About Microsoft Recommended Block Rules","text":""},{"location":"WDAC/WDAC%20Notes/#how-to-manually-consume-the-microsoft-recommended-block-rules","title":"How to Manually Consume the Microsoft Recommended Block Rules","text":"

    From Microsoft recommended block rules document, copy the WDAC policy XML at the end (you might need to expand that section to view it), use a text editor like VS Code to edit it as recommended:

    The blocklist policy includes \"Allow all\" rules for both kernel and user mode files that make it safe to deploy as a standalone WDAC policy or side-by-side any other policy by keeping its allow all rules in place. Refer to this document about how multiple base policies work.

    "},{"location":"WDAC/WDAC%20Notes/#how-do-the-allow-all-rules-work","title":"How Do the Allow All Rules Work","text":"

    Only applications allowed by all Base policies run without generating block events, that means even though the Microsoft recommended block rules have 2 allow all rules, they don't actually allow everything to run, because for instance in a realistic scenario, the same allow all rules don't exist in other base policies such as AllowMicrosoft or DefaultWindows base policy, they would only contain explicit allow rules.

    The policy must be in multiple policy format, which can be achieved by using the Set-CiPolicyIdInfo cmdlet with the -ResetPolicyId switch.

    Important

    If merging into an existing policy that includes an explicit allowlist, you should first remove the two \"Allow all\" rules and their corresponding FileRuleRefs:

    <Allow ID=\"ID_ALLOW_A_1\" FriendlyName=\"Allow Kernel Drivers\" FileName=\"*\" />\n<Allow ID=\"ID_ALLOW_A_2\" FriendlyName=\"Allow User mode components\" FileName=\"*\" />\n
    <FileRuleRef RuleID=\"ID_ALLOW_A_1\" />\n<FileRuleRef RuleID=\"ID_ALLOW_A_2\" />\n

    "},{"location":"WDAC/WDAC%20Notes/#microsoft-recommended-driver-block-rules","title":"Microsoft Recommended Driver Block Rules","text":"

    Citation: If you only manage Windows 11 22H2 systems (and above), then you don't need the recommended driver block rules in your WDAC policy. Otherwise, you should have the driver block rules in your policy. In either scenario, you should have the recommended user mode rules.

    Citation: ISG does not include the recommended blocklist(s).

    "},{"location":"WDAC/WDAC%20Notes/#miscellaneous","title":"Miscellaneous","text":"

    "},{"location":"WDAC/WDAC%20Notes/#blocking-individual-windows-components","title":"Blocking Individual Windows components","text":""},{"location":"WDAC/WDAC%20Notes/#blocking-microsoft-store","title":"Blocking Microsoft Store","text":"
    $Package = Get-AppXPackage -Name \"Microsoft.WindowsStore\"\n$Rules += New-CIPolicyRule -Package $Package -Deny\nNew-CIPolicy -FilePath \".\\store.xml\" -Rules $Rules\n
    "},{"location":"WDAC/WDAC%20Notes/#how-to-remove-flight-signing-certificates-from-default-example-policies","title":"How to Remove Flight Signing Certificates From Default Example Policies","text":"

    Removing these do not cause any problem as long as your Windows build is in the Stable, Release Preview or Beta channel.

    # Flight root Certs removal\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_STORE_FLIGHT_ROOT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WINDOWS_FLIGHT_ROOT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_ELAM_FLIGHT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_HAL_FLIGHT\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WHQL_FLIGHT_SHA2\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WINDOWS_FLIGHT_ROOT_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_ELAM_FLIGHT_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_HAL_FLIGHT_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_WHQL_FLIGHT_SHA2_USER\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_RT_FLIGHT\"\n

    "},{"location":"WDAC/WDAC%20Notes/#how-to-remove-wdac-policy-refresh-tool-certificates-from-default-example-policies","title":"How to Remove WDAC Policy Refresh Tool Certificates From Default Example Policies","text":"

    Starting with Windows 11 22H2, CITool is available in Windows by default and Refresh tool is no longer needed, so use the commands below to remove the certificates that allow that tool to be executed, their order of execution is important.

    Remove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_SIGNER_MICROSOFT_REFRESH_POLICY\"\nRemove-CIPolicyRule -FilePath \"DefaultWindows_Enforced.xml\" -Id \"ID_FILEATTRIB_REFRESH_POLICY\"\n

    "},{"location":"WDAC/WDAC%20Notes/#allowing-questionable-software-in-a-wdac-policy","title":"Allowing Questionable Software in a WDAC Policy","text":"

    Questionable software such as pirated software are never recommended to be allowed in the WDAC policy because they are tampered with. Pirated software can have signed files too, but they are modified and as a result there is a mismatch between the file hash and the hash of the file saved in their digital signature. When such a mismatch exists for signed files, Authenticode reports the mismatch, and the file can't be allowed in a WDAC policy.

    If you want to go through many files and see which ones have a mismatch between their file hash and signature hash, you can use the following PowerShell command, it searches through a folder and all of its sub-folders quickly.

    Foreach ($File in (Get-ChildItem -Path 'Path\\To\\a\\Folder' -File -Recurse)) {\n    $Signature = Get-AuthenticodeSignature -FilePath $File.FullName\n    if ($Signature.Status -eq 'HashMismatch') {\n        Write-Output -InputObject $File.FullName\n    }\n}\n

    "},{"location":"WDAC/WDAC%20Notes/#performing-system-reset-while-signed-wdac-policy-is-deployed","title":"Performing System Reset While Signed WDAC Policy Is Deployed","text":"

    If you've deployed a Signed WDAC policy on a system and then decide to reset it, either using local install or cloud download, it will fail during the reset process. You must remove the signed WDAC policy prior to performing the reset.

    Unsigned WDAC policies don't have this behavior. Since they are neither cryptographically signed nor tamper-proof, they will be removed during the reset process and after reset the system will not have the WDAC policy.

    This behavior is true for Lightly managed, Allow Microsoft and Default Windows WDAC policy types.

    "},{"location":"WDAC/WDAC%20Notes/#the-cip-binary-file-can-have-any-name-or-no-name-at-all","title":"The .CIP Binary File Can Have Any Name or No Name at All","text":"

    Using CiTool in Windows 11 build 22621 and above, .CIP binary files can be deployed with any name, even without a name, and lead to a successful WDAC policy deployment.

    "},{"location":"WDAC/WDAC%20Notes/#policies-with-requiredev-signers-rule-option","title":"Policies with Required:EV Signers rule option","text":"

    If a base policy has rule option number 8, Required:EV Signers, it will require all kernel-mode drivers to have EV signer certificates.

    "},{"location":"WDAC/WDAC%20Notes/#the-following-policy-rule-options-only-apply-to-user-mode-binariesdrivers","title":"The Following Policy Rule Options Only Apply to User Mode Binaries/Drivers","text":"

    When we remove the SigningScenario Value=\"12\" completely which is responsible for User Mode code integrity in the xml policy and also remove any signers that belong to User mode section, such as those that have _user in their ID, the Merge-CIPolicy cmdlet automatically removes EKUs that belong to the policy rule options mentioned above during a merge.

    Removing the User mode signers, rules and Enabled:UMCI rule option allows us to create a Kernel-only WDAC policy that doesn't touch User mode binaries/drivers.

    For a Kernel-mode only WDAC policy, only the following EKUs are necessary

    <EKUs>\n    <EKU ID=\"ID_EKU_WINDOWS\" Value=\"010A2B0601040182370A0306\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_ELAM\" Value=\"010A2B0601040182373D0401\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_HAL_EXT\" Value=\"010a2b0601040182373d0501\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_WHQL\" Value=\"010A2B0601040182370A0305\" FriendlyName=\"\" />\n</EKUs>\n

    Important

    Refer to this document for complete info about Kernel-Mode policies

    "},{"location":"WDAC/WDAC%20Notes/#you-can-merge-the-same-policy-xml-file-with-itself","title":"You Can Merge the Same Policy XML File With Itself","text":"

    In order to automatically remove unnecessary things from a policy file, such as the EKUs mentioned earlier, you can run a command like this:

    Merge-CIPolicy .\\Policy.xml -OutputFilePath .\\Policy1.xml\n

    It essentially merges a policy with itself, adding _0 to each ID and SignerID of the xml nodes which is easily removable using WDACConfig module, although it's not necessary to remove them at all, they are perfectly fine.

    "},{"location":"WDAC/WDAC%20Notes/#-audit-parameter-of-the-configci-cmdlets","title":"-Audit Parameter of the ConfigCi Cmdlets","text":"

    When you use -Audit parameter of ConfigCI cmdlets such as Get-SystemDriver and New-CIPolicy, these 2 event logs are scanned

    1. AppLocker \u2013 MSI and Script event log
    2. CodeIntegrity - Operational

    Explained more in here

    "},{"location":"WDAC/WDAC%20Notes/#about-double-signed-files-and-filepublisher-level","title":"About Double-Signed Files and Filepublisher Level","text":"

    Sometimes there are files that are signed by 2 or more certificates, aka double signed files.

    When a level such as FilePublisher is used, ConfigCI cmdlets create signer rules for one of the intermediate certificates of each of the signers of those files.

    Depending on Kernel or use mode, 2 Allowed Signers are created for the file in either UMCI or KMCI Signing scenario sections.

    However, if the file is a kernel mode driver and user mode driver, then 4 signers are created for it, 2 Allowed Signers in the UMCI Signing Scenario and 2 in the KMCI Signing scenario.

    "},{"location":"WDAC/WDAC%20Notes/#an-example","title":"An example","text":"

    In the signer below

    <Signer ID=\"ID_SIGNER_F_2\" Name=\"Microsoft Windows Third Party Component CA 2014\">\n    <CertRoot Type=\"TBS\" Value=\"D8BE9E4D9074088EF818BC6F6FB64955E90378B2754155126FEEBBBD969CF0AE\" />\n    <CertPublisher Value=\"Microsoft Windows Hardware Compatibility Publisher\" />\n    <FileAttribRef RuleID=\"ID_FILEATTRIB_F_46\" />\n</Signer>\n

    "},{"location":"WDAC/WDAC%20Notes/#some-notes","title":"Some Notes","text":"
    1. If 2 files have the same Leaf certificate CN and also have an Intermediate Certificate in common (that has the same TBS and CN) then they should be listed under the same Signer.

    2. Any Intermediate certificate in the certificate chain/path of a file can be used to allow a file using FilePublisher level.

    3. In case of a multi-certificate signed file, such as the Office installer which is triple-signed, any of the certificates can be used to allow the file in a Supplemental policy or Deny it in a base policy.

    "},{"location":"WDAC/WDAC%20Notes/#what-does-hvci-option-set-to-strict-mean","title":"What Does HVCI option Set to Strict Mean?","text":"

    HVCI stands for Hypervisor-protected Code Integrity and it is a feature that uses virtualization-based security (VBS) to protect the Windows kernel from memory attacks. HVCI can be set to different options in a WDAC policy, such as Enabled, DebugMode, or Strict.

    Setting HVCI to Strict in a WDAC policy provides the highest level of protection for kernel mode code integrity, as it enforces these additional restrictions:

    "},{"location":"WDAC/WDAC%20Notes/#about-certificates-and-certificate-chains","title":"About Certificates and Certificate Chains","text":"

    "},{"location":"WDAC/WDAC%20Notes/#msi-files-and-their-applicable-rule-levels","title":"MSI Files and Their Applicable Rule Levels","text":"

    MSI files cannot be allowed using FilePublisher rule level because they are not PEs and do not have the necessary attributes (Such as file version, original file name, product name, file description and so on) of the PEs (Portable Executable) in order to create FilePublisher/SignedVersion rules for them, so they need to be allowed by other levels such as Publisher or Hash.

    "},{"location":"WDAC/WDAC%20Notes/#the-length-of-the-ids-in-the-policy-xml-file-has-no-effect-on-the-size-of-the-generated-cip-file","title":"The Length of the IDs in the policy XML file has no effect on the size of the generated CIP file","text":"

    It doesn't matter how long or short the IDs are in the policy XML file, such as Signer IDs, Allowed Signer IDs, CiSigner IDs and so on, you can even use GUIDs as IDs to make sure they stay unique, the size of the generated CIP file will not change. In fact, even the hash of the generated CIP file stays the same when you change the length of the IDs in the policy XML file.

    "},{"location":"WDAC/WDAC%20Notes/#continue-reading-about-byovd-protection-with-wdac","title":"Continue reading about BYOVD protection with WDAC","text":""},{"location":"WDAC/WDAC%20Notes/#wdac-policy-for-byovd-kernel-mode-only-protection","title":"WDAC policy for BYOVD Kernel mode only protection","text":""},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/","title":"WDAC policy for Fully managed device - Variant 2","text":"Base policy type Method used Signed Protection score 1-5 Default Windows WDACConfig module No 4
    flowchart TD\n    A(Deploy Default Windows base policy) -->B(Identify Important apps that need Supplemental policy)\n    B --> C[Create Supplemental policy based on App's directory]\n    C --> D[Want to allow an entire directory?]\n    D --> E[New-SupplementalWDACConfig -FilePathWildCards]\n    C --> F[Want to Scan the app's install directory?]\n    F --> G[New-SupplementalWDACConfig -Normal]\n    B --> H[Is it a game Installed using Xbox app?]\n    H --> I[Or Is it an app that installs drivers outside app's directory?]\n    I --> J[Edit-WDACConfig -AllowNewApps]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically, any software that you can run.

    This scenario provides a very high protection level. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#deploy-the-default-windows-base-policy-on-the-system","title":"Deploy the Default Windows Base Policy on the System","text":"

    Start by deploying the Default Windows base policy on the system, which allows only files and apps that come pre-installed in Windows to run and anything else is blocked.

    Since this is an unsigned policy, no reboot is required but it's better to perform a reboot if you want the currently running non-Windows apps to stop running.

    New-WDACConfig -PolicyType DefaultWindows -Deploy\n

    After deploying the base policy, you can create Supplemental policies to allow other apps that don't come by default with Windows to run. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    If you deployed the Default Windows base policy on a system that already had apps installed, you can create Supplemental policy for them using the following syntaxes:

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\DefaultWindowsPlusBlockRules.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the Default Windows base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#based-on-apps-install-directory-and-other-signals","title":"Based on App\u2019s Install Directory and Other Signals","text":"
    Edit-WDACConfig -AllowNewApps -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/","title":"WDAC policy for Fully managed device - Variant 3","text":"Base policy type Method used Signed Protection score 1-5 Allow Microsoft WDACConfig module Yes 4.5
    flowchart TD\n    A(Deploy Allow Microsoft Signed base policy) -->B(Identify Important apps that need Supplemental policy)\n    B --> C[Create Supplemental policy based on App's directory]\n    C --> D[Want to allow an entire directory?]\n    D --> E[New-SupplementalWDACConfig -FilePathWildCards]\n    E --> AA[Deploy-SignedWDACConfig]\n    C --> F[Want to Scan the app's install directory?]\n    F --> G[New-SupplementalWDACConfig -Normal]\n    G --> AB[Deploy-SignedWDACConfig]\n    B --> H[Is it a game Installed using Xbox app?]\n    H --> I[Or Is it an app that installs drivers outside app's directory?]\n    I --> J[Edit-SignedWDACConfig -AllowNewApps]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically, any software that you can run.

    This scenario provides a very high protection level. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#deploy-the-allow-microsoft-base-policy-on-the-system","title":"Deploy the Allow Microsoft Base Policy on the System","text":"

    Start by creating the Allow Microsoft base policy xml file, which allows only files and apps that are signed by Microsoft's trusted root certificate.

    New-WDACConfig -PolicyType AllowMicrosoft\n

    Now what we have the policy xml file for the Allow Microsoft base policy, we need to sign and deploy it.

    Deploy-SignedWDACConfig -CertPath \"C:\\Certificate.cer\" -PolicyPaths \"C:\\AllowMicrosoftPlusBlockRules.xml\" -CertCN \"WDAC Certificate\" -Deploy\n

    Since this is a signed base policy, you need to perform a reboot after deployment so that the anti-tamper protection of a signed base policy will start.

    After deploying the base policy, you can create Supplemental policies to allow other apps that aren't signed by Microsoft's trusted root certificate to run. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    If you deployed the Allow Microsoft base policy on a system that already had apps installed, you can create Supplemental policy for them using the following syntaxes. After creating each Supplemental policy, you need to sign and deploy it using the same Cmdlet we used above.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\AllowMicrosoftPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\AllowMicrosoftPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\AllowMicrosoftPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the Allow Microsoft base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#based-on-apps-install-directory-and-other-signals","title":"Based on App\u2019s Install Directory and Other Signals","text":"
    Edit-SignedWDACConfig -AllowNewApps -CertPath \"C:\\Certificate.cer\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\AllowMicrosoftPlusBlockRules.xml\" -CertCN \"WDAC Certificate\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/","title":"WDAC policy for Fully managed device - Variant 4","text":"Base policy type Method used Signed Protection score 1-5 Default Windows WDACConfig module Yes 5
    flowchart TD\n    A(Deploy Default Windows Signed base policy) -->B(Identify Important apps that need Supplemental policy)\n    B --> C[Create Supplemental policy based on App's directory]\n    C --> D[Want to allow an entire directory?]\n    D --> E[New-SupplementalWDACConfig -FilePathWildCards]\n    E --> AA[Deploy-SignedWDACConfig]\n    C --> F[Want to Scan the app's install directory?]\n    F --> G[New-SupplementalWDACConfig -Normal]\n    G --> AB[Deploy-SignedWDACConfig]\n    B --> H[Is it a game Installed using Xbox app?]\n    H --> I[Or Is it an app that installs drivers outside app's directory?]\n    I --> J[Edit-SignedWDACConfig -AllowNewApps]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically, any software that you can run.

    This scenario provides the ultimate protection level. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#deploy-the-default-windows-base-policy-on-the-system","title":"Deploy the Default Windows Base Policy on the System","text":"

    Start by creating the Default Windows base policy xml file, which allows only files and apps that come pre-installed in Windows to run and anything else is blocked.

    New-WDACConfig -PolicyType DefaultWindows\n

    Now what we have the policy xml file for the Default Windows base policy, we need to sign and deploy it.

    Deploy-SignedWDACConfig -CertPath \"C:\\Certificate.cer\" -PolicyPaths \"C:\\DefaultWindowsPlusBlockRules.xml\" -CertCN \"WDAC Certificate\" -Deploy\n

    Since this is a signed base policy, you need to perform a reboot after deployment so that the anti-tamper protection of a signed base policy will start.

    After deploying the base policy, you can create Supplemental policies to allow other apps that don't come by default with Windows to run. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    If you deployed the Default Windows base policy on a system that already had apps installed, you can create Supplemental policy for them using the following syntaxes. After creating each Supplemental policy, you need to sign and deploy it using the same Cmdlet we used above.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the Default Windows base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#based-on-apps-install-directory-and-other-signals","title":"Based on App's install directory and Other Signals","text":"
    Edit-SignedWDACConfig -AllowNewApps -CertPath \"C:\\Certificate.cer\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\DefaultWindowsPlusBlockRules.xml\" -CertCN \"WDAC Certificate\"\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/","title":"WDAC policy for Fully Managed device - Variant 1","text":"Base policy type Method used Signed Protection score 1-5 Allow Microsoft / Default Windows WDACConfig module No 4

    Note

    This variant helps you create and deploy a WDAC policy for fully managed device using only Event Viewer audit logs.

    This scenario includes using explicit Allow rules for files and certificates/signers, anything not allowed by the policies we are going to make are automatically denied/blocked.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#prepare-a-virtual-machine","title":"Prepare a Virtual Machine","text":"

    Install Hyper-V role from optional Windows features if you haven't already.

    Enable-WindowsOptionalFeature -Online -FeatureName Containers-DisposableClientVM -All -norestart\n

    Download the latest Windows .ISO file from Microsoft website, create a new VM with it, install Windows and log in. Fully update Windows and then restart to apply the updates. You can create a Hyper-V checkpoint at this point so that you can return back to this clean state later on if you need to.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#prepare-a-base-policy","title":"Prepare a Base policy","text":"

    There are 2 types of base policies you can choose from.

    1. Allow Microsoft: Allows only files and apps that are signed by Microsoft's trusted root certificates.

    2. Default Windows: Allows only files and apps that come pre-installed by Windows.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#deploy-the-allow-microsoft-audit-mode-base-policy","title":"Deploy the Allow Microsoft Audit Mode Base Policy","text":"
    New-WDACConfig -PolicyType AllowMicrosoft -Audit -LogSize 20MB\n
    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#deploy-the-default-windows-audit-mode-base-policy","title":"Deploy the Default Windows Audit Mode Base Policy","text":"
    New-WDACConfig -PolicyType DefaultWindows -Audit -LogSize 20MB\n

    Depending on whichever of the option you choose, it deploys the base policy in audit mode. No reboot required.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#generate-audit-event-logs-on-the-system","title":"Generate Audit Event Logs on the System","text":"

    Install all of the programs that you want to allow in the WDAC policy, on the VM. These are the programs that you want to allow to run and be installed on the target system once you've deployed the WDAC policy.

    These event logs are exactly what we need to identify and create Allow rules for the detected files.

    Only files that are executed during audit mode phase generate event logs, so by simply installing a program using its installer, we can't trigger event log generation for each of the components and executables that each program has. So, after installing the programs, run them, use them a bit as you normally would so that all of the programs' components are executed and event logs generated for them.

    "},{"location":"WDAC/WDAC%20for%20Fully%20Managed%20Devices/#generate-supplemental-policy-from-the-audit-event-logs","title":"Generate Supplemental Policy From the Audit Event Logs","text":"

    Run the following command which will scan the local machine's Code Integrity and AppLocker logs and display them to you in a nice GUI (Graphical User Interface) window so that you can see detailed information of each file and choose which ones you want to include in the supplemental policy.

    ConvertTo-WDACPolicy -BasePolicyFile <Path To The Base Policy XML File>\n

    The cmdlet offers a lot more features, you can read about them here.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/","title":"WDAC policy for Lightly managed device","text":"Base policy type Method used Signed Protection score 1-5 SignedAndReputable (ISG) WDACConfig module No / Yes 3.5 / 4
    flowchart TD\n    A(Deploy WDAC base policy with ISG) -->B(Start using your apps)\n    B --> C(Did your app run without problem?)\n    C -->|Yes| D[Awesome]\n    C -->|No| E[Create a Supplemental policy for it]

    Note

    Every time I use the word \"App\", I'm referring to regular Win32 programs as well as Microsoft Store installed apps; Basically any software that you can run.

    This scenario provides a high protection level, higher if you cryptographically Sign it. Using the WDACConfig module, it's very easy to deploy, manage and maintain a system with this configuration.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#deploy-the-signedandreputable-base-policy-on-the-system","title":"Deploy the SignedAndReputable Base Policy on the System","text":"

    Start by deploying the SignedAndReputable base policy on the system, which allows only files and apps that are authorized by the Intelligent Security Graph Authorization which have known good state to run and anything else is blocked.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#unsigned-version","title":"Unsigned version","text":"
    New-WDACConfig -PolicyType SignedAndReputable -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#signed-version","title":"Signed version","text":"
    New-WDACConfig -PolicyType SignedAndReputable\n
    Deploy-SignedWDACConfig -CertPath \"C:\\Certificate.cer\" -PolicyPaths \"C:\\Users\\HotCakeX\\SignedAndReputable.xml\" -CertCN \"WDAC Certificate\" -Deploy\n

    After finishing deploying the SignedAndReputable base policy, if there is an app that is getting blocked and you want to allow it, you can create Supplemental policies to expand your base policy. To do that, you have multiple options.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#creating-supplemental-policy-for-apps-already-installed","title":"Creating Supplemental Policy for Apps Already Installed","text":"

    The following commands use the -Deploy optional switch parameter, meaning after Supplemental policy creation, they are automatically deployed on the system.

    If you chose the Signed path, omit it from the commands and instead use the Deploy-SignedWDACConfig cmdlet to Sign and Deploy the Supplemental policy xml files.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-signer-rules-hashes-file-names-etc","title":"Based on Signer Rules, Hashes, File Names Etc.","text":"
    New-SupplementalWDACConfig -Normal -ScanLocation \"C:\\Program Files\\Program\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\SignedAndReputable.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-file-path-with-one-or-more-wildcard-characters","title":"Based on File Path With One or More Wildcard Characters","text":"
    New-SupplementalWDACConfig -FilePathWildCards -WildCardPath \"C:\\Program Files\\Program\\*\" -SuppPolicyName \"App's Name\" -PolicyPath\n\"C:\\SignedAndReputable.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-an-installed-windows-apps-name","title":"Based on an Installed Windows App\u2019s Name","text":"
    New-SupplementalWDACConfig -InstalledAppXPackages -PackageName \"*App's name*\" -SuppPolicyName \"App's name\" -PolicyPath \"C:\\SignedAndReputable.xml\" -Deploy\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#creating-supplemental-policy-for-new-app-installations-or-apps-already-installed","title":"Creating Supplemental Policy for New App Installations or Apps Already Installed","text":"

    If the app you are trying to allow isn't installed, and when you try to install it you see a blocked/error message, you can use the following syntaxes to allow them to run and then automatically create Supplemental policy for them.

    These methods also work for apps that were installed prior to deploying the \"SignedAndReputable\" base policy and now you want to allow them to run by creating Supplemental policy for them.

    You can create a Supplemental policy for more than 1 app at a time by browsing for multiple apps' install directories using the commands below.

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-apps-install-directory-and-other-signals-unsigned-version","title":"Based on App\u2019s Install Directory and Other Signals - Unsigned Version","text":"
    Edit-WDACConfig -AllowNewApps -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\SignedAndReputable.xml\"\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#based-on-apps-install-directory-and-other-signals-signed-version","title":"Based on App\u2019s Install Directory and Other Signals - Signed Version","text":"
    Edit-SignedWDACConfig -AllowNewApps -CertPath \"C:\\Certificate.cer\" -SuppPolicyName \"App's Name\" -PolicyPath \"C:\\SignedAndReputable.xml\" -CertCN \"WDAC Certificate\"\n
    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#security-considerations","title":"Security Considerations","text":"

    One of the differences between using ISG in a WDAC policy vs using Smart App Control (which also use ISG) is that WDAC policy + ISG rule option passes along reputation from app installers to the binaries they write to disk, it can over-authorize files in some cases. For example, if the installer launches the app upon completion, any files the app writes during that first run will also be allowed.

    Smart App Control however doesn't do this, it will trust the installer file itself if it's trustworthy and subsequently checks the trustworthiness of any binaries the installer tries to use and write to the disk, if any of those binaries or components can't be verified or are malicious, they get blocked.

    Explained more in here:

    "},{"location":"WDAC/WDAC%20for%20Lightly%20Managed%20Devices/#what-to-do-when-there-is-an-update-for-an-allowed-app","title":"What to Do When There Is an Update for an Allowed App?","text":"

    If you've created a Supplemental policy for an app that is already installed and now there is a newer version of that app available, you have multiple options:

    1. If the Supplemental policy that you created to allow that app is based on FilePath with wildcards, then the app can be updated and no change in policy is required.

    2. If the Supplemental policy is based on PFN (Package Family Name) of the app, available only for apps that use MSIX installers, like some of the modern apps installed through Microsoft Store, then you don't need to take any action and the app will be updated without any issues.

    3. If the Supplemental policy is only based on the app's digital signature, which is common for well-made apps, then you don't need to take any further action. As long as the new version of the app has the same digital signature / developer identity, then it will be allowed to run.

    4. If the Supplemental policy is based on individual File Paths (in contrast to wildcard FilePath rules), or based on FileName rules, then most likely there is no need for any further action to be taken as long as the new app's version uses the same file names or the same file paths for its components.

    5. If the Supplemental policy is based on Hash of the app's files, either partially (mixed with signer rules) or entirely (for apps without any digital identity/signature) then all you have to do is to remove the deployed Supplemental policy and create a new Supplemental policy for the app using live audit mode in the module as explained above. Don't need to reboot immediately, but to finish the removal process of a Supplemental policy, whether it's signed or unsigned, a reboot will be eventually needed.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/","title":"WDAC Policy for BYOVD Kernel Mode Only Protection","text":"

    This scenario involves removing the trust to any Kernel mode driver, whether they are vulnerable or not. It does not affect User-mode binaries or drivers. Any 3rd party software/hardware Kernel mode driver will need to be explicitly allowed. This scenario protects against all BYOVD scenarios and much more.

    Drivers can access the Kernel which is the core of the operating system. Microsoft requires all drivers to be digitally signed:

    A BYOVD (Bring Your Own Vulnerable Driver) scenario involves exploiting one of the digitally signed drivers that harbors a security flaw to attain direct access to the core of the OS. This attack vector applies to all OSes, not just Windows.

    People who seek to obtain code signing certificates, even for Extended Validation certificates, are not undergoing proper verification.

    YOUTUBE VIDEO: How to easily protect against BYOVD attack scenarios with WDAC policy in Windows

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#there-are-3-types-of-kernel-mode-drivers-that-can-run-on-windows","title":"There Are 3 Types of Kernel Mode Drivers That Can Run on Windows","text":""},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#regular-drivers","title":"Regular drivers","text":"

    A regular signed driver is a driver that has been digitally signed by the developer using a software publisher certificate (SPC) issued by a Microsoft approved Certificate Authority (CA).

    These are regular signed Kernel mode drivers from 3rd parties that shouldn't be trusted by default in a secure and high-risk environment.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#whql-drivers","title":"WHQL drivers","text":"

    A WHQL driver is a driver that has been tested and certified by Microsoft's Windows Hardware Quality Labs (WHQL). A WHQL driver has passed Microsoft's compatibility tests and can be distributed through Windows Update or other Microsoft-supported channels, while a regular signed driver may not have passed those tests and may not be eligible. A WHQL driver is signed by Microsoft.

    WHQL drivers have a slightly higher security bar than regular Kernel mode drivers. Any driver updates are required to pass the WHQL testing too.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#ev-signed-drivers","title":"EV Signed Drivers","text":"

    EV signed kernel mode drivers are drivers that have been signed with an extended validation code signing certificate issued by a trusted certificate authority (CA).

    EV certificates cost more than regular code signing certificates, they require to be on an HSM (to ensure the private key is stored properly) and CAs issuing them only validate that the company of the person requesting them exists. Anyone can get EV certificate as long as they have a HSM and a company, which is not hard to come by, costs about ~100$ to set up in the US as a resident.

    Sometimes the issuing CA also needs you to send in your driver's license and a picture of you holding it, but things like extended background checks, criminal history check, nationality check, or the proper checks explained in here are not performed.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#what-is-the-solution","title":"What Is the Solution?","text":"

    We need to establish a Zero-Trust situation by eliminating the default trust to any signed driver and explicitly authorizing each driver that seeks to access the kernel.

    Numerous applications incorporate drivers that interact with the Kernel. Ordinarily, they are unnoticeable, but if you deploy the WDAC policy that we are going to create, in Audit mode, you will be able to observe event logs generated for each of the kernel-mode drivers.

    By creating a strict kernel mode WDAC policy, you will have a powerful security feature at your fingertips.

    This approach is the kind of future-leading technology you need. You can't afford waiting for analysis to predict malicious behavior or wait for malware to be found and cataloged before something is done about it.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#how-to-make-a-strict-kernel-mode-wdac-policy","title":"How to make a strict Kernel mode WDAC policy","text":"

    We take the Default Windows example policy from C:\\Windows\\schemas\\CodeIntegrity\\ExamplePolicies and remove the following items from it:

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-ekus-section","title":"From the EKUs section","text":"
    <EKU ID=\"ID_EKU_WHQL\" Value=\"010A2B0601040182370A0305\" />\n<EKU ID=\"ID_EKU_RT_EXT\" Value=\"010a2b0601040182370a0315\" />\n<EKU ID=\"ID_EKU_STORE\" FriendlyName=\"Windows Store EKU - 1.3.6.1.4.1.311.76.3.1 Windows Store\" Value=\"010a2b0601040182374c0301\" />\n<EKU ID=\"ID_EKU_DCODEGEN\" FriendlyName=\"Dynamic Code Generation EKU - 1.3.6.1.4.1.311.76.5.1\" Value=\"010A2B0601040182374C0501\" />\n<EKU ID=\"ID_EKU_AM\" FriendlyName=\"AntiMalware EKU -1.3.6.1.4.1.311.76.11.1 \" Value=\"010a2b0601040182374c0b01\" />\n

    For our strict Kernel-mode-only WDAC policy, only the following EKUs are necessary

    <EKUs>\n    <EKU ID=\"ID_EKU_WINDOWS\" Value=\"010A2B0601040182370A0306\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_ELAM\" Value=\"010A2B0601040182373D0401\" FriendlyName=\"\" />\n    <EKU ID=\"ID_EKU_HAL_EXT\" Value=\"010a2b0601040182373d0501\" FriendlyName=\"\" />\n</EKUs>\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-filerules-section","title":"From the FileRules section","text":"

    User Mode Refresh policy program

    <FileAttrib ID=\"ID_FILEATTRIB_REFRESH_POLICY\" FriendlyName=\"RefreshPolicy.exe FileAttribute\" FileName=\"RefreshPolicy.exe\" MinimumFileVersion=\"10.0.19042.0\" />\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-signers-section","title":"From the Signers section","text":"
    <Signer ID=\"ID_SIGNER_RT_PRODUCTION\" Name=\"Microsoft Product Root 2010 RT EKU\">\n    <CertRoot Type=\"Wellknown\" Value=\"06\" />\n    <CertEKU ID=\"ID_EKU_RT_EXT\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_RT_FLIGHT\" Name=\"Microsoft Flighting Root 2014 RT EKU\">\n    <CertRoot Type=\"Wellknown\" Value=\"0E\" />\n    <CertEKU ID=\"ID_EKU_RT_EXT\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_RT_STANDARD\" Name=\"Microsoft Standard Root 2011 RT EKU\">\n    <CertRoot Type=\"Wellknown\" Value=\"07\" />\n    <CertEKU ID=\"ID_EKU_RT_EXT\" />\n</Signer>\n
    <Signer ID=\"ID_SIGNER_WHQL_SHA2\" Name=\"Microsoft Product Root 2010 WHQL EKU\">\n  <CertRoot Type=\"Wellknown\" Value=\"06\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_WHQL_SHA1\" Name=\"Microsoft Product Root WHQL EKU SHA1\">\n  <CertRoot Type=\"Wellknown\" Value=\"05\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n<Signer ID=\"ID_SIGNER_WHQL_MD5\" Name=\"Microsoft Product Root WHQL EKU MD5\">\n  <CertRoot Type=\"Wellknown\" Value=\"04\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n

    <Signer ID=\"ID_SIGNER_WHQL_FLIGHT_SHA2\" Name=\"Microsoft Flighting Root 2014 WHQL EKU\">\n  <CertRoot Type=\"Wellknown\" Value=\"0E\" />\n  <CertEKU ID=\"ID_EKU_WHQL\" />\n</Signer>\n

    <Signer ID=\"ID_SIGNER_TEST2010\" Name=\"MincryptKnownRootMicrosoftTestRoot2010\">\n<CertRoot Type=\"Wellknown\" Value=\"0A\" />\n</Signer>\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-the-signingscenarios-section","title":"From the SigningScenarios section","text":""},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#in-the-kernel-mode-signing-scenario-block","title":"In the Kernel Mode Signing Scenario block","text":"
    <AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA2\" />\n<AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA1\" />\n<AllowedSigner SignerId=\"ID_SIGNER_WHQL_MD5\" />\n
    <AllowedSigner SignerId=\"ID_SIGNER_WHQL_FLIGHT_SHA2\" />\n
    <AllowedSigner SignerId=\"ID_SIGNER_TEST2010\" />\n
    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#in-the-user-mode-signing-scenario-block","title":"In the User Mode Signing Scenario block","text":"

    This entire block should either be removed

    <!--User Mode Signing Scenario-->\n<SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_UMCI\" FriendlyName=\"User Mode Signing Scenario\">\n  <ProductSigners>\n    <AllowedSigners>\n      <AllowedSigner SignerId=\"ID_SIGNER_WINDOWS_PRODUCTION_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_ELAM_PRODUCTION_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_HAL_PRODUCTION_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA2_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_SHA1_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_MD5_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WINDOWS_FLIGHT_ROOT_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_ELAM_FLIGHT_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_HAL_FLIGHT_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_WHQL_FLIGHT_SHA2_USER\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_STORE\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_STORE_FLIGHT_ROOT\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_RT_PRODUCTION\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_DRM\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_DCODEGEN\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_AM\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_RT_FLIGHT\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_RT_STANDARD\" />\n      <AllowedSigner SignerId=\"ID_SIGNER_MICROSOFT_REFRESH_POLICY\" />\n      <!-- Test signer is trusted by ConfigCI, however, it will not be trusted by CI unless testsigning BCD is set -->\n      <AllowedSigner SignerId=\"ID_SIGNER_TEST2010_USER\" />\n    </AllowedSigners>\n  </ProductSigners>\n</SigningScenario>\n

    Or replaced with

    <SigningScenario Value=\"12\" ID=\"ID_SIGNINGSCENARIO_UMCI\" FriendlyName=\"User Mode Signing Scenario\">\n  <ProductSigners />\n</SigningScenario>\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#flight-root-signers-optional","title":"Flight root signers - Optional","text":"

    They can also be removed if you don't intend to use Windows insider builds. They all have flight or _flight in their ID.

    When removing them, also use the 4 Disabled:Flight Signing policy rule option.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#from-cisigners","title":"From CiSigners","text":"

    Remove this item which is for Windows Store EKU

    <CiSigner SignerId=\"ID_SIGNER_STORE\" />\n

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#how-to-use-and-automate-this-entire-process","title":"How to Use and Automate This Entire Process","text":"

    Use the WDACConfig module to automatically Audit and deploy the Strict Kernel-mode WDAC policies.

    As mentioned earlier, this policy only enforces and applies to Kernel-mode drivers, so your non-Kernel mode files are unaffected. Keep in mind that Kernel-mode does not mean programs that require Administrator privileges, those 2 categories are completely different. Also, not all drivers are Kernel mode, there are user-mode drivers too.

    This strict Kernel mode policy can be perfectly deployed side by side any other WDAC policy.

    For instance, since HVCI is turned on by default on my system, the Microsoft Recommended driver block rules is automatically deployed and it's only Kernel mode. It has 2 allow all rules, making it primarily a block-list policy.

    Then I deploy Strict Kernel-mode WDAC policy, which also only applies to Kernel-mode drivers. It doesn't have allow all rules of course, instead it allows Windows components that are required for Windows to function properly to run and then will let you hand pick any 3rd party Kernel-mode drivers and easily allow them in your policy.

    Now the Allow all rules that exist in the first policy are neutralized. Only applications allowed by both policies run without generating block events., so since the same allow all rules do not exist in our Strict Kernel-mode base policy, they no longer apply.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#what-about-user-mode-binaries","title":"What About User-mode Binaries?","text":"

    So far, we've only been doing Kernel-mode administration. We can use User-mode WDAC policies as well.

    After using those 2 Kernel-mode policies, I deploy a 3rd policy which is going to authorize and validate User-mode binaries too. I choose the Lightly managed WDAC policy that utilizes ISG (Intelligent Security Graph). This policy applies to both Kernel and User modes, but since we already know the logic and learned that only applications allowed by all base policies are allowed to run, we're confident that our Strict Kernel-mode base policy is the only one in charge of authorizing and validating Kernel-mode files/drivers. Our User-mode WDAC policy that utilizes ISG validates User-mode binaries only.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#a-rule-of-thumb","title":"A rule of thumb","text":"

    The strictest policy wins the race in multiple base policy deployments, which in this case is the Strict Kernel-Mode policy. Even though ISG policy which uses Allow Microsoft rules and allows all the WHQL signed drivers, they still won't be able to run unless the Kernel-Mode policy authorizes them, because for a Kernel driver to be allowed to run in this scenario, all base policies must allow it.

    So only the policy that has the least allow listings in common with all other policies takes priority.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#supplemental-policy","title":"Supplemental policy","text":"

    Each of the deployed policies (except for the automatically deployed block rules by HVCI) support having supplemental policies. So, whenever you feel the need to allow additional files that are Kernel-mode drivers or User-mode binaries blocked by ISG, you can add a Supplemental policy for them.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#about-elam-early-launch-anti-malware","title":"About ELAM (Early Launch Anti-Malware)","text":"

    Anti-malware or antivirus vendors need to sign enforceable and binding legal agreements and develop an early launched anti-malware driver that Microsoft will sign. This driver includes a list of certificate hashes that enable that AV vendor to sign new versions without Microsoft\u2019s involvement each time. When code integrity loads this ELAM driver, it permits any executables signed by the certificates in that list to run as anti-malware light.

    "},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#continue-reading-about-important-wdac-notes","title":"Continue reading about important WDAC notes","text":""},{"location":"WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/#important-notes-and-tips-about-wdac-policies","title":"Important Notes and Tips about WDAC policies","text":""},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/","title":"Assert-WDACConfigIntegrity available parameters","text":""},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#syntax","title":"Syntax","text":"
    Assert-WDACConfigIntegrity\n    [-SaveLocally]\n    [-Path <FileInfo>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#description","title":"Description","text":"

    This cmdlet scans all of the relevant files in the WDACConfig module's folder and computes their SHA2/SHA3-512 hashes.

    Then it downloads the cloud CSV file from the GitHub repository and compares the hashes of the local files with the ones in the cloud.

    By doing so, you can ascertain that the files in your local WDACConfig folder are identical to the ones in the cloud and devoid of any interference.

    If there is any indication of tampering, the outcomes will be displayed on the console.

    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#-savelocally","title":"-SaveLocally","text":"

    This parameter is used to generate hashes of the final module's files prior to publishing them to the GitHub. This parameter shouldn't be used.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#-path","title":"-Path","text":"

    Can define a different path for the Hashes.csv file. This parameter shouldn't be used.

    Type: FileInfo Position: Named Default value: Module's Root Directory Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Assert-WDACConfigIntegrity/#note","title":"Note","text":"

    The WDACConfig module comprises of .ps1 and .psm1 files that bear the cryptographic signature of my local certificate authority's (CA) certificate. The module incorporates mechanisms to automatically ascertain the integrity of the module files and prevent any unauthorized modifications. The module manifest, .psd1 file, on the other hand, lacks a signature due to the installation error that arises from the PowerShell gallery when it is signed with a self-signed certificate.

    The public key of the certificate used to sign the module files can be obtained from here.

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/","title":"Build-WDACCertificate available parameters","text":""},{"location":"WDACConfig%20Module/Build-WDACCertificate/#syntax","title":"Syntax","text":"
    Build-WDACCertificate\n    [[-CommonName] <String>]\n    [[-FileName] <String>]\n    [[-BuildingMethod] <String>]\n    [[-Password] <SecureString>]\n    [-Force]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#description","title":"Description","text":"

    This cmdlet constructs self-signed certificates that adhere to Microsoft's specifications for WDAC policy signing. With this cmdlet, you can dispense with Windows Server with a CA role to generate a certificate.

    The generated certificates type is Code Signing, they employ SHA2-512 hashing algorithm with RSA 4096-bit encryption (the maximum supported key size for WDAC signing.)

    Upon constructing a certificate, the cmdlet stores it in the Current User's personal store, then it exports that certificate in 2 files. One of the files has a .cer extension and encompasses only the public key, the other file has a .pfx extension and encompasses both public and private keys.

    The PFX file is encrypted with SHA-256 encryption and safeguarded with the password supplied by the user. After the 2 files are exported, the cmdlet eliminates the certificate from Current Users personal store and then re-imports it using the PFX file, but this time it will store the private key using VSM (Virtual Secure Mode). In this method, the private keys are stored in the TPM and are highly secured with VBS (Virtualized-Based Security). The entire process happens in just few seconds.

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-commonname","title":"-CommonName","text":"

    The common name of the certificate, it will also be assigned as the friendly name of the certificate.

    Tip

    If you enter a CommonName but do not enter a FileName, the FileName will be set to the same value as the CommonName for better user experience.

    Type: String Position: Named Default value: Code Signing Certificate Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-filename","title":"-FileName","text":"

    The name of the .cer and .pfx files that will be generated.

    Type: String Position: Named Default value: Code Signing Certificate Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-buildingmethod","title":"-BuildingMethod","text":"

    2 methods are used to build the certificates. Method 1 uses the Certreq and the Method 2 uses the New-SelfSignedCertificate.

    Type: String Position: Named Default value: Method2 Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-password","title":"-Password","text":"

    The password to be employed to encrypt the .pfx file that encompasses the private and public keys of the certificate. It necessitates being in Secure String type. If it\u2019s not supplied, the user will be prompted to input a password (and a second time to verify it). The minimum password length is 5 characters.

    Type: SecureString Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#-force","title":"-Force","text":"

    The cmdlet verifies whether there is any certificate with the identical common name as the certificate that is being created, on the system. If it detects one, it will prompt the user to for permission to remove them. If this parameter is employed, the prompt will be omitted as it will presume that the user acquiesced.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#related-resources","title":"Related Resources","text":""},{"location":"WDACConfig%20Module/Build-WDACCertificate/#additional-resources","title":"Additional Resources","text":"

    To enhance the security and safeguarding of your certificate further, you can remove the certificate from the Personal store of the Current User certificates and then utilize the PFX file to import it anew in the same location, but this time you will mark additional boxes in the import wizard.

    This video illustrates how to safeguard the Code Signing Certificate generated by the WDACConfig module, so that you will be compelled to either enter your security password or verify your identity every time the certificate is employed. By storing the certificate in this manner, only your user account will have access to it, and you will inherently possess administrator privileges to implement the signed WDAC policy on the system.

    These options are only accessible in GUI and they are to deter automatic scripts from utilizing the certificates without authentication, this is why the Build-WDACCertificate cmdlet does not activate this security feature by default.

    "},{"location":"WDACConfig%20Module/Build-WDACCertificate/#hsm-hardware-security-module","title":"HSM (Hardware Security Module)","text":"

    The most secure method of storing code signing certificates is to use a hardware security module (HSM) or a similar device. Furthermore, obtaining certificates from a regulated or publicly trusted certificate authority (CA) requires the use of an HSM. The HSMs must also comply with the Federal Information Processing Standards (FIPS).

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/","title":"Confirm-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#confirm-wdacconfig-listactivepolicies","title":"Confirm-WDACConfig -ListActivePolicies","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#syntax","title":"Syntax","text":"
    Confirm-WDACConfig\n    [-ListActivePolicies]\n    [-OnlyBasePolicies]\n    [-OnlySupplementalPolicies]\n    [-OnlySystemPolicies]\n
    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#description","title":"Description","text":"

    Lists the deployed Base and Supplemental WDAC Policies using CITool and displays their counts and details.

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#-onlybasepolicies","title":"-OnlyBasePolicies","text":"

    Using this will only display Base policies.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#-onlysupplementalpolicies","title":"-OnlySupplementalPolicies","text":"

    Using this will only display Supplemental policies.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#-onlysystempolicies","title":"-OnlySystemPolicies","text":"

    Using this will only display system policies.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#confirm-wdacconfig-verifywdacstatus","title":"Confirm-WDACConfig -VerifyWDACStatus","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#syntax_1","title":"Syntax","text":"
    Confirm-WDACConfig\n    [-VerifyWDACStatus]\n
    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#description_1","title":"Description","text":"

    Shows the status of User-mode and Kernel-mode application control.

    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#confirm-wdacconfig-checksmartappcontrolstatus","title":"Confirm-WDACConfig -CheckSmartAppControlStatus","text":""},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#syntax_2","title":"Syntax","text":"
    Confirm-WDACConfig\n    [-CheckSmartAppControlStatus]\n
    "},{"location":"WDACConfig%20Module/Confirm-WDACConfig/#description_2","title":"Description","text":"

    Checks the status of Smart App Control and reports the results on the console, including the evaluation mode expiration date.

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/","title":"ConvertTo-WDACPolicy available parameters","text":""},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#syntax","title":"Syntax","text":"
    ConvertTo-WDACPolicy\n    [-PolicyToAddLogsTo <FileInfo>]\n    [-Source <String>]\n    [-SuppPolicyName <String>]\n    [-MDEAHLogs <FileInfo[]>]\n    [-EVTXLogs <FileInfo[]>]\n    [-FilterByPolicyNames <String[]>]\n    [-TimeSpan <String>]\n    [-TimeSpanAgo <UInt64>]\n    [-KernelModeOnly]\n    [-LogType <String>]\n    [-Deploy]\n    [-ExtremeVisibility]\n    [<CommonParameters>]\n
    ConvertTo-WDACPolicy\n    [-BasePolicyFile <FileInfo>]\n    [-Source <String>]\n    [-SuppPolicyName <String>]\n    [-MDEAHLogs <FileInfo[]>]\n    [-EVTXLogs <FileInfo[]>]\n    [-FilterByPolicyNames <String[]>]\n    [-TimeSpan <String>]\n    [-TimeSpanAgo <UInt64>]\n    [-KernelModeOnly]\n    [-LogType <String>]\n    [-Deploy]\n    [-ExtremeVisibility]\n    [<CommonParameters>]\n
    ConvertTo-WDACPolicy\n    [-BasePolicyGUID <Guid>]\n    [-Source <String>]\n    [-SuppPolicyName <String>]\n    [-MDEAHLogs <FileInfo[]>]\n    [-EVTXLogs <FileInfo[]>]\n    [-FilterByPolicyNames <String[]>]\n    [-TimeSpan <String>]\n    [-TimeSpanAgo <UInt64>]\n    [-KernelModeOnly]\n    [-LogType <String>]\n    [-Deploy]\n    [-ExtremeVisibility]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#description","title":"Description","text":"

    This is a multi-purpose cmdlet that offers a wide range of functionalities that can either be used separately or mixed together for very detailed and specific tasks.

    It currently supports Code Integrity and AppLocker logs from the following sources:

    The cmdlet displays the logs in a GUI and allows the user to select the logs to be processed further.

    The logs can be filtered based on many criteria using the available parameters.

    The output of this cmdlet is a Supplemental Application Control (WDAC) policy. Based on the input parameters, it can be associated with a base policy or merged with an existing Base or Supplemental policy.

    The cmdlet can be used for local and remote systems. You can utilize this cmdlet to create Application Control for Business policies from MDE Advanced Hunting and then deploy them using Microsoft Intune to your endpoints.

    You can utilize this cmdlet to use the evtx log files you aggregated from your endpoints and create a WDAC policy from them.

    This offers scalability and flexibility in managing your security policies.

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-policytoaddlogsto","title":"-PolicyToAddLogsTo","text":"

    The policy to add the selected logs to, it can either be a base or supplemental policy.

    Important

    Only select one of the following three parameters: -PolicyToAddLogsTo, -BasePolicyFile, or -BasePolicyGUID.

    Type: FileInfo Aliases: AddLogs Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-basepolicyfile","title":"-BasePolicyFile","text":"

    The base policy file to associate the supplemental policy with.

    Important

    Only select one of the following three parameters: -PolicyToAddLogsTo, -BasePolicyFile, or -BasePolicyGUID.

    Type: FileInfo Aliases: BaseFile Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-basepolicyguid","title":"-BasePolicyGUID","text":"

    The GUID of the base policy to associate the supplemental policy with.

    Important

    Only select one of the following three parameters: -PolicyToAddLogsTo, -BasePolicyFile, or -BasePolicyGUID.

    Type: Guid Aliases: BaseGUID Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-source","title":"-Source","text":"

    The source of the logs. Supports validate set and auto-completion, press TAB key to view the list of the available options.

    Type: String Aliases: Src Position: Named Accepted values: LocalEventLogs, MDEAdvancedHunting, EVTXFiles Default value: LocalEventLogs Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-supppolicyname","title":"-SuppPolicyName","text":"

    The name of the supplemental policy to create

    Type: String Aliases: Name Position: Named Default value: The cmdlet will generate a proper name based on the selected source and time Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-mdeahlogs","title":"-MDEAHLogs","text":"

    The path(s) to use MDE AH CSV files.

    Note

    This is a dynamic parameter and will only be available if the Source parameter is set to MDEAdvancedHunting.

    Important

    Please read this article for complete information on how to use this feature.

    Type: FileInfo[] Aliases: MDELogs Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-evtxlogs","title":"-EVTXLogs","text":"

    The path(s) of EVTX files to use.

    Note

    This is a dynamic parameter and will only be available if the Source parameter is set to EVTXFiles.

    Type: FileInfo[] Aliases: Evtx Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-timespan","title":"-TimeSpan","text":"

    The unit of time to use when filtering the logs by the time.

    Type: String Aliases: Duration Position: Named Accepted values: Minutes, Hours, Days Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-timespanago","title":"-TimeSpanAgo","text":"

    The number of the selected time unit to go back in time from the current time.

    Note

    This is a dynamic parameter and will only be available if the TimeSpan parameter is set.

    Type: String Aliases: Past Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-filterbypolicynames","title":"-FilterByPolicyNames","text":"

    The names of the policies to filter the logs by. Supports auto-completion, press TAB key to view the list of the deployed base policy names to choose from. It will not display the policies that are already selected on the command line.

    You can manually enter the name of the policies that are no longer available on the system.

    Type: String[] Aliases: FilterNames Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-kernelmodeonly","title":"-KernelModeOnly","text":"

    If used, will filter the logs by including only the Kernel-Mode logs.

    Type: SwitchParameter Aliases: KMode Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-logtype","title":"-LogType","text":"

    The type of logs to display.

    Type: String Aliases: LogKind Position: Named Accepted values: Audit, Blocked Default value: Audit Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-deploy","title":"-Deploy","text":"

    If used, will deploy the policy on the system.

    Type: SwitchParameter Aliases: Up Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/ConvertTo-WDACPolicy/#-extremevisibility","title":"-ExtremeVisibility","text":"

    If used, will display all the properties of the logs without any filtering.

    Type: SwitchParameter Aliases: XVis Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/","title":"Deploy-SignedWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#syntax","title":"Syntax","text":"
    Deploy-SignedWDACConfig\n    -PolicyPaths <FileInfo[]>\n    [-Deploy]\n    [-CertPath <FileInfo>]\n    [-CertCN <String>]\n    [-SignToolPath <FileInfo>]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#description","title":"Description","text":"

    Creates and signs a .CIP file that can be either deployed locally using the -Deploy parameter or you can deploy the signed policy binary on a different machine later using the built-in Citool, Intune etc.

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-policypaths","title":"-PolicyPaths","text":"

    The XML Policies to deploy. Supports File picker GUI.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-certpath","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-certcn","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-deploy","title":"-Deploy","text":"

    Deploys the signed policy on the system

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Deploy-SignedWDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with deploying the signed policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/","title":"Edit-SignedWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#edit-signedwdacconfig-allownewapps","title":"Edit-SignedWDACConfig -AllowNewApps","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#syntax","title":"Syntax","text":"
    Edit-SignedWDACConfig\n     [-AllowNewApps]\n     -SuppPolicyName <String>\n     [-BoostedSecurity]\n     [-PolicyPath <FileInfo>]\n     [-CertPath <FileInfo>]\n     [-CertCN <String>]\n     [-LogSize <UInt64>]\n     [-NoScript]\n     [-NoUserPEs]\n     [-SpecificFileNameLevel <String>]\n     [-Level <String>]\n     [-Fallbacks <String[]>]\n     [-SignToolPath <FileInfo>]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#description","title":"Description","text":"

    While a Signed Windows Defender Application Control (WDAC) policy is already deployed on the system, rebootlessly turns on Audit mode in it, which will allow you to install a new app that was otherwise getting blocked.

    After installation, you will be able to browse for the path(s) of the installed app(s) for scanning, which is optional.

    Any file outside of the paths you select that was executed or run during the audit mode phase and was detected in the audit logs, will be displayed to you in a nice GUI (Graphical User Interface) so you will be able to see detailed information about them and decide whether to include them in the Supplemental policy or not.

    This parameter can also be used for apps that are already installed on the system.

    A new supplemental policy will be created, it will be signed and deployed on the system. The base policy that was initially set to Audit mode will also revert back to enforced mode. The entire process happens without the need for reboot. If something like a power outage occurs during the audit mode phase, on the next reboot, the enforced mode base policy will be automatically deployed.

    Note

    This parameter can also detect and create allow rules for Kernel protected files, such as the executables of games installed using Xbox app. Make sure you run the game while the base policy is deployed in Audit mode so that it can capture those executables.

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-supppolicyname","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-boostedsecurity","title":"-BoostedSecurity","text":"

    Implements Sandboxing-like restrictions around the program's dependencies.

    Tip

    When using this mode, it's recommended to only target one program at a time. E.g., don't use this method for creating a supplemental policy for Adobe Photoshop and Steam client at the same time, because they will be put in the same supplemental policy and the dependency sandboxing will be ineffective.

    This mode requires the main executable(s) of the programs that need access to the dependencies (such as DLLs) to have the OriginalFileName property. Most of the time they do. Use the -Verbose parameter to see when they don't.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certpath","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certcn","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-policypath","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports tab completion by showing only .xml files with Base Policy Type.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels for scanning event logs and the specified directory path(s).

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks for scanning event logs and the specified directory path(s).

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-logsize","title":"-LogSize","text":"

    Specifies the log size for Microsoft-Windows-CodeIntegrity/Operational events. The values must be in the form of <Digit + Data measurement unit>. e.g., 2MB, 10MB, 1GB, 1TB. The minimum accepted value is 1MB which is the default.

    Type: UInt64 Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default, the module includes user PEs in the scan. When you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#edit-signedwdacconfig-mergesupplementalpolicies","title":"Edit-SignedWDACConfig -MergeSupplementalPolicies","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#syntax_1","title":"Syntax","text":"
    Edit-SignedWDACConfig\n     [-MergeSupplementalPolicies]\n     -SuppPolicyName <String>\n     -SuppPolicyPaths <FileInfo[]>\n     [-PolicyPath <FileInfo>]\n     [-KeepOldSupplementalPolicies]\n     [-CertPath <FileInfo>]\n     [-CertCN <String>]\n     [-SignToolPath <FileInfo>]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#description_1","title":"Description","text":"

    Merge multiple deployed Signed Supplemental policies into 1 and deploy it, remove the individual ones, all happening automatically.

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-supppolicyname_1","title":"-SuppPolicyName","text":"

    Choose a descriptive name for the Supplemental policy that is going to be the merge of multiple policies.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-supppolicypaths","title":"-SuppPolicyPaths","text":"

    Path to the Supplemental policies xml files. Supports argument tab completion by showing only Supplemental policy types.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certpath_1","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certcn_1","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-policypath_1","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports tab completion by showing only .xml files with Base Policy Type.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-signtoolpath_1","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-keepoldsupplementalpolicies","title":"-KeepOldSupplementalPolicies","text":"

    Indicates that the module will not remove the old Supplemental policy xml files after creating and deploying the new merged one.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#edit-signedwdacconfig-updatebasepolicy","title":"Edit-SignedWDACConfig -UpdateBasePolicy","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#syntax_2","title":"Syntax","text":"
    Edit-SignedWDACConfig\n     [-UpdateBasePolicy]\n     -CurrentBasePolicyName <String[]>\n     -NewBasePolicyType <String>\n     [-CertPath <FileInfo>]\n     [-CertCN <String>]\n     [-SignToolPath <FileInfo>]\n     [-RequireEVSigners]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#description_2","title":"Description","text":"

    It can rebootlessly change the type or rule options of the deployed signed base policy. The deployed Supplemental policies will stay intact and continue to work with the new Base policy.

    Note

    When switching from a more permissive base policy type to a more restrictive one, make sure your Supplemental policies will continue to work. E.g., if your current base policy type is AllowMicrosoft and the one you are switching to is DefaultWindows, there might be files that will get blocked as a result of this switch.

    That's simply because they were allowed by the more permissive AllowMicrosoft policy type so they didn't trigger audit logs (in case the supplemental policy was created based on audit logs) thus weren't needed to be included in the Supplemental policy. You will need to update those Supplemental policies if that happens by deleting and recreating them, no immediate reboot required.

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-currentbasepolicyname","title":"-CurrentBasePolicyName","text":"

    The name of the currently deployed base policy. It supports tab completion so just press tab to autofill it.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-newbasepolicytype","title":"-NewBasePolicyType","text":"

    The new type of the base policy to deploy. It supports tab completion so just press tab to autofill it. Supports all 3 main Base policy types.

    Note

    If the selected policy type is DefaultWindows and the detected PowerShell is not installed through Microsoft Store, the module will scan the PowerShell files and add them to the DefaultWindows base policy as allowed files so you will be able to continue using the module after deploying the policy.

    Type: String Position: Named Accepted values: AllowMicrosoft, DefaultWindows, SignedAndReputable Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certpath_2","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-certcn_2","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the -CertPath is specified and the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-signtoolpath_2","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-SignedWDACConfig/#-requireevsigners","title":"-RequireEVSigners","text":"

    Indicates that the created/deployed policy will have Require EV Signers policy rule option.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/","title":"Edit-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#edit-wdacconfig-allownewapps","title":"Edit-WDACConfig -AllowNewApps","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#syntax","title":"Syntax","text":"
    Edit-WDACConfig\n     [-AllowNewApps]\n     -SuppPolicyName <String>\n     [-BoostedSecurity]\n     [-PolicyPath <FileInfo>]\n     [-Level <String>]\n     [-Fallbacks <String[]>]\n     [-NoScript]\n     [-NoUserPEs]\n     [-SpecificFileNameLevel <String>]\n     [-LogSize <UInt64>]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#description","title":"Description","text":"

    While a Windows Defender Application Control (WDAC) policy is already deployed on the system, rebootlessly turns on Audit mode in it, which will allow you to install a new app that was otherwise getting blocked.

    After installation, you will be able to browse for the path(s) of the installed app(s) for scanning, which is optional.

    Any file outside of the paths you select that was executed or run during the audit mode phase and was detected in the audit logs, will be displayed to you in a nice GUI (Graphical User Interface) so you will be able to see detailed information about them and decide whether to include them in the Supplemental policy or not.

    This parameter can also be used for apps that are already installed on the system.

    A new supplemental policy will be created and deployed on the system. The base policy that was initially set to Audit mode will also revert back to enforced mode. The entire process happens without the need for reboot. If something like a power outage occurs during the audit mode phase, on the next reboot, the enforced mode base policy will be automatically deployed.

    Note

    This parameter can also detect and create allow rules for Kernel protected files, such as the executables of games installed using Xbox app. Make sure you run the game while the base policy is deployed in Audit mode so that it can capture those executables.

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-supppolicyname","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-boostedsecurity","title":"-BoostedSecurity","text":"

    Implements Sandboxing-like restrictions around the program's dependencies.

    Tip

    When using this mode, it's recommended to only target one program at a time. E.g., don't use this method for creating a supplemental policy for Adobe Photoshop and Steam client at the same time, because they will be put in the same supplemental policy and the dependency sandboxing will be ineffective.

    This mode requires the main executable(s) of the programs that need access to the dependencies (such as DLLs) to have the OriginalFileName property. Most of the time they do. Use the -Verbose parameter to see when they don't.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-policypath","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports tab completion by showing only .xml files with Base Policy Type.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-logsize","title":"-LogSize","text":"

    Specifies the log size for Microsoft-Windows-CodeIntegrity/Operational events. The values must be in the form of <Digit + Data measurement unit>. e.g., 2MB, 10MB, 1GB, 1TB. The minimum accepted value is 1MB which is the default.

    Type: UInt64 Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels for scanning event logs and the specified directory path(s).

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks for scanning event logs and the specified directory path(s).

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default, the module includes user PEs in the scan. When you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#edit-wdacconfig-mergesupplementalpolicies","title":"Edit-WDACConfig -MergeSupplementalPolicies","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#syntax_1","title":"Syntax","text":"
    Edit-WDACConfig\n     [-MergeSupplementalPolicies]\n     -SuppPolicyName <String>\n     [-PolicyPath <FileInfo>]\n     -SuppPolicyPaths <FileInfo[]>\n     [-KeepOldSupplementalPolicies]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#description_1","title":"Description","text":"

    Merge multiple deployed Supplemental policies into 1 and deploy it, remove the individual ones, all happening automatically.

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-supppolicyname_1","title":"-SuppPolicyName","text":"

    Choose a descriptive name for the Supplemental policy that is going to be the merge of multiple policies.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-supppolicypaths","title":"-SuppPolicyPaths","text":"

    Path to the Supplemental policies xml files. Supports argument tab completion by showing only Supplemental policy types.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-policypath_1","title":"-PolicyPath","text":"

    Path to the Base policy xml file the Supplemental policies belong to. Supports argument tab completion by showing only Base policy types.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-keepoldsupplementalpolicies","title":"-KeepOldSupplementalPolicies","text":"

    Indicates that the module will not remove the old Supplemental policy xml files after creating and deploying the new merged one.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#edit-wdacconfig-updatebasepolicy","title":"Edit-WDACConfig -UpdateBasePolicy","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#syntax_2","title":"Syntax","text":"
    Edit-WDACConfig\n     [-UpdateBasePolicy]\n     -CurrentBasePolicyName <String[]>\n     -NewBasePolicyType <String>\n     [-RequireEVSigners]\n     [-SkipVersionCheck]\n     [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#description_2","title":"Description","text":"

    It can rebootlessly change the type or rule options of the deployed base policy. The deployed Supplemental policies will stay intact and continue to work with the new Base policy.

    Note

    When switching from a more permissive base policy type to a more restrictive one, make sure your Supplemental policies will continue to work. E.g., if your current base policy type is AllowMicrosoft and the one you are switching to is DefaultWindows, there might be files that will get blocked as a result of this switch.

    That's simply because they were allowed by the more permissive AllowMicrosoft policy type so they didn't trigger audit logs (in case the supplemental policy was created based on audit logs) thus weren't needed to be included in the Supplemental policy. You will need to update those Supplemental policies if that happens by deleting and recreating them, no immediate reboot required.

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-currentbasepolicyname","title":"-CurrentBasePolicyName","text":"

    The name of the currently deployed base policy. It supports tab completion so just press tab to autofill it.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-newbasepolicytype","title":"-NewBasePolicyType","text":"

    The new type of the base policy to deploy. It supports tab completion so just press tab to autofill it. Supports all 3 main Base policy types.

    Note

    If the selected policy type is DefaultWindows and the detected PowerShell is not installed through Microsoft Store, the module will scan the PowerShell files and add them to the DefaultWindows base policy as allowed files so you will be able to continue using the module after deploying the policy.

    Type: String Position: Named Accepted values: AllowMicrosoft, DefaultWindows, SignedAndReputable Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Edit-WDACConfig/#-requireevsigners","title":"-RequireEVSigners","text":"

    Indicates that the created/deployed policy will have Require EV Signers policy rule option.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/","title":"Get-CIPolicySetting available parameters","text":""},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#syntax","title":"Syntax","text":"
    Get-CIPolicySetting\n    [-Provider] <String>\n    [-Key] <String>\n    [-ValueName] <String>\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#description","title":"Description","text":"

    Gets the secure settings value from the deployed CI policies. If there is a policy with the same provider, key and value then it returns the following details:

    Property Description Value The actual value of the string ValueType The type of setting: WldpString, WldpInteger or WldpBoolean ValueSize the size of the returned value Status True/False depending on whether the setting exists on the system or not StatusCode 0 if the value exists on the system, non-zero if it doesn't."},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#-provider","title":"-Provider","text":"

    The provider of the secure setting.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#-key","title":"-Key","text":"

    The key of the secure setting.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CIPolicySetting/#-valuename","title":"-ValueName","text":"

    The name of the secure setting.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CiFileHashes/","title":"Get-CiFileHashes available parameters","text":""},{"location":"WDACConfig%20Module/Get-CiFileHashes/#syntax","title":"Syntax","text":"
    Get-CiFileHashes\n    [-FilePath] <FileInfo>\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Get-CiFileHashes/#description","title":"Description","text":"

    Calculates the Authenticode hash and first page hash of the PEs with SHA1 and SHA256 algorithms. The hashes are compliant wih the Windows Defender Application Control (WDAC) policy.

    The cmdlet outputs an ordered hashtable. The keys are the hash algorithm names and the values are the hashes.

    For more information please visit this page

    Tip

    If the file is non-conformant, the function will calculate the flat hash of the file using the specified hash algorithm and return them as the Authenticode hashes. This is compliant with how the WDAC engine in Windows works.

    "},{"location":"WDACConfig%20Module/Get-CiFileHashes/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Get-CiFileHashes/#-filepath","title":"-FilePath","text":"

    The path to the file for which the hashes are to be calculated. Supports TAB completion, when you press Tab key, file picker GUI will open allowing you to select a file.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/","title":"Get-CommonWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#syntax","title":"Syntax","text":"
    Get-CommonWDACConfig\n    [-CertCN]\n    [-CertPath]\n    [-SignToolPath]\n    [-SignedPolicyPath]\n    [-UnsignedPolicyPath]\n    [-StrictKernelPolicyGUID]\n    [-StrictKernelNoFlightRootsPolicyGUID]\n    [-Open]\n    [-LastUpdateCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#description","title":"Description","text":"

    Use this cmdlet to query and display the values for common and frequently used parameters in the User Configurations Json file.

    All of the applicable cmdlets of the module automatically check the User Configuration file for any available input, if you don't specify values for their parameters. Learn more about the User Configuration file here.

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-certcn","title":"-CertCN","text":"

    Displays the Common Name of an installed certificate.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-certpath","title":"-CertPath","text":"

    Displays the path to a certificate .cer file.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Displays the path to the SignTool executable.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-signedpolicypath","title":"-SignedPolicyPath","text":"

    Displays the path to the xml file of a Signed policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-unsignedpolicypath","title":"-UnSignedPolicyPath","text":"

    Displays the path to the xml file of an Unsigned policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-open","title":"-Open","text":"

    Opens the User Config Json file in the default editor.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Get-CommonWDACConfig/#-lastupdatecheck","title":"-LastUpdateCheck","text":"

    Displays the last time online update check was performed.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/","title":"Invoke-WDACSimulation available parameters","text":""},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#syntax","title":"Syntax","text":"
    Invoke-WDACSimulation\n  [-XmlFilePath] <FileInfo>\n  [[-FolderPath] <DirectoryInfo>]\n  [[-FilePath] <FileInfo>]\n  [-BooleanOutput]\n  [-Log]\n  [-CSVOutput]\n  [-SkipVersionCheck]\n  [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#description","title":"Description","text":"

    This cmdlet allows you to simulate a WDAC (App Control for Business) policy deployment. Simply select a folder or file and a policy XML file, it will show you whether the selected files would be allowed or blocked by your WDAC policy if it was actually deployed on a system and those files were run.

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#supported-levels-and-specificfilenamelevel-options","title":"Supported Levels and SpecificFileNameLevel Options","text":"

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#accuracy","title":"Accuracy","text":"

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#some-use-cases","title":"Some Use Cases","text":""},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-folderpath","title":"-FolderPath","text":"

    Path to a folder. Supports argument tab completion, select the parameter then press TAB to open the Folder picker GUI.

    Tip

    Either FilePath or FolderPath must be provided.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-filepath","title":"-FilePath","text":"

    Provide path to a file that you want WDAC simulation to run against

    Uses LiteralPath to take the path exactly as typed including Special characters such as [ and ]

    Tip

    Either FilePath or FolderPath must be provided.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-xmlfilepath","title":"-XmlFilePath","text":"

    Path to a xml file. Supports argument tab completion, select the parameter then press TAB to open the file picker GUI that only shows xml files.

    Type: FileInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-booleanoutput","title":"-BooleanOutput","text":"

    Can be used with any parameter to return a boolean value instead of displaying the object output

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-log","title":"-Log","text":"

    Use this switch to start a transcript of the WDAC simulation and log everything displayed on the screen.

    Tip

    Highly recommended to use the -Verbose parameter with this switch to log the verbose output as well.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Invoke-WDACSimulation/#-csvoutput","title":"-CSVOutput","text":"

    Upon completion of the simulation, you will obtain a CSV file containing the output of the simulation with exhaustive details of each file that would be blocked/allowed by the selected policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/","title":"New-DenyWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-normal","title":"New-DenyWDACConfig -Normal","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-Normal]\n    -PolicyName <String>\n    [-ScanLocations <DirectoryInfo[]>]\n    [-Deploy]\n    [-Level <String>]\n    [-Fallbacks <String[]>]\n    [-SpecificFileNameLevel <String>]\n    [-NoUserPEs]\n    [-NoScript]\n    [-SkipVersionCheck]\n    [-WhatIf]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description","title":"Description","text":"

    Creates a Deny base policy by scanning a directory. The base policy will have 2 allow all rules, meaning it can be deployed as a standalone base policy, side-by-side any other Base/Supplemental policies.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-scanlocations","title":"-ScanLocations","text":"

    Accepts one or more comma separated folder paths. Supports argument completion, when you press tab, folder picker GUI will open allowing you to easily select a folder, you can then add a comma , and press tab again to select another folder path or paste a folder path manually, works both ways.

    Type: DirectoryInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels to scan the specified directory path(s).

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks to scan the specified directory path(s).

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default the module includes user PEs in the scan, but when you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-drivers","title":"New-DenyWDACConfig -Drivers","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax_1","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-Drivers]\n    -PolicyName <String>\n    [-ScanLocations <DirectoryInfo[]>]\n    [-Deploy]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description_1","title":"Description","text":"

    Creates a Deny base policy by scanning a directory, this parameter uses DriverFile objects so it's best suitable for driver files. The base policy will have 2 allow all rules, meaning it can be deployed as a standalone base policy, side-by-side any other Base/Supplemental policies.

    Note

    The scan uses WHQLFilePublisher level without any fallbacks, and includes both usermode and kernel mode drivers.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname_1","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-scanlocations_1","title":"-ScanLocations","text":"

    Accepts one or more comma separated folder paths. Supports argument completion, when you press tab, folder picker GUI will open allowing you to easily select a folder, you can then add a comma , and press tab again to select another folder path or paste a folder path manually, works both ways.

    Type: DirectoryInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy_1","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-installedappxpackages","title":"New-DenyWDACConfig -InstalledAppXPackages","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax_2","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-InstalledAppXPackages]\n    -PackageName <String>\n    -PolicyName <String>\n    [-Deploy]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description_2","title":"Description","text":"

    Creates a Deny base policy for one or more installed Windows Apps (Appx) based on their PFN (Package Family Name). The base policy will have 2 allow all rules, meaning it can be deployed as a standalone base policy, side-by-side any other Base/Supplemental policies.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-packagename","title":"-PackageName","text":"

    Enter the package name of an installed app. Supports wildcard * character. e.g, *Edge* or \"*Microsoft*\".

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname_2","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy_2","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with creating the deny policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#new-denywdacconfig-pathwildcards","title":"New-DenyWDACConfig -PathWildCards","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#syntax_3","title":"Syntax","text":"
    New-DenyWDACConfig\n    [-PathWildCards]\n    -PolicyName <String>\n    -FolderPath <DirectoryInfo>\n    [-Deploy]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#description_3","title":"Description","text":"

    Creates a Deny standalone base policy for a folder using wildcards. The base policy created by this parameter can be deployed side by side any other base/supplemental policy.

    Note

    This feature is also used internally by the Harden Windows Security Module.

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#parameters_3","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-policyname_3","title":"-PolicyName","text":"

    Add a descriptive name for the Deny base policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-folderpath","title":"-FolderPath","text":"

    A folder path that includes at least one wildcard * character. Press TAB to open the folder picker GUI. Once you selected a folder, you will see the path will have \\* at the end of it. You can modify the selected path by adding/removing wildcards * to it before proceeding.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-DenyWDACConfig/#-deploy_3","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Deny base policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/","title":"New-KernelModeWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#syntax","title":"Syntax","text":"
    New-KernelModeWDACConfig\n    -Mode <String>\n    [-Deploy]\n    [-EVSigners]\n    [-Base <String>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#description","title":"Description","text":"

    This cmdlet generates a Kernel-mode WDAC policy derived from the Default Windows template policy. You can learn more about that procedure in here.

    Initially, you need to use the -Mode Prep parameter to deploy the base policy in Audit mode, then restart your system. After restarting, event logs are produced for Kernel-mode drivers that are running but would otherwise be blocked if the policy was not deployed in Audit mode.

    Subsequently, you need to use the -Mode AuditAndEnforce parameter to generate the final base policy. This parameter will:

    1. Scan all of the event logs that were produced after deploying the audit mode policy on the system
    2. Generate a supplemental policy for the drivers detected in event logs
    3. Merge the supplemental policy with the Strict Kernel-mode base policy
    4. Deploy it as a single base policy, rebootlessly.

    Tip

    All Kernel-mode drivers are scanned with WHQLFilePublisher level, so they will not necessitate a policy update when they are updated.

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-mode","title":"-Mode","text":"

    Specifies the mode of operation. The acceptable values for this parameter are: Prep and AuditAndEnforce.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the policy will be deployed. If you want to deploy the final strict kernel-mode base policy Signed, do not use this parameter, Instead just create the policy and then use the Deploy-SignedWDACConfig cmdlet to deploy it.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-evsigners","title":"-EVSigners","text":"

    Uses EVSigners policy rule option. If you want to use this parameter, make sure you use it for both Prep and AuditAndEnforce modes. Read more about EV Signers

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-KernelModeWDACConfig/#-base","title":"-Base","text":"

    The base policy to be used. The acceptable values for this parameter are: Default and NoFlightRoots.

    Note

    The NoFlightRoots value signifies that the Strict Kernel-mode WDAC policy will not be deployed with flight root certificates, disallowing you to use insider builds of the OS in the Dev and Canary channels. Insider builds in the Beta and Release Preview channels are signed with production root certificates and will not be affected.

    Type: String Position: Named Default value: Default Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/","title":"New-SupplementalWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-normal","title":"New-SupplementalWDACConfig -Normal","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax","title":"Syntax","text":"
    New-SupplementalWDACConfig\n    [-Normal]\n    -ScanLocation <DirectoryInfo>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-SpecificFileNameLevel <String>]\n    [-NoUserPEs]\n    [-NoScript]\n    [-Level <String>]\n    [-Fallbacks <String[]>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description","title":"Description","text":"

    Creates a Supplemental policy for a base policy based on a folder path.

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-scanlocation","title":"-ScanLocation","text":"

    The directory or drive that you want to scan for files that will be allowed to run by the Supplemental policy. Supports GUI folder picker, press TAB after the parameter to launch it.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-levels","title":"-Levels","text":"

    Offers the same official Levels to scan the specified directory path.

    Type: String Position: Named Default value: WHQLFilePublisher Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-fallbacks","title":"-Fallbacks","text":"

    Offers the same official Fallbacks to scan the specified directory path.

    Type: String[] Position: Named Default value: FilePublisher,Hash Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-specificfilenamelevel","title":"-SpecificFileNameLevel","text":"

    More info available on Microsoft Learn

    Type: String Position: Named Accepted values: OriginalFileName, InternalName, FileDescription, ProductName, PackageFamilyName, FilePath Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-nouserpes","title":"-NoUserPEs","text":"

    By default, the module includes user PEs in the scan. When you use this switch parameter, they won't be included. More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-noscript","title":"-NoScript","text":"

    More info available on Microsoft Learn

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#the-outputs-of-the-parameter-are","title":"The outputs of the parameter are","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-pathwildcards","title":"New-SupplementalWDACConfig -PathWildCards","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax_1","title":"Syntax","text":"
    New-SupplementalWDACConfig\n    [-PathWildCards]\n    -FolderPath <DirectoryInfo>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description_1","title":"Description","text":"

    Creates a Supplemental policy that allows a folder path that includes one or more wildcard * character in it.

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-folderpath","title":"-FolderPath","text":"

    A folder path that includes at least one wildcard * character. Press TAB to open the folder picker GUI. Once you selected a folder, you will see the path will have \\* at the end of it. You can modify the selected path by adding/removing wildcards * to it before proceeding.

    Type: DirectoryInfo Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname_1","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath_1","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy_1","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#the-outputs-of-the-parameter-are_1","title":"The outputs of the parameter are","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-installedappxpackages","title":"New-SupplementalWDACConfig -InstalledAppXPackages","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax_2","title":"Syntax","text":"
    New-SupplementalWDACConfig\n    [-InstalledAppXPackages]\n    -PackageName <String>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description_2","title":"Description","text":"

    Creates a Supplemental policy based on the package name of an installed app. More information at Microsoft Learn

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-packagename","title":"-PackageName","text":"

    Enter the package name of an installed app. Supports wildcard * character. e.g., *Edge* or \"*Microsoft*\".

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname_2","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath_2","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy_2","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with creating the Supplemental policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#the-outputs-of-the-parameter-are_2","title":"The outputs of the parameter are","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#new-supplementalwdacconfig-certificates","title":"New-SupplementalWDACConfig -Certificates","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#syntax_3","title":"Syntax","text":"
        New-SupplementalWDACConfig\n    [-Certificates]\n    -CertificatePaths <FileInfo[]>\n    -SuppPolicyName <String>\n    [-PolicyPath <FileInfo>]\n    [-Deploy]\n    [-SigningScenario <String>]\n    [-SkipVersionCheck]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#description_3","title":"Description","text":"

    Creates a Supplemental policy based on the certificate paths.

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#parameters_3","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-certificatepaths","title":"-CertificatePaths","text":"

    Browse for the certificate file(s) that you want to use to create the Supplemental policy. Supports file picker GUI by showing only .cer files.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: True

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-supppolicyname_3","title":"-SuppPolicyName","text":"

    Add a descriptive name for the Supplemental policy. Accepts only alphanumeric and space characters.

    Type: String Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-policypath_3","title":"-PolicyPath","text":"

    Browse for the xml file of the Base policy this Supplemental policy is going to expand. Supports GUI file picker that only shows XML files, press TAB after the parameter to launch it.

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-deploy_3","title":"-Deploy","text":"

    Indicates that the module will automatically deploy the Supplemental policy after creation.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-SupplementalWDACConfig/#-signingscenario","title":"-SigningScenario","text":"

    You can choose one of the following options: \"UserMode\", \"KernelMode\" The certificate will be added to the policy based on the selected scenario.

    Type: SwitchParameter Position: Named Default value: UserMode Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/","title":"New-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#new-wdacconfig-policytype","title":"New-WDACConfig -PolicyType","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#syntax","title":"Syntax","text":"
    New-WDACConfig\n    [-PolicyType <String>]\n    [-Deploy]\n    [-Audit]\n    [-TestMode]\n    [-RequireEVSigners]\n    [-EnableScriptEnforcement]\n    [-LogSize <UInt64>]\n
    "},{"location":"WDACConfig%20Module/New-WDACConfig/#description","title":"Description","text":"

    Use this parameter to create a new WDAC (Application Control) base policy with different policy types and configurations.

    Note

    If the selected policy type is DefaultWindows and the detected PowerShell is not installed through Microsoft Store, the module will scan the PowerShell files and add them to the DefaultWindows base policy as allowed files so you will be able to continue using the module after deploying the policy.

    Tip

    The SignedAndReputable policy type uses ISG, The Microsoft Intelligent Security Graph.

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#-policytype","title":"-PolicyType","text":"

    There are 3 policy types you can choose from and they are listed below:

    Type: String Position: Named Accepted values: AllowMicrosoft, DefaultWindows, SignedAndReputable Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-deploy","title":"-Deploy","text":"

    Indicates that the policy is to be deployed to the local machine.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-audit","title":"-Audit","text":"

    Turns on Audit mode in the policy so that the policy will be auditing files after deployment instead of blocking them.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-testmode","title":"-TestMode","text":"

    Indicates that the created policy will have Enabled:Boot Audit on Failure and Enabled:Advanced Boot Options Menu policy rule options.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-requireevsigners","title":"-RequireEVSigners","text":"

    Indicates that the created policy will have Require EV Signers policy rule option.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-enablescriptenforcement","title":"-EnableScriptEnforcement","text":"

    Enables script enforcement in the created policy.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-logsize","title":"-LogSize","text":"

    Note

    This parameter is only available when the -Audit parameter is used.

    Specifies the log size for Microsoft-Windows-CodeIntegrity/Operational events. The values must be in the form of <Digit + Data measurement unit>. e.g., 2MB, 10MB, 1GB, 1TB. The minimum accepted value is 1MB which is the default.

    Type: UInt64 Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#new-wdacconfig-getusermodeblockrules","title":"New-WDACConfig -GetUserModeBlockRules","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#syntax_1","title":"Syntax","text":"
    New-WDACConfig\n    [-GetUserModeBlockRules]\n    [-Deploy]\n
    "},{"location":"WDACConfig%20Module/New-WDACConfig/#description_1","title":"Description","text":"

    Downloads the latest Microsoft Recommended User-Mode Block Rules.

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#-deploy_1","title":"-Deploy","text":"

    Indicates that the policy is to be deployed to the local machine.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#new-wdacconfig-getdriverblockrules","title":"New-WDACConfig -GetDriverBlockRules","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#syntax_2","title":"Syntax","text":"
    New-WDACConfig\n    [-GetDriverBlockRules]\n    [-Deploy]\n    [-AutoUpdate]\n
    "},{"location":"WDACConfig%20Module/New-WDACConfig/#description_2","title":"Description","text":"

    Downloads the latest Microsoft Recommended Drivers Block rules.

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#parameters_2","title":"Parameters","text":""},{"location":"WDACConfig%20Module/New-WDACConfig/#-deploy_2","title":"-Deploy","text":"

    Indicates that the policy is to be deployed to the local machine.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/New-WDACConfig/#-autoupdate","title":"-AutoUpdate","text":"

    Creates a scheduled task that runs every 7 days to automatically perform the official method for updating Microsoft recommended driver block rules.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False"},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/","title":"Remove-CommonWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#syntax","title":"Syntax","text":"
    Remove-CommonWDACConfig\n    [-CertCN]\n    [-CertPath]\n    [-SignToolPath]\n    [-UnsignedPolicyPath]\n    [-SignedPolicyPath]\n    [-StrictKernelPolicyGUID]\n    [-StrictKernelNoFlightRootsPolicyGUID]\n
    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#description","title":"Description","text":"

    Use this cmdlet to remove the values stored in the User Configurations JSON file. If you use it without any parameters it will delete the User configuration folder and everything in it, which is located in C:\\Users\\UserName\\.WDACConfig

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-certcn","title":"-CertCN","text":"

    Removes the saved Certificate Common Name from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-certpath","title":"-CertPath","text":"

    Removes the saved Certificate path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Removes the saved SignTool.exe Path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-unsignedpolicypath","title":"-UnsignedPolicyPath","text":"

    Removes the saved Unsigned Policy Path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-signedpolicypath","title":"-SignedPolicyPath","text":"

    Removes the saved Signed Policy Path from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-strictkernelpolicyguid","title":"-StrictKernelPolicyGUID","text":"

    Removes the saved Strict Kernel Policy GUID from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-CommonWDACConfig/#-strictkernelnoflightrootspolicyguid","title":"-StrictKernelNoFlightRootsPolicyGUID","text":"

    Removes the saved Strict Kernel NoFlight Roots Policy GUID from User Configurations

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/","title":"Remove-WDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#remove-wdacconfig-signedbase","title":"Remove-WDACConfig -SignedBase","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#syntax","title":"Syntax","text":"
    Remove-WDACConfig\n    [-SignedBase]\n    -PolicyPaths <FileInfo[]>\n    [-CertCN <String>]\n    [-SignToolPath <FileInfo>]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#description","title":"Description","text":"

    Uses the official procedure to Re-Deploy the Signed base WDAC policies with Enabled:Unsigned System Integrity Policy rule option.

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-policypaths","title":"-PolicyPaths","text":"

    Path to xml file(s) of the currently deployed policy that you want to remove. Supports tab completion by showing only .xml files.

    Type: FileInfo[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-certcn","title":"-CertCN","text":"

    Common name of the certificate - Supports argument completion so you don't have to manually enter the Certificate's CN. Make sure the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Tip

    Refer to this section for more info

    Type: FileInfo Position: Named Default value: None Required: False Automatic: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-force","title":"-Force","text":"

    Indicates that the cmdlet won't ask for confirmation and will proceed with redeploying the signed base policy in unsigned mode.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#remove-wdacconfig-unsignedorsupplemental","title":"Remove-WDACConfig -UnsignedOrSupplemental","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#syntax_1","title":"Syntax","text":"
    Remove-WDACConfig\n    [-UnsignedOrSupplemental]\n    [-PolicyNames <String[]>]\n    [-PolicyIDs <String[]>]\n    [-Force]\n    [-SkipVersionCheck]\n    [-Confirm]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#description_1","title":"Description","text":"

    Removes Unsigned deployed WDAC policies as well as Signed deployed Supplemental WDAC policies

    Note

    When using -PolicyNames parameter, if multiple policies with the exact same name are deployed, when you press TAB, you will only see 1 of them, if you select it, all of the policies with that name will be removed. If that's not desired, consider using -PolicyIDs parameter instead.

    Note

    The auto-completion in these 2 parameters are smart. E.g., if there are 10 policies deployed on the system, you can press Tab to select 5 of them by IDs, but when you try to select the other 5 by their names, the name of the policies that you already selected by IDs don't show up anymore. This greatly reduces user error and simplifies the workflow for end user.

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#parameters_1","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-policyids","title":"-PolicyIDs","text":"

    The submitted values are verified against the currently deployed policies and if they match, the policies are removed.

    Just press TAB key and it will autofill the values for you based on the deployed policies. If you want to select multiple names, after each one, enter a comma , and then press TAB again to choose another name.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Remove-WDACConfig/#-policynames","title":"-PolicyNames","text":"

    The submitted values are verified against the currently deployed policies and if they match, the policies are removed.

    Just press TAB key and it will autofill the values for you based on the deployed policies. If you want to select multiple IDs, after each one, enter a comma , and then press TAB again to choose another ID.

    Type: String[] Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/","title":"Set-CiRuleOptions available parameters","text":""},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#syntax","title":"Syntax","text":"
    Set-CiRuleOptions\n    -FilePath <FileInfo>\n    [-Template <String>]\n    [-RulesToAdd <String[]>]\n    [-RulesToRemove <String[]>]\n    [-RequireWHQL <Boolean>]\n    [-EnableAuditMode <Boolean>]\n    [-DisableFlightSigning <Boolean>]\n    [-RequireEVSigners <Boolean>]\n    [-ScriptEnforcement <Boolean>]\n    [-TestMode <Boolean>]\n    [-RemoveAll]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#description","title":"Description","text":"

    Configures the Policy rule options in a given XML file and sets the HVCI to Strict in the output XML file. It offers many ways to configure the policy rule options in a given XML file.

    All of its various parameters provide the flexibility that ensures only one pass is needed to configure the policy rule options.

    Tip

    First the template is processed, then the individual boolean parameters, and finally the individual rules to add and remove.

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-filepath","title":"-FilePath","text":"

    The path to the XML file that contains the WDAC Policy.

    Type: FileInfo Aliases: MDELogs Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-template","title":"-Template","text":"

    Specifies the template to use for the CI policy rules.

    Type: String Position: Named Accepted values: Base, BaseISG, BaseKernel, Supplemental Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-rulestoadd","title":"-RulesToAdd","text":"

    Specifies the rule options to add to the policy XML file. Supports auto tab-completion so you don't need to type them manually.

    Note

    If a rule option is already selected by the RulesToRemove parameter, it won't be suggested by the argument completer of this parameter.

    Type: String[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-rulestoremove","title":"-RulesToRemove","text":"

    Specifies the rule options to remove from the policy XML file. Supports auto tab-completion so you don't need to type them manually.

    Note

    If a rule option is already selected by the RulesToAdd parameter, it won't be suggested by the argument completer of this parameter.

    Type: String[] Position: Named Default value: None Required: True Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-requirewhql","title":"-RequireWHQL","text":"

    Specifies whether to require WHQL signatures for all drivers.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-enableauditmode","title":"-EnableAuditMode","text":"

    Specifies whether to enable audit mode.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-disableflightsigning","title":"-DisableFlightSigning","text":"

    Specifies whether to disable flight signing.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-requireevsigners","title":"-RequireEVSigners","text":"

    Specifies whether to require EV signers.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-scriptenforcement","title":"-ScriptEnforcement","text":"

    Specifies whether to disable script enforcement

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-testmode","title":"-TestMode","text":"

    Specifies whether to enable Enabled:Boot Audit on Failure and Enabled:Advanced Boot Options Menu rule options in the policy XML file.

    Type: BooleanParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CiRuleOptions/#-removeall","title":"-RemoveAll","text":"

    Removes all the existing rule options from the policy XML file.

    Type: SwitchParameter Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/","title":"Set-CommonWDACConfig available parameters","text":""},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#syntax","title":"Syntax","text":"
    Set-CommonWDACConfig\n    [[-CertCN] <String>]\n    [[-CertPath] <FileInfo>]\n    [[-SignToolPath] <FileInfo>]\n    [[-UnsignedPolicyPath] <FileInfo>]\n    [[-SignedPolicyPath] <FileInfo>]\n    [[-StrictKernelPolicyGUID] <Guid>]\n    [[-StrictKernelNoFlightRootsPolicyGUID] <Guid>]\n    [[-LastUpdateCheck] <DateTime>]\n    [[-StrictKernelModePolicyTimeOfDeployment] <DateTime>]\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#description","title":"Description","text":"

    Use this cmdlet to store the values for common and frequently used parameters so that you won't have to specify them again every time.

    All of the applicable cmdlets of the module automatically check the User Configuration file for any available input, if you don't specify values for their parameters. Learn more about the User Configuration file here.

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#an-example","title":"An Example","text":"

    Instead of specifying all of the parameters for Edit-SignedWDACConfig cmdlet like this:

    Edit-SignedWDACConfig -AllowNewApps -SuppPolicyName \"App 1\" -CertPath \"Path To Certificate.cer\" -PolicyPaths \"Path To Policy.xml\" -CertCN \"Certificate Common Name\"\n

    You can just run this

    Edit-SignedWDACConfig -AllowNewApps -SuppPolicyName \"App 1\"\n

    If correct and valid values for the missing parameters exist in User Configuration file, the cmdlet will automatically detect and use them seamlessly.

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-certcn","title":"-CertCN","text":"

    Common Name of an installed certificate. Supports argument completion so you don't have to manually enter the Certificate's CN, just make sure the certificate is installed in the personal store of the user certificates, then press TAB to auto complete the name. You can however enter it manually if you want to.

    Type: String Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-certpath","title":"-CertPath","text":"

    Path to the certificate .cer file. Press TAB to open the file picker GUI and browse for a .cer file.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-signtoolpath","title":"-SignToolPath","text":"

    Press TAB to open the file picker GUI and browse for SignTool.exe

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-unsignedpolicypath","title":"-UnSignedPolicyPath","text":"

    Path to the xml file of an Unsigned policy. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Set-CommonWDACConfig/#-signedpolicypath","title":"-SignedPolicyPath","text":"

    Path to the xml file of a Signed policy. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Test-CiPolicy/","title":"Test-CiPolicy available parameters","text":""},{"location":"WDACConfig%20Module/Test-CiPolicy/#syntax","title":"Syntax","text":"
    Test-CiPolicy\n    -XmlFile <FileInfo>\n    -CipFile <FileInfo>\n    [<CommonParameters>]\n
    "},{"location":"WDACConfig%20Module/Test-CiPolicy/#description","title":"Description","text":"

    Tests a Code Integrity (WDAC) Policy XML file against the Schema file located at:

    $Env:SystemDrive\\Windows\\schemas\\CodeIntegrity\\cipolicy.xsd\n

    It returns a boolean value indicating whether the XML file is valid or not.

    It can also be used to display the signer certificates used to sign a .CIP binary file.

    "},{"location":"WDACConfig%20Module/Test-CiPolicy/#parameters","title":"Parameters","text":""},{"location":"WDACConfig%20Module/Test-CiPolicy/#-xmlfile","title":"-XmlFile","text":"

    The Code Integrity Policy XML file to test. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/Test-CiPolicy/#-cipfile","title":"-CipFile","text":"

    The binary Code Integrity Policy file to test for signers. Supports file picker GUI.

    Type: FileInfo Position: Named Default value: None Required: False Accept pipeline input: False Accept wildcard characters: False

    "},{"location":"WDACConfig%20Module/WDACConfig/","title":"WDACConfig (Windows Defender Application Control) Module","text":"

    WDACConfig is an advanced PowerShell module designed with the aim of automating Application and File whitelisting in Windows using Windows Defender Application Control (App Control for Business Policies). You can always find its source code on GitHub and Install it from PowerShell Gallery.

    This page is also available on my website.

    "},{"location":"WDACConfig%20Module/WDACConfig/#requirements","title":"Requirements","text":"

    "},{"location":"WDACConfig%20Module/WDACConfig/#features","title":"Features","text":"

    "},{"location":"WDACConfig%20Module/WDACConfig/#install-the-module","title":"Install The Module","text":"
    Install-Module -Name 'WDACConfig' -Scope 'AllUsers' -Force\n
    "},{"location":"WDACConfig%20Module/WDACConfig/#video-guides","title":"Video Guides","text":"Video Link Description Microsoft Defender For Endpoint Advanced Hunting With WDACConfig Module Sandboxing-like capabilities in the WDAC Policies Create, Deploy & Audit WDAC Policies How To Set And Query Secure Settings in WDAC Policies How To Create And Deploy Signed WDAC Policies Create Code Signing Certificate Using Windows Server"},{"location":"WDACConfig%20Module/WDACConfig/#wdacconfig-modules-table-of-content","title":"WDACConfig Module's Table of Content","text":"Cmdlet Guide Usage PowerShell Console Help New-WDACConfig Mainly for creating and deploying WDAC policies Get-Help New-WDACConfig New-SupplementalWDACConfig To create and deploy Supplemental policies Get-Help New-SupplementalWDACConfig Remove-WDACConfig To remove deployed WDAC policies Get-Help Remove-WDACConfig Edit-WDACConfig To edit deployed unsigned WDAC policies Get-Help Edit-WDACConfig Edit-SignedWDACConfig To edit deployed signed WDAC policies Get-Help Edit-SignedWDACConfig Deploy-SignedWDACConfig To sign and deploy WDAC policies Get-Help Deploy-SignedWDACConfig Confirm-WDACConfig To confirm deployment and check the status of WDAC policies Get-Help Confirm-WDACConfig New-DenyWDACConfig To create a deny mode WDAC policy Get-Help New-DenyWDACConfig Set-CommonWDACConfig To add or edit user configurations for common WDACConfig parameters Get-Help Set-CommonWDACConfig New-KernelModeWDACConfig To create a Strict Kernel mode WDAC policy for total BYOVD protection Get-Help New-KernelModeWDACConfig Get-CommonWDACConfig To display or fetch user configurations for common WDACConfig parameters Get-Help Get-CommonWDACConfig Invoke-WDACSimulation To simulate a WDAC policy deployment quickly Get-Help Invoke-WDACSimulation Remove-CommonWDACConfig To remove user configurations for common WDACConfig parameters Get-Help Remove-CommonWDACConfig Assert-WDACConfigIntegrity To ascertain that the files in your local WDACConfig folder are identical to the ones in the cloud Get-Help Assert-WDACConfigIntegrity Build-WDACCertificate To create proper code signing certificates for WDAC policy signing Get-Help Build-WDACCertificate Test-CiPolicy Tests a Code Integrity (WDAC) Policy XML file against the Schema and shows the signers in a signed .CIP files Get-Help Test-CiPolicy Get-CiFileHashes Calculates the Authenticode hash and first page hash of the PEs with SHA1 and SHA256 algorithms Get-Help Get-CiFileHashes ConvertTo-WDACPolicy Multi-Purpose & Powerful functionalities such as converting local and MDE logs to App Control Policies Get-Help ConvertTo-WDACPolicy Set-CiRuleOptions Configures Policy Rule Options in the WDAC policies Get-Help Set-CiRuleOptions Get-CIPolicySetting Queries the Secure Settings among the deployed policies on the system Get-Help Get-CIPolicySetting"},{"location":"WDACConfig%20Module/WDACConfig/#user-configurations-directory","title":"User Configurations Directory","text":"

    The module stores user configurations and all of the outputs only in the following directory:

    C:\\Program Files\\WDACConfig\n

    It's an Admin-protected path that provides security against non-elevated users and processes.

    "},{"location":"WDACConfig%20Module/WDACConfig/#the-temporary-files-are-stored-in-the-following-directory","title":"The Temporary Files Are Stored in the Following Directory","text":"
    C:\\Program Files\\WDACConfig\\StagingArea\n

    Each cmdlet of the module creates a subdirectory in the StagingArea to store its temporary files. The subdirectory is named after the cmdlet's name. At the end of the cmdlet's execution, the temporary subdirectory is deleted, unless the -Debug parameter is used.

    "},{"location":"WDACConfig%20Module/WDACConfig/#about-automatic-parameters","title":"About Automatic Parameters","text":"

    A parameter with an Automatic value of True in the description means that the module will use its default value set by the Set-CommonWDACConfig cmdlet. This simplifies the process and avoids redundancy. However, if an Automatic parameter has no value in User Configurations and you do not specify one in the command line, you will encounter an error requesting a value. Specifying a value for an Automatic parameter in the command line supersedes its default value in User Configurations, so the module will disregard the value of that parameter in the User Configurations file.

    "},{"location":"WDACConfig%20Module/WDACConfig/#the-logic-behind-the-signtoolpath-parameter-in-the-module","title":"The Logic Behind The -SignToolPath Parameter in the Module","text":"
    1. If Windows SDK Signing Tools for Desktop Apps components is installed in the default location C:\\Program Files (x86)\\Windows Kits, then specifying -SignToolPath parameter isn't necessary as the SignTool.exe will be detected automatically.

    2. If Windows SDK Signing Tools for Desktop Apps components is not installed in the default location or you want to manually browse for the signtool.exe, then make sure you either specify its path using Set-CommonWDACConfig -SignToolPath or use the -SignToolPath parameter.

    3. If SignTool.exe path is available in user configurations then it will be automatically used.

    4. Specifying -SignToolPath parameter explicitly on the command line takes priority over auto detection and value in the user configurations.

    5. If SignTool.exe cannot be auto-detected and the user didn't specify it on the command line, you will receive a prompt to authorize the automatic download of the most recent SignTool.exe version from the official Microsoft servers. Upon confirmation, it will be saved in your user configurations and utilized by the cmdlet.

    "},{"location":"WDACConfig%20Module/WDACConfig/#feedback-and-feature-request","title":"Feedback and Feature Request","text":"

    If there are any feedback or feature requests regarding this module, please open a new discussion/issue on GitHub.

    "}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index ef34aac..e1e28b0 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,322 +2,322 @@ https://spynetgirl.github.io/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Azure/Clean%20Source%20principle%2C%20Azure%20and%20Privileged%20Access%20Workstations/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Azure/How%20to%20Securely%20Connect%20to%20Azure%20VMs%20and%20Use%20RDP/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/GitHub/Cloning%20Personal%20and%20Enterprise%20Repositories%20Using%20GitHub%20Desktop/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/GitHub/Git%20GitHub%20Desktop%20and%20Mandatory%20ASLR/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/GitHub/Signed%20and%20Verified%20commits%20with%20GitHub%20desktop/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Harden-Windows-Security-Module/Harden-Windows-Security-Module/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/About%20TLS%2C%20DNS%2C%20Encryption%20and%20OPSEC%20concepts/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/BitLocker%2C%20TPM%20and%20Pluton%20What%20Are%20They%20and%20How%20Do%20They%20Work/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Comparison%20of%20Security%20Benchmarks/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Create%20Bootable%20USB%20flash%20drive%20with%20no%203rd%20party%20tools/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Device%20Guard%20and%20Virtualization%20Based%20Security%20in%20Windows/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Event%20Viewer/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Group%20Policy/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/How%20to%20Detect%20Changes%20in%20User%20and%20Local%20Machine%20Certificate%20Stores%20in%20Real%20Time%20Using%20PowerShell/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/How%20to%20compact%20your%20OS%20and%20free%20up%20extra%20space/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Hyper%20V/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Only%20a%20Small%20Portion%20of%20The%20Windows%20OS%20Security%20Apparatus/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Overrides%20for%20Microsoft%20Security%20Baseline/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/Miscellaneous/Things%20to%20do%20for%20clean%20installing%20Windows/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%202/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%203/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/Basic%20PowerShell%20tricks%20and%20notes%20Part%204/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/Basic%20PowerShell%20tricks%20and%20notes/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/How%20To%20Access%20All%20Stream%20Outputs%20From%20Thread%20Jobs%20In%20PowerShell%20In%20Real%20Time/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/How%20To%20Asynchronously%20Access%20All%20Stream%20Outputs%20From%20Background%20Jobs%20In%20PowerShell/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/PowerShell%20Best%20Practices/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/Powershell%20Dynamic%20Parameters%20and%20How%20to%20Add%20Them%20to%20the%20Get-Help%20Syntax/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/PowerShell/RunSpaces%20In%20PowerShell/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/Application%20Control%20WDAC%20Frequently%20Asked%20Questions%20FAQs/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/EKUs%20in%20WDAC%2C%20App%20Control%20for%20Business%2C%20Policies/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/Fast%20and%20Automatic%20Microsoft%20Recommended%20Driver%20Block%20Rules%20updates/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/How%20to%20Create%20and%20Deploy%20a%20Signed%20WDAC%20Policy%20Windows%20Defender%20Application%20Control/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/How%20to%20Use%20Microsoft%20Defender%20for%20Endpoint%20Advanced%20Hunting%20With%20WDAC%20App%20Control/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/Introduction/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/Script%20Enforcement%20and%20PowerShell%20Constrained%20Language%20Mode%20in%20WDAC%20App%20Control%20Policies/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20Notes/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20for%20Fully%20Managed%20Devices%20%282nd%20variant%29/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%203/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20for%20Fully%20Managed%20Devices%20Variant%204/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20for%20Fully%20Managed%20Devices/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20for%20Lightly%20Managed%20Devices/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDAC/WDAC%20policy%20for%20BYOVD%20Kernel%20mode%20only%20protection/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Assert-WDACConfigIntegrity/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Build-WDACCertificate/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Confirm-WDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/ConvertTo-WDACPolicy/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Deploy-SignedWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Edit-SignedWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Edit-WDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Get-CIPolicySetting/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Get-CiFileHashes/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Get-CommonWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Invoke-WDACSimulation/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/New-DenyWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/New-KernelModeWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/New-SupplementalWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/New-WDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Remove-CommonWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Remove-WDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Set-CiRuleOptions/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Set-CommonWDACConfig/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/Test-CiPolicy/ - 2024-06-19 + 2024-06-21 daily https://spynetgirl.github.io/WDACConfig%20Module/WDACConfig/ - 2024-06-19 + 2024-06-21 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index b5262d2..a0157ce 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ