Windows Hardening: From Default Install to Fortress

// TABLE OF CONTENTS
  1. Introduction
  2. Storage Security — BitLocker & DMA
  3. Identity & Access Management
  4. Firewall Hardening
  5. Application Control — WDAC & ASR
  6. Computer Management
  7. PowerShell Hardening
  8. Conclusion

Introduction

A default Windows installation is not a secure baseline — it's a starting point. Out of the box, Windows ships with legacy protocols enabled, weak default policies, and services running that most endpoints will never need. For a red teamer, this is opportunity. For a defender, it's debt.

Windows hardening is the disciplined process of reducing attack surface before an adversary finds it. The goal isn't perfection — it's raising the cost of exploitation high enough that attackers move on or make noise that detection picks up. This guide covers the layers that matter most: storage, identity, network, application control, and PowerShell — the attacker's favorite tool turned against them.

// SCOPE
This guide targets Windows 10 22H2+ and Windows 11. Some features (hardware-accelerated BitLocker, Kernel DMA Protection) require Windows 11 24H2 or compatible hardware. Test all changes in a non-production environment first.
Red team perspective: Every item in this guide is something I look for being absent during an engagement. If you skip even one section, assume a competent attacker will find it.

Storage Security — BitLocker & DMA

Physical access is game over — unless your data at rest is encrypted. BitLocker is the built-in answer, but default settings are not the hardened settings.

BitLocker with XTS-AES 256

The default BitLocker cipher in many environments is still AES-CBC 128-bit. You want XTS-AES 256-bit. XTS mode is resistant to ciphertext manipulation attacks that CBC is vulnerable to, and 256-bit keys provide the headroom you need against future threats. Windows 11 24H2+ supports hardware-accelerated encryption via the SoC, so performance is no longer a reason to downgrade.

Enforce this before encrypting. If a drive is already encrypted with weaker settings, decrypt and re-encrypt.

PowerShell
# Check current BitLocker status and cipher strength
manage-bde -status

# Output to look for:
# Encryption Method: XTS-AES 256
# Protection Status: Protection On
# Key Protectors: TPM, Numerical Password

Set the encryption method via Group Policy before enabling BitLocker:

GPO Path
Computer Configuration
  > Administrative Templates
    > Windows Components
      > BitLocker Drive Encryption
        > Operating System Drives
          → "Configure use of hardware-based encryption" → Enabled
          → "Choose drive encryption method and cipher strength" → XTS-AES 256-bit

TPM 2.0 — Hardware Root of Trust

TPM 2.0 seals the BitLocker key against platform state. Without it, the encrypted drive can be decrypted by anyone who knows the recovery key — which attackers extract via memory attacks or Active Directory. Verify TPM is enabled and version 2.0:

PowerShell
Get-Tpm | Select-Object TpmPresent, TpmReady, TpmEnabled, ManufacturerVersion

Kernel DMA Protection

Thunderbolt and PCIe ports can be used to perform Direct Memory Access (DMA) attacks — an attacker plugs in a malicious device and reads arbitrary physical memory, bypassing the OS entirely and extracting BitLocker keys in seconds. Kernel DMA Protection prevents this by restricting DMA operations from external peripherals until they are explicitly authorized.

// WARNING
Enabling Kernel DMA Protection may break some older Thunderbolt docks and PCIe devices. Audit your hardware peripherals before enforcing this in production.
PowerShell
# Check if Kernel DMA Protection is enabled
(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard").EnableVirtualizationBasedSecurity

# Also check in System Information (msinfo32):
# Kernel DMA Protection → On

Identity & Access Management

Identity is the new perimeter. Once an attacker has valid credentials — even a low-privilege account — they're no longer an outsider. The question becomes: how much can they do with what they have?

Principle of Least Privilege (PoLP)

No user should run as a local administrator for daily tasks. This is the single most impactful thing you can do. Standard user accounts cannot install software, modify system settings, or write to protected directories — which stops the majority of malware cold at the privilege level it lands with.

// RED TEAM NOTE
During engagements, the first thing I check after initial access is whoami /priv and whoami /groups. If the compromised user is a local admin, lateral movement and persistence become trivially easy. PoLP is your single highest-ROI hardening control.

Windows LAPS — Rotating Local Admin Passwords

If every machine in your fleet shares the same local administrator password, one compromised credential = full domain lateral movement. Windows LAPS (built into Windows since the April 2023 update) generates unique, rotating passwords for the built-in local admin account and stores them in Active Directory or Azure AD — readable only by authorized accounts.

PowerShell
# Enable Windows LAPS (requires April 2023+ cumulative update)
# First, update the AD schema to support LAPS attributes
Update-LapsADSchema

# Configure via GPO:
# Computer Configuration > Administrative Templates
#   > System > LAPS
#     → "Configure password backup directory" → Active Directory
#     → "Password Settings" → Complexity: Large letters + small + numbers + specials
#     → "Password age (days)" → 30

UAC — Always Notify

UAC is not a security boundary — it's a friction layer. But friction matters. Set it to Always Notify, which prompts on both software installs and any system setting changes, even for administrators. The default "Notify me only when apps try to make changes" can be bypassed via COM object abuse without triggering a UAC prompt.

Registry
# Set UAC to Always Notify (value 2 = always notify)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `
    -Name "ConsentPromptBehaviorAdmin" -Value 2

Account Lockout Policy

Brute-force and password spray attacks are stopped dead by a properly configured lockout policy. The recommended baseline per CIS Benchmark is: lock after 5 invalid attempts, lockout duration of 15 minutes, reset counter after 15 minutes.

GPO Path
Computer Configuration
  > Windows Settings
    > Security Settings
      > Account Policies
        > Account Lockout Policy
          → Account lockout threshold: 5 invalid logon attempts
          → Account lockout duration: 15 minutes
          → Reset account lockout counter after: 15 minutes

Firewall Hardening

Windows Defender Firewall is underutilized in most environments. The hardened posture is Default Deny — block everything, then explicitly allow what's needed.

PowerShell
# Enforce firewall on ALL profiles — non-negotiable
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True

# Set default inbound action to Block
Set-NetFirewallProfile -Profile Domain,Public,Private -DefaultInboundAction Block

# Disable ICMP responses (stealth mode — machine won't respond to pings)
New-NetFirewallRule -DisplayName "Block ICMP Echo Request" `
    -Protocol ICMPv4 -IcmpType 8 -Direction Inbound -Action Block

New-NetFirewallRule -DisplayName "Block ICMPv6 Echo Request" `
    -Protocol ICMPv6 -IcmpType 128 -Direction Inbound -Action Block

In high-security environments, apply outbound rules too. Restricting outbound traffic to known-good destinations forces malware C2 communication through channels you can monitor and block.

Attacker's view: A machine that doesn't respond to ICMP is invisible in basic network scans. It won't appear in nmap -sn host discovery. This is a small but effective way to reduce your exposure during early reconnaissance phases.

Application Control — WDAC & ASR

Malware almost always executes code. Application control means you decide what code is allowed to run — anything else is blocked at the kernel level before it ever executes.

Windows Defender Application Control (WDAC)

WDAC is the successor to AppLocker, enforced at the kernel level rather than in user-space. This matters because user-space controls (including AppLocker) can be bypassed by processes with the right privileges. WDAC is enforced by the hypervisor and is significantly harder to bypass.

A practical starting policy: allow trusted publishers + Microsoft + specific folders (e.g., C:\Program Files). Anything unsigned or from an untrusted publisher is blocked.

PowerShell
# Generate a starter WDAC policy based on your current system's running apps
# (Audit mode first — never enforce before auditing)
New-CIPolicy -Level Publisher -FilePath "C:\Policies\WDACPolicy.xml" `
    -UserPEs -ScanPath "C:\Program Files" -Audit

# Convert XML policy to binary
ConvertFrom-CIPolicy -XmlFilePath "C:\Policies\WDACPolicy.xml" `
    -BinaryFilePath "C:\Policies\WDACPolicy.bin"

# Deploy the policy (test in audit mode first)
Copy-Item "C:\Policies\WDACPolicy.bin" `
    -Destination "C:\Windows\System32\CodeIntegrity\SIPolicy.p7b"
// WARNING
Always deploy WDAC in Audit mode first. Enforced mode without proper auditing will block legitimate software and can render systems unusable. Review Event ID 3076 (audit block) in Event Viewer before switching to Enforce mode.

Attack Surface Reduction (ASR) Rules

ASR rules are targeted mitigations for specific attacker techniques — blocking Office macros from spawning child processes, preventing credential theft from LSASS, blocking executable content from email. Each rule has a GUID and targets a specific technique from the MITRE ATT&CK framework.

PowerShell
# Block executable content from email client and webmail
Add-MpPreference -AttackSurfaceReductionRules_Ids BE9BA2D9-53ED-4437-B4F0-E0888FAF706D `
    -AttackSurfaceReductionRules_Actions Enabled

# Block Office applications from creating child processes
Add-MpPreference -AttackSurfaceReductionRules_Ids D4F940AB-401B-4EFC-AADC-AD5F3C50688A `
    -AttackSurfaceReductionRules_Actions Enabled

# Block credential stealing from LSASS
Add-MpPreference -AttackSurfaceReductionRules_Ids 9E6C4E1F-7D60-472F-BA1A-A39EF669E4B2 `
    -AttackSurfaceReductionRules_Actions Enabled

# Block untrusted and unsigned processes that run from USB
Add-MpPreference -AttackSurfaceReductionRules_Ids B2B3F03D-6A65-4F7B-A9C7-1C7EF74A9BA4 `
    -AttackSurfaceReductionRules_Actions Enabled

Computer Management

Legacy protocols and default system settings are a goldmine for attackers. These are the controls that get overlooked because they don't have a flashy UI — but they're exactly what Responder, Impacket, and BloodHound rely on.

Disable LLMNR and NetBIOS

LLMNR (Link-Local Multicast Name Resolution) and NBT-NS (NetBIOS Name Service) are legacy name resolution protocols that broadcast queries on the local network. When a machine asks "who is FILESERVER?" and no DNS answer exists, LLMNR broadcasts the question. An attacker running Responder answers that query, captures the NTLMv2 hash, and cracks or relays it.

There is no legitimate reason to have these enabled in a modern Active Directory environment with functioning DNS.

PowerShell
# Disable LLMNR via Registry
New-Item "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" -Force
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" `
    -Name "EnableMulticast" -Value 0

# Disable NetBIOS over TCP/IP on all adapters
$adapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled }
foreach ($adapter in $adapters) {
    $adapter.SetTcpipNetbios(2)  # 2 = Disable NetBIOS over TCP/IP
}

Write-Host "[+] LLMNR and NetBIOS disabled."

Disable Built-in Administrator & Guest

The built-in Administrator (RID 500) account is a well-known target. It cannot be locked out by Account Lockout Policy, making it ideal for brute-force attacks. Rename it to something non-obvious and disable it if LAPS is managing local admin credentials.

PowerShell
# Disable the built-in Administrator account
Disable-LocalUser -Name "Administrator"

# Disable the Guest account
Disable-LocalUser -Name "Guest"

# Optionally rename Administrator to something non-obvious
Rename-LocalUser -Name "Administrator" -NewName "svcmgr"

RDP Hardening

If RDP must be enabled, harden it. Default port 3389 is scanned constantly. Network Level Authentication (NLA) forces authentication before a session is established, preventing unauthenticated pre-auth exploits.

PowerShell
# Enforce Network Level Authentication
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
    -Name "UserAuthentication" -Value 1

# Change RDP port from default 3389 (security by obscurity — not a replacement for NLA)
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
    -Name "PortNumber" -Value 53389  # use any non-default port

# Restart Remote Desktop Services to apply
Restart-Service -Name "TermService" -Force

Secure Boot Certificate Update (June 2026)

This is one most people miss. In June 2026, many original Secure Boot signing certificates expire. If your system hasn't received the 2023+ certificate updates, Secure Boot may fail after that date. Verify you're on the updated certificates now.

PowerShell
# Check Secure Boot status
Confirm-SecureBootUEFI

# Check UEFI certificate database for updated 2023 certs
# Should return entries dated 2023 or later
Get-SecureBootPolicy

PowerShell Hardening

PowerShell is a double-edged sword. It's the most powerful management tool on Windows — and consequently, the most abused post-exploitation tool. It enables fileless malware, in-memory execution, AMSI bypasses, and living-off-the-land techniques that bypass most AV. Hardening it is non-negotiable.

Constrained Language Mode (CLM)

CLM restricts PowerShell to a limited subset of commands, blocking access to .NET types, COM objects, and Win32 API calls — exactly the things used in offensive scripts. It doesn't prevent all attacks, but it significantly raises the bar.

PowerShell
# Check current language mode
$ExecutionContext.SessionState.LanguageMode
# Should return: ConstrainedLanguage (when enforced via WDAC)

# CLM is enforced by WDAC policy — if WDAC is active, CLM activates automatically
# To test: try to use a .NET type in a session with CLM enforced
[System.Net.WebClient]  # This should fail in CLM with "type not available" error
// NOTE
CLM is most effective when enforced via WDAC. Setting it via AppLocker or registry alone can be bypassed by an admin. The combination of WDAC + CLM is substantially harder to escape.

Script Block Logging — Event ID 4104

Script Block Logging records the actual PowerShell code that executes — including code that was obfuscated, downloaded from the internet, or dynamically generated at runtime. This is your primary forensic artifact for PowerShell-based attacks.

GPO Path
Computer Configuration
  > Administrative Templates
    > Windows Components
      > Windows PowerShell
        → "Turn on PowerShell Script Block Logging" → Enabled
        → "Log script block invocation start / stop events" → Enabled (optional, verbose)
        → "Turn on Module Logging" → Enabled → Module Names: *

After enabling, monitor Event ID 4104 in the Microsoft-Windows-PowerShell/Operational log. Any script that looks obfuscated, base64-heavy, or invokes suspicious methods is worth investigating.

Remove PowerShell Version 2

PowerShell v2 does not support Script Block Logging, AMSI, or Constrained Language Mode. Attackers explicitly downgrade to v2 (powershell -version 2) to bypass all modern logging and security controls. Remove it.

PowerShell
# Remove PowerShell v2 engine (requires reboot)
Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root -NoRestart

# Verify it's gone — this should fail after removal
powershell -version 2 -command "Write-Host 'v2 still present'"

Conclusion

None of these controls in isolation makes a system secure. What they do — applied together — is force an attacker to work harder, make more noise, and burn more time. That's the goal. Security is about raising cost, not achieving invulnerability.

From a red team perspective: every one of these controls has a bypass. But a system with all of them configured correctly? That system is no longer the low-hanging fruit. It forces advanced tradecraft, which generates detectable artifacts, which is exactly what your blue team needs.

Control Category What It Stops
BitLocker XTS-AES 256StoragePhysical access, cold boot, offline attacks
Kernel DMA ProtectionStoragePCIe/Thunderbolt DMA key extraction
Windows LAPSIdentityLateral movement via shared local admin password
UAC Always NotifyIdentitySilent privilege escalation via COM abuse
Account LockoutIdentityPassword spray and brute-force
Default-Deny FirewallNetworkUnsolicited inbound connections, C2 exfil
WDACApplicationsUnsigned / untrusted code execution
ASR RulesApplicationsLSASS dumping, macro abuse, email payloads
Disable LLMNR/NetBIOSComputer MgmtResponder hash capture, NTLM relay
PowerShell CLMPowerShellWin32 API abuse, .NET exploitation
Script Block LoggingPowerShellObfuscated/fileless malware (detection)
Remove PSv2PowerShellLogging and CLM downgrade bypass
// TAKEAWAY
Start with PoLP + LAPS + Disable LLMNR + Remove PSv2. These four are the highest ROI, lowest disruption controls that stop the most common attacker techniques seen in real-world engagements. Then layer in WDAC and ASR rules once you've audited your environment.

// All configurations documented for educational and defensive purposes. Test in isolated environments before production deployment.