Windows Credential Dumping
There have been written and researched a lot about credential dumping in Windows and I have read a lot about various aspects of it all throughout my career.
In the last months, I felt the desire to grasp the whole picture of the topic, well, let’s say a bigger picture. Over the years people have found so many ways to circumvent protections in Windows that other people built to prevent unprivileged access of credentials.
If you are interested in windows protection and detection techniques and how they behave under the various attacks on Windows credentials, this article is for you.
This blog tries to answer four questions:
- How do credentials come into the system and how are they processed?
- How can an attacker gain access to those credentials?
- How does Windows & Defender for Endpoint fight against those attacks and …
- … how successful are they with this fight?
Table of Content
- Authentication & Trust
- How to find/get Passwords
- Protection & Detection
Authentication & Trust
Now, let’s have a deeper look into the Mitre technique T1003 and its sub-technique T1003.001 ‘LSASS Memory’.
First, let’s get an overview of today’s authentication possibilities. A Windows 10 Computer could be standalone, domain joined, hybrid joined or AAD joined. To find out about the status of a computer, you can do a DSREGCMD /STATUS:
Find out what these values mean here.
Depending on the ‘device state’, during logon, you authenticate against different authorities, let’s concentrate on the most common scenarios:
- If your computer is domain joined (AD), you will authenticate through communication with the KDC on your domain controller. As a result of this, you will receive a Ticket Granting Ticket (TGT), if the authentication was successful.
- If your computer is hybrid joined, in addition to the above, in the background, your computer is communicating with AAD to receive a Primary Refresh Token (PRT), the cloud equivalent to the TGT.
- If your computer is AAD joined, it will only contact the AAD to receive a PRT, unless you are accessing onprem resources later.
There are many ways to provide credentials to Windows including:
- Windows Hello (Face- and Fingerprint Recognition)
- Smart Cards
Loging on with a local Windows account by providing a username/password gives us the possibility to read the NTLM hash of the password from memory:
The same is possible, if your device is AD or AAD joined, and you provide a username & password either during logon or during a later authentication against a resource. This logon information (NTLM hash or Kerberos Ticket) can be used to either logon to systems (pass the hash / pass the ticket) or to ‘crack’ the hash with a dictionary attack offline on another system. So, when we talk about credential dumping, it all comes down to what (I believe) Lao-Tse said:
If Windows does not know your password, nobody can steal it from there.Lao-Tse
It’s not in the scope of this article to go through the different logon and authentication possibilities that you have in Windows, however if you want to get a good overview, I recommend the following links:
- How Azure AD Sign-In works
- Deep dive: Logging on to Windows
- How SSO works in Windows 10 Devices
- What happens when you type in your password into Windows?
- Windows Logon Scenarios
- Windows Hello for Business and Authentication
- What is a Primary Refresh Token?
- Password-less authentication options for Azure AD
If you are interested in how, you can protect your identities in general, this article might be interesting too.
The Password Dilemma
However, if you have not been in IT since last week, you will know that it is not that easy, even in small companies, to get rid of passwords. Even if you are in a modern workplace environment, you will have some older systems TM that will require a password for access.
Now that you – dear reader, have acknowledged that we will have to cope with passwords on Windows for a while, let’s see what we can do to protect them.
How to find/get Passwords
From an attacker’s perspective, there are two ways to obtain these secrets: either by registering your own security package or by accessing LSASS memory. The latter is done by mimikatz by searching for well-known patterns in memory to find sensible data, which is outlined in great detail by Adam Chester here:
Adam shows that this pattern search in memory of course can also be done via WinDbg for example:
Mimikatz is searching in memory for similar structures when other security packages (e.g.: msv_01) are used.
To access LSASS memory, an attacker needs administrative rights on the system and debug privileges (which are not assigned to admins by default but can be requested through system API):
That’s exactly what mimikatz is doing for you:
But again, you need to have admin permission already, otherwise mimikatz cannot obtain debug privileges:
If you attach WinDbg to mimikatz and execute “!token” in the debug command line, you will see the current access token privileges of the mimikatz process:
If you now provide privilege::debug to the mimikatz cmd, the privilege table will change accordingly:
(You can also view this information with Process Explorer on the Security Tab of the process properties).
Another way to gain access to passwords from memory is to first dump the lsass memory and use mimikatz offline (on another box) to search the dump for those sensitive structures instead of searching the live memory.
Working with your own Security Package
Now, let’s have a look at the other option to gain access to the sensible data that I have mentioned before: working with our own security package that hooks into the lsass process. As mentioned at the beginning, lsass will simply ask all security packages registered in the system, if they can handle the logon process. Mimikatz provides two ways to use your own security package. Either by registering it in the registry (mimikatz comes with mimilib.dll for that case) or by directly manipulating the memory to leave less traces. In both cases, the password can be captured.
If an attacker has debug privileges, it’s very easy in mimikatz to patch the memory with the new security package:
This will then automatically log all passwords into a txt-file in System32:
Read more about these two functions in Adam’s 2nd article here.
Protection & Detection
In this section we will discuss protection techniques that help fight attacks against lsass from e.g., mimikatz. Of course, there are bypasses for some of those techniques as well, but that is out of the scope of this article.
To test all this in my ‘hardened’ lab, I enabled MDE troubleshooting mode that comes in handy to be able to temporarily turn off e.g., real time monitoring. We don’t want to test Defender’s capabilities to recognize the mimikatz binaries by matching signatures but want to take a deeper look into what behavioral protection and detection possibilities we have available.
Putting the possible attack vectors together: there are three known ways to get access to credentials that are either cached by lsass or provided to lsass:
- Directly access lsass process’ memory and search for sensible data by patterns
- Dump lsass memory and search for patterns offline
- Register a security package on your own and ‘listen’ whenever passwords are provided
LSASS Process Protection Light (PPL)
The first obvious protection against the access of the lsass’ memory space is to harden the access to this memory space by running lsass as a protected process.
In the Windows security model, any process running with a token containing the debug privilege (…) can request any access right that is desired to any other process running on the machine. For example, read and write arbitrary process memory, inject code (…)Windows Internals Part 1, 7th Edition, Page 113
That’s exactly what mimikatz is doing: manipulating lsass memory space to get access to sensitive data. That’s why we need to protect the lsass process.
If LSA protection is enabled, you cannot debug a custom LSA plugin. You can’t attach a debugger to LSASS when it’s a protected process. In general, there is no supported way to debug a running protected process.https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection
Process protection can be configured in the registry e.g., by adding the regkey RunAsPPL and setting it to 1:
After a reboot you should see the following event:
You can also check the protection level of lsass with Process Explorer (run as Admin):
This then leads to an “Access Denied” (0x0000005) for mimikatz when trying to access lsass’ memory …
… and when trying to load an additional security package into the lsass process, this is denied too:
When Secure Boot is enabled, the registry setting (RunAsPPL) does not change the protection level of the lsass process any more – even when set to 0 in the registry, lsass will run as PPL since the setting will be stored in the UEFI firmware. However, this doesn’t prevent mimikatz from being able to remove the PPL flag from the process in memory unfortunately (after the next reboot, lsass will still be protected, since the setting is loaded again, but in the meanwhile passwords and hashes can be extracted).
Virtualization Based Security
Our next iron in the fire is called ‘virtualization-based security (VBS)’ including a configuration called ‘Hypervisor enforced Code Integrity (HVCI), also called ‘Memory integrity’, which is part of ‘Core isolation‘ – easy, isn’t it?
VBS brings in an additional virtualized kernel that is running on a new trust level. While the rest of the system, including the ‘normal’ kernel is on Virtual Trust Level 0 (VTL 0), the new secure kernel is on VTL 1 and is hiding memory addresses from the normal kernel. As we have read above about how mimikatz is gaining access to the credentials in memory, these virtualization technologies are important to be protected against those kinds of attacks.
In modern Windows systems, you turn all the above on with one setting:
Neither feature improved the situation on the defender side, I was still able to retrieve the credentials via sekurlsa::logonpasswords and by injecting the mimi-driver, but it prepared the ground for our next step: Credential Guard. By turning on VBS, windows starts a second process for lsass – the isolated, virtualized version of lsass: lsassIso:
Credential Guard is using lsassIso to store the credentials there instead of storing it in the normal lsass process. LsassIso is running in VTL 1 and cannot be accessed by a normal administrator, even if she has debug privileges.
To verify if Credential Guard, VBS and HVCI are enabled, start MSINFO:
If enabled, mimikatz cannot access the secrets anymore since they are stored in the isolated LsassIso process:
However, Credential Guard has no influence on loading mimikatz’s own security package in memory. It’s still possible to listen to new passwords then:
Removing the right to gain debug privileges
Another way to make it harder to access these memory areas would be to set a policy in Intune/MEM to prevent users (admins) from getting debug privileges (this CSP should help you).
Attack Surface Reduction Rule (ASR)
The ASR Rule Block credential stealing from the Windows local security authority subsystem, brings us another step further:
If you turn on this ASR rule by …
Add-MpPreference -AttackSurfaceReductionRules_Ids 9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2 -AttackSurfaceReductionRules_Actions Enabled
… mimikatz cannot access the lsass memory anymore:
and mimikatz cannot register a security package anymore:
Microsoft Defender for Endpoint
With the techniques above, we have tried to prevent credential attacks by closing some doors. Let’s now investigate how Defender for Endpoint is actively monitoring the sensible parts of the OS and then -hopefully- raising alerts.
In this article, we are not so much interested in those more signature-based alerts that are looking for known malicious tools:
We are looking for behavioral based alerts, which will recognize suspicious behavior (like modifying the process memory of LSASS) no matter how the binary looks like:
MDE also knows about when you read from lsass memory:
Here is another great alert, which recognizes that the mimikatz driver was loaded (Thats the reaction of MDE to the !+ command in mimikatz):
If you then do a !processprotect /process:lsass.exe /remove, MDE throws this alert:
Besides mimikatz, if you use OS based or third-party tools to dump lsass memory, this is something that is recognized by MDE as well:
Now, let’s come to my favorite part.
In the DeviceEvents table in MDE, we have some interesting ActionTypes for our hunt:
With the following query, we can bring some light into what mimikatz and other tools actions look like in the defender telemetry:
With that, we can see e.g. ‘simple’ process dumps from lsass, in that case from procdump:
And we see when mimikatz e.g. is reading from protected memory or is writing to lsass memory:
No matter what I was testing above with mimikatz, I always had to request Debug Privileges for the mimikatz process in order to access the memory space of another process (lsass.exe). So why not hunt for processes that gained SeDebugPrivileges:
The most important part of this query (second last line) in which we are translating a decimal value into a binary value and then looking for the 20th bit, is coming from Ruben Bouman in his article about token privileges.
|Prevention/Detection Technique||Gain Debug Privilege||Access Lsass Memory||Manipulate Lsass Memory||Remove Lsass Protection||Security Package|
|LSASS Process Protection||no protection||protected||protected||bypass||protected|
|Virtualization Based Security||no protection||no protection||no protection||no protection||no protection|
|Credential Guard||no protection||encrypted credentials||credentials secured in lsassIso||credentials secured in lsassIso||no protection|
|Removing the right to gain debug privilege||protected||protected||protected||protected||protected|
|Defender for Endpoint Alerts||no alert||event available||alert||alert||alert|
|Defender for Endpoint Hunting||data available||data available||data available||data available||data available|
There will always be ways to circumvent protections. From the defender’s perspective, it is important to stay at the edge of technology to be well prepared for the most creative attackers and red teamers. So, we shall never sleep but always improve the systems we are responsible for ;-). And so does Microsoft: Credential guard and “additional protection for LSA” will be on by default with upcoming versions of Windows 11 as this blog states. Let’s see what that means.