NTLM and Pass-the-Hash

Windows Does It Its Own Way

Generic hash cracking applies anywhere. But Windows has its own hash format, its own storage, and its own fatal weaknesses, and those weaknesses unlock attacks you can’t pull off on other systems.

Local account passwords are hashed and stored in the SAM (Security Account Manager) database. The modern format is the NTLM hash.

Its ancient predecessor, LM, was so weak (case-insensitive, and split into two separately-hashed 7-character chunks) that it’s been disabled by default since Windows Vista.


NTLM’s Fatal Flaw: No Salt

A salt is random data added to a password before hashing, so that two users with the same password end up with different hashes. Salts exist for one reason: to stop precomputation.

NTLM hashes in the SAM are not salted.


No salt means two devastating consequences:

  1. Identical passwords produce identical hashes, so you spot password reuse for free
  2. Hashes can be precomputed. Hash every possible password once, store the results in a giant lookup table (a rainbow table), and then crack any unsalted hash by lookup instead of computation, near-instantly

Salting is what makes precomputation pointless. NTLM’s lack of it is why these hashes fall so fast, and, as we’ll see, why they can be reused as-is.


Getting the Hashes Out

You can’t just copy the SAM while Windows is running, the kernel holds an exclusive lock on it. The standard tool to bypass this is Mimikatz, which reads hashes straight from memory and the SAM.

Extraction needs administrator privileges plus the SeDebugPrivilege, then elevation to SYSTEM:

mimikatz # privilege::debug
mimikatz # token::elevate
mimikatz # lsadump::sam

This dumps each local user’s NTLM hash. Mimikatz can also pull cached hashes from LSASS memory with sekurlsa::logonpasswords.


Cracking It

Once extracted, an NTLM hash cracks like any other, mode 1000 in Hashcat:

hashcat -m 1000 hashes.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule

With a decent wordlist and rules, a typical user password falls in seconds. But what about a strong one, long, random, never in any wordlist?


You Might Not Need to Crack It

Here’s the part that feels like cheating.

For NTLM, the hash isn’t just used to check the password. It effectively is the password. When a Windows client authenticates with NTLM, it never sends the plaintext, it proves identity using the hash. The plaintext was never the real secret.

So if you hold the hash, you can authenticate as that user without cracking anything. This is Pass-the-Hash.


You hand the hash to a tool and it logs in. To access an SMB share with just the hash:

smbclient \\10.10.10.20\share -U Administrator --pw-nt-hash <NThash>

To get an interactive shell, the hash format is LMhash:NThash, and since LM is dead you fill the LM half with 32 zeros:

impacket-psexec -hashes 00000000000000000000000000000000:<NThash> [email protected]

A tool detail worth remembering: psexec runs as a service, so your shell comes back as SYSTEM. wmiexec runs as the user you authenticated with. Pick based on what you need.


Why It Scales: Password Reuse

Pass-the-Hash would be a neat trick on its own. What makes it devastating is local-admin password reuse.


Organizations image machines from a golden template, and that template has one local Administrator password. So the same NTLM hash sits in the SAM of every machine built from it.

Crack or grab that hash on one box, and it authenticates to all of them. You cracked nothing extra.

One hash, an entire fleet. This is why Pass-the-Hash is a cornerstone of lateral movement: a single foothold becomes network-wide access.


The Catch: UAC Remote Restrictions

There’s an important limit. Since Windows Vista, UAC remote restrictions block remote administrative actions for local admin accounts, with one exception: the built-in Administrator account (RID 500).


So when you Pass-the-Hash for code execution:

AccountResult
Built-in Administrator (RID 500)Full remote admin, you get your shell
Any other local adminAuthenticates, but remote admin is blocked unless UAC remote restrictions are disabled on the target

Not all local admins are equal over the network. The built-in Administrator hash is the prize, because it sails past UAC remote restrictions where other local admins get stopped.


When You Can’t Even Get the Hash

Everything here assumed you could reach the SAM, which means you already had admin and SYSTEM on the machine.

But what if you don’t? What if you’re a low-privileged user with a shell, no way to run Mimikatz, no way to touch the SAM?

You can still attack Windows credentials. You just go after a different kind of hash, one that travels across the network. That’s the next note.