Once an attacker reaches Domain Admin, the entire directory is theirs — and the part people underestimate is just how fast every password in the domain falls out of it. This post walks through how to dump NTDS.dit and crack the password hashes inside it, why those hashes are unsalted MD4 (NT) hashes that crack far faster than people expect, and — the part that actually matters for defenders — how to detect the dump and harden against it. Everything here is framed for authorized testing of your own domain in a lab.
Authorized use only. The techniques below extract every credential in an Active Directory domain. Run them solely against systems you own or have written permission to test. Dumping NTDS.dit from a production domain you do not control is a criminal offense in most jurisdictions, Germany included.
Key Takeaways
- Active Directory stores passwords as unsalted NT hashes — a single MD4 of the UTF-16LE password — which means identical passwords produce identical hashes and crack extremely quickly.
- To dump NTDS.dit and crack the password hashes offline you need both the database file and the SYSTEM registry hive, because the hashes are encrypted with a key derived from the boot key.
- On a domain controller, an attacker with replication rights can skip the file entirely and pull hashes over the wire with a DCSync-style replication request.
- Cracking is done with
hashcat -m 1000or John the Ripper inntformat; an 8-character password from a common wordlist often falls in minutes on a single GPU. - Detection centers on Event ID 4662 replication access,
ntdsutilandvssadminusage, and the controls that limit blast radius: tiered admin, the Protected Users group, and genuinely long passwords.
Environment
- A lab Active Directory domain on Windows Server 2022, single domain controller, functional level 2016.
- A domain account with Domain Admin rights (the privilege level this attack assumes you have already reached).
- Impacket 0.12 for
secretsdump.py, running on a separate Linux testing host. - Hashcat 6.2 and John the Ripper (jumbo) for the cracking step.
The Problem
The uncomfortable truth about Active Directory is that the entire security of every account collapses to one file. C:\Windows\NTDS\ntds.dit is an ESE (Jet) database holding every object in the domain, and for user objects it holds the NT hash of their password. There is no per-user salt. Microsoft never added one. An NT hash is simply MD4(UTF-16LE(password)) — no salt, no iteration count, no work factor.
Unsalted matters more than it sounds. With a salt, two users who both chose Summer2026! would have different stored hashes, and an attacker would have to attack each one separately. Without a salt, they share the exact same hash, precomputed rainbow tables work, and a single dictionary run cracks every reuse of a password at once. MD4 is also computationally trivial, so a modern GPU churns through tens of billions of NT-hash guesses per second. The combination — no salt, a fast hash — is why "we reached Domain Admin" quietly means "we have every plaintext password worth having."
The hashes are not stored in the clear inside the file. They are encrypted with the Password Encryption Key (PEK), which is itself encrypted with the domain's boot key, stored in the SYSTEM registry hive. That is the one speed bump: to decrypt the hashes offline you need ntds.dit and the SYSTEM hive together. Get both, and the encryption is just a formality.
The Solution
Step 1 — Dump NTDS.dit with ntdsutil (the supported way)
The file is locked while AD DS is running, so you cannot just copy it. The cleanest method is the same one Microsoft documents for building a replica from media: ntdsutil's Install-From-Media (IFM) feature. It produces a consistent snapshot containing both the database and the registry hives you need.
ntdsutil "activate instance ntds" "ifm" "create full C:\temp\ifm" quit quit
That writes ntds.dit into C:\temp\ifm\Active Directory\ and the SYSTEM and SECURITY hives into C:\temp\ifm\registry\. It is built-in, requires no third-party tooling, and on a real domain controller it generates almost no noise — which is precisely why it is worth detecting. The Volume Shadow Copy route (vssadmin create shadow, then copy the file out of the snapshot) achieves the same result and is the more common attacker fallback when ntdsutil is unavailable.
Step 2 — Extract the NT hashes offline with secretsdump
Move the ntds.dit and SYSTEM hive to your testing host. Impacket's secretsdump.py parses the ESE database, pulls the PEK out of the registry, decrypts every NT hash, and prints them in the standard pwdump format:
secretsdump.py -ntds ntds.dit -system SYSTEM LOCAL
The output is one line per account, username:rid:lmhash:nthash::::
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
jsmith:1104:aad3b435b51404eeaad3b435b51404ee:5835048ce94ad0564e29a924a03510ef:::
svc_sql:1108:aad3b435b51404eeaad3b435b51404ee:64f12cddaa88057e06a81b54e73b949b:::
The aad3b435... repeated across every line is the empty LM hash — LM storage has been off by default for years, so only the final field, the NT hash, is real. Notice there is nothing distinguishing one account's hash from another beyond the password itself. That is the missing salt, visible. Strip the NT hashes into a file for cracking:
cut -d: -f4 secrets.txt > nthashes.txt
A heads-up if your lab domain controller runs Windows Server 2022 or 2025: the Impacket build shipped on current Kali (v0.14.0.dev0 when I tested) can fail to parse the newer ntds.dit, bailing out with [-] bytearray index out of range the moment it finishes reading the boot key. The database is not corrupt — esentutl /mh reports a clean shutdown and Windows' own tools read it fine — it is the pure-Python ESE parser choking on the larger database page size the newer schema uses. If you hit it, the dependable alternative is the DSInternals PowerShell module, which reads the same IFM output through Windows' native ESE engine, on the domain controller, with no transfer to a Linux host at all:
$key = Get-BootKey -SystemHiveFilePath 'C:\temp\ifm\registry\SYSTEM'
Get-ADDBAccount -All -DBPath 'C:\temp\ifm\Active Directory\ntds.dit' -BootKey $key |
Where-Object NTHash |
ForEach-Object { '{0}:{1}' -f $_.SamAccountName, ([BitConverter]::ToString($_.NTHash) -replace '-').ToLower() }
That prints one account:nthash line per user, ready to drop straight into hashcat or John. For a defensively minded audience DSInternals is arguably the more natural tool to reach for than a pentest framework, and it sidesteps the parser bug entirely.
The full set of domain NT hashes extracted off the domain controller with DSInternals — one account:nthash line each, unsalted, ready for offline cracking.
On a live domain controller, an attacker with replication rights skips Steps 1 and 2 entirely and asks the DC to replicate the hashes directly — the DCSync technique, secretsdump.py domain/admin@dc01 -just-dc. No file touches disk, which is exactly why the replication event in Step 4 is the detection that matters most.
Step 3 — Crack the MD4 (NT) hashes with hashcat and John
NT hashes are hashcat mode 1000. A straight wordlist run against the classic rockyou.txt, with a rule set to cover common mutations, looks like this:
hashcat -m 1000 -a 0 nthashes.txt rockyou.txt -r rules/best64.rule
For passwords a wordlist will not find, a mask (brute-force) attack is viable precisely because MD4 is so cheap. An eight-character mixed mask is well within reach on a single modern GPU:
hashcat -m 1000 -a 3 nthashes.txt ?u?l?l?l?l?d?d?d
John the Ripper does the same job with the nt format and needs no GPU, which makes it the practical choice on a CPU-only lab VM. Its hybrid mask mode is exactly what shreds the season-plus-year passwords people actually pick — it appends a four-digit year to each wordlist entry:
john --format=nt --wordlist=rockyou.txt --mask='?w20?d?d' nthashes.txt
john --format=nt --show nthashes.txt
A password like Summer2026 falls in seconds this way: Summer is already in the wordlist and the mask supplies the year, so no full brute force is needed. A genuinely long, random password does not fall in the same run — which is the entire argument for Step 5.
John recovering the weak account's password (Summer2026) from its NT hash in seconds, while a long random password in the same run does not fall.
The result is sobering the first time you run it against a real (lab) domain: the service accounts with a password set in 2019 and never rotated, the help-desk pattern of CompanyNameMonthYear, and the handful of users who all picked the same thing all surface in the same run. Because the hashes are unsalted, cracking one instance of a reused password cracks it everywhere it appears. This is the same arithmetic that makes Kerberoasting so effective — a weak password behind a service account is a weak password whether you pull it from a TGS ticket or from NTDS.dit.
Step 4 — Detect the dump
Prevention is in Step 5, but you will never prevent everything, so detection comes first in practice. The single highest-value signal is the replication request used by DCSync. Audit Directory Service Access and watch domain controllers for Event ID 4662 where the object access includes the replication control access rights — the GUIDs 1131f6aa-9c07-11d1-f79f-00c04fc2dcd2 (DS-Replication-Get-Changes) and 1131f6ad-... (Get-Changes-All). A 4662 with those GUIDs from anything that is not a domain controller computer account is a red flag.
Get-WinEvent -FilterHashtable @{ LogName='Security'; Id=4662 } |
Where-Object { $_.Message -match '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2' } |
Select-Object TimeCreated, @{n='Account';e={ $_.Properties[1].Value }}
For the file-based methods, watch process creation (Event ID 4688, with command-line auditing on) for ntdsutil and vssadmin create shadow on domain controllers, and for any process opening ntds.dit. These belong in the broader catalog of signals covered in Essential Windows Event IDs for Security Monitoring, and a tuned Sysmon configuration makes the process and file-access events far cleaner than the native logs alone.
Worth knowing before you build any of that: on a current domain controller, Microsoft Defender Antivirus already flags the IFM dump on its own. Running ntdsutil ... ifm create full is detected and quarantined out of the box as Trojan:Win32/SuspShadowAccess.DA, logged as Event ID 1116 (detected) and 1117 (remediated) in the Microsoft-Windows-Windows Defender/Operational log. It is a behavioral detection keyed on the command line and the shadow-copy access the technique performs, not on the ntdsutil.exe file — which is why an ordinary antivirus process exclusion does not suppress it, and why the attempt simply fails to launch with "Access is denied". Treat that built-in block as a useful backstop, not a finish line: an attacker who has already reached Domain Admin can disable Defender first, and the Volume Shadow Copy route can be shaped to look less like the textbook command line. Your own auditing of replication and process creation is what catches the version that does not announce itself.
Defender quarantining the ntdsutil IFM attempt as Trojan:Win32/SuspShadowAccess.DA, logged as Event ID 1117 in the Defender Operational log — a behavioral detection an antivirus exclusion does not bypass.
Step 5 — Harden so the dump is worth less
You cannot salt NT hashes — that is a property of the protocol, not a setting. So hardening is about three things: limiting who can perform the dump, shrinking what a stolen hash unlocks, and making the cracking step fail.
- Tier your admin model. Domain Admin should be rare, used from dedicated privileged access workstations, and never used to log on to ordinary endpoints. The whole attack assumes the attacker already walked the Active Directory kill chain to that tier; tiering is what makes reaching it hard.
- Put privileged accounts in the Protected Users group. It blocks NTLM, disables credential caching, and forces Kerberos with stronger settings, which limits the reuse value of a stolen hash.
- Make cracking lose. Length beats complexity against an unsalted fast hash. A 15+ character minimum for users and long random passwords or group-managed service accounts (gMSA) for services push brute force out of practical range. The reused-password problem is exactly what Windows LAPS solves for local administrator accounts.
- Audit for unexpected replication rights. DCSync needs Get-Changes and Get-Changes-All on the domain object. Review who holds them; it should be domain controllers and nothing else.
Microsoft's own guidance on the attack and its mitigations lives in the Defender for Identity credential-access alert documentation, which maps neatly onto MITRE ATT&CK T1003.003, OS Credential Dumping: NTDS.
Frequently Asked Questions
Why are Active Directory password hashes not salted?
The NT hash predates the modern understanding of password storage and was never updated. It is a bare MD4 of the UTF-16LE password with no salt and no iteration count, kept for backward compatibility with NTLM authentication. Because there is no salt, identical passwords share identical hashes and precomputed rainbow tables remain viable.
Do I need the SYSTEM hive to crack NTDS.dit?
Yes, for the offline file method. The NT hashes inside ntds.dit are encrypted with the Password Encryption Key, which is protected by the domain boot key stored in the SYSTEM registry hive. Without the matching SYSTEM hive, secretsdump.py cannot decrypt the hashes. The DCSync method avoids this because the domain controller hands over already-decrypted hashes.
Does Microsoft Defender detect an ntdsutil NTDS.dit dump?
Yes. On a current Defender build, running ntdsutil ... ifm create full on a domain controller is detected and remediated out of the box as Trojan:Win32/SuspShadowAccess.DA, logged as Event ID 1116 and 1117 in the Microsoft-Windows-Windows Defender/Operational log. It is a behavioral detection keyed on the command line, so an antivirus process exclusion does not bypass it. It is a useful backstop, not a replacement for auditing replication (Event ID 4662) and process creation, since an attacker with Domain Admin can turn Defender off first.
Can Credential Guard stop an NTDS.dit dump?
No. Credential Guard and LSA protection defend the secrets held in the LSASS process on a member machine; they do not protect the Active Directory database on a domain controller. NTDS.dit is a separate concern, defended by limiting domain controller access, tiering admin, and detecting replication abuse rather than by LSASS hardening.
Is dumping NTDS.dit legal to practice?
Only against systems you own or are explicitly authorized to test, such as a lab domain or a sanctioned penetration test with written scope. Performing it against a domain you do not control is unauthorized access to a computer system and is prosecutable. Build a throwaway lab domain and practice there.
Conclusion
The mechanics of dumping NTDS.dit and cracking the password hashes are not exotic — a built-in utility, one Impacket command, and a hashcat run. What the exercise drives home is the structural weakness underneath it: Active Directory stores passwords as unsalted, fast NT hashes, so the moment the database leaves the domain controller, every weak or reused password in the organization is on a countdown measured in minutes.
You cannot fix the lack of salt, so the defense is everything around it. Keep the Domain Admin tier small and clean, watch for the replication and file-access events that betray a dump, and make passwords long enough that cracking stops being worth the electricity. None of that is glamorous, but it is the difference between a dumped database being a catastrophe and being an expensive inconvenience.
Related Posts
- Detecting Kerberoasting with Windows Event ID 4769 — another route to crackable AD credentials, defended with the same length-over-complexity logic.
- Managing Windows LAPS with Microsoft Intune — kills the reused local-admin password that often gets an attacker to Domain Admin in the first place.
- Essential Windows Event IDs for Security Monitoring — the broader event catalog that includes the replication and process-creation signals used here.
Editorial note: posts on this blog are drafted with AI assistance and then reviewed, edited, and tested against a real environment before publishing. Commands, output, and screenshots come from systems I actually ran the work on.
0 comments:
Post a Comment