Hardening

LSASS Protection: Credential Guard, RunAsPPL and Gaps

22 September 2026 9 min read

LSASS is the one process on a Windows host where a single successful read operation can hand an attacker every credential a machine has touched since boot. Two separate Windows features change what that read operation can get: RunAsPPL, which wraps LSASS in a protected process container, and Credential Guard, which moves the actual secrets into a separate, isolated VBS enclave. They are not the same control, they do not cover the same threat model, and a host can pass a compliance check for one while the other silently failed to load. This is what each one actually stops, what hardware it demands, what it breaks on the way in, and how to confirm it is running rather than just configured.

What attackers actually read out of LSASS

When a tool like Mimikatz calls sekurlsa::logonpasswords, it is not reading one secret, it is walking a set of provider structures inside LSASS memory that each hold a different credential form left over from every logon session still active on the box.

Credential type Where it lives Typical extraction Still exposed with RunAsPPL alone?
NTLM hash MSV1_0 provider sekurlsa::logonpasswords, Pass-the-Hash No, if RunAsPPL loads cleanly
Kerberos TGT / service tickets Kerberos provider sekurlsa::tickets, Pass-the-Ticket, Golden/Silver Ticket forging No, if RunAsPPL loads cleanly
Plaintext password WDigest provider, only when UseLogonCredential=1 sekurlsa::wdigest No, provider is disabled by policy on current builds
Cached domain verifier (MSCache2) SECURITY registry hive, not LSASS memory secretsdump.py, reg save + offline crack Yes, RunAsPPL does not touch the hive
DPAPI-protected secrets Credential Manager, browser stores, user profile DPAPI master key decryption with the user or domain backup key Yes, out of scope for both controls

RunAsPPL closes the in-memory read path, but the last two rows in that table live outside LSASS memory entirely, so no amount of process protection touches them. A finding that says “credential dumping possible” needs to specify which row it means before the remediation note can claim RunAsPPL alone closes it.

RunAsPPL: prerequisites, enablement, and what it breaks first

RunAsPPL turns LSASS into a Protected Process Light with signer level PsProtectedSignerLsa-Light. Once that is active, only drivers and DLLs signed with a compatible Microsoft signature are allowed to load into the process or open a handle with the rights needed to read its memory. Anything else, including a debugger, a memory-scraping tool, or an unsigned legacy credential provider, gets an access-denied handle instead of a memory dump.

Enablement is a single registry value plus a reboot:

  • Path: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsa
  • Value: RunAsPPL (DWORD)
  • Data: 1 for standard protection, 2 to also require a code-signed EV/HVCI-eligible signer for boot start drivers

Before flipping it on a fleet, run in audit mode first. Windows Defender Application Control and Code Integrity write event 3033 (a driver would have been blocked) and 3063/3065 to 3067 (attestation and signing failures) to the Microsoft-Windows-CodeIntegrity/Operational log whenever something tries to load into a protected LSASS and would be refused. Pull those events for two to four weeks across a representative set of endpoint images before enforcing, not after.

The drivers that actually get blocked in practice cluster in a short list: antivirus engines with an unsigned or improperly signed LSA-hooking component, biometric or smartcard middleware that never updated its signing, and third-party Security Support Providers (SSPs) that inject directly into LSASS instead of using the documented SSP interface. None of these crash the box; the driver just fails to load, and the feature it provided stops working silently until someone checks the event log.

Credential Guard: the hardware bar that GPO does not check for you

Credential Guard is built on virtualization-based security (VBS), which means the secrets are not merely fenced off inside LSASS, they are moved into a separate virtual trust level that the normal kernel, and therefore any kernel-mode rootkit, cannot address directly. That isolation has a real hardware cost:

  • A 64-bit CPU with second-level address translation (Intel EPT or AMD RVI)
  • Virtualization extensions enabled in firmware: VT-x/AMD-V, plus VT-d/AMD-Vi if you want DMA protection against Thunderbolt and PCIe attacks
  • UEFI Secure Boot enabled and not in a compatibility/legacy BIOS mode
  • TPM 2.0, strongly recommended, required if you want the key material sealed to the platform rather than just software-protected
  • Windows 10/11 Enterprise or Education edition; Pro editions can enable the underlying Hyper-V and VBS features manually but lose the managed Credential Guard policy surface in some builds

Enable it centrally through Group Policy: Computer Configuration > Administrative Templates > System > Device Guard > Turn On Virtualization Based Security, then set Credential Guard Configuration to “Enabled with UEFI lock.” The lock writes a firmware variable so the setting cannot be turned off remotely by changing a registry value or GPO and rebooting, which is exactly the sequence an attacker with local admin would try. The tradeoff is that legitimate decommissioning also needs a local, two-reboot disable sequence (Microsoft ships DG_Readiness.ps1 -Disable for this), so build that into imaging and decommission runbooks ahead of time.

Because these prerequisites vary by hardware generation and firmware revision, knowing which endpoints actually qualify is an inventory question before it is a policy question. A platform that keeps a live hardware and firmware baseline across the fleet, such as the asset inventory view in SITEY, can flag machines missing TPM 2.0, VT-d, or a current firmware build before a GPO gets pushed and silently fails to take effect on the ones that cannot meet it.

What Credential Guard does not protect

Vendors market Credential Guard as closing the credential theft problem on Windows. It closes one specific path. Several adjacent ones stay wide open:

  • Cached domain logons. MSCache2 verifiers used for offline logon live in the SECURITY registry hive, not in LSASS memory. An attacker with SYSTEM can still dump them with secretsdump.py and crack them offline; Credential Guard was never in that data path.
  • DPAPI-protected data. Saved RDP credentials, Wi-Fi profiles, and browser-stored passwords are decrypted with the user’s password-derived key or, for domain accounts, the domain’s DPAPI backup key. Isolating LSASS does not move or re-key any of this.
  • Fresh interactive sessions. When a user types a password, at the console or over RDP, that plaintext transits Winlogon and LSASS before it is converted to a hash. A keylogger or a compromised RDP host on the other end captures it regardless of what Credential Guard does afterward; the control stops post-hoc dumping, not interception at entry.
  • Local SAM accounts. The local Administrator account sits in the SAM database, not behind Credential Guard. Pass-the-Hash with a local admin hash still works unless something like LAPS is separately rotating that password.
  • NTLM relay. Relay attacks never require reading a hash out of LSASS, so Credential Guard has no effect on them at all.

Treat a Credential Guard finding as closing exactly the row in the earlier table it closes, and keep separate remediation tracks open for cached logons, DPAPI exposure, and local account hygiene. Folding all of these into one “credential protection” line item on a report tends to produce false confidence once one control lands.

Compatibility casualties: what breaks first in a real rollout

Category Typical symptom Root cause
Legacy VPN clients (older Cisco AnyConnect and Juniper Pulse builds) Authentication fails or falls back to a prompt loop Client calls an unsupported LSA API to pull NTLM material directly instead of using the documented negotiate path
Remote support / unattended access agents Service crash or silent handle failure during credential injection Agent hooks LSASS to inject session credentials for unattended logon, which a protected process refuses
WDigest-dependent tools Plaintext credential feed used by a monitoring or SSO tool stops returning data WDigest plaintext storage is blocked under Credential Guard even if UseLogonCredential is still set to 1 in the registry
Third-party credential providers / biometric SSO agents Login method disappears from the logon screen Provider DLL is unsigned or not recompiled against the current LSA interface and fails to load into a protected LSASS

None of these failures announce themselves as a security control working correctly. They show up as helpdesk tickets days after a policy push, which is why the audit-mode step described earlier for RunAsPPL is worth repeating for Credential Guard: run VBS in a pilot ring through a normal patch cycle and read the CodeIntegrity log before enforcing fleet-wide.

Verifying the protection is actually running, not just configured

The gap between “policy applied” and “control running” is where most audits of this area go wrong. A GPO can apply cleanly and still leave the underlying feature dark because the hardware did not meet the bar, a driver blocked VBS from starting, or a firmware update reset a UEFI variable.

Check the real state with PowerShell, not with the policy console:

  • Get-CimInstance -ClassName Win32_DeviceGuard -Namespace rootMicrosoftWindowsDeviceGuard | Select SecurityServicesConfigured, SecurityServicesRunning
  • Value 1 in SecurityServicesConfigured means Credential Guard is set to run; the same value must also appear in SecurityServicesRunning or it configured but did not start. Value 2 in either array refers to HVCI.
  • msinfo32 under System Summary shows “Virtualization-based security” as either “Running” or “Enabled but not running,” which is the same gap in a human-readable form.

For RunAsPPL, confirm the signer level on the live process rather than trusting the registry value alone, since a value of 1 with a blocked boot-start driver can still leave LSASS running unprotected on some builds. Cross-check the registry value against a clean CodeIntegrity event log (no 3065 to 3067 entries since the last reboot) before treating a host as protected.

This is also where a one-time check stops being enough. A driver update, an antivirus engine upgrade, or a firmware patch can flip SecurityServicesRunning back off without touching the GPO or the registry value at all, so a host can pass a scan in January and silently regress in March. Platforms that automate this phase, such as SITEY, re-test the specific control on each scan cycle instead of trusting the last recorded status, re-reading Win32_DeviceGuard and the CodeIntegrity log rather than assuming a setting that applied once still holds. Mapping that same check to the relevant control IDs also turns one query into evidence for several frameworks at once: if you already track hardening findings against ISO 27001, PCI DSS, or a CIS benchmark, a compliance mapping layer over the same check saves re-running the audit per framework. Because LSASS access is a direct pivot point for lateral movement, it belongs in whatever view your team uses for attack surface tracking rather than sitting as a one-off hardening ticket, and any finding here should stay open in the vulnerability lifecycle until the re-check, not just the initial push, comes back clean.

Neither RunAsPPL nor Credential Guard is a single setting you turn on and forget. They are two narrow, non-overlapping controls with real hardware and compatibility costs, and the only way to know either one is actually doing its job on a given host is to query the live state after every change that could plausibly break it.

About SITEY

SITEY is an autonomous vulnerability management platform. It discovers, validates, prioritizes, remediates and re-tests vulnerabilities through an eight-phase automated pipeline, unifying output from 17 integrated scanners. SITEY is self-hosted: it runs in your own infrastructure and your findings are stored there. Outbound connections are limited to licence activation and the optional services you enable, such as an AI provider, CVE enrichment and patch catalogues. Pricing is 599 USD per month or 5,999 USD for a perpetual lifetime license. See pricing or how the platform works.

SITEY closes the loop, not just the report.Discover, validate, fix and verify in your own infrastructure.

See pricing